From 99ece2f7d39077b0af3eecbbb108232e2a2261a6 Mon Sep 17 00:00:00 2001 From: tyeth Date: Wed, 27 Nov 2024 16:36:52 +0000 Subject: [PATCH 01/19] Add RPi Pico2W build --- platformio.ini | 82 +- src/Wippersnapper_Boards.h | 2 +- .../statusLED/Wippersnapper_StatusLED.cpp | 820 +++++++++--------- src/provisioning/tinyusb/Wippersnapper_FS.cpp | 2 +- 4 files changed, 491 insertions(+), 415 deletions(-) diff --git a/platformio.ini b/platformio.ini index dd4acafc2..427a7ea94 100644 --- a/platformio.ini +++ b/platformio.ini @@ -71,7 +71,7 @@ lib_deps = adafruit/Adafruit TouchScreen adafruit/Adafruit MQTT Library bblanchon/ArduinoJson - https://github.com/pstolarz/OneWireNg.git + https://github.com/tyeth/pstolarz_OneWireNg.git#pico2w https://github.com/milesburton/Arduino-Temperature-Control-Library.git https://github.com/Sensirion/arduino-sht.git https://github.com/Sensirion/arduino-i2c-scd4x.git @@ -112,9 +112,9 @@ lib_archive = no ; debug timer issues see https://community.platformio.org/t/cho lib_ignore = OneWire [common:rp2040] -platform = https://github.com/maxgerhardt/platform-raspberrypi.git +platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop ; platform_packages = -; framework-arduinopico @ symlink:///Users/tyeth/Projects/arduino-pico +; ; framework-arduinopico @ symlink:///Users/tyeth/Projects/arduino-pico ; framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#master board = rpipicow framework = arduino @@ -511,3 +511,79 @@ build_flags = ; ; No USB stack ; build_flags = -DPIO_FRAMEWORK_ARDUINO_NO_USB ; -DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6 + + +[env:raspberypi_pico2w] +extends = common:rp2040 +platform = https://github.com/tyeth/maxgerhardt_platform-raspberrypi.git#pico2w +; platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop +platform_packages = + framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git +board = rpipico2w +build_flags = + -DWIFICC=CYW43_COUNTRY_UK + ; -DARDUINO_ARCH_RP2040 + ; -DUSBD_MAX_POWER_MA=500 + ; -DPICO_CYW43_SUPPORTED=1 + +[env:raspberypi_pico2w_debug] +extends = common:rp2040 +platform = https://github.com/tyeth/maxgerhardt_platform-raspberrypi.git#pico2w +; platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop +platform_packages = + framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git +; ; framework-arduinopico @ symlink:///Users/tyeth/Projects/arduino-pico +board = rpipico2w +build_type = debug +framework = arduino +debug_tool = cmsis-dap +upload_protocol = cmsis-dap +; board can use both Arduino cores -- we select Arduino-Pico here +board_build.core = earlephilhower +board_build.filesystem_size = 0.5m +debug_init_break = tbreak runNetFSM +build_flags = + ; -UARDUINO + ; -DPICO_BUILD + -DARDUINO_ARCH_RP2040 + -DUSBD_MAX_POWER_MA=500 + -DPICO_CYW43_SUPPORTED=1 + -DWIFICC=CYW43_COUNTRY_UK + ; -DDEBUG + ; -DDEBUG_RP2040_WIRE + ; -DDEBUG_RP2040_SPI + ; -DDEBUG_RP2040_CORE + ; -DDEBUG_RP2040_WIFI + ; -DNDEBUG + ; -DLWIP_DEBUG + ; -DDEBUG_RP2040_PORT=Serial1 + ; -DDEBUG_RP2040_UART_1 + ; -DDEBUG_RP2040_UART=1 + -Og + ; Enable debug stack protection + -fstack-protector + ; Enable Exceptions + -DPIO_FRAMEWORK_ARDUINO_ENABLE_EXCEPTIONS + ; Enable RTTI + -DPIO_FRAMEWORK_ARDUINO_ENABLE_RTTI + ; ; Enable default USB Stack of Pico SDK USB Stack with none of below usb options + ; Adafruit TinyUSB + -DUSE_TINYUSB + ; ; No USB stack + ; build_flags = -DPIO_FRAMEWORK_ARDUINO_NO_USB + ; -DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6 + + +[env:pimoroni_pico_plus_2w] +extends = common:rp2040 +platform = https://github.com/tyeth/maxgerhardt_platform-raspberrypi.git#pico2w +; platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop +platform_packages = + framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git +board = pimoroni_pico_plus_2w +build_flags = + -DWIFICC=CYW43_COUNTRY_UK + -DUSE_TINYUSB + ; -DARDUINO_ARCH_RP2040 + ; -DUSBD_MAX_POWER_MA=500 + ; -DPICO_CYW43_SUPPORTED=1 diff --git a/src/Wippersnapper_Boards.h b/src/Wippersnapper_Boards.h index 37e3db870..4e89862e0 100644 --- a/src/Wippersnapper_Boards.h +++ b/src/Wippersnapper_Boards.h @@ -185,7 +185,7 @@ #define BOARD_ID "mkrwifi1010" #define USE_STATUS_LED #define STATUS_LED_PIN 6 -#elif defined(ARDUINO_RASPBERRY_PI_PICO_W) +#elif defined(ARDUINO_RASPBERRY_PI_PICO_W) || defined(ARDUINO_ARCH_RP2040) #define BOARD_ID "rpi-pico-w" #define USE_TINYUSB #define USE_STATUS_LED diff --git a/src/components/statusLED/Wippersnapper_StatusLED.cpp b/src/components/statusLED/Wippersnapper_StatusLED.cpp index 47b170462..ba9061cb2 100644 --- a/src/components/statusLED/Wippersnapper_StatusLED.cpp +++ b/src/components/statusLED/Wippersnapper_StatusLED.cpp @@ -1,411 +1,411 @@ -/*! - * @file Wippersnapper_StatusLED.cpp - * - * Interfaces for the Wippersnapper status indicator LED/NeoPixel/Dotstar/RGB - * LED. - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2020-2022 for Adafruit Industries. - * - * BSD license, all text here must be included in any redistribution. - * - */ -#include "Wippersnapper_StatusLED.h" -#include "Wippersnapper.h" - -extern Wippersnapper WS; -#ifdef USE_STATUS_NEOPIXEL -Adafruit_NeoPixel *statusPixel = new Adafruit_NeoPixel( - STATUS_NEOPIXEL_NUM, STATUS_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800); -#endif - -#ifdef USE_STATUS_DOTSTAR -Adafruit_DotStar *statusPixelDotStar = - new Adafruit_DotStar(STATUS_DOTSTAR_NUM, STATUS_DOTSTAR_PIN_DATA, - STATUS_DOTSTAR_PIN_CLK, DOTSTAR_BRG); -#endif - -/****************************************************************************/ -/*! - @brief Initializes board-specific status LED pixel -*/ -/****************************************************************************/ -void initStatusLED() { -#ifdef USE_STATUS_NEOPIXEL - if (WS.lockStatusNeoPixel == false) { -#if defined(NEOPIXEL_I2C_POWER) - pinMode(NEOPIXEL_I2C_POWER, OUTPUT); - digitalWrite(NEOPIXEL_I2C_POWER, HIGH); -#elif defined(NEOPIXEL_POWER) - pinMode(NEOPIXEL_POWER, OUTPUT); -// turn NeoPixel power pin on -#ifndef ARDUINO_MAGTAG29_ESP32S2 - digitalWrite(NEOPIXEL_POWER, HIGH); -#else - digitalWrite(NEOPIXEL_POWER, LOW); -#endif -#endif - statusPixel = new Adafruit_NeoPixel( - STATUS_NEOPIXEL_NUM, STATUS_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800); - statusPixel->begin(); - statusPixel->show(); // turn OFF all pixels - WS.lockStatusNeoPixel = true; - } -#endif - -#ifdef USE_STATUS_DOTSTAR - if (WS.lockStatusDotStar == false) { -#ifdef STATUS_DOTSTAR_COLOR_ORDER - // Board requires a non-default color order in the constructor - statusPixelDotStar = new Adafruit_DotStar( - STATUS_DOTSTAR_NUM, STATUS_DOTSTAR_PIN_DATA, STATUS_DOTSTAR_PIN_CLK, - STATUS_DOTSTAR_COLOR_ORDER); -#else - statusPixelDotStar = - new Adafruit_DotStar(STATUS_DOTSTAR_NUM, STATUS_DOTSTAR_PIN_DATA, - STATUS_DOTSTAR_PIN_CLK, STATUS_DOTSTAR_COLOR_ORDER) -#endif - statusPixelDotStar->begin(); - statusPixelDotStar->show(); // turn OFF all pixels - WS.lockStatusDotStar = true; - } -#endif - -#ifdef USE_STATUS_LED - pinMode(STATUS_LED_PIN, OUTPUT); - -// Turn off LED initially -#if defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) - analogWrite(STATUS_LED_PIN, 255); -#elif defined(ARDUINO_ARCH_ESP32) - WS._pwmComponent->attach(STATUS_LED_PIN, LEDC_BASE_FREQ, LEDC_TIMER_12_BIT); - WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, 0); // turn OFF -#elif defined(ARDUINO_RASPBERRY_PI_PICO_W) - digitalWrite(STATUS_LED_PIN, 0); -#else - analogWrite(STATUS_LED_PIN, 0); -#endif - - WS.lockStatusLED = true; // set global pin "lock" flag -#endif -} - -/****************************************************************************/ -/*! - @brief De-initializes the status LED and releases pin. -*/ -/****************************************************************************/ -void releaseStatusLED() { -#ifdef USE_STATUS_NEOPIXEL - delete statusPixel; // Deallocate Adafruit_NeoPixel object, set data pin back - // to INPUT. - WS.lockStatusNeoPixel = false; // unlock -#endif - -#ifdef USE_STATUS_DOTSTAR - delete statusPixelDotStar; // Deallocate Adafruit_DotStar object, set data pin - // back to INPUT. - WS.lockStatusDotStar = false; // unlock -#endif - -#ifdef USE_STATUS_LED - digitalWrite(STATUS_LED_PIN, 0); // turn off - pinMode(STATUS_LED_PIN, - INPUT); // "release" for use by setting to input (hi-z) - WS.lockStatusLED = false; // un-set global pin "lock" flag -#endif -} - -/****************************************************************************/ -/*! - @brief Sets the status pixel's brightness - @param brightness - Desired pixel brightness, from 0.0 (0%) to 1.0 (100%). -*/ -/****************************************************************************/ -void setStatusLEDBrightness(float brightness) { - WS.status_pixel_brightness = brightness; -} - -/****************************************************************************/ -/*! - @brief Sets a status RGB LED's color - @param color - Desired RGB color. -*/ -/****************************************************************************/ -void setStatusLEDColor(uint32_t color) { -#ifdef USE_STATUS_NEOPIXEL - if (!WS.lockStatusNeoPixel) - return; // status pixel is in-use elsewhere - - uint8_t red = (color >> 16) & 0xff; // red - uint8_t green = (color >> 8) & 0xff; // green - uint8_t blue = color & 0xff; // blue - // map() the WS.status_pixel_brightness - int brightness = WS.status_pixel_brightness * 255.0; - // flood all neopixels - for (int i = 0; i < STATUS_NEOPIXEL_NUM; i++) { - statusPixel->setPixelColor(i, brightness * red / 255, - brightness * green / 255, - brightness * blue / 255); - } - statusPixel->show(); -#endif - -#ifdef USE_STATUS_DOTSTAR - if (!WS.lockStatusDotStar) - return; // status pixel is in-use elsewhere - - uint8_t red = (color >> 16) & 0xff; // red - uint8_t green = (color >> 8) & 0xff; // green - uint8_t blue = color & 0xff; // blue - // map() the WS.status_pixel_brightness - int brightness = WS.status_pixel_brightness * 255.0; - // flood all dotstar pixels - for (int i = 0; i < STATUS_DOTSTAR_NUM; i++) { - statusPixelDotStar->setPixelColor(i, brightness * red / 255, - brightness * green / 255, - brightness * blue / 255); - } - statusPixelDotStar->show(); -#endif - -#ifdef USE_STATUS_LED - if (!WS.lockStatusLED) - return; // status pixel is in-use elsewhere -#ifdef ARDUINO_RASPBERRY_PI_PICO_W - digitalWrite(STATUS_LED_PIN, color > 0); -#else - if (color != BLACK) - WS._pwmComponent->writeDutyCycle( - STATUS_LED_PIN, map(WS.status_pixel_brightness, 0.0, 1.0, 0, 1023)); - else - WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, 0); -#endif -#endif -} - -/****************************************************************************/ -/*! - @brief Sets a status RGB LED's color - @param color - Desired RGB color. - @param brightness - Brightness level, as an integer -*/ -/****************************************************************************/ -void setStatusLEDColor(uint32_t color, int brightness) { -#ifdef USE_STATUS_NEOPIXEL - if (!WS.lockStatusNeoPixel) - return; // status pixel is in-use elsewhere - - // parse out the color elements - uint8_t red = (color >> 16) & 0xff; // red - uint8_t green = (color >> 8) & 0xff; // green - uint8_t blue = color & 0xff; // blue - // flood all neopixels - for (int i = 0; i < STATUS_NEOPIXEL_NUM; i++) { - statusPixel->setPixelColor(i, brightness * red / 255, - brightness * green / 255, - brightness * blue / 255); - } - statusPixel->show(); -#endif - -#ifdef USE_STATUS_DOTSTAR - if (!WS.lockStatusDotStar) - return; // status pixel is in-use elsewhere - - uint8_t red = (color >> 16) & 0xff; // red - uint8_t green = (color >> 8) & 0xff; // green - uint8_t blue = color & 0xff; // blue - // flood all dotstar pixels - for (int i = 0; i < STATUS_DOTSTAR_NUM; i++) { - statusPixelDotStar->setPixelColor(i, brightness * red / 255, - brightness * green / 255, - brightness * blue / 255); - } - statusPixelDotStar->show(); -#endif - -#ifdef USE_STATUS_LED - if (!WS.lockStatusLED) - return; - -#ifdef ARDUINO_RASPBERRY_PI_PICO_W - digitalWrite(STATUS_LED_PIN, color > 0); -#else - if (color != BLACK) { - // re-map for pixel as a LED - int pulseWidth = map(brightness, 0, 255, 0, 1023); - WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, pulseWidth); - } else { - WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, 0); - } -#endif -#endif -} - -/****************************************************************************/ -/*! - @brief Retrieve the pin number used for NeoPixel data output. - @return Arduino pin number (-2 if not set). -*/ -/****************************************************************************/ -int16_t getStatusNeoPixelPin() { -#ifdef USE_STATUS_NEOPIXEL - return statusPixel->getPin(); -#endif - return -2; -} - -/****************************************************************************/ -/*! - @brief Retrieve the pin number used for DotStar data output. - @return Arduino pin number (-2 if not set). -*/ -/****************************************************************************/ -int16_t getStatusDotStarDataPin() { -#ifdef USE_STATUS_DOTSTAR - return STATUS_DOTSTAR_PIN_DATA; -#endif - return -2; -} - -/****************************************************************************/ -/*! - @brief Fades the status LED. - @param color - The specific color to fade the status LED. - @param numFades - The amount of time to fade/pulse the status LED. -*/ -/****************************************************************************/ -void statusLEDFade(uint32_t color, int numFades = 3) { - // don't fade if our pixel is off - if (WS.status_pixel_brightness == 0.0) - return; - - // pulse `numFades` times - for (int i = 0; i < numFades; i++) { - // fade up - for (int i = 0; i <= 255; i += 5) { - setStatusLEDColor(color, i); - delay(10); - } - // fade down - for (int i = 0; i >= 255; i -= 5) { - setStatusLEDColor(color, i); - delay(10); - } - } - -// Turn status LED off -#if not defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) - setStatusLEDColor(BLACK); -#else - // The Adafruit Feather ESP8266's built-in LED is reverse wired - setStatusLEDColor(BLACK ^ 1); -#endif -} - -/****************************************************************************/ -/*! - @brief Converts the a ws_led_status_t status state to color. - @param statusState - Hardware's status state. - @return Color as a uint32_t -*/ -/****************************************************************************/ -uint32_t ledStatusStateToColor(ws_led_status_t statusState) { - uint32_t ledColor; - switch (statusState) { - case WS_LED_STATUS_KAT: - ledColor = GREEN; - break; - case WS_LED_STATUS_ERROR_RUNTIME: - ledColor = RED; - break; - case WS_LED_STATUS_WIFI_CONNECTING: - ledColor = AMBER; - break; - case WS_LED_STATUS_MQTT_CONNECTING: - ledColor = BLUE; - break; - case WS_LED_STATUS_WAITING_FOR_REG_MSG: - ledColor = PINK; - break; - case WS_LED_STATUS_FS_WRITE: - ledColor = YELLOW; - break; - default: - ledColor = BLACK; - break; - } - return ledColor; -} - -/****************************************************************************/ -/*! - @brief Sets the status LED to a specific color depending on - the hardware's state. - @param statusState - Hardware's status state. -*/ -/****************************************************************************/ -void statusLEDSolid(ws_led_status_t statusState = WS_LED_STATUS_ERROR_RUNTIME) { -#ifdef USE_STATUS_LED - if (!WS.lockStatusLED) - return; -#endif - -#ifdef USE_STATUS_NEOPIXEL - if (!WS.lockStatusNeoPixel) - return; // status pixel is in-use elsewhere -#endif - - uint32_t ledColor = ledStatusStateToColor(statusState); - setStatusLEDColor(ledColor); -} - -/****************************************************************************/ -/*! - @brief Blinks a status LED a specific color depending on - the hardware's state. - @param statusState - Hardware's status state. -*/ -/****************************************************************************/ -void statusLEDBlink(ws_led_status_t statusState) { -#ifdef USE_STATUS_LED - if (!WS.lockStatusLED) - return; -#endif - -#ifdef USE_STATUS_NEOPIXEL - if (!WS.lockStatusNeoPixel) - return; // status pixel is in-use elsewhere -#endif - - // set number of times to blink - int blinkNum = 3; - // set blink color - uint32_t ledColor = ledStatusStateToColor(statusState); - - while (blinkNum > 0) { - setStatusLEDColor(ledColor); - delay(100); -#if defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) - // The Adafruit Feather ESP8266's built-in LED is reverse wired - setStatusLEDColor(BLACK ^ 1); -#else - setStatusLEDColor(BLACK); -#endif - delay(100); - blinkNum--; - } +/*! + * @file Wippersnapper_StatusLED.cpp + * + * Interfaces for the Wippersnapper status indicator LED/NeoPixel/Dotstar/RGB + * LED. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2020-2022 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#include "Wippersnapper_StatusLED.h" +#include "Wippersnapper.h" + +extern Wippersnapper WS; +#ifdef USE_STATUS_NEOPIXEL +Adafruit_NeoPixel *statusPixel = new Adafruit_NeoPixel( + STATUS_NEOPIXEL_NUM, STATUS_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800); +#endif + +#ifdef USE_STATUS_DOTSTAR +Adafruit_DotStar *statusPixelDotStar = + new Adafruit_DotStar(STATUS_DOTSTAR_NUM, STATUS_DOTSTAR_PIN_DATA, + STATUS_DOTSTAR_PIN_CLK, DOTSTAR_BRG); +#endif + +/****************************************************************************/ +/*! + @brief Initializes board-specific status LED pixel +*/ +/****************************************************************************/ +void initStatusLED() { +#ifdef USE_STATUS_NEOPIXEL + if (WS.lockStatusNeoPixel == false) { +#if defined(NEOPIXEL_I2C_POWER) + pinMode(NEOPIXEL_I2C_POWER, OUTPUT); + digitalWrite(NEOPIXEL_I2C_POWER, HIGH); +#elif defined(NEOPIXEL_POWER) + pinMode(NEOPIXEL_POWER, OUTPUT); +// turn NeoPixel power pin on +#ifndef ARDUINO_MAGTAG29_ESP32S2 + digitalWrite(NEOPIXEL_POWER, HIGH); +#else + digitalWrite(NEOPIXEL_POWER, LOW); +#endif +#endif + statusPixel = new Adafruit_NeoPixel( + STATUS_NEOPIXEL_NUM, STATUS_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800); + statusPixel->begin(); + statusPixel->show(); // turn OFF all pixels + WS.lockStatusNeoPixel = true; + } +#endif + +#ifdef USE_STATUS_DOTSTAR + if (WS.lockStatusDotStar == false) { +#ifdef STATUS_DOTSTAR_COLOR_ORDER + // Board requires a non-default color order in the constructor + statusPixelDotStar = new Adafruit_DotStar( + STATUS_DOTSTAR_NUM, STATUS_DOTSTAR_PIN_DATA, STATUS_DOTSTAR_PIN_CLK, + STATUS_DOTSTAR_COLOR_ORDER); +#else + statusPixelDotStar = + new Adafruit_DotStar(STATUS_DOTSTAR_NUM, STATUS_DOTSTAR_PIN_DATA, + STATUS_DOTSTAR_PIN_CLK, STATUS_DOTSTAR_COLOR_ORDER) +#endif + statusPixelDotStar->begin(); + statusPixelDotStar->show(); // turn OFF all pixels + WS.lockStatusDotStar = true; + } +#endif + +#ifdef USE_STATUS_LED + pinMode(STATUS_LED_PIN, OUTPUT); + +// Turn off LED initially +#if defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) + analogWrite(STATUS_LED_PIN, 255); +#elif defined(ARDUINO_ARCH_ESP32) + WS._pwmComponent->attach(STATUS_LED_PIN, LEDC_BASE_FREQ, LEDC_TIMER_12_BIT); + WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, 0); // turn OFF +#elif defined(ARDUINO_ARCH_RP2040) + digitalWrite(STATUS_LED_PIN, 0); +#else + analogWrite(STATUS_LED_PIN, 0); +#endif + + WS.lockStatusLED = true; // set global pin "lock" flag +#endif +} + +/****************************************************************************/ +/*! + @brief De-initializes the status LED and releases pin. +*/ +/****************************************************************************/ +void releaseStatusLED() { +#ifdef USE_STATUS_NEOPIXEL + delete statusPixel; // Deallocate Adafruit_NeoPixel object, set data pin back + // to INPUT. + WS.lockStatusNeoPixel = false; // unlock +#endif + +#ifdef USE_STATUS_DOTSTAR + delete statusPixelDotStar; // Deallocate Adafruit_DotStar object, set data pin + // back to INPUT. + WS.lockStatusDotStar = false; // unlock +#endif + +#ifdef USE_STATUS_LED + digitalWrite(STATUS_LED_PIN, 0); // turn off + pinMode(STATUS_LED_PIN, + INPUT); // "release" for use by setting to input (hi-z) + WS.lockStatusLED = false; // un-set global pin "lock" flag +#endif +} + +/****************************************************************************/ +/*! + @brief Sets the status pixel's brightness + @param brightness + Desired pixel brightness, from 0.0 (0%) to 1.0 (100%). +*/ +/****************************************************************************/ +void setStatusLEDBrightness(float brightness) { + WS.status_pixel_brightness = brightness; +} + +/****************************************************************************/ +/*! + @brief Sets a status RGB LED's color + @param color + Desired RGB color. +*/ +/****************************************************************************/ +void setStatusLEDColor(uint32_t color) { +#ifdef USE_STATUS_NEOPIXEL + if (!WS.lockStatusNeoPixel) + return; // status pixel is in-use elsewhere + + uint8_t red = (color >> 16) & 0xff; // red + uint8_t green = (color >> 8) & 0xff; // green + uint8_t blue = color & 0xff; // blue + // map() the WS.status_pixel_brightness + int brightness = WS.status_pixel_brightness * 255.0; + // flood all neopixels + for (int i = 0; i < STATUS_NEOPIXEL_NUM; i++) { + statusPixel->setPixelColor(i, brightness * red / 255, + brightness * green / 255, + brightness * blue / 255); + } + statusPixel->show(); +#endif + +#ifdef USE_STATUS_DOTSTAR + if (!WS.lockStatusDotStar) + return; // status pixel is in-use elsewhere + + uint8_t red = (color >> 16) & 0xff; // red + uint8_t green = (color >> 8) & 0xff; // green + uint8_t blue = color & 0xff; // blue + // map() the WS.status_pixel_brightness + int brightness = WS.status_pixel_brightness * 255.0; + // flood all dotstar pixels + for (int i = 0; i < STATUS_DOTSTAR_NUM; i++) { + statusPixelDotStar->setPixelColor(i, brightness * red / 255, + brightness * green / 255, + brightness * blue / 255); + } + statusPixelDotStar->show(); +#endif + +#ifdef USE_STATUS_LED + if (!WS.lockStatusLED) + return; // status pixel is in-use elsewhere +#ifdef ARDUINO_ARCH_RP2040 + digitalWrite(STATUS_LED_PIN, color > 0); +#else + if (color != BLACK) + WS._pwmComponent->writeDutyCycle( + STATUS_LED_PIN, map(WS.status_pixel_brightness, 0.0, 1.0, 0, 1023)); + else + WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, 0); +#endif +#endif +} + +/****************************************************************************/ +/*! + @brief Sets a status RGB LED's color + @param color + Desired RGB color. + @param brightness + Brightness level, as an integer +*/ +/****************************************************************************/ +void setStatusLEDColor(uint32_t color, int brightness) { +#ifdef USE_STATUS_NEOPIXEL + if (!WS.lockStatusNeoPixel) + return; // status pixel is in-use elsewhere + + // parse out the color elements + uint8_t red = (color >> 16) & 0xff; // red + uint8_t green = (color >> 8) & 0xff; // green + uint8_t blue = color & 0xff; // blue + // flood all neopixels + for (int i = 0; i < STATUS_NEOPIXEL_NUM; i++) { + statusPixel->setPixelColor(i, brightness * red / 255, + brightness * green / 255, + brightness * blue / 255); + } + statusPixel->show(); +#endif + +#ifdef USE_STATUS_DOTSTAR + if (!WS.lockStatusDotStar) + return; // status pixel is in-use elsewhere + + uint8_t red = (color >> 16) & 0xff; // red + uint8_t green = (color >> 8) & 0xff; // green + uint8_t blue = color & 0xff; // blue + // flood all dotstar pixels + for (int i = 0; i < STATUS_DOTSTAR_NUM; i++) { + statusPixelDotStar->setPixelColor(i, brightness * red / 255, + brightness * green / 255, + brightness * blue / 255); + } + statusPixelDotStar->show(); +#endif + +#ifdef USE_STATUS_LED + if (!WS.lockStatusLED) + return; + +#ifdef ARDUINO_ARCH_RP2040 + digitalWrite(STATUS_LED_PIN, color > 0); +#else + if (color != BLACK) { + // re-map for pixel as a LED + int pulseWidth = map(brightness, 0, 255, 0, 1023); + WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, pulseWidth); + } else { + WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, 0); + } +#endif +#endif +} + +/****************************************************************************/ +/*! + @brief Retrieve the pin number used for NeoPixel data output. + @return Arduino pin number (-2 if not set). +*/ +/****************************************************************************/ +int16_t getStatusNeoPixelPin() { +#ifdef USE_STATUS_NEOPIXEL + return statusPixel->getPin(); +#endif + return -2; +} + +/****************************************************************************/ +/*! + @brief Retrieve the pin number used for DotStar data output. + @return Arduino pin number (-2 if not set). +*/ +/****************************************************************************/ +int16_t getStatusDotStarDataPin() { +#ifdef USE_STATUS_DOTSTAR + return STATUS_DOTSTAR_PIN_DATA; +#endif + return -2; +} + +/****************************************************************************/ +/*! + @brief Fades the status LED. + @param color + The specific color to fade the status LED. + @param numFades + The amount of time to fade/pulse the status LED. +*/ +/****************************************************************************/ +void statusLEDFade(uint32_t color, int numFades = 3) { + // don't fade if our pixel is off + if (WS.status_pixel_brightness == 0.0) + return; + + // pulse `numFades` times + for (int i = 0; i < numFades; i++) { + // fade up + for (int i = 0; i <= 255; i += 5) { + setStatusLEDColor(color, i); + delay(10); + } + // fade down + for (int i = 0; i >= 255; i -= 5) { + setStatusLEDColor(color, i); + delay(10); + } + } + +// Turn status LED off +#if not defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) + setStatusLEDColor(BLACK); +#else + // The Adafruit Feather ESP8266's built-in LED is reverse wired + setStatusLEDColor(BLACK ^ 1); +#endif +} + +/****************************************************************************/ +/*! + @brief Converts the a ws_led_status_t status state to color. + @param statusState + Hardware's status state. + @return Color as a uint32_t +*/ +/****************************************************************************/ +uint32_t ledStatusStateToColor(ws_led_status_t statusState) { + uint32_t ledColor; + switch (statusState) { + case WS_LED_STATUS_KAT: + ledColor = GREEN; + break; + case WS_LED_STATUS_ERROR_RUNTIME: + ledColor = RED; + break; + case WS_LED_STATUS_WIFI_CONNECTING: + ledColor = AMBER; + break; + case WS_LED_STATUS_MQTT_CONNECTING: + ledColor = BLUE; + break; + case WS_LED_STATUS_WAITING_FOR_REG_MSG: + ledColor = PINK; + break; + case WS_LED_STATUS_FS_WRITE: + ledColor = YELLOW; + break; + default: + ledColor = BLACK; + break; + } + return ledColor; +} + +/****************************************************************************/ +/*! + @brief Sets the status LED to a specific color depending on + the hardware's state. + @param statusState + Hardware's status state. +*/ +/****************************************************************************/ +void statusLEDSolid(ws_led_status_t statusState = WS_LED_STATUS_ERROR_RUNTIME) { +#ifdef USE_STATUS_LED + if (!WS.lockStatusLED) + return; +#endif + +#ifdef USE_STATUS_NEOPIXEL + if (!WS.lockStatusNeoPixel) + return; // status pixel is in-use elsewhere +#endif + + uint32_t ledColor = ledStatusStateToColor(statusState); + setStatusLEDColor(ledColor); +} + +/****************************************************************************/ +/*! + @brief Blinks a status LED a specific color depending on + the hardware's state. + @param statusState + Hardware's status state. +*/ +/****************************************************************************/ +void statusLEDBlink(ws_led_status_t statusState) { +#ifdef USE_STATUS_LED + if (!WS.lockStatusLED) + return; +#endif + +#ifdef USE_STATUS_NEOPIXEL + if (!WS.lockStatusNeoPixel) + return; // status pixel is in-use elsewhere +#endif + + // set number of times to blink + int blinkNum = 3; + // set blink color + uint32_t ledColor = ledStatusStateToColor(statusState); + + while (blinkNum > 0) { + setStatusLEDColor(ledColor); + delay(100); +#if defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) + // The Adafruit Feather ESP8266's built-in LED is reverse wired + setStatusLEDColor(BLACK ^ 1); +#else + setStatusLEDColor(BLACK); +#endif + delay(100); + blinkNum--; + } } \ No newline at end of file diff --git a/src/provisioning/tinyusb/Wippersnapper_FS.cpp b/src/provisioning/tinyusb/Wippersnapper_FS.cpp index d99c6098b..74e58a90f 100644 --- a/src/provisioning/tinyusb/Wippersnapper_FS.cpp +++ b/src/provisioning/tinyusb/Wippersnapper_FS.cpp @@ -24,7 +24,7 @@ defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM) || \ defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3) || \ defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT) || \ - defined(ARDUINO_RASPBERRY_PI_PICO_W) || \ + defined(ARDUINO_ARCH_RP2040) || \ defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3_REVTFT) || \ defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2_REVTFT) || \ defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3_N4R2) From 8ea03941be6784d7c24df6809e698a5814d1d862 Mon Sep 17 00:00:00 2001 From: tyeth Date: Wed, 27 Nov 2024 18:05:21 +0000 Subject: [PATCH 02/19] Add tinyusb to pico2w non debug target --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index 427a7ea94..149c92bae 100644 --- a/platformio.ini +++ b/platformio.ini @@ -522,6 +522,7 @@ platform_packages = board = rpipico2w build_flags = -DWIFICC=CYW43_COUNTRY_UK + -DUSE_TINYUSB ; -DARDUINO_ARCH_RP2040 ; -DUSBD_MAX_POWER_MA=500 ; -DPICO_CYW43_SUPPORTED=1 From 9b8479425cc95a6dc2603af570e77c38f3a62486 Mon Sep 17 00:00:00 2001 From: tyeth Date: Thu, 28 Nov 2024 15:29:55 +0000 Subject: [PATCH 03/19] Add .test.skip/.generate and CI test --- .github/workflows/build-clang-doxy.yml | 4 ++-- examples/Wippersnapper_NoFS/.picow_rp2350_tinyusb.test.skip | 1 + examples/Wippersnapper_demo/.picow_rp2350_tinyusb.generate | 1 + examples/wippersnapper_debug/.picow_rp2350_tinyusb.test.skip | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 examples/Wippersnapper_NoFS/.picow_rp2350_tinyusb.test.skip create mode 100644 examples/Wippersnapper_demo/.picow_rp2350_tinyusb.generate create mode 100644 examples/wippersnapper_debug/.picow_rp2350_tinyusb.test.skip diff --git a/.github/workflows/build-clang-doxy.yml b/.github/workflows/build-clang-doxy.yml index 084aca223..b35ab4792 100644 --- a/.github/workflows/build-clang-doxy.yml +++ b/.github/workflows/build-clang-doxy.yml @@ -494,7 +494,7 @@ jobs: strategy: fail-fast: false matrix: - arduino-platform: ["picow_rp2040_tinyusb"] + arduino-platform: ["picow_rp2040_tinyusb", "picow_rp2350_tinyusb"] steps: - uses: actions/setup-python@v5 with: @@ -508,7 +508,7 @@ jobs: - uses: actions/checkout@v4 with: repository: adafruit/ci-arduino - ref: ci-wippersnapper + ref: ci-wippersnapper-rp2040 path: ci - name: Install CI-Arduino run: bash ci/actions_install.sh diff --git a/examples/Wippersnapper_NoFS/.picow_rp2350_tinyusb.test.skip b/examples/Wippersnapper_NoFS/.picow_rp2350_tinyusb.test.skip new file mode 100644 index 000000000..d3f5a12fa --- /dev/null +++ b/examples/Wippersnapper_NoFS/.picow_rp2350_tinyusb.test.skip @@ -0,0 +1 @@ + diff --git a/examples/Wippersnapper_demo/.picow_rp2350_tinyusb.generate b/examples/Wippersnapper_demo/.picow_rp2350_tinyusb.generate new file mode 100644 index 000000000..d3f5a12fa --- /dev/null +++ b/examples/Wippersnapper_demo/.picow_rp2350_tinyusb.generate @@ -0,0 +1 @@ + diff --git a/examples/wippersnapper_debug/.picow_rp2350_tinyusb.test.skip b/examples/wippersnapper_debug/.picow_rp2350_tinyusb.test.skip new file mode 100644 index 000000000..d3f5a12fa --- /dev/null +++ b/examples/wippersnapper_debug/.picow_rp2350_tinyusb.test.skip @@ -0,0 +1 @@ + From 0f91cb9cfbabe8267479522b7a8495ff83bd470c Mon Sep 17 00:00:00 2001 From: tyeth Date: Fri, 29 Nov 2024 14:42:04 +0000 Subject: [PATCH 04/19] Swap back to official repos since upstreaming --- platformio.ini | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/platformio.ini b/platformio.ini index 149c92bae..d66126ff7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -71,7 +71,7 @@ lib_deps = adafruit/Adafruit TouchScreen adafruit/Adafruit MQTT Library bblanchon/ArduinoJson - https://github.com/tyeth/pstolarz_OneWireNg.git#pico2w + https://github.com/pstolarz/OneWireNg.git https://github.com/milesburton/Arduino-Temperature-Control-Library.git https://github.com/Sensirion/arduino-sht.git https://github.com/Sensirion/arduino-i2c-scd4x.git @@ -473,7 +473,7 @@ extends = common:rp2040 [env:raspberypi_picow_debug] extends = common:rp2040 -platform = https://github.com/maxgerhardt/platform-raspberrypi.git +; platform = https://github.com/maxgerhardt/platform-raspberrypi.git ; platform_packages = ; framework-arduinopico @ symlink:///Users/tyeth/Projects/arduino-pico ; framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#master @@ -515,8 +515,7 @@ build_flags = [env:raspberypi_pico2w] extends = common:rp2040 -platform = https://github.com/tyeth/maxgerhardt_platform-raspberrypi.git#pico2w -; platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop +platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git board = rpipico2w @@ -529,8 +528,7 @@ build_flags = [env:raspberypi_pico2w_debug] extends = common:rp2040 -platform = https://github.com/tyeth/maxgerhardt_platform-raspberrypi.git#pico2w -; platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop +platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git ; ; framework-arduinopico @ symlink:///Users/tyeth/Projects/arduino-pico From 1ceafabf7a1515686cdde50e6b7543bd2d03e3b3 Mon Sep 17 00:00:00 2001 From: tyeth Date: Fri, 29 Nov 2024 14:46:42 +0000 Subject: [PATCH 05/19] Swap RP2040 CI-Arduino branch back to ci-wippersnapper --- .github/workflows/build-clang-doxy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-clang-doxy.yml b/.github/workflows/build-clang-doxy.yml index b35ab4792..7db6818c9 100644 --- a/.github/workflows/build-clang-doxy.yml +++ b/.github/workflows/build-clang-doxy.yml @@ -508,7 +508,7 @@ jobs: - uses: actions/checkout@v4 with: repository: adafruit/ci-arduino - ref: ci-wippersnapper-rp2040 + ref: ci-wippersnapper path: ci - name: Install CI-Arduino run: bash ci/actions_install.sh From e92cd181ec4befbff428882008fe6295d93f6e91 Mon Sep 17 00:00:00 2001 From: tyeth Date: Mon, 2 Dec 2024 19:54:59 +0000 Subject: [PATCH 06/19] Add Pico2W definition to boards list + fix LEDs --- platformio.ini | 19 ++----------------- src/Wippersnapper_Boards.h | 9 +++++++-- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/platformio.ini b/platformio.ini index d66126ff7..3a65738be 100644 --- a/platformio.ini +++ b/platformio.ini @@ -523,7 +523,7 @@ build_flags = -DWIFICC=CYW43_COUNTRY_UK -DUSE_TINYUSB ; -DARDUINO_ARCH_RP2040 - ; -DUSBD_MAX_POWER_MA=500 + ; -DUSBD_MAX_POWER_MA=250 ; -DPICO_CYW43_SUPPORTED=1 [env:raspberypi_pico2w_debug] @@ -545,7 +545,7 @@ build_flags = ; -UARDUINO ; -DPICO_BUILD -DARDUINO_ARCH_RP2040 - -DUSBD_MAX_POWER_MA=500 + -DUSBD_MAX_POWER_MA=250 -DPICO_CYW43_SUPPORTED=1 -DWIFICC=CYW43_COUNTRY_UK ; -DDEBUG @@ -571,18 +571,3 @@ build_flags = ; ; No USB stack ; build_flags = -DPIO_FRAMEWORK_ARDUINO_NO_USB ; -DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6 - - -[env:pimoroni_pico_plus_2w] -extends = common:rp2040 -platform = https://github.com/tyeth/maxgerhardt_platform-raspberrypi.git#pico2w -; platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop -platform_packages = - framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git -board = pimoroni_pico_plus_2w -build_flags = - -DWIFICC=CYW43_COUNTRY_UK - -DUSE_TINYUSB - ; -DARDUINO_ARCH_RP2040 - ; -DUSBD_MAX_POWER_MA=500 - ; -DPICO_CYW43_SUPPORTED=1 diff --git a/src/Wippersnapper_Boards.h b/src/Wippersnapper_Boards.h index 4e89862e0..f98acb4e5 100644 --- a/src/Wippersnapper_Boards.h +++ b/src/Wippersnapper_Boards.h @@ -185,11 +185,16 @@ #define BOARD_ID "mkrwifi1010" #define USE_STATUS_LED #define STATUS_LED_PIN 6 -#elif defined(ARDUINO_RASPBERRY_PI_PICO_W) || defined(ARDUINO_ARCH_RP2040) +#elif defined(ARDUINO_RASPBERRY_PI_PICO_W) #define BOARD_ID "rpi-pico-w" #define USE_TINYUSB #define USE_STATUS_LED -#define STATUS_LED_PIN 32 +#define STATUS_LED_PIN LED_BUILTIN +#elif defined(ARDUINO_RASPBERRY_PI_PICO_2W) +#define BOARD_ID "rpi-pico-2w" +#define USE_TINYUSB +#define USE_STATUS_LED +#define STATUS_LED_PIN LED_BUILTIN #else #warning "Board type not identified within Wippersnapper_Boards.h!" #endif From 53ca34914f4a35c0771d2e168ec17e3d0b59d8fd Mon Sep 17 00:00:00 2001 From: tyeth Date: Wed, 11 Dec 2024 21:27:22 +0000 Subject: [PATCH 07/19] Stop blinding status lights --- src/provisioning/littlefs/WipperSnapper_LittleFS.cpp | 9 +++++++++ src/provisioning/tinyusb/Wippersnapper_FS.cpp | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/src/provisioning/littlefs/WipperSnapper_LittleFS.cpp b/src/provisioning/littlefs/WipperSnapper_LittleFS.cpp index de76fc79f..637c5d25e 100644 --- a/src/provisioning/littlefs/WipperSnapper_LittleFS.cpp +++ b/src/provisioning/littlefs/WipperSnapper_LittleFS.cpp @@ -138,6 +138,15 @@ void WipperSnapper_LittleFS::parseSecrets() { "credentials!\n"); } + if (doc["status_pixel_brightness"]) { + // check it casts to float and support user specifying 0.0f which is + // default, by using the |operator instead of .as + // https://arduinojson.org/v7/api/jsonvariant/or/ + if ((doc["status_pixel_brightness"] | -1.0f) != -1.0f) { + WS.status_pixel_brightness = doc["status_pixel_brightness"].as(); + } + } + // Close the file secretsFile.close(); diff --git a/src/provisioning/tinyusb/Wippersnapper_FS.cpp b/src/provisioning/tinyusb/Wippersnapper_FS.cpp index e4fa0ee72..495fae4d4 100644 --- a/src/provisioning/tinyusb/Wippersnapper_FS.cpp +++ b/src/provisioning/tinyusb/Wippersnapper_FS.cpp @@ -452,6 +452,14 @@ void Wippersnapper_FS::parseSecrets() { "credentials!"); } + if (doc["status_pixel_brightness"]){ + // check it casts to float and support user specifying 0.0f which is default, + // by using the |operator instead of .as https://arduinojson.org/v7/api/jsonvariant/or/ + if ((doc["status_pixel_brightness"] | -1.0f) != -1.0f) { + WS.status_pixel_brightness = doc["status_pixel_brightness"].as(); + } + } + // Close secrets.json file secretsFile.close(); } From 45461242f2064fe8fbc08e2b612b5f663f63dd2a Mon Sep 17 00:00:00 2001 From: tyeth Date: Tue, 10 Dec 2024 18:42:38 +0000 Subject: [PATCH 08/19] Report BSSID's to help distinguish wifi networks --- platformio.ini | 2 +- .../statusLED/Wippersnapper_StatusLED.cpp | 820 +++++++++--------- src/network_interfaces/ws_networking_pico.h | 19 +- 3 files changed, 426 insertions(+), 415 deletions(-) diff --git a/platformio.ini b/platformio.ini index 3a65738be..6b8decfd5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -494,7 +494,7 @@ build_flags = -DDEBUG_RP2040_CORE -DDEBUG_RP2040_WIFI -DNDEBUG - -DLWIP_DEBUG + -DLWIP_DEBUG=1 -DDEBUG_RP2040_PORT=Serial1 -DDEBUG_RP2040_UART_1 -DDEBUG_RP2040_UART=1 diff --git a/src/components/statusLED/Wippersnapper_StatusLED.cpp b/src/components/statusLED/Wippersnapper_StatusLED.cpp index ba9061cb2..464e0b8ba 100644 --- a/src/components/statusLED/Wippersnapper_StatusLED.cpp +++ b/src/components/statusLED/Wippersnapper_StatusLED.cpp @@ -1,411 +1,411 @@ -/*! - * @file Wippersnapper_StatusLED.cpp - * - * Interfaces for the Wippersnapper status indicator LED/NeoPixel/Dotstar/RGB - * LED. - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2020-2022 for Adafruit Industries. - * - * BSD license, all text here must be included in any redistribution. - * - */ -#include "Wippersnapper_StatusLED.h" -#include "Wippersnapper.h" - -extern Wippersnapper WS; -#ifdef USE_STATUS_NEOPIXEL -Adafruit_NeoPixel *statusPixel = new Adafruit_NeoPixel( - STATUS_NEOPIXEL_NUM, STATUS_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800); -#endif - -#ifdef USE_STATUS_DOTSTAR -Adafruit_DotStar *statusPixelDotStar = - new Adafruit_DotStar(STATUS_DOTSTAR_NUM, STATUS_DOTSTAR_PIN_DATA, - STATUS_DOTSTAR_PIN_CLK, DOTSTAR_BRG); -#endif - -/****************************************************************************/ -/*! - @brief Initializes board-specific status LED pixel -*/ -/****************************************************************************/ -void initStatusLED() { -#ifdef USE_STATUS_NEOPIXEL - if (WS.lockStatusNeoPixel == false) { -#if defined(NEOPIXEL_I2C_POWER) - pinMode(NEOPIXEL_I2C_POWER, OUTPUT); - digitalWrite(NEOPIXEL_I2C_POWER, HIGH); -#elif defined(NEOPIXEL_POWER) - pinMode(NEOPIXEL_POWER, OUTPUT); -// turn NeoPixel power pin on -#ifndef ARDUINO_MAGTAG29_ESP32S2 - digitalWrite(NEOPIXEL_POWER, HIGH); -#else - digitalWrite(NEOPIXEL_POWER, LOW); -#endif -#endif - statusPixel = new Adafruit_NeoPixel( - STATUS_NEOPIXEL_NUM, STATUS_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800); - statusPixel->begin(); - statusPixel->show(); // turn OFF all pixels - WS.lockStatusNeoPixel = true; - } -#endif - -#ifdef USE_STATUS_DOTSTAR - if (WS.lockStatusDotStar == false) { -#ifdef STATUS_DOTSTAR_COLOR_ORDER - // Board requires a non-default color order in the constructor - statusPixelDotStar = new Adafruit_DotStar( - STATUS_DOTSTAR_NUM, STATUS_DOTSTAR_PIN_DATA, STATUS_DOTSTAR_PIN_CLK, - STATUS_DOTSTAR_COLOR_ORDER); -#else - statusPixelDotStar = - new Adafruit_DotStar(STATUS_DOTSTAR_NUM, STATUS_DOTSTAR_PIN_DATA, - STATUS_DOTSTAR_PIN_CLK, STATUS_DOTSTAR_COLOR_ORDER) -#endif - statusPixelDotStar->begin(); - statusPixelDotStar->show(); // turn OFF all pixels - WS.lockStatusDotStar = true; - } -#endif - -#ifdef USE_STATUS_LED - pinMode(STATUS_LED_PIN, OUTPUT); - -// Turn off LED initially -#if defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) - analogWrite(STATUS_LED_PIN, 255); -#elif defined(ARDUINO_ARCH_ESP32) - WS._pwmComponent->attach(STATUS_LED_PIN, LEDC_BASE_FREQ, LEDC_TIMER_12_BIT); - WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, 0); // turn OFF -#elif defined(ARDUINO_ARCH_RP2040) - digitalWrite(STATUS_LED_PIN, 0); -#else - analogWrite(STATUS_LED_PIN, 0); -#endif - - WS.lockStatusLED = true; // set global pin "lock" flag -#endif -} - -/****************************************************************************/ -/*! - @brief De-initializes the status LED and releases pin. -*/ -/****************************************************************************/ -void releaseStatusLED() { -#ifdef USE_STATUS_NEOPIXEL - delete statusPixel; // Deallocate Adafruit_NeoPixel object, set data pin back - // to INPUT. - WS.lockStatusNeoPixel = false; // unlock -#endif - -#ifdef USE_STATUS_DOTSTAR - delete statusPixelDotStar; // Deallocate Adafruit_DotStar object, set data pin - // back to INPUT. - WS.lockStatusDotStar = false; // unlock -#endif - -#ifdef USE_STATUS_LED - digitalWrite(STATUS_LED_PIN, 0); // turn off - pinMode(STATUS_LED_PIN, - INPUT); // "release" for use by setting to input (hi-z) - WS.lockStatusLED = false; // un-set global pin "lock" flag -#endif -} - -/****************************************************************************/ -/*! - @brief Sets the status pixel's brightness - @param brightness - Desired pixel brightness, from 0.0 (0%) to 1.0 (100%). -*/ -/****************************************************************************/ -void setStatusLEDBrightness(float brightness) { - WS.status_pixel_brightness = brightness; -} - -/****************************************************************************/ -/*! - @brief Sets a status RGB LED's color - @param color - Desired RGB color. -*/ -/****************************************************************************/ -void setStatusLEDColor(uint32_t color) { -#ifdef USE_STATUS_NEOPIXEL - if (!WS.lockStatusNeoPixel) - return; // status pixel is in-use elsewhere - - uint8_t red = (color >> 16) & 0xff; // red - uint8_t green = (color >> 8) & 0xff; // green - uint8_t blue = color & 0xff; // blue - // map() the WS.status_pixel_brightness - int brightness = WS.status_pixel_brightness * 255.0; - // flood all neopixels - for (int i = 0; i < STATUS_NEOPIXEL_NUM; i++) { - statusPixel->setPixelColor(i, brightness * red / 255, - brightness * green / 255, - brightness * blue / 255); - } - statusPixel->show(); -#endif - -#ifdef USE_STATUS_DOTSTAR - if (!WS.lockStatusDotStar) - return; // status pixel is in-use elsewhere - - uint8_t red = (color >> 16) & 0xff; // red - uint8_t green = (color >> 8) & 0xff; // green - uint8_t blue = color & 0xff; // blue - // map() the WS.status_pixel_brightness - int brightness = WS.status_pixel_brightness * 255.0; - // flood all dotstar pixels - for (int i = 0; i < STATUS_DOTSTAR_NUM; i++) { - statusPixelDotStar->setPixelColor(i, brightness * red / 255, - brightness * green / 255, - brightness * blue / 255); - } - statusPixelDotStar->show(); -#endif - -#ifdef USE_STATUS_LED - if (!WS.lockStatusLED) - return; // status pixel is in-use elsewhere -#ifdef ARDUINO_ARCH_RP2040 - digitalWrite(STATUS_LED_PIN, color > 0); -#else - if (color != BLACK) - WS._pwmComponent->writeDutyCycle( - STATUS_LED_PIN, map(WS.status_pixel_brightness, 0.0, 1.0, 0, 1023)); - else - WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, 0); -#endif -#endif -} - -/****************************************************************************/ -/*! - @brief Sets a status RGB LED's color - @param color - Desired RGB color. - @param brightness - Brightness level, as an integer -*/ -/****************************************************************************/ -void setStatusLEDColor(uint32_t color, int brightness) { -#ifdef USE_STATUS_NEOPIXEL - if (!WS.lockStatusNeoPixel) - return; // status pixel is in-use elsewhere - - // parse out the color elements - uint8_t red = (color >> 16) & 0xff; // red - uint8_t green = (color >> 8) & 0xff; // green - uint8_t blue = color & 0xff; // blue - // flood all neopixels - for (int i = 0; i < STATUS_NEOPIXEL_NUM; i++) { - statusPixel->setPixelColor(i, brightness * red / 255, - brightness * green / 255, - brightness * blue / 255); - } - statusPixel->show(); -#endif - -#ifdef USE_STATUS_DOTSTAR - if (!WS.lockStatusDotStar) - return; // status pixel is in-use elsewhere - - uint8_t red = (color >> 16) & 0xff; // red - uint8_t green = (color >> 8) & 0xff; // green - uint8_t blue = color & 0xff; // blue - // flood all dotstar pixels - for (int i = 0; i < STATUS_DOTSTAR_NUM; i++) { - statusPixelDotStar->setPixelColor(i, brightness * red / 255, - brightness * green / 255, - brightness * blue / 255); - } - statusPixelDotStar->show(); -#endif - -#ifdef USE_STATUS_LED - if (!WS.lockStatusLED) - return; - -#ifdef ARDUINO_ARCH_RP2040 - digitalWrite(STATUS_LED_PIN, color > 0); -#else - if (color != BLACK) { - // re-map for pixel as a LED - int pulseWidth = map(brightness, 0, 255, 0, 1023); - WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, pulseWidth); - } else { - WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, 0); - } -#endif -#endif -} - -/****************************************************************************/ -/*! - @brief Retrieve the pin number used for NeoPixel data output. - @return Arduino pin number (-2 if not set). -*/ -/****************************************************************************/ -int16_t getStatusNeoPixelPin() { -#ifdef USE_STATUS_NEOPIXEL - return statusPixel->getPin(); -#endif - return -2; -} - -/****************************************************************************/ -/*! - @brief Retrieve the pin number used for DotStar data output. - @return Arduino pin number (-2 if not set). -*/ -/****************************************************************************/ -int16_t getStatusDotStarDataPin() { -#ifdef USE_STATUS_DOTSTAR - return STATUS_DOTSTAR_PIN_DATA; -#endif - return -2; -} - -/****************************************************************************/ -/*! - @brief Fades the status LED. - @param color - The specific color to fade the status LED. - @param numFades - The amount of time to fade/pulse the status LED. -*/ -/****************************************************************************/ -void statusLEDFade(uint32_t color, int numFades = 3) { - // don't fade if our pixel is off - if (WS.status_pixel_brightness == 0.0) - return; - - // pulse `numFades` times - for (int i = 0; i < numFades; i++) { - // fade up - for (int i = 0; i <= 255; i += 5) { - setStatusLEDColor(color, i); - delay(10); - } - // fade down - for (int i = 0; i >= 255; i -= 5) { - setStatusLEDColor(color, i); - delay(10); - } - } - -// Turn status LED off -#if not defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) - setStatusLEDColor(BLACK); -#else - // The Adafruit Feather ESP8266's built-in LED is reverse wired - setStatusLEDColor(BLACK ^ 1); -#endif -} - -/****************************************************************************/ -/*! - @brief Converts the a ws_led_status_t status state to color. - @param statusState - Hardware's status state. - @return Color as a uint32_t -*/ -/****************************************************************************/ -uint32_t ledStatusStateToColor(ws_led_status_t statusState) { - uint32_t ledColor; - switch (statusState) { - case WS_LED_STATUS_KAT: - ledColor = GREEN; - break; - case WS_LED_STATUS_ERROR_RUNTIME: - ledColor = RED; - break; - case WS_LED_STATUS_WIFI_CONNECTING: - ledColor = AMBER; - break; - case WS_LED_STATUS_MQTT_CONNECTING: - ledColor = BLUE; - break; - case WS_LED_STATUS_WAITING_FOR_REG_MSG: - ledColor = PINK; - break; - case WS_LED_STATUS_FS_WRITE: - ledColor = YELLOW; - break; - default: - ledColor = BLACK; - break; - } - return ledColor; -} - -/****************************************************************************/ -/*! - @brief Sets the status LED to a specific color depending on - the hardware's state. - @param statusState - Hardware's status state. -*/ -/****************************************************************************/ -void statusLEDSolid(ws_led_status_t statusState = WS_LED_STATUS_ERROR_RUNTIME) { -#ifdef USE_STATUS_LED - if (!WS.lockStatusLED) - return; -#endif - -#ifdef USE_STATUS_NEOPIXEL - if (!WS.lockStatusNeoPixel) - return; // status pixel is in-use elsewhere -#endif - - uint32_t ledColor = ledStatusStateToColor(statusState); - setStatusLEDColor(ledColor); -} - -/****************************************************************************/ -/*! - @brief Blinks a status LED a specific color depending on - the hardware's state. - @param statusState - Hardware's status state. -*/ -/****************************************************************************/ -void statusLEDBlink(ws_led_status_t statusState) { -#ifdef USE_STATUS_LED - if (!WS.lockStatusLED) - return; -#endif - -#ifdef USE_STATUS_NEOPIXEL - if (!WS.lockStatusNeoPixel) - return; // status pixel is in-use elsewhere -#endif - - // set number of times to blink - int blinkNum = 3; - // set blink color - uint32_t ledColor = ledStatusStateToColor(statusState); - - while (blinkNum > 0) { - setStatusLEDColor(ledColor); - delay(100); -#if defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) - // The Adafruit Feather ESP8266's built-in LED is reverse wired - setStatusLEDColor(BLACK ^ 1); -#else - setStatusLEDColor(BLACK); -#endif - delay(100); - blinkNum--; - } +/*! + * @file Wippersnapper_StatusLED.cpp + * + * Interfaces for the Wippersnapper status indicator LED/NeoPixel/Dotstar/RGB + * LED. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2020-2022 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#include "Wippersnapper_StatusLED.h" +#include "Wippersnapper.h" + +extern Wippersnapper WS; +#ifdef USE_STATUS_NEOPIXEL +Adafruit_NeoPixel *statusPixel = new Adafruit_NeoPixel( + STATUS_NEOPIXEL_NUM, STATUS_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800); +#endif + +#ifdef USE_STATUS_DOTSTAR +Adafruit_DotStar *statusPixelDotStar = + new Adafruit_DotStar(STATUS_DOTSTAR_NUM, STATUS_DOTSTAR_PIN_DATA, + STATUS_DOTSTAR_PIN_CLK, DOTSTAR_BRG); +#endif + +/****************************************************************************/ +/*! + @brief Initializes board-specific status LED pixel +*/ +/****************************************************************************/ +void initStatusLED() { +#ifdef USE_STATUS_NEOPIXEL + if (WS.lockStatusNeoPixel == false) { +#if defined(NEOPIXEL_I2C_POWER) + pinMode(NEOPIXEL_I2C_POWER, OUTPUT); + digitalWrite(NEOPIXEL_I2C_POWER, HIGH); +#elif defined(NEOPIXEL_POWER) + pinMode(NEOPIXEL_POWER, OUTPUT); +// turn NeoPixel power pin on +#ifndef ARDUINO_MAGTAG29_ESP32S2 + digitalWrite(NEOPIXEL_POWER, HIGH); +#else + digitalWrite(NEOPIXEL_POWER, LOW); +#endif +#endif + statusPixel = new Adafruit_NeoPixel( + STATUS_NEOPIXEL_NUM, STATUS_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800); + statusPixel->begin(); + statusPixel->show(); // turn OFF all pixels + WS.lockStatusNeoPixel = true; + } +#endif + +#ifdef USE_STATUS_DOTSTAR + if (WS.lockStatusDotStar == false) { +#ifdef STATUS_DOTSTAR_COLOR_ORDER + // Board requires a non-default color order in the constructor + statusPixelDotStar = new Adafruit_DotStar( + STATUS_DOTSTAR_NUM, STATUS_DOTSTAR_PIN_DATA, STATUS_DOTSTAR_PIN_CLK, + STATUS_DOTSTAR_COLOR_ORDER); +#else + statusPixelDotStar = + new Adafruit_DotStar(STATUS_DOTSTAR_NUM, STATUS_DOTSTAR_PIN_DATA, + STATUS_DOTSTAR_PIN_CLK, STATUS_DOTSTAR_COLOR_ORDER) +#endif + statusPixelDotStar->begin(); + statusPixelDotStar->show(); // turn OFF all pixels + WS.lockStatusDotStar = true; + } +#endif + +#ifdef USE_STATUS_LED + pinMode(STATUS_LED_PIN, OUTPUT); + +// Turn off LED initially +#if defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) + analogWrite(STATUS_LED_PIN, 255); +#elif defined(ARDUINO_ARCH_ESP32) + WS._pwmComponent->attach(STATUS_LED_PIN, LEDC_BASE_FREQ, LEDC_TIMER_12_BIT); + WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, 0); // turn OFF +#elif defined(ARDUINO_ARCH_RP2040) + digitalWrite(STATUS_LED_PIN, 0); +#else + analogWrite(STATUS_LED_PIN, 0); +#endif + + WS.lockStatusLED = true; // set global pin "lock" flag +#endif +} + +/****************************************************************************/ +/*! + @brief De-initializes the status LED and releases pin. +*/ +/****************************************************************************/ +void releaseStatusLED() { +#ifdef USE_STATUS_NEOPIXEL + delete statusPixel; // Deallocate Adafruit_NeoPixel object, set data pin back + // to INPUT. + WS.lockStatusNeoPixel = false; // unlock +#endif + +#ifdef USE_STATUS_DOTSTAR + delete statusPixelDotStar; // Deallocate Adafruit_DotStar object, set data pin + // back to INPUT. + WS.lockStatusDotStar = false; // unlock +#endif + +#ifdef USE_STATUS_LED + digitalWrite(STATUS_LED_PIN, 0); // turn off + pinMode(STATUS_LED_PIN, + INPUT); // "release" for use by setting to input (hi-z) + WS.lockStatusLED = false; // un-set global pin "lock" flag +#endif +} + +/****************************************************************************/ +/*! + @brief Sets the status pixel's brightness + @param brightness + Desired pixel brightness, from 0.0 (0%) to 1.0 (100%). +*/ +/****************************************************************************/ +void setStatusLEDBrightness(float brightness) { + WS.status_pixel_brightness = brightness; +} + +/****************************************************************************/ +/*! + @brief Sets a status RGB LED's color + @param color + Desired RGB color. +*/ +/****************************************************************************/ +void setStatusLEDColor(uint32_t color) { +#ifdef USE_STATUS_NEOPIXEL + if (!WS.lockStatusNeoPixel) + return; // status pixel is in-use elsewhere + + uint8_t red = (color >> 16) & 0xff; // red + uint8_t green = (color >> 8) & 0xff; // green + uint8_t blue = color & 0xff; // blue + // map() the WS.status_pixel_brightness + int brightness = WS.status_pixel_brightness * 255.0; + // flood all neopixels + for (int i = 0; i < STATUS_NEOPIXEL_NUM; i++) { + statusPixel->setPixelColor(i, brightness * red / 255, + brightness * green / 255, + brightness * blue / 255); + } + statusPixel->show(); +#endif + +#ifdef USE_STATUS_DOTSTAR + if (!WS.lockStatusDotStar) + return; // status pixel is in-use elsewhere + + uint8_t red = (color >> 16) & 0xff; // red + uint8_t green = (color >> 8) & 0xff; // green + uint8_t blue = color & 0xff; // blue + // map() the WS.status_pixel_brightness + int brightness = WS.status_pixel_brightness * 255.0; + // flood all dotstar pixels + for (int i = 0; i < STATUS_DOTSTAR_NUM; i++) { + statusPixelDotStar->setPixelColor(i, brightness * red / 255, + brightness * green / 255, + brightness * blue / 255); + } + statusPixelDotStar->show(); +#endif + +#ifdef USE_STATUS_LED + if (!WS.lockStatusLED) + return; // status pixel is in-use elsewhere +#ifdef ARDUINO_ARCH_RP2040 + digitalWrite(STATUS_LED_PIN, color > 0); +#else + if (color != BLACK) + WS._pwmComponent->writeDutyCycle( + STATUS_LED_PIN, map(WS.status_pixel_brightness, 0.0, 1.0, 0, 1023)); + else + WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, 0); +#endif +#endif +} + +/****************************************************************************/ +/*! + @brief Sets a status RGB LED's color + @param color + Desired RGB color. + @param brightness + Brightness level, as an integer +*/ +/****************************************************************************/ +void setStatusLEDColor(uint32_t color, int brightness) { +#ifdef USE_STATUS_NEOPIXEL + if (!WS.lockStatusNeoPixel) + return; // status pixel is in-use elsewhere + + // parse out the color elements + uint8_t red = (color >> 16) & 0xff; // red + uint8_t green = (color >> 8) & 0xff; // green + uint8_t blue = color & 0xff; // blue + // flood all neopixels + for (int i = 0; i < STATUS_NEOPIXEL_NUM; i++) { + statusPixel->setPixelColor(i, brightness * red / 255, + brightness * green / 255, + brightness * blue / 255); + } + statusPixel->show(); +#endif + +#ifdef USE_STATUS_DOTSTAR + if (!WS.lockStatusDotStar) + return; // status pixel is in-use elsewhere + + uint8_t red = (color >> 16) & 0xff; // red + uint8_t green = (color >> 8) & 0xff; // green + uint8_t blue = color & 0xff; // blue + // flood all dotstar pixels + for (int i = 0; i < STATUS_DOTSTAR_NUM; i++) { + statusPixelDotStar->setPixelColor(i, brightness * red / 255, + brightness * green / 255, + brightness * blue / 255); + } + statusPixelDotStar->show(); +#endif + +#ifdef USE_STATUS_LED + if (!WS.lockStatusLED) + return; + +#ifdef ARDUINO_ARCH_RP2040 + digitalWrite(STATUS_LED_PIN, color > 0); +#else + if (color != BLACK) { + // re-map for pixel as a LED + int pulseWidth = map(brightness, 0, 255, 0, 1023); + WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, pulseWidth); + } else { + WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, 0); + } +#endif +#endif +} + +/****************************************************************************/ +/*! + @brief Retrieve the pin number used for NeoPixel data output. + @return Arduino pin number (-2 if not set). +*/ +/****************************************************************************/ +int16_t getStatusNeoPixelPin() { +#ifdef USE_STATUS_NEOPIXEL + return statusPixel->getPin(); +#endif + return -2; +} + +/****************************************************************************/ +/*! + @brief Retrieve the pin number used for DotStar data output. + @return Arduino pin number (-2 if not set). +*/ +/****************************************************************************/ +int16_t getStatusDotStarDataPin() { +#ifdef USE_STATUS_DOTSTAR + return STATUS_DOTSTAR_PIN_DATA; +#endif + return -2; +} + +/****************************************************************************/ +/*! + @brief Fades the status LED. + @param color + The specific color to fade the status LED. + @param numFades + The amount of time to fade/pulse the status LED. +*/ +/****************************************************************************/ +void statusLEDFade(uint32_t color, int numFades = 3) { + // don't fade if our pixel is off + if (WS.status_pixel_brightness == 0.0) + return; + + // pulse `numFades` times + for (int i = 0; i < numFades; i++) { + // fade up + for (int i = 0; i <= 255; i += 5) { + setStatusLEDColor(color, i); + delay(10); + } + // fade down + for (int i = 0; i >= 255; i -= 5) { + setStatusLEDColor(color, i); + delay(10); + } + } + +// Turn status LED off +#if not defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) + setStatusLEDColor(BLACK); +#else + // The Adafruit Feather ESP8266's built-in LED is reverse wired + setStatusLEDColor(BLACK ^ 1); +#endif +} + +/****************************************************************************/ +/*! + @brief Converts the a ws_led_status_t status state to color. + @param statusState + Hardware's status state. + @return Color as a uint32_t +*/ +/****************************************************************************/ +uint32_t ledStatusStateToColor(ws_led_status_t statusState) { + uint32_t ledColor; + switch (statusState) { + case WS_LED_STATUS_KAT: + ledColor = GREEN; + break; + case WS_LED_STATUS_ERROR_RUNTIME: + ledColor = RED; + break; + case WS_LED_STATUS_WIFI_CONNECTING: + ledColor = AMBER; + break; + case WS_LED_STATUS_MQTT_CONNECTING: + ledColor = BLUE; + break; + case WS_LED_STATUS_WAITING_FOR_REG_MSG: + ledColor = PINK; + break; + case WS_LED_STATUS_FS_WRITE: + ledColor = YELLOW; + break; + default: + ledColor = BLACK; + break; + } + return ledColor; +} + +/****************************************************************************/ +/*! + @brief Sets the status LED to a specific color depending on + the hardware's state. + @param statusState + Hardware's status state. +*/ +/****************************************************************************/ +void statusLEDSolid(ws_led_status_t statusState = WS_LED_STATUS_ERROR_RUNTIME) { +#ifdef USE_STATUS_LED + if (!WS.lockStatusLED) + return; +#endif + +#ifdef USE_STATUS_NEOPIXEL + if (!WS.lockStatusNeoPixel) + return; // status pixel is in-use elsewhere +#endif + + uint32_t ledColor = ledStatusStateToColor(statusState); + setStatusLEDColor(ledColor); +} + +/****************************************************************************/ +/*! + @brief Blinks a status LED a specific color depending on + the hardware's state. + @param statusState + Hardware's status state. +*/ +/****************************************************************************/ +void statusLEDBlink(ws_led_status_t statusState) { +#ifdef USE_STATUS_LED + if (!WS.lockStatusLED) + return; +#endif + +#ifdef USE_STATUS_NEOPIXEL + if (!WS.lockStatusNeoPixel) + return; // status pixel is in-use elsewhere +#endif + + // set number of times to blink + int blinkNum = 3; + // set blink color + uint32_t ledColor = ledStatusStateToColor(statusState); + + while (blinkNum > 0) { + setStatusLEDColor(ledColor); + delay(100); +#if defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) + // The Adafruit Feather ESP8266's built-in LED is reverse wired + setStatusLEDColor(BLACK ^ 1); +#else + setStatusLEDColor(BLACK); +#endif + delay(100); + blinkNum--; + } } \ No newline at end of file diff --git a/src/network_interfaces/ws_networking_pico.h b/src/network_interfaces/ws_networking_pico.h index 25ce278b1..0ea955112 100644 --- a/src/network_interfaces/ws_networking_pico.h +++ b/src/network_interfaces/ws_networking_pico.h @@ -137,12 +137,23 @@ class ws_networking_pico : public Wippersnapper { // User-set network not found, print scan results to serial console WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); - WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: "); - for (int i = 0; i < n; ++i) { + WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks:"); + for (uint8_t i = 0; i < n; ++i) { WS_DEBUG_PRINT(WiFi.SSID(i)); - WS_DEBUG_PRINT(" "); + WS_DEBUG_PRINT(" ("); + uint8_t BSSID[WL_MAC_ADDR_LENGTH]; + WiFi.BSSID(i, BSSID); + for (int m = 0; m < WL_MAC_ADDR_LENGTH; ++m) { + if (m != 0) { + WS_DEBUG_PRINT(":"); + } + WS_DEBUG_PRINTHEX(BSSID[m]); + } + WS_DEBUG_PRINT(") "); WS_DEBUG_PRINT(WiFi.RSSI(i)); - WS_DEBUG_PRINTLN("dB"); + WS_DEBUG_PRINT("dB (ch"); + WS_DEBUG_PRINT(WiFi.channel(i)) + WS_DEBUG_PRINTLN(")"); } return false; From 04f1c3cce170983ce8df195348aff81722b5ba2d Mon Sep 17 00:00:00 2001 From: tyeth Date: Tue, 17 Dec 2024 18:04:13 +0000 Subject: [PATCH 09/19] USB Reattach fixes + Specify reset time remaining + secrets != 0xFF --- platformio.ini | 51 +++++++++++++------ src/Wippersnapper.cpp | 12 ++++- src/provisioning/tinyusb/Wippersnapper_FS.cpp | 17 +++++-- 3 files changed, 60 insertions(+), 20 deletions(-) diff --git a/platformio.ini b/platformio.ini index dd4acafc2..7e1733d34 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,8 +16,16 @@ framework = arduino monitor_speed = 115200 lib_compat_mode = strict lib_deps = + ;;;;;;;;;;; FunHouse / LVGL Boards uncomment these ;;;;;;;;;;;;;; + ; https://github.com/adafruit/Adafruit_HX8357_Library.git + ; https://github.com/adafruit/Adafruit_ILI9341.git + ; https://github.com/adafruit/Adafruit_STMPE610.git + ; https://github.com/adafruit/Adafruit-ST7735-Library.git + ; https://github.com/adafruit/Adafruit_TouchScreen.git + ; https://github.com/brentru/lvgl.git#wippersnapper + ; https://github.com/brentru/Adafruit_LvGL_Glue.git#development + ;;;;;;;;;;; All Boards need these libraries included ;;;;;;;;;;;;;; adafruit/Adafruit Zero DMA Library - https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git adafruit/Adafruit NeoPixel adafruit/Adafruit SPIFlash adafruit/Adafruit DotStar @@ -78,14 +86,8 @@ lib_deps = https://github.com/Sensirion/arduino-i2c-sen5x.git https://github.com/adafruit/WiFiNINA.git https://github.com/Starmbi/hp_BH1750.git - ;;;;;;;;;;; FunHouse / LVGL Boards ;;;;;;;;;;;;;; - https://github.com/adafruit/Adafruit_HX8357_Library.git - https://github.com/adafruit/Adafruit_ILI9341.git - https://github.com/adafruit/Adafruit_STMPE610.git - https://github.com/adafruit/Adafruit-ST7735-Library.git - https://github.com/adafruit/Adafruit_TouchScreen.git - https://github.com/brentru/lvgl.git#wippersnapper - https://github.com/brentru/Adafruit_LvGL_Glue.git#development + https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git + ; Common build environment for ESP32 platform @@ -107,9 +109,10 @@ platform = atmelsam platform_packages = platformio/framework-arduino-samd-adafruit@^1.7.13 platformio/tool-jlink@^1.78811.0 -lib_ldf_mode = deep +lib_ldf_mode = chain+ +lib_compat_mode = strict lib_archive = no ; debug timer issues see https://community.platformio.org/t/choose-usb-stack-as-tiny-usb/22451/5 -lib_ignore = OneWire +lib_ignore = OneWire, USBHost [common:rp2040] platform = https://github.com/maxgerhardt/platform-raspberrypi.git @@ -408,7 +411,23 @@ extra_scripts = pre:rename_usb_config.py [env:huzzah] extends=common:esp8266 board = huzzah -build_flags = -DARDUINO_ESP8266_ADAFRUIT_HUZZAH +board_build.f_cpu = 80000000L +; Arduino CLI uses this from adafruit_ci#ci-wippersnapper +; esp8266:esp8266:huzzah:xtal=80,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,eesz=4M2M,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=115200 +build_flags = + -Wl,--gc-sections + -Wl,-Map=output.map + -DARDUINO_ESP8266_ADAFRUIT_HUZZAH + -DDEBUG_ESP_PORT=Serial + -DVTABLES_IN_FLASH + -DNO_EXCEPTIONS + -DNO_STACK_SMASH_PROTECTION + -DSSL_ALL + -DMMU_3232 + -DNON32XFER_FAST + -DDEBUG_DISABLED + -DDEBUG_LEVEL_NONE +board_build.eesz=4M2M board_build.filesystem = littlefs upload_port = /dev/cu.SLAB_USBtoUART @@ -418,8 +437,9 @@ upload_port = /dev/cu.SLAB_USBtoUART [env:adafruit_pyportal_m4] extends = common:atsamd board = adafruit_pyportal_m4 -build_flags = -DUSE_TINYUSB=1 +build_flags = -DUSE_TINYUSB -DADAFRUIT_PYPORTAL +extra_scripts = pre:rename_usb_config.py ; Adafruit PyPortal M4 Titano [env:adafruit_pyportal_m4_titano] @@ -463,8 +483,9 @@ build_flags = -DUSE_TINYUSB [env:adafruit_metro_m4_airliftlite] extends = common:atsamd board = adafruit_metro_m4_airliftlite -build_flags = -DUSE_TINYUSB=1 +build_flags = -DUSE_TINYUSB -DADAFRUIT_METRO_M4_AIRLIFT_LITE +; extra_scripts = pre:rename_usb_config.py upload_port = /dev/cu.usbmodem1201 @@ -494,7 +515,7 @@ build_flags = -DDEBUG_RP2040_CORE -DDEBUG_RP2040_WIFI -DNDEBUG - -DLWIP_DEBUG + -DLWIP_DEBUG=1 -DDEBUG_RP2040_PORT=Serial1 -DDEBUG_RP2040_UART_1 -DDEBUG_RP2040_UART=1 diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index a4c190825..a7ad455bd 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2500,8 +2500,10 @@ void Wippersnapper::runNetFSM() { */ /**************************************************************************/ void Wippersnapper::haltError(String error, ws_led_status_t ledStatusColor) { - for (;;) { - WS_DEBUG_PRINT("ERROR [WDT RESET]: "); + for (int i = 0;; i++) { + WS_DEBUG_PRINT("ERROR [WDT RESET IN "); + WS_DEBUG_PRINT(25 - i); + WS_DEBUG_PRINTLN("]: "); WS_DEBUG_PRINTLN(error); // let the WDT fail out and reset! statusLEDSolid(ledStatusColor); @@ -2512,6 +2514,12 @@ void Wippersnapper::haltError(String error, ws_led_status_t ledStatusColor) { // hardware and software watchdog timers, delayMicroseconds does not. delayMicroseconds(1000000); #endif + if (i < 20) { + yield(); + WS.feedWDT(); // feed the WDT for the first 20 seconds + } else if (i == 20) { + WS.enableWDT(5000); + } } } diff --git a/src/provisioning/tinyusb/Wippersnapper_FS.cpp b/src/provisioning/tinyusb/Wippersnapper_FS.cpp index e4fa0ee72..a84647fb3 100644 --- a/src/provisioning/tinyusb/Wippersnapper_FS.cpp +++ b/src/provisioning/tinyusb/Wippersnapper_FS.cpp @@ -106,6 +106,7 @@ Wippersnapper_FS::Wippersnapper_FS() { // If a filesystem does not already exist - attempt to initialize a new // filesystem if (!initFilesystem() && !initFilesystem(true)) { + TinyUSBDevice.attach(); setStatusLEDColor(RED); fsHalt("ERROR Initializing Filesystem"); } @@ -217,7 +218,12 @@ void Wippersnapper_FS::initUSBMSC() { // init MSC usb_msc.begin(); + // Attach MSC and wait for enumeration + if (TinyUSBDevice.mounted()) { + TinyUSBDevice.detach(); + delay(10); + } TinyUSBDevice.attach(); delay(500); } @@ -232,6 +238,13 @@ bool Wippersnapper_FS::configFileExists() { // Does secrets.json file exist? if (!wipperFatFs.exists("/secrets.json")) return false; + File32 file = wipperFatFs.open("/secrets.json", FILE_READ); + if (!file) + return false; + int firstChar = file.peek(); + file.close(); + if (firstChar <= 0 || firstChar == 255) + return false; return true; } @@ -318,7 +331,7 @@ bool Wippersnapper_FS::createBootFile() { void Wippersnapper_FS::createSecretsFile() { // Open file for writing File32 secretsFile = wipperFatFs.open("/secrets.json", FILE_WRITE); - + secretsFile.truncate(0); // Create a default secretsConfig structure secretsConfig secretsConfig; strcpy(secretsConfig.aio_user, "YOUR_IO_USERNAME_HERE"); @@ -485,8 +498,6 @@ void Wippersnapper_FS::writeToBootOut(PGM_P str) { */ /**************************************************************************/ void Wippersnapper_FS::fsHalt(String msg) { - TinyUSBDevice.attach(); - delay(500); statusLEDSolid(WS_LED_STATUS_FS_WRITE); while (1) { WS_DEBUG_PRINTLN("Fatal Error: Halted execution!"); From 2475f33072db884c5e78cd1c70fe50562957a97c Mon Sep 17 00:00:00 2001 From: tyeth Date: Tue, 17 Dec 2024 18:49:04 +0000 Subject: [PATCH 10/19] RP2040 WDT=8.3secs - enable after wifi connect --- platformio.ini | 6 ++++++ src/Wippersnapper.cpp | 8 +++++++- src/Wippersnapper.h | 7 ++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index dd4acafc2..26b8a7bcb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -471,6 +471,12 @@ upload_port = /dev/cu.usbmodem1201 [env:raspberypi_picow] extends = common:rp2040 +[env:raspberypi_picow_debug_port_only] +extends = common:rp2040 +build_flags = + -DUSE_TINYUSB + -DDEBUG_RP2040_PORT=Serial + [env:raspberypi_picow_debug] extends = common:rp2040 platform = https://github.com/maxgerhardt/platform-raspberrypi.git diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index a4c190825..b8bf018b2 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2748,8 +2748,10 @@ void Wippersnapper::connect() { // Dump device info to the serial monitor printDeviceInfo(); - // enable global WDT +// enable global WDT +#ifndef ARDUINO_ARCH_RP2040 WS.enableWDT(WS_WDT_TIMEOUT); +#endif // Generate device identifier if (!generateDeviceUID()) { @@ -2772,7 +2774,11 @@ void Wippersnapper::connect() { WS_DEBUG_PRINTLN("Running Network FSM..."); // Run the network fsm runNetFSM(); +#ifdef ARDUINO_ARCH_RP2040 + WS.enableWDT(WS_WDT_TIMEOUT); // wifi multi doesn't feed the WDT +#else WS.feedWDT(); +#endif #ifdef USE_DISPLAY WS._ui_helper->set_load_bar_icon_complete(loadBarIconCloud); diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index ede523228..3d597713b 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -214,7 +214,12 @@ typedef enum { FSM_NET_ESTABLISH_MQTT, } fsm_net_t; -#define WS_WDT_TIMEOUT 60000 ///< WDT timeout +#ifdef ARDUINO_ARCH_RP2040 +#define WS_WDT_TIMEOUT 8388 ///< Pico Max WDT timeout +#else +#define WS_WDT_TIMEOUT 60000 ///< WDT timeout +#endif + #define WS_MAX_ALT_WIFI_NETWORKS 3 ///< Maximum number of alternative networks /* MQTT Configuration */ #define WS_KEEPALIVE_INTERVAL_MS \ From 9ddb1206d32650f7bd5a3695adb35edd5f6b5c7e Mon Sep 17 00:00:00 2001 From: tyeth Date: Thu, 19 Dec 2024 17:01:59 +0000 Subject: [PATCH 11/19] Use defined default + rem 2nd check of brightness --- .../littlefs/WipperSnapper_LittleFS.cpp | 13 +++++-------- src/provisioning/tinyusb/Wippersnapper_FS.cpp | 14 ++++++-------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/provisioning/littlefs/WipperSnapper_LittleFS.cpp b/src/provisioning/littlefs/WipperSnapper_LittleFS.cpp index 637c5d25e..f564ef93f 100644 --- a/src/provisioning/littlefs/WipperSnapper_LittleFS.cpp +++ b/src/provisioning/littlefs/WipperSnapper_LittleFS.cpp @@ -138,14 +138,11 @@ void WipperSnapper_LittleFS::parseSecrets() { "credentials!\n"); } - if (doc["status_pixel_brightness"]) { - // check it casts to float and support user specifying 0.0f which is - // default, by using the |operator instead of .as - // https://arduinojson.org/v7/api/jsonvariant/or/ - if ((doc["status_pixel_brightness"] | -1.0f) != -1.0f) { - WS.status_pixel_brightness = doc["status_pixel_brightness"].as(); - } - } + // specify type of value for json key, by using the |operator to include + // a typed default value equivalent of with .as w/ default value + // https://arduinojson.org/v7/api/jsonvariant/or/ + WS._config.status_pixel_brightness = + doc["status_pixel_brightness"] | (float)STATUS_PIXEL_BRIGHTNESS_DEFAULT; // Close the file secretsFile.close(); diff --git a/src/provisioning/tinyusb/Wippersnapper_FS.cpp b/src/provisioning/tinyusb/Wippersnapper_FS.cpp index 495fae4d4..2f1daee98 100644 --- a/src/provisioning/tinyusb/Wippersnapper_FS.cpp +++ b/src/provisioning/tinyusb/Wippersnapper_FS.cpp @@ -325,7 +325,7 @@ void Wippersnapper_FS::createSecretsFile() { strcpy(secretsConfig.aio_key, "YOUR_IO_KEY_HERE"); strcpy(secretsConfig.network.ssid, "YOUR_WIFI_SSID_HERE"); strcpy(secretsConfig.network.pass, "YOUR_WIFI_PASS_HERE"); - secretsConfig.status_pixel_brightness = 0.2; + secretsConfig.status_pixel_brightness = STATUS_PIXEL_BRIGHTNESS_DEFAULT; // Serialize the struct to a JSON document JsonDocument doc; @@ -452,13 +452,11 @@ void Wippersnapper_FS::parseSecrets() { "credentials!"); } - if (doc["status_pixel_brightness"]){ - // check it casts to float and support user specifying 0.0f which is default, - // by using the |operator instead of .as https://arduinojson.org/v7/api/jsonvariant/or/ - if ((doc["status_pixel_brightness"] | -1.0f) != -1.0f) { - WS.status_pixel_brightness = doc["status_pixel_brightness"].as(); - } - } + // specify type of value for json key, by using the |operator to include + // a typed default value equivalent of with .as w/ default value + // https://arduinojson.org/v7/api/jsonvariant/or/ + WS._config.status_pixel_brightness = + doc["status_pixel_brightness"] | (float)STATUS_PIXEL_BRIGHTNESS_DEFAULT; // Close secrets.json file secretsFile.close(); From 04dbf36da5980fef2a8813785659728567a19bec Mon Sep 17 00:00:00 2001 From: tyeth Date: Thu, 19 Dec 2024 17:15:46 +0000 Subject: [PATCH 12/19] Parameterise the reset timeout for haltError --- src/Wippersnapper.cpp | 13 ++++++++----- src/Wippersnapper.h | 3 ++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index a7ad455bd..47e472c39 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2499,10 +2499,13 @@ void Wippersnapper::runNetFSM() { The desired color to blink. */ /**************************************************************************/ -void Wippersnapper::haltError(String error, ws_led_status_t ledStatusColor) { +void Wippersnapper::haltError(String error, ws_led_status_t ledStatusColor, + uint8_t seconds_until_reboot) { + uint8_t wdt_timeout = 5; // future platform-specific differences + int seconds_until_wdt_enable = seconds_until_reboot - wdt_timeout; for (int i = 0;; i++) { WS_DEBUG_PRINT("ERROR [WDT RESET IN "); - WS_DEBUG_PRINT(25 - i); + WS_DEBUG_PRINT(seconds_until_reboot - i); WS_DEBUG_PRINTLN("]: "); WS_DEBUG_PRINTLN(error); // let the WDT fail out and reset! @@ -2514,11 +2517,11 @@ void Wippersnapper::haltError(String error, ws_led_status_t ledStatusColor) { // hardware and software watchdog timers, delayMicroseconds does not. delayMicroseconds(1000000); #endif - if (i < 20) { + if (i < seconds_until_wdt_enable) { yield(); WS.feedWDT(); // feed the WDT for the first 20 seconds - } else if (i == 20) { - WS.enableWDT(5000); + } else if (i == seconds_until_reboot) { + WS.enableWDT(wdt_timeout * 1000); } } } diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index ede523228..2962b7710 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -306,7 +306,8 @@ class Wippersnapper { // Error handling helpers void haltError(String error, - ws_led_status_t ledStatusColor = WS_LED_STATUS_ERROR_RUNTIME); + ws_led_status_t ledStatusColor = WS_LED_STATUS_ERROR_RUNTIME, + uint8_t seconds_until_reboot = 25); void errorWriteHang(String error); // MQTT topic callbacks // From f87a2083acffc3831d62de1c11a3d26c62ce7cca Mon Sep 17 00:00:00 2001 From: tyeth Date: Thu, 19 Dec 2024 17:22:34 +0000 Subject: [PATCH 13/19] Swap WDT timeout to milliseconds in haltError to match Arch differerences --- src/Wippersnapper.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 47e472c39..3c222a21b 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2494,15 +2494,19 @@ void Wippersnapper::runNetFSM() { @brief Prints an error to the serial and halts the hardware until the WDT bites. @param error - The desired error to print to serial. + The error to print to serial. @param ledStatusColor - The desired color to blink. + The color to blink. + @param seconds_until_reboot + The amount of time to wait before rebooting. */ /**************************************************************************/ void Wippersnapper::haltError(String error, ws_led_status_t ledStatusColor, uint8_t seconds_until_reboot) { - uint8_t wdt_timeout = 5; // future platform-specific differences - int seconds_until_wdt_enable = seconds_until_reboot - wdt_timeout; + uint8_t wdt_timeout_ms = 5000; // future platform-specific differences + int seconds_until_wdt_enable = + seconds_until_reboot - (int)(wdt_timeout_ms / 1000); + for (int i = 0;; i++) { WS_DEBUG_PRINT("ERROR [WDT RESET IN "); WS_DEBUG_PRINT(seconds_until_reboot - i); @@ -2521,7 +2525,7 @@ void Wippersnapper::haltError(String error, ws_led_status_t ledStatusColor, yield(); WS.feedWDT(); // feed the WDT for the first 20 seconds } else if (i == seconds_until_reboot) { - WS.enableWDT(wdt_timeout * 1000); + WS.enableWDT(wdt_timeout_ms); } } } From b594a3b872961c2627423aac1595faa0d017e388 Mon Sep 17 00:00:00 2001 From: tyeth Date: Thu, 19 Dec 2024 18:25:55 +0000 Subject: [PATCH 14/19] Add custom WDT timeout for ESP8266 --- src/Wippersnapper.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 3c222a21b..7488787af 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2503,7 +2503,11 @@ void Wippersnapper::runNetFSM() { /**************************************************************************/ void Wippersnapper::haltError(String error, ws_led_status_t ledStatusColor, uint8_t seconds_until_reboot) { - uint8_t wdt_timeout_ms = 5000; // future platform-specific differences +#ifdef ARDUINO_ARCH_ESP8266 + uint8_t wdt_timeout_ms = 3200; +#else + uint8_t wdt_timeout_ms = 5000; +#endif int seconds_until_wdt_enable = seconds_until_reboot - (int)(wdt_timeout_ms / 1000); @@ -2523,7 +2527,7 @@ void Wippersnapper::haltError(String error, ws_led_status_t ledStatusColor, #endif if (i < seconds_until_wdt_enable) { yield(); - WS.feedWDT(); // feed the WDT for the first 20 seconds + WS.feedWDT(); // feed the WDT for the first X-5 seconds } else if (i == seconds_until_reboot) { WS.enableWDT(wdt_timeout_ms); } From 34cd2bd7d91f23ff85c9cafa82b0c4d2d876e3a9 Mon Sep 17 00:00:00 2001 From: tyeth Date: Thu, 19 Dec 2024 19:53:48 +0000 Subject: [PATCH 15/19] Add VCNL4200 --- library.properties | 2 +- platformio.ini | 1 + src/components/i2c/WipperSnapper_I2C.cpp | 11 ++ src/components/i2c/WipperSnapper_I2C.h | 2 + .../WipperSnapper_I2C_Driver_VCNL4200.h | 107 ++++++++++++++++++ 5 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 src/components/i2c/drivers/WipperSnapper_I2C_Driver_VCNL4200.h diff --git a/library.properties b/library.properties index 82be4896d..66f28cb02 100644 --- a/library.properties +++ b/library.properties @@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper category=Communication url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino architectures=* -depends=Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork +depends=Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork diff --git a/platformio.ini b/platformio.ini index dd4acafc2..b373ee1b2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -43,6 +43,7 @@ lib_deps = adafruit/Adafruit Si7021 Library adafruit/Adafruit VCNL4020 Library adafruit/Adafruit VCNL4040 + adafruit/Adafruit VCNL4200 Library adafruit/Adafruit MCP3421 adafruit/Adafruit MCP9808 Library adafruit/Adafruit MCP9600 Library diff --git a/src/components/i2c/WipperSnapper_I2C.cpp b/src/components/i2c/WipperSnapper_I2C.cpp index 70ca0b5d5..173e8fa1d 100644 --- a/src/components/i2c/WipperSnapper_I2C.cpp +++ b/src/components/i2c/WipperSnapper_I2C.cpp @@ -553,6 +553,17 @@ bool WipperSnapper_Component_I2C::initI2CDevice( _vcnl4040->configureDriver(msgDeviceInitReq); drivers.push_back(_vcnl4040); WS_DEBUG_PRINTLN("VCNL4040 Initialized Successfully!"); + } else if (strcmp("vcnl4200", msgDeviceInitReq->i2c_device_name) == 0) { + _vcnl4200 = new WipperSnapper_I2C_Driver_VCNL4200(this->_i2c, i2cAddress); + if (!_vcnl4200->begin()) { + WS_DEBUG_PRINTLN("ERROR: Failed to initialize VCNL4200!"); + _busStatusResponse = + wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL; + return false; + } + _vcnl4200->configureDriver(msgDeviceInitReq); + drivers.push_back(_vcnl4200); + WS_DEBUG_PRINTLN("VCNL4200 Initialized Successfully!"); } else if (strcmp("veml7700", msgDeviceInitReq->i2c_device_name) == 0) { _veml7700 = new WipperSnapper_I2C_Driver_VEML7700(this->_i2c, i2cAddress); if (!_veml7700->begin()) { diff --git a/src/components/i2c/WipperSnapper_I2C.h b/src/components/i2c/WipperSnapper_I2C.h index 58cd5c5fc..e992f2758 100644 --- a/src/components/i2c/WipperSnapper_I2C.h +++ b/src/components/i2c/WipperSnapper_I2C.h @@ -64,6 +64,7 @@ #include "drivers/WipperSnapper_I2C_Driver_TSL2591.h" #include "drivers/WipperSnapper_I2C_Driver_VCNL4020.h" #include "drivers/WipperSnapper_I2C_Driver_VCNL4040.h" +#include "drivers/WipperSnapper_I2C_Driver_VCNL4200.h" #include "drivers/WipperSnapper_I2C_Driver_VEML7700.h" #include "drivers/WipperSnapper_I2C_Driver_VL53L0X.h" #include "drivers/WipperSnapper_I2C_Driver_VL53L1X.h" @@ -159,6 +160,7 @@ class WipperSnapper_Component_I2C { WipperSnapper_I2C_Driver_TSL2591 *_tsl2591 = nullptr; WipperSnapper_I2C_Driver_VCNL4020 *_vcnl4020 = nullptr; WipperSnapper_I2C_Driver_VCNL4040 *_vcnl4040 = nullptr; + WipperSnapper_I2C_Driver_VCNL4200 *_vcnl4200 = nullptr; WipperSnapper_I2C_Driver_VEML7700 *_veml7700 = nullptr; WipperSnapper_I2C_Driver_SCD4X *_scd40 = nullptr; WipperSnapper_I2C_Driver_SEN5X *_sen5x = nullptr; diff --git a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_VCNL4200.h b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_VCNL4200.h new file mode 100644 index 000000000..3f0199f15 --- /dev/null +++ b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_VCNL4200.h @@ -0,0 +1,107 @@ +/*! + * @file WipperSnapper_I2C_Driver_VCNL4200.h + * + * Device driver for the VCNL4200 light + proximity sensor. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Tyeth Gundry 2024 for Adafruit Industries. + * + * MIT license, all text here must be included in any redistribution. + * + */ +#ifndef WipperSnapper_I2C_Driver_VCNL4200_H +#define WipperSnapper_I2C_Driver_VCNL4200_H + +#include "WipperSnapper_I2C_Driver.h" +#include + +/**************************************************************************/ +/*! + @brief Class that provides a driver interface for a VCNL4200 sensor. +*/ +/**************************************************************************/ +class WipperSnapper_I2C_Driver_VCNL4200 : public WipperSnapper_I2C_Driver { +public: + /*******************************************************************************/ + /*! + @brief Constructor for a VCNL4200 sensor. + @param i2c + The I2C interface. + @param sensorAddress + The 7-bit I2C address of the sensor. + */ + /*******************************************************************************/ + WipperSnapper_I2C_Driver_VCNL4200(TwoWire *i2c, uint16_t sensorAddress) + : WipperSnapper_I2C_Driver(i2c, sensorAddress) { + _i2c = i2c; + _sensorAddress = sensorAddress; + } + + /*******************************************************************************/ + /*! + @brief Destructor for an VCNL4200 sensor. + */ + /*******************************************************************************/ + ~WipperSnapper_I2C_Driver_VCNL4200() { delete _vcnl4200; } + + /*******************************************************************************/ + /*! + @brief Initializes the VCNL4200 sensor and begins I2C. + @returns True if initialized successfully, False otherwise. + */ + /*******************************************************************************/ + bool begin() { + _vcnl4200 = new Adafruit_VCNL4200(); + bool status = false; + // Attempt to initialize and configure VCNL4200 + if (!_vcnl4200->begin(_sensorAddress, _i2c)) { + return false; + } + status = _vcnl4200->setALSshutdown(false); + status &= _vcnl4200->setProxShutdown(false); + status &= _vcnl4200->setProxHD(true); // 16bit instead of 12bit + status &= _vcnl4200->setALSIntegrationTime(VCNL4200_ALS_IT_400MS); + status &= _vcnl4200->setProxDuty(VCNL4200_PS_DUTY_1_160); + status &= _vcnl4200->setProxLEDCurrent(VCNL4200_LED_I_200MA); + status &= _vcnl4200->setProxIntegrationTime(VCNL4200_PS_IT_9T); + return status; + } + + /*******************************************************************************/ + /*! + @brief Performs a light sensor read using the Adafruit + Unified Sensor API. + @param lightEvent + Light sensor reading, in lux. + @returns True if the sensor event was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventLight(sensors_event_t *lightEvent) { + // Get sensor event populated in lux via AUTO integration and gain + lightEvent->light = _vcnl4200->readALSdata(); + return true; + } + + /*******************************************************************************/ + /*! + @brief Reads the VCNL4200's proximity value into an event (no unit). + @param proximityEvent + Pointer to an Adafruit_Sensor event. + @returns True if the proximity was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventProximity(sensors_event_t *proximityEvent) { + proximityEvent->data[0] = (float)_vcnl4200->readProxData(); + return true; + } + +protected: + Adafruit_VCNL4200 *_vcnl4200; ///< Pointer to VCNL4200 light sensor object +}; + +#endif // WipperSnapper_I2C_Driver_VCNL4200 \ No newline at end of file From 86936f2acf8f942cf06e7e18fff878fc34ac5770 Mon Sep 17 00:00:00 2001 From: tyeth Date: Fri, 20 Dec 2024 18:08:47 +0000 Subject: [PATCH 16/19] Move enableWDT to after wifi connection for all platforms --- src/Wippersnapper.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index b8bf018b2..44e318223 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2748,11 +2748,6 @@ void Wippersnapper::connect() { // Dump device info to the serial monitor printDeviceInfo(); -// enable global WDT -#ifndef ARDUINO_ARCH_RP2040 - WS.enableWDT(WS_WDT_TIMEOUT); -#endif - // Generate device identifier if (!generateDeviceUID()) { haltError("Unable to generate Device UID"); @@ -2774,11 +2769,9 @@ void Wippersnapper::connect() { WS_DEBUG_PRINTLN("Running Network FSM..."); // Run the network fsm runNetFSM(); -#ifdef ARDUINO_ARCH_RP2040 - WS.enableWDT(WS_WDT_TIMEOUT); // wifi multi doesn't feed the WDT -#else - WS.feedWDT(); -#endif + + // Enable WDT after wifi connection as wifiMulti doesnt feed WDT + WS.enableWDT(WS_WDT_TIMEOUT); #ifdef USE_DISPLAY WS._ui_helper->set_load_bar_icon_complete(loadBarIconCloud); From 24cf18051b114ba4792c9720b515efa65bb6e159 Mon Sep 17 00:00:00 2001 From: tyeth Date: Fri, 20 Dec 2024 18:10:20 +0000 Subject: [PATCH 17/19] Correct verbiage for RP2040 rather than Pico --- src/Wippersnapper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index 3d597713b..18c942435 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -215,7 +215,7 @@ typedef enum { } fsm_net_t; #ifdef ARDUINO_ARCH_RP2040 -#define WS_WDT_TIMEOUT 8388 ///< Pico Max WDT timeout +#define WS_WDT_TIMEOUT 8388 ///< RP2040 Max WDT timeout #else #define WS_WDT_TIMEOUT 60000 ///< WDT timeout #endif From 0de83b9925cc740b9fd1688c6dc9c9563f9c7ec1 Mon Sep 17 00:00:00 2001 From: tyeth Date: Fri, 20 Dec 2024 17:11:47 +0000 Subject: [PATCH 18/19] Always show Wifi scan results (RSSI, channel, bssid) --- src/Wippersnapper.h | 3 +- src/Wippersnapper_Networking.h | 91 +++++++++-------- .../Wippersnapper_AIRLIFT.h | 42 ++++---- src/network_interfaces/Wippersnapper_ESP32.h | 48 ++++----- .../Wippersnapper_ESP8266.h | 99 +++++++++---------- .../Wippersnapper_WIFININA.h | 43 ++++---- src/network_interfaces/ws_networking_pico.h | 48 ++++----- 7 files changed, 191 insertions(+), 183 deletions(-) diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index ede523228..0520406bc 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -214,8 +214,7 @@ typedef enum { FSM_NET_ESTABLISH_MQTT, } fsm_net_t; -#define WS_WDT_TIMEOUT 60000 ///< WDT timeout -#define WS_MAX_ALT_WIFI_NETWORKS 3 ///< Maximum number of alternative networks +#define WS_WDT_TIMEOUT 60000 ///< WDT timeout /* MQTT Configuration */ #define WS_KEEPALIVE_INTERVAL_MS \ 5000 ///< Session keepalive interval time, in milliseconds diff --git a/src/Wippersnapper_Networking.h b/src/Wippersnapper_Networking.h index 5e401a4ff..e5c2c75f6 100644 --- a/src/Wippersnapper_Networking.h +++ b/src/Wippersnapper_Networking.h @@ -1,44 +1,49 @@ -/*! - * @file Wippersnapper_Networking.h - * - * This file includes network interfaces at compile-time. - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2020-2021 for Adafruit Industries. - * - * BSD license, all text here must be included in any redistribution. - * - */ - -#ifndef WIPPERSNAPPER_NETWORKING_H -#define WIPPERSNAPPER_NETWORKING_H - -#if defined(ADAFRUIT_METRO_M4_EXPRESS) || \ - defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) || defined(ADAFRUIT_PYPORTAL) || \ - defined(ADAFRUIT_PYPORTAL_M4_TITANO) || defined(USE_AIRLIFT) -#include "network_interfaces/Wippersnapper_AIRLIFT.h" -/** Nina-FW (adafruit fork) networking class */ -typedef Wippersnapper_AIRLIFT Wippersnapper_WiFi; -#elif defined(ARDUINO_ARCH_ESP8266) -#include "network_interfaces/Wippersnapper_ESP8266.h" -/** ESP8266's networking class */ -typedef Wippersnapper_ESP8266 Wippersnapper_WiFi; -#elif defined(ARDUINO_ARCH_ESP32) -#include "network_interfaces/Wippersnapper_ESP32.h" -/** ESP32's networking class */ -typedef Wippersnapper_ESP32 Wippersnapper_WiFi; -#elif defined(ARDUINO_ARCH_RP2040) -#include "network_interfaces/ws_networking_pico.h" -typedef ws_networking_pico Wippersnapper_WiFi; -#elif defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRWIFI1010) -/** Nina-FW (arduino) networking class */ -#include "network_interfaces/Wippersnapper_WIFININA.h" -typedef Wippersnapper_WIFININA Wippersnapper_WiFi; -#else -#warning "Must define network interface in config.h!" -#endif - +/*! + * @file Wippersnapper_Networking.h + * + * This file includes network interfaces at compile-time. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2020-2021 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ + +#ifndef WIPPERSNAPPER_NETWORKING_H +#define WIPPERSNAPPER_NETWORKING_H + +#ifndef WL_MAC_ADDR_LENGTH +#define WL_MAC_ADDR_LENGTH 6 ///< MAC address length - from RP2040 BSP +#endif +#define WS_MAX_ALT_WIFI_NETWORKS 3 ///< Maximum number of alternative networks + +#if defined(ADAFRUIT_METRO_M4_EXPRESS) || \ + defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) || defined(ADAFRUIT_PYPORTAL) || \ + defined(ADAFRUIT_PYPORTAL_M4_TITANO) || defined(USE_AIRLIFT) +#include "network_interfaces/Wippersnapper_AIRLIFT.h" +/** Nina-FW (adafruit fork) networking class */ +typedef Wippersnapper_AIRLIFT Wippersnapper_WiFi; +#elif defined(ARDUINO_ARCH_ESP8266) +#include "network_interfaces/Wippersnapper_ESP8266.h" +/** ESP8266's networking class */ +typedef Wippersnapper_ESP8266 Wippersnapper_WiFi; +#elif defined(ARDUINO_ARCH_ESP32) +#include "network_interfaces/Wippersnapper_ESP32.h" +/** ESP32's networking class */ +typedef Wippersnapper_ESP32 Wippersnapper_WiFi; +#elif defined(ARDUINO_ARCH_RP2040) +#include "network_interfaces/ws_networking_pico.h" +typedef ws_networking_pico Wippersnapper_WiFi; +#elif defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRWIFI1010) +/** Nina-FW (arduino) networking class */ +#include "network_interfaces/Wippersnapper_WIFININA.h" +typedef Wippersnapper_WIFININA Wippersnapper_WiFi; +#else +#warning "Must define network interface in config.h!" +#endif + #endif // WIPPERSNAPPER_NETWORKING_H \ No newline at end of file diff --git a/src/network_interfaces/Wippersnapper_AIRLIFT.h b/src/network_interfaces/Wippersnapper_AIRLIFT.h index 4c564b4e1..a278d1fe1 100644 --- a/src/network_interfaces/Wippersnapper_AIRLIFT.h +++ b/src/network_interfaces/Wippersnapper_AIRLIFT.h @@ -103,8 +103,8 @@ class Wippersnapper_AIRLIFT : public Wippersnapper { /***********************************************************/ /*! - @brief Performs a scan of local WiFi networks. - @returns True if `_network_ssid` is found, False otherwise. + @brief Performs a scan of local WiFi networks. + @returns True if `_network_ssid` is found, False otherwise. */ /***********************************************************/ bool check_valid_ssid() { @@ -119,26 +119,33 @@ class Wippersnapper_AIRLIFT : public Wippersnapper { return false; } - // Was the network within secrets.json found? - for (int i = 0; i < n; ++i) { - if (strcmp(_ssid, WiFi.SSID(i)) == 0) { - WS_DEBUG_PRINT("SSID found! RSSI: "); - WS_DEBUG_PRINTLN(WiFi.RSSI(i)); - return true; - } - } + bool foundNetwork = false; - // User-set network not found, print scan results to serial console - WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); - WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: "); - for (int i = 0; i < n; ++i) { + WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks:"); + for (uint8_t i = 0; i < n; i++) { + if (!foundNetwork && strcmp(WiFi.SSID(i), _ssid) == 0) { + foundNetwork = true; + } WS_DEBUG_PRINT(WiFi.SSID(i)); - WS_DEBUG_PRINT(" "); + WS_DEBUG_PRINT(" ("); + uint8_t BSSID[WL_MAC_ADDR_LENGTH]; + WiFi.BSSID(i, BSSID); + for (int m = 0; m < WL_MAC_ADDR_LENGTH; m++) { + if (m != 0) + WS_DEBUG_PRINT(":"); + WS_DEBUG_PRINTHEX(BSSID[m]); + } + WS_DEBUG_PRINT(") "); WS_DEBUG_PRINT(WiFi.RSSI(i)); - WS_DEBUG_PRINTLN("dB"); + WS_DEBUG_PRINT("dB (ch"); + WS_DEBUG_PRINT(WiFi.channel(i)) + WS_DEBUG_PRINTLN(")"); } - return false; + if (!foundNetwork) { + WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); + } + return foundNetwork; } /********************************************************/ @@ -323,6 +330,7 @@ class Wippersnapper_AIRLIFT : public Wippersnapper { // validate co-processor's firmware version if (!firmwareCheck()) { + // TODO: see if there's a way to add to bootlog without usb reattach WS_DEBUG_PRINTLN("Please upgrade the firmware on the ESP module to the " "latest version."); } diff --git a/src/network_interfaces/Wippersnapper_ESP32.h b/src/network_interfaces/Wippersnapper_ESP32.h index 99c4d47be..98fc8ae05 100644 --- a/src/network_interfaces/Wippersnapper_ESP32.h +++ b/src/network_interfaces/Wippersnapper_ESP32.h @@ -120,40 +120,40 @@ class Wippersnapper_ESP32 : public Wippersnapper { return false; } - // Was the network within secrets.json found? - for (int i = 0; i < n; ++i) { - if (strcmp(_ssid, WiFi.SSID(i).c_str()) == 0) { - WS_DEBUG_PRINT("SSID ("); - WS_DEBUG_PRINT(_ssid); - WS_DEBUG_PRINT(") found! RSSI: "); - WS_DEBUG_PRINTLN(WiFi.RSSI(i)); - return true; - } - if (WS._isWiFiMulti) { + bool foundNetwork = false; + + WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks:"); + for (uint8_t i = 0; i < n; i++) { + if (!foundNetwork && strcmp(WiFi.SSID(i).c_str(), _ssid) == 0) { + foundNetwork = true; + } else if (!foundNetwork && WS._isWiFiMulti) { // multi network mode for (int j = 0; j < WS_MAX_ALT_WIFI_NETWORKS; j++) { if (strcmp(WS._multiNetworks[j].ssid, WiFi.SSID(i).c_str()) == 0) { - WS_DEBUG_PRINT("SSID ("); - WS_DEBUG_PRINT(WS._multiNetworks[j].ssid); - WS_DEBUG_PRINT(") found! RSSI: "); - WS_DEBUG_PRINTLN(WiFi.RSSI(i)); - return true; + foundNetwork = true; } } } - } - - // User-set network not found, print scan results to serial console - WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); - WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: "); - for (int i = 0; i < n; ++i) { WS_DEBUG_PRINT(WiFi.SSID(i)); - WS_DEBUG_PRINT(" "); + WS_DEBUG_PRINT(" ("); + uint8_t BSSID[WL_MAC_ADDR_LENGTH]; + WiFi.BSSID(i, BSSID); + for (int m = 0; m < WL_MAC_ADDR_LENGTH; m++) { + if (m != 0) + WS_DEBUG_PRINT(":"); + WS_DEBUG_PRINTHEX(BSSID[m]); + } + WS_DEBUG_PRINT(") "); WS_DEBUG_PRINT(WiFi.RSSI(i)); - WS_DEBUG_PRINTLN("dB"); + WS_DEBUG_PRINT("dB (ch"); + WS_DEBUG_PRINT(WiFi.channel(i)) + WS_DEBUG_PRINTLN(")"); } - return false; + if (!foundNetwork) { + WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); + } + return foundNetwork; } /********************************************************/ diff --git a/src/network_interfaces/Wippersnapper_ESP8266.h b/src/network_interfaces/Wippersnapper_ESP8266.h index c7fa6b693..1a9989d07 100644 --- a/src/network_interfaces/Wippersnapper_ESP8266.h +++ b/src/network_interfaces/Wippersnapper_ESP8266.h @@ -133,40 +133,40 @@ class Wippersnapper_ESP8266 : public Wippersnapper { return false; } - // Was the network within secrets.json found? - for (int i = 0; i < n; ++i) { - if (strcmp(_ssid, WiFi.SSID(i).c_str()) == 0) { - WS_DEBUG_PRINT("SSID ("); - WS_DEBUG_PRINT(_ssid); - WS_DEBUG_PRINT(") found! RSSI: "); - WS_DEBUG_PRINTLN(WiFi.RSSI(i)); - return true; - } - if (WS._isWiFiMulti) { + bool foundNetwork = false; + + WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks:"); + for (uint8_t i = 0; i < n; i++) { + if (!foundNetwork && strcmp(WiFi.SSID(i).c_str(), _ssid) == 0) { + foundNetwork = true; + } else if (!foundNetwork && WS._isWiFiMulti) { // multi network mode for (int j = 0; j < WS_MAX_ALT_WIFI_NETWORKS; j++) { if (strcmp(WS._multiNetworks[j].ssid, WiFi.SSID(i).c_str()) == 0) { - WS_DEBUG_PRINT("SSID ("); - WS_DEBUG_PRINT(WS._multiNetworks[j].ssid); - WS_DEBUG_PRINT(") found! RSSI: "); - WS_DEBUG_PRINTLN(WiFi.RSSI(i)); - return true; + foundNetwork = true; } } } - } - - // User-set network not found, print scan results to serial console - WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); - WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: "); - for (int i = 0; i < n; ++i) { WS_DEBUG_PRINT(WiFi.SSID(i)); - WS_DEBUG_PRINT(" "); + WS_DEBUG_PRINT(" ("); + uint8_t BSSID[WL_MAC_ADDR_LENGTH]; + memcpy(BSSID, WiFi.BSSID(i), WL_MAC_ADDR_LENGTH); + for (int m = 0; m < WL_MAC_ADDR_LENGTH; m++) { + if (m != 0) + WS_DEBUG_PRINT(":"); + WS_DEBUG_PRINTHEX(BSSID[m]); + } + WS_DEBUG_PRINT(") "); WS_DEBUG_PRINT(WiFi.RSSI(i)); - WS_DEBUG_PRINTLN("dB"); + WS_DEBUG_PRINT("dB (ch"); + WS_DEBUG_PRINT(WiFi.channel(i)) + WS_DEBUG_PRINTLN(")"); } - return false; + if (!foundNetwork) { + WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); + } + return foundNetwork; } /********************************************************/ @@ -260,7 +260,6 @@ class Wippersnapper_ESP8266 : public Wippersnapper { delay(100); // ESP8266 MUST be in STA mode to avoid device acting as client/server WiFi.mode(WIFI_STA); - WiFi.begin(_ssid, _pass); _status = WS_NET_DISCONNECTED; delay(100); @@ -274,38 +273,28 @@ class Wippersnapper_ESP8266 : public Wippersnapper { WS._multiNetworks[i].pass); } } - // add default network - if (_wifiMulti.existsAP(_ssid) == false) { - _wifiMulti.addAP(_ssid, _pass); - } - long startRetry = millis(); - WS_DEBUG_PRINTLN("CONNECTING"); - while (_wifiMulti.run(5000) != WL_CONNECTED && - millis() - startRetry < 10000) { - // ESP8266 WDT requires yield() during a busy-loop so it doesn't bite - yield(); - } - if (WiFi.status() == WL_CONNECTED) { - _status = WS_NET_CONNECTED; - } else { - _status = WS_NET_DISCONNECTED; - } + } + + // add default network + if (_wifiMulti.existsAP(_ssid) == false) { + _wifiMulti.addAP(_ssid, _pass); + } + + long startRetry = millis(); + WS_DEBUG_PRINTLN("CONNECTING"); + + while (_wifiMulti.run(5000) != WL_CONNECTED && + millis() - startRetry < 10000) { + // ESP8266 WDT requires yield() during a busy-loop so it doesn't bite + yield(); + } + + if (WiFi.status() == WL_CONNECTED) { + _status = WS_NET_CONNECTED; } else { - // single network mode - - // wait for a connection to be established - long startRetry = millis(); - WS_DEBUG_PRINTLN("CONNECTING"); - while (WiFi.status() != WL_CONNECTED && millis() - startRetry < 10000) { - // ESP8266 WDT requires yield() during a busy-loop so it doesn't bite - yield(); - } - if (WiFi.status() == WL_CONNECTED) { - _status = WS_NET_CONNECTED; - } else { - _status = WS_NET_DISCONNECTED; - } + _status = WS_NET_DISCONNECTED; } + WS.feedWDT(); } } diff --git a/src/network_interfaces/Wippersnapper_WIFININA.h b/src/network_interfaces/Wippersnapper_WIFININA.h index 74f50bffe..29fa1691b 100644 --- a/src/network_interfaces/Wippersnapper_WIFININA.h +++ b/src/network_interfaces/Wippersnapper_WIFININA.h @@ -111,8 +111,8 @@ class Wippersnapper_WIFININA : public Wippersnapper { /***********************************************************/ /*! - @brief Performs a scan of local WiFi networks. - @returns True if `_network_ssid` is found, False otherwise. + @brief Performs a scan of local WiFi networks. + @returns True if `_network_ssid` is found, False otherwise. */ /***********************************************************/ bool check_valid_ssid() { @@ -122,32 +122,39 @@ class Wippersnapper_WIFININA : public Wippersnapper { delay(100); // Perform a network scan - int n = WiFi.scanNetworks(); + int8_t n = WiFi.scanNetworks(); if (n == 0) { WS_DEBUG_PRINTLN("ERROR: No WiFi networks found!"); return false; } - // Was the network within secrets.json found? - for (int i = 0; i < n; ++i) { - if (strcmp(_ssid, WiFi.SSID(i)) == 0) { - WS_DEBUG_PRINT("SSID found! RSSI: "); - WS_DEBUG_PRINTLN(WiFi.RSSI(i)); - return true; - } - } + bool foundNetwork = false; - // User-set network not found, print scan results to serial console - WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); - WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: "); - for (int i = 0; i < n; ++i) { + WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks:"); + for (uint8_t i = 0; i < n; i++) { + if (!foundNetwork && strcmp(WiFi.SSID(i), _ssid) == 0) { + foundNetwork = true; + } WS_DEBUG_PRINT(WiFi.SSID(i)); - WS_DEBUG_PRINT(" "); + WS_DEBUG_PRINT(" ("); + uint8_t BSSID[WL_MAC_ADDR_LENGTH]; + WiFi.BSSID(i, BSSID); + for (int m = 0; m < WL_MAC_ADDR_LENGTH; m++) { + if (m != 0) + WS_DEBUG_PRINT(":"); + WS_DEBUG_PRINTHEX(BSSID[m]); + } + WS_DEBUG_PRINT(") "); WS_DEBUG_PRINT(WiFi.RSSI(i)); - WS_DEBUG_PRINTLN("dB"); + WS_DEBUG_PRINT("dB (ch"); + WS_DEBUG_PRINT(WiFi.channel(i)) + WS_DEBUG_PRINTLN(")"); } - return false; + if (!foundNetwork) { + WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); + } + return foundNetwork; } /********************************************************/ diff --git a/src/network_interfaces/ws_networking_pico.h b/src/network_interfaces/ws_networking_pico.h index 25ce278b1..c6d90abcd 100644 --- a/src/network_interfaces/ws_networking_pico.h +++ b/src/network_interfaces/ws_networking_pico.h @@ -112,40 +112,40 @@ class ws_networking_pico : public Wippersnapper { return false; } - // Was the network within secrets.json found? - for (int i = 0; i < n; ++i) { - if (strcmp(_ssid, WiFi.SSID(i)) == 0) { - WS_DEBUG_PRINT("SSID ("); - WS_DEBUG_PRINT(_ssid); - WS_DEBUG_PRINT(") found! RSSI: "); - WS_DEBUG_PRINTLN(WiFi.RSSI(i)); - return true; - } - if (WS._isWiFiMulti) { + bool foundNetwork = false; + + WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks:"); + for (uint8_t i = 0; i < n; i++) { + if (!foundNetwork && strcmp(WiFi.SSID(i), _ssid) == 0) { + foundNetwork = true; + } else if (!foundNetwork && WS._isWiFiMulti) { // multi network mode for (int j = 0; j < WS_MAX_ALT_WIFI_NETWORKS; j++) { if (strcmp(WS._multiNetworks[j].ssid, WiFi.SSID(i)) == 0) { - WS_DEBUG_PRINT("SSID ("); - WS_DEBUG_PRINT(WS._multiNetworks[j].ssid); - WS_DEBUG_PRINT(") found! RSSI: "); - WS_DEBUG_PRINTLN(WiFi.RSSI(i)); - return true; + foundNetwork = true; } } } - } - - // User-set network not found, print scan results to serial console - WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); - WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: "); - for (int i = 0; i < n; ++i) { WS_DEBUG_PRINT(WiFi.SSID(i)); - WS_DEBUG_PRINT(" "); + WS_DEBUG_PRINT(" ("); + uint8_t BSSID[WL_MAC_ADDR_LENGTH]; + WiFi.BSSID(i, BSSID); + for (int m = 0; m < WL_MAC_ADDR_LENGTH; m++) { + if (m != 0) + WS_DEBUG_PRINT(":"); + WS_DEBUG_PRINTHEX(BSSID[m]); + } + WS_DEBUG_PRINT(") "); WS_DEBUG_PRINT(WiFi.RSSI(i)); - WS_DEBUG_PRINTLN("dB"); + WS_DEBUG_PRINT("dB (ch"); + WS_DEBUG_PRINT(WiFi.channel(i)) + WS_DEBUG_PRINTLN(")"); } - return false; + if (!foundNetwork) { + WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!"); + } + return foundNetwork; } /********************************************************/ From 0923b827152daf1c4bde3a1af8ac8bd822b38663 Mon Sep 17 00:00:00 2001 From: tyeth Date: Sat, 21 Dec 2024 02:14:31 +0000 Subject: [PATCH 19/19] 20s wifi attempt timeout for PicoW/2W --- src/network_interfaces/ws_networking_pico.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network_interfaces/ws_networking_pico.h b/src/network_interfaces/ws_networking_pico.h index c6d90abcd..f1e394cb2 100644 --- a/src/network_interfaces/ws_networking_pico.h +++ b/src/network_interfaces/ws_networking_pico.h @@ -319,7 +319,7 @@ class ws_networking_pico : public Wippersnapper { WS._multiNetworks[i].pass); } WS.feedWDT(); - if (_wifiMulti.run(10000) == WL_CONNECTED) { + if (_wifiMulti.run(20000) == WL_CONNECTED) { WS.feedWDT(); _status = WS_NET_CONNECTED; return;