diff --git a/library.properties b/library.properties index c46d7db17..ec5018627 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=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit AS5600 Library, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA237 and INA238 Library, Adafruit INA260 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit MLX90632 Library, 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, Sensirion I2C SEN66, 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 QMC5883P Library, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, 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, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, RTClib, StreamUtils, Adafruit SHT4x Library, Adafruit GPS Library, Adafruit uBlox +depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit LIS3DH, Adafruit LIS3MDL, Adafruit LSM6DS, Adafruit LSM9DS1 Library, Adafruit LSM303 Accel, Adafruit LSM303DLH Mag, Adafruit LIS2MDL, Adafruit AS5600 Library, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA237 and INA238 Library, Adafruit INA260 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit MLX90632 Library, 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, Sensirion I2C SEN66, 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 QMC5883P Library, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, 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, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, RTClib, StreamUtils, Adafruit SHT4x Library, Adafruit GPS Library, Adafruit uBlox diff --git a/platformio.ini b/platformio.ini index a8dc0dd7b..cb32d494e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -46,6 +46,13 @@ lib_deps = adafruit/Adafruit HTS221 adafruit/Adafruit HTU21DF Library adafruit/Adafruit HTU31D Library + adafruit/Adafruit LIS3DH + adafruit/Adafruit LIS3MDL + adafruit/Adafruit LIS2MDL + adafruit/Adafruit LSM6DS + adafruit/Adafruit LSM9DS1 Library + adafruit/Adafruit LSM303 Accel + adafruit/Adafruit LSM303DLH Mag adafruit/Adafruit LTR390 Library adafruit/Adafruit LTR329 and LTR303 adafruit/Adafruit PCT2075 @@ -111,8 +118,8 @@ lib_deps = ; Common build environment for ESP32 platform [common:esp32] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.13/platform-espressif32.zip -lib_ignore = WiFiNINA, WiFi101 +platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.33/platform-espressif32.zip +lib_ignore = WiFiNINA, WiFi101, WiFiNINA_-_Adafruit_Fork monitor_filters = esp32_exception_decoder, time ; upload_speed = 921600 @@ -139,9 +146,9 @@ board = rpipicow framework = arduino board_build.core = earlephilhower board_build.filesystem_size = 0.5m -build_flags = -DUSE_TINYUSB +build_flags = -DUSE_TINYUSB -DBUILD_OFFLINE_ONLY ; Once https://github.com/platformio/platformio-core > 6.1.11 these can be removed -lib_ignore = WiFiNINA, WiFi101, Adafruit Zero DMA Library +lib_ignore = WiFiNINA, WiFi101, Adafruit Zero DMA Library, WiFiNINA_-_Adafruit_Fork lib_compat_mode = soft ; can be strict once pio detects SleepyDog on RP2040 @@ -190,13 +197,32 @@ board_build.filesystem = littlefs [env:featheresp32s2] extends = common:esp32 board = featheresp32-s2 -build_flags = -DARDUINO_ADAFRUIT_FEATHER_ESP32S2 -DBOARD_HAS_PSRAM -DBUILD_OFFLINE_ONLY +build_flags = + -DARDUINO_ADAFRUIT_FEATHER_ESP32S2 + -DBOARD_HAS_PSRAM + -DBUILD_OFFLINE_ONLY + ; -DSDFAT_FILE_TYPE=3 board_build.partitions = tinyuf2-partitions-4MB-noota.csv ;board_build.partitions = tinyuf2-partitions-4MB.csv ;build_type = debug monitor_filters = esp32_exception_decoder extra_scripts = pre:rename_usb_config.py +[env:featheresp32s2_debug] +extends = env:featheresp32s2 +build_type = debug +build_flags = + -DARDUINO_ADAFRUIT_FEATHER_ESP32S2 + -DBOARD_HAS_PSRAM + -DBUILD_OFFLINE_ONLY + ; -DSDFAT_FILE_TYPE=3 + -DDEBUG=1 + -DCFG_TUSB_DEBUG=1 + -DESP_LOG_LEVEL=ESP_LOG_VERBOSE + -DARDUINO_CORE_DEBUG_LEVEL=5 + -DCORE_DEBUG_LEVEL=5 + -DARDUHAL_LOG_LEVEL=5 + ; Adafruit Feather ESP32-S2 TFT [env:adafruit_feather_esp32s2_tft] extends = common:esp32 @@ -460,43 +486,62 @@ build_flags = -DUSE_TINYUSB=1 upload_port = /dev/cu.usbmodem1201 [env:raspberrypi_pico] +extends = common:rp2040 platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop board = rpipico platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git board_build.filesystem_size = 0.5m build_flags = -DUSE_TINYUSB ; Once https://github.com/platformio/platformio-core > 6.1.11 these can be removed -lib_ignore = WiFiNINA, WiFi101, Adafruit Zero DMA Library [env:raspberrypi_pico_2] +extends = common:rp2040 platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop board = rpipico2 platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git board_build.filesystem_size = 0.5m build_flags = -DUSE_TINYUSB -DBUILD_OFFLINE_ONLY ; Once https://github.com/platformio/platformio-core > 6.1.11 these can be removed -lib_ignore = WiFiNINA, WiFi101, Adafruit Zero DMA Library + +[env:raspberrypi_pico_2w] +extends: common:rp2040 +platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop +board = rpipico2w +platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git +board_build.filesystem_size = 0.5m +build_flags = -DUSE_TINYUSB -DBUILD_OFFLINE_ONLY +; Once https://github.com/platformio/platformio-core > 6.1.11 these can be removed [env:adafruit_feather_adalogger] +extends = common:rp2040 platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop board = adafruit_feather_adalogger platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git board_build.filesystem_size = 0.5m build_flags = -DUSE_TINYUSB ; Once https://github.com/platformio/platformio-core > 6.1.11 these can be removed -lib_ignore = WiFiNINA, WiFi101, Adafruit Zero DMA Library + +[env:adafruit_feather_rp2350_hstx] +extends = common:rp2040 +platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop +board = adafruit_feather_rp2350_hstx +platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git +board_build.filesystem_size = 0.5m +build_flags = -DUSE_TINYUSB +; Once https://github.com/platformio/platformio-core > 6.1.11 these can be removed [env:adafruit_metro_rp2350] +extends = common:rp2040 platform = https://github.com/brentru/platform-raspberrypi.git#develop board = adafruit_metro_rp2350 platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git board_build.filesystem_size = 0.5m build_flags = -DUSE_TINYUSB -DBUILD_OFFLINE_ONLY ; Once https://github.com/platformio/platformio-core > 6.1.11 these can be removed -lib_ignore = WiFiNINA, WiFi101, Adafruit Zero DMA Library [env:adafruit_metro_rp2350_debug] +extends = common:rp2040 platform = https://github.com/brentru/platform-raspberrypi.git#develop platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git board = adafruit_metro_rp2350 @@ -535,7 +580,6 @@ build_flags = ; build_flags = -DPIO_FRAMEWORK_ARDUINO_NO_USB ; -DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6 ; Once https://github.com/platformio/platformio-core > 6.1.11 these can be removed -lib_ignore = WiFiNINA, WiFi101, Adafruit Zero DMA Library [env:raspberypi_picow] @@ -564,14 +608,14 @@ build_flags = -DDEBUG_RP2040_CORE -DDEBUG_RP2040_WIFI -DLWIP_DEBUG - -DDEBUG_RP2040_PORT=Serial1 - -DDEBUG_RP2040_UART_1 - -DDEBUG_RP2040_UART=1 + ; -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 + ; -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 @@ -580,3 +624,4 @@ build_flags = ; ; No USB stack ; build_flags = -DPIO_FRAMEWORK_ARDUINO_NO_USB ; -DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6 + -DBUILD_OFFLINE_ONLY diff --git a/src/Wippersnapper_Boards.h b/src/Wippersnapper_Boards.h index 21e5a675e..fef336086 100644 --- a/src/Wippersnapper_Boards.h +++ b/src/Wippersnapper_Boards.h @@ -245,6 +245,13 @@ #define STATUS_NEOPIXEL_NUM 1 #define SD_USE_SPI_1 #define SD_CS_PIN 23 +#elif defined(ARDUINO_ADAFRUIT_FEATHER_RP2350_HSTX) +#define BOARD_ID "feather-rp2350-hstx" +#define USE_TINYUSB +#define USE_STATUS_NEOPIXEL +#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL +#define STATUS_NEOPIXEL_NUM 1 +#define SD_CS_PIN 1 #elif defined(ARDUINO_ADAFRUIT_METRO_RP2350) #define BOARD_ID "metro-rp2350" #define USE_TINYUSB diff --git a/src/Wippersnapper_V2.cpp b/src/Wippersnapper_V2.cpp index 1bdb80aeb..8f9525299 100644 --- a/src/Wippersnapper_V2.cpp +++ b/src/Wippersnapper_V2.cpp @@ -936,6 +936,7 @@ void Wippersnapper_V2::haltErrorV2(const char *error, if (!reboot) { WsV2.feedWDTV2(); // Feed the WDT indefinitely to hold the WIPPER drive // open + delay(1000); } else { // Let the WDT fail out and reset! #ifndef ARDUINO_ARCH_ESP8266 @@ -946,6 +947,13 @@ void Wippersnapper_V2::haltErrorV2(const char *error, delayMicroseconds(1000000); #endif } + WS_DEBUG_PRINT("ERROR "); + if (reboot) { + WS_DEBUG_PRINT("[RESET]: "); + } else { + WS_DEBUG_PRINT("[HANG]: "); + } + WS_DEBUG_PRINTLN(error); } } diff --git a/src/Wippersnapper_demo.ino b/src/Wippersnapper_demo.ino index 817f5b53c..b2e9ea0a7 100644 --- a/src/Wippersnapper_demo.ino +++ b/src/Wippersnapper_demo.ino @@ -23,7 +23,11 @@ ws_adapter_offline wipper; void setup() { Serial.begin(115200); - while(!Serial); + // Wait for serial to connect when dev mode, but don't wait forever + uint8_t countdown = 200; + while(!Serial && countdown-- > 0) { + delay(10); + } wipper.provision(); wipper.connect(); } diff --git a/src/adapters/offline/ws_offline_pico.h b/src/adapters/offline/ws_offline_pico.h index 247ea5f68..7fad9bd01 100644 --- a/src/adapters/offline/ws_offline_pico.h +++ b/src/adapters/offline/ws_offline_pico.h @@ -19,6 +19,7 @@ #if defined(ARDUINO_RASPBERRY_PI_PICO) || \ defined(ARDUINO_RASPBERRY_PI_PICO_2) || \ defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) || \ + defined(ARDUINO_ADAFRUIT_FEATHER_RP2350_HSTX) || \ defined(ARDUINO_ADAFRUIT_METRO_RP2350) #define PICO_CONNECT_TIMEOUT_MS 20000 /*!< Connection timeout (in ms) */ diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index 6637f80db..7a5b67bfd 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -168,6 +168,56 @@ static const std::map I2cFactorySensor = { const char *driver_name) -> drvBase * { return new drvLc709203f(i2c, addr, mux_channel, driver_name); }}, + {"lis3dh", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvLis3dh(i2c, addr, mux_channel, driver_name); + }}, + {"lis2mdl", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvLis2mdl(i2c, addr, mux_channel, driver_name); + }}, + {"lis3mdl", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvLis3mdl(i2c, addr, mux_channel, driver_name); + }}, + {"lsm303agr", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvLsm303agr(i2c, addr, mux_channel, driver_name); + }}, + {"lsm303dlh", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvLsm303dlh(i2c, addr, mux_channel, driver_name); + }}, + {"lsm6ds3", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvLsm6ds3(i2c, addr, mux_channel, driver_name); + }}, + {"lsm6dso32", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvLsm6dso32(i2c, addr, mux_channel, driver_name); + }}, + {"ism330dlc", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvIsm330dhcx(i2c, addr, mux_channel, driver_name); + }}, + {"ism330dhcx", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvIsm330dhcx(i2c, addr, mux_channel, driver_name); + }}, + {"lsm9ds1", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvBase * { + return new drvLsm9ds1(i2c, addr, mux_channel, driver_name); + }}, {"lps3xhw", [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, const char *driver_name) -> drvBase * { @@ -407,13 +457,13 @@ static const std::unordered_map> {0x0B, {"lc709203f"}}, {0x12, {"pmsa003i"}}, {0x13, {"vncl4020"}}, - {0x18, {"ds2484", "mcp9808", "mprls"}}, - {0x19, {"mcp9808"}}, + {0x18, {"ds2484", "mcp9808", "mprls", "lis3dh"}}, + {0x19, {"mcp9808", "lsm303agr", "lsm303dlh", "lis3dh"}}, // LIS3DH last - seems to match LSM303AGR {0x1A, {"mcp9808"}}, {0x1B, {"mcp9808"}}, - {0x1C, {"mcp9808"}}, + {0x1C, {"mcp9808", "lis3mdl"}}, {0x1D, {"mcp9808"}}, - {0x1E, {"mcp9808"}}, + {0x1E, {"mcp9808", "lis3mdl", "lis2mdl"}}, // "lsm303dlh", "lsm303agr", but rely on first addr {0x1F, {"mcp9808"}}, {0x23, {"bh1750"}}, {0x28, {"pct2075"}}, @@ -458,7 +508,11 @@ static const std::unordered_map> {0x62, {"scd40"}}, {0x68, {"mcp3421"}}, {0x69, {"sen55"}}, - {0x6B, {"sen66"}}, + {0x6A, {"lsm6dso32", "ism330dhcx", "lsm6ds3"}}, + {0x6B, {"sen66", "lsm6ds3", "lsm6dso32", "ism330dhcx"}}, + {0x6C, {"lsm303dlh"}}, + {0x6D, {"lsm303agr"}}, + {0x6E, {"lsm9ds1"}}, {0x70, {"pct2075", "shtc3"}}, {0x71, {"pct2075"}}, {0x72, {"pct2075"}}, diff --git a/src/components/i2c/controller.h b/src/components/i2c/controller.h index 9ef28b5bf..57d582420 100644 --- a/src/components/i2c/controller.h +++ b/src/components/i2c/controller.h @@ -39,10 +39,19 @@ #include "drivers/drvIna237.h" #include "drivers/drvIna238.h" #include "drivers/drvIna260.h" +#include "drivers/drvIsm330dhcx.h" #include "drivers/drvLc709203f.h" +#include "drivers/drvLis2mdl.h" +#include "drivers/drvLis3dh.h" +#include "drivers/drvLis3mdl.h" #include "drivers/drvLps22hb.h" #include "drivers/drvLps25hb.h" #include "drivers/drvLps3xhw.h" +#include "drivers/drvLsm303agr.h" +#include "drivers/drvLsm303dlh.h" +#include "drivers/drvLsm6ds3.h" +#include "drivers/drvLsm6dso32.h" +#include "drivers/drvLsm9ds1.h" #include "drivers/drvLtr329_Ltr303.h" #include "drivers/drvLtr390.h" #include "drivers/drvMCP9808.h" diff --git a/src/components/i2c/drivers/drvBase.h b/src/components/i2c/drivers/drvBase.h index 846ea09d3..b36222392 100644 --- a/src/components/i2c/drivers/drvBase.h +++ b/src/components/i2c/drivers/drvBase.h @@ -511,6 +511,15 @@ class drvBase { return false; } + /*! + @brief Gets a sensor's Boolean value. + @param booleanEvent + The Boolean value. + @returns True if the sensor value was obtained successfully, False + otherwise. + */ + virtual bool getEventBoolean(sensors_event_t *booleanEvent) { return false; } + /*! @brief Gets a sensor's Raw value. @param rawEvent @@ -633,6 +642,10 @@ class drvBase { // Maps SensorType to function calls std::map SensorEventHandlers = { + {wippersnapper_sensor_SensorType_SENSOR_TYPE_BOOLEAN, + [this](sensors_event_t *event) -> bool { + return this->getEventBoolean(event); + }}, {wippersnapper_sensor_SensorType_SENSOR_TYPE_UNSPECIFIED, [this](sensors_event_t *event) -> bool { return this->getEventRaw(event); diff --git a/src/components/i2c/drivers/drvBaseAccelLsm6.cpp b/src/components/i2c/drivers/drvBaseAccelLsm6.cpp new file mode 100644 index 000000000..9d87f0ab6 --- /dev/null +++ b/src/components/i2c/drivers/drvBaseAccelLsm6.cpp @@ -0,0 +1,125 @@ +/*! + * @file drvBaseAccelLsm6.cpp + */ + +#include "drvBaseAccelLsm6.h" + +#include + +drvBaseAccelLsm6::drvBaseAccelLsm6(TwoWire *i2c, uint16_t sensorAddress, + uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) {} + +drvBaseAccelLsm6::~drvBaseAccelLsm6() {} + +void drvBaseAccelLsm6::setInternalPollingInterval(uint32_t interval_ms) { + _internalPollPeriod = interval_ms; +} + +bool drvBaseAccelLsm6::readAllEvents() { + Adafruit_LSM6DS *imu = getLSM6Sensor(); + if (!imu) { + return false; + } + + uint32_t now = millis(); + if (_has_last_events && _internalPollPeriod > 0 && + (now - _lastPoll) < _internalPollPeriod) { + // too soon reuse cached data, except first run or interval=0 + return true; + } + + _lastPoll = now; + + if (imu->shake()) { + WS_DEBUG_PRINT("["); + WS_DEBUG_PRINT(_name); + WS_DEBUG_PRINTLN("] Shake detected!"); + _last_shake = true; + } + +// uint16_t step_change = imu->readPedometer(); +// if (step_change > 0) { +// WS_DEBUG_PRINT("["); +// WS_DEBUG_PRINT(_name); +// WS_DEBUG_PRINT("] Steps detected !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n!: "); +// WS_DEBUG_PRINTLN(step_change); +// _last_steps += step_change; +// imu->resetPedometer(); +// } + + bool success = imu->getEvent(&_lastAccelEvent, &_lastGyroEvent, &_lastTempEvent); + _has_last_events = success; + return success; +} + +bool drvBaseAccelLsm6::computeAccelMagnitude(float *magnitude) { + if (!readAllEvents()) { + return false; + } + + *magnitude = sqrtf(_lastAccelEvent.acceleration.x * + _lastAccelEvent.acceleration.x + + _lastAccelEvent.acceleration.y * + _lastAccelEvent.acceleration.y + + _lastAccelEvent.acceleration.z * + _lastAccelEvent.acceleration.z); + return true; +} + +bool drvBaseAccelLsm6::getEventRaw(sensors_event_t *rawEvent) { + if (!readAllEvents()) { + return false; + } + return computeAccelMagnitude(&(rawEvent->data[0])); +} + +bool drvBaseAccelLsm6::getEventAmbientTemp(sensors_event_t *temperatureEvent) { + if (!readAllEvents()) { + return false; + } + + *temperatureEvent = _lastTempEvent; + return true; +} + +// NO Shake/tap/wakeup for now, using pedometer steps instead on INT1 +bool drvBaseAccelLsm6::getEventBoolean(sensors_event_t *booleanEvent) { + if (!readAllEvents()) { + return false; + } + + booleanEvent->data[0] = _last_shake ? 1.0f : 0.0f; + if (_last_shake) { + WS_DEBUG_PRINT("["); + WS_DEBUG_PRINT(_name); + WS_DEBUG_PRINTLN("] *** Threshold event detected ***"); + _last_shake = false; + } + return true; +} + +bool drvBaseAccelLsm6::getEventAccelerometer(sensors_event_t *accelEvent) { + if (!readAllEvents()) { + return false; + } + + *accelEvent = _lastAccelEvent; + return true; +} + +bool drvBaseAccelLsm6::getEventGyroscope(sensors_event_t *gyroEvent) { + if (!readAllEvents()) { + return false; + } + + *gyroEvent = _lastGyroEvent; + return true; +} + +void drvBaseAccelLsm6::ConfigureDefaultSensorTypes() { + _default_sensor_types_count = 1; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_ACCELEROMETER; +} diff --git a/src/components/i2c/drivers/drvBaseAccelLsm6.h b/src/components/i2c/drivers/drvBaseAccelLsm6.h new file mode 100644 index 000000000..2ed730f53 --- /dev/null +++ b/src/components/i2c/drivers/drvBaseAccelLsm6.h @@ -0,0 +1,56 @@ +/*! + * @file drvBaseAccelLsm6.h + * + * Shared helper for Adafruit LSM6-series accelerometer/gyroscope drivers + * that expose shake and pedometer functionality. + */ +#ifndef DRV_BASE_ACCEL_LSM6_H +#define DRV_BASE_ACCEL_LSM6_H + +#include "drvBase.h" + +#include + +class drvBaseAccelLsm6 : public drvBase { +public: + drvBaseAccelLsm6(TwoWire *i2c, uint16_t sensorAddress, + uint32_t mux_channel, const char *driver_name); + virtual ~drvBaseAccelLsm6(); + + bool getEventBoolean(sensors_event_t *booleanEvent) override; + bool getEventRaw(sensors_event_t *rawEvent) override; + bool getEventAccelerometer(sensors_event_t *accelEvent) override; + bool getEventGyroscope(sensors_event_t *gyroEvent) override; + bool getEventAmbientTemp(sensors_event_t *temperatureEvent) override; + + void ConfigureDefaultSensorTypes() override; + + void setInternalPollingInterval(uint32_t interval_ms); + +protected: + virtual Adafruit_LSM6DS *getLSM6Sensor() const = 0; + + uint32_t getLsmSensorID() { + // allow 4 ids per sensor (acc/mag/gyro/temp) + uint32_t sensor_id = 10 * GetAddress(); + if (GetMuxAddress() != 0x0) { + sensor_id += 10000 + GetMuxAddress(); + sensor_id += 1000 + (1000 * GetMuxChannel()); + } + return sensor_id; + } + + bool readAllEvents(); + bool computeAccelMagnitude(float *magnitude); + + bool _has_last_events = false; ///< Flag to track if last events are stored + bool _last_shake = false; ///< Last state of shake / tap detection + sensors_event_t _lastAccelEvent; ///< Last accelerometer event + sensors_event_t _lastGyroEvent; ///< Last gyroscope event + sensors_event_t _lastTempEvent; ///< Last temperature event (raw) +// uint16_t _last_steps = 0; ///< Last step count + uint32_t _lastPoll = 0; ///< Last poll time + uint32_t _internalPollPeriod = 200; ///< Internal Polling interval in ms +}; + +#endif // DRV_BASE_ACCEL_LSM6_H diff --git a/src/components/i2c/drivers/drvIsm330dhcx.cpp b/src/components/i2c/drivers/drvIsm330dhcx.cpp new file mode 100644 index 000000000..eacfc10e2 --- /dev/null +++ b/src/components/i2c/drivers/drvIsm330dhcx.cpp @@ -0,0 +1,56 @@ +/*! + * @file drvIsm330dhcx.cpp + * + * Driver wrapper for the Adafruit ISM330DHCX (LSM6DSOX core) 6-DoF IMU. + */ + +#include "drvIsm330dhcx.h" + +drvIsm330dhcx::drvIsm330dhcx(TwoWire *i2c, uint16_t sensorAddress, + uint32_t mux_channel, const char *driver_name) + : drvBaseAccelLsm6(i2c, sensorAddress, mux_channel, driver_name) {} + +drvIsm330dhcx::~drvIsm330dhcx() { + if (_imu) { + delete _imu; + _imu = nullptr; + } +} + +bool drvIsm330dhcx::begin() { + if (_imu) { + delete _imu; + _imu = nullptr; + } + + _imu = new Adafruit_ISM330DHCX(); + if (!_imu) { + return false; + } + + uint8_t addr = _address == 0 ? LSM6DS_I2CADDR_DEFAULT : (uint8_t)_address; + WS_DEBUG_PRINT("[drvIsm330dhcx] Initialising @ 0x"); + WS_DEBUG_PRINTHEX(addr); + WS_DEBUG_PRINTLN("..."); + + if (!_imu->begin_I2C(addr, _i2c)) { + WS_DEBUG_PRINTLN("[drvIsm330dhcx] Failed to initialise sensor"); + delete _imu; + _imu = nullptr; + return false; + } + + _imu->setAccelRange(LSM6DS_ACCEL_RANGE_4_G); + _imu->setAccelDataRate(LSM6DS_RATE_104_HZ); + _imu->setGyroRange(LSM6DS_GYRO_RANGE_500_DPS); + _imu->setGyroDataRate(LSM6DS_RATE_104_HZ); + // _imu->highPassFilter(true, LSM6DS_HPF_ODR_DIV_100); + _imu->configInt1(false, false, false, false, true); + _imu->configInt2(false, false, false); + // _imu->enablePedometer(true); + _imu->enableWakeup(true); + + WS_DEBUG_PRINTLN("[drvIsm330dhcx] Sensor initialised successfully"); + return true; +} + diff --git a/src/components/i2c/drivers/drvIsm330dhcx.h b/src/components/i2c/drivers/drvIsm330dhcx.h new file mode 100644 index 000000000..67960748f --- /dev/null +++ b/src/components/i2c/drivers/drvIsm330dhcx.h @@ -0,0 +1,30 @@ +/*! + * @file drvIsm330dhcx.h + * + * Driver wrapper for the Adafruit ISM330DHCX (LSM6DSOX core) 6-DoF IMU. + */ +#ifndef DRV_ISM330DHCX_H +#define DRV_ISM330DHCX_H + +#include "Wippersnapper_V2.h" +#include "drvBaseAccelLsm6.h" +#include + +#define ISM330_TAP_THRESHOLD_MSS 15.0f + +class drvIsm330dhcx : public drvBaseAccelLsm6 { +public: + drvIsm330dhcx(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name); + ~drvIsm330dhcx(); + + bool begin() override; + +protected: + Adafruit_LSM6DS *getLSM6Sensor() const override { return _imu; } + +private: + Adafruit_ISM330DHCX *_imu = nullptr; ///< Pointer to the ISM330DHCX sensor +}; + +#endif // DRV_ISM330DHCX_H diff --git a/src/components/i2c/drivers/drvLis2mdl.cpp b/src/components/i2c/drivers/drvLis2mdl.cpp new file mode 100644 index 000000000..5a2b27ea2 --- /dev/null +++ b/src/components/i2c/drivers/drvLis2mdl.cpp @@ -0,0 +1,143 @@ +/*! + * @file drvLis2mdl.cpp + * + * Driver wrapper for the Adafruit LIS2MDL 3-axis magnetometer. + */ + +#include "drvLis2mdl.h" + +#include + +#define LIS2MDL_DEFAULT_ADDR 0x1E + +/******************************************************************************/ +/*! + @brief Destructor for the LIS2MDL driver wrapper. +*/ +/******************************************************************************/ +drvLis2mdl::~drvLis2mdl() { + if (_mag) { + delete _mag; + _mag = nullptr; + } +} + +/******************************************************************************/ +/*! + @brief Initializes the LIS2MDL sensor and begins I2C. + @returns True if initialized successfully, False otherwise. +*/ +/******************************************************************************/ +bool drvLis2mdl::begin() { + WS_DEBUG_PRINTLN("[drvLis2mdl] Initialising sensor"); + + if (_mag) { + delete _mag; + _mag = nullptr; + } + + _mag = new Adafruit_LIS2MDL(); + if (!_mag) { + return false; + } + + const uint8_t addr = + _address == 0 ? LIS2MDL_DEFAULT_ADDR : static_cast(_address); + if (!_mag->begin(addr, _i2c)) { + WS_DEBUG_PRINTLN("[drvLis2mdl] Failed to initialise sensor"); + delete _mag; + _mag = nullptr; + return false; + } + + _mag->setDataRate(LIS2MDL_RATE_50_HZ); + _mag->enableInterrupts(false); + _mag->interruptsActiveHigh(false); + + WS_DEBUG_PRINTLN("[drvLis2mdl] Sensor initialised successfully"); + return true; +} + +/******************************************************************************/ +/*! + @brief Reads the LIS2MDL's magnetometer event. + @param event Pointer to the magnetometer event to populate. + @returns True if the event was obtained successfully. +*/ +/******************************************************************************/ +bool drvLis2mdl::readMagEvent(sensors_event_t *event) { + if (!_mag) { + return false; + } + return _mag->getEvent(event); +} + +/******************************************************************************/ +/*! + @brief Computes the vector magnitude of a magnetometer reading. + @param event Magnetometer event to evaluate. + @param magnitude Reference to store the computed magnitude (micro Tesla). + @returns True if the magnitude was computed successfully. +*/ +/******************************************************************************/ +bool drvLis2mdl::computeMagnitude(const sensors_event_t &event, + float &magnitude) { + magnitude = sqrtf(event.magnetic.x * event.magnetic.x + + event.magnetic.y * event.magnetic.y + + event.magnetic.z * event.magnetic.z); + return true; +} + +/******************************************************************************/ +/*! + @brief Gets the LIS2MDL's raw sensor event (magnitude stored in data[0]). + @param rawEvent Pointer to the sensor event. + @returns True if the sensor event was obtained successfully. +*/ +/******************************************************************************/ +bool drvLis2mdl::getEventRaw(sensors_event_t *rawEvent) { + sensors_event_t magEvent; + if (!readMagEvent(&magEvent)) { + return false; + } + + float magnitude = 0.0f; + computeMagnitude(magEvent, magnitude); + rawEvent->data[0] = magnitude; + return true; +} + +/******************************************************************************/ +/*! + @brief Gets the LIS2MDL's boolean sensor event. + @param booleanEvent Pointer to the sensor event. + @returns True once the placeholder value has been populated. +*/ +/******************************************************************************/ +bool drvLis2mdl::getEventBoolean(sensors_event_t *booleanEvent) { + // Magnetometers do not emit boolean events; reserve the field for future use. + booleanEvent->data[0] = 0.0f; + return true; +} + +/******************************************************************************/ +/*! + @brief Gets the LIS2MDL's magnetometer sensor event (x,y,z in microTesla). + @param magEvent Pointer to the magnetometer sensor event. + @returns True if the sensor event was obtained successfully. +*/ +/******************************************************************************/ +bool drvLis2mdl::getEventMagneticField(sensors_event_t *magEvent) { + return readMagEvent(magEvent); +} + +/******************************************************************************/ +/*! + @brief Registers the driver's default magnetometer sensor type. +*/ +/******************************************************************************/ +void drvLis2mdl::ConfigureDefaultSensorTypes() { + _default_sensor_types_count = 1; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_MAGNETIC_FIELD; +} diff --git a/src/components/i2c/drivers/drvLis2mdl.h b/src/components/i2c/drivers/drvLis2mdl.h new file mode 100644 index 000000000..e8c00f0a4 --- /dev/null +++ b/src/components/i2c/drivers/drvLis2mdl.h @@ -0,0 +1,104 @@ +/*! + * @file drvLis2mdl.h + * + * Driver wrapper for the Adafruit LIS2MDL 3-axis magnetometer. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * MIT license, all text here must be included in any redistribution. + */ +#ifndef DRV_LIS2MDL_H +#define DRV_LIS2MDL_H + +#include "Wippersnapper_V2.h" +#include "drvBase.h" + +#include + +/**************************************************************************/ +/*! + @brief Class that provides a driver interface for a LIS2MDL magnetometer. +*/ +/**************************************************************************/ +class drvLis2mdl : public drvBase { +public: + drvLis2mdl(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) {} + + /**************************************************************************/ + /*! + @brief Destructor for the LIS2MDL driver wrapper. + */ + /**************************************************************************/ + ~drvLis2mdl(); + + /**************************************************************************/ + /*! + @brief Initializes the LIS2MDL sensor and begins I2C. + @returns True if initialized successfully, False otherwise. + */ + /**************************************************************************/ + bool begin() override; + + /**************************************************************************/ + /*! + @brief Gets a raw magnetometer magnitude event (micro Tesla). + @param rawEvent Pointer to the destination sensor event. + @returns True if the event was obtained successfully. + */ + /**************************************************************************/ + bool getEventRaw(sensors_event_t *rawEvent) override; + + /**************************************************************************/ + /*! + @brief Placeholder boolean event implementation for compatibility. + @param booleanEvent Pointer to the destination sensor event. + @returns True once the placeholder event has been populated. + */ + /**************************************************************************/ + bool getEventBoolean(sensors_event_t *booleanEvent) override; + + /**************************************************************************/ + /*! + @brief Retrieves the LIS2MDL's magnetometer vector event. + @param magEvent Pointer to the destination sensor event. + @returns True if the event was obtained successfully. + */ + /**************************************************************************/ + bool getEventMagneticField(sensors_event_t *magEvent) override; + +protected: + /**************************************************************************/ + /*! + @brief Registers the default virtual sensors exposed by the driver. + */ + /**************************************************************************/ + void ConfigureDefaultSensorTypes() override; + +private: + /**************************************************************************/ + /*! + @brief Reads a magnetometer event from the LIS2MDL helper. + @param event Pointer to the destination sensor event. + @returns True if the event was obtained successfully. + */ + /**************************************************************************/ + bool readMagEvent(sensors_event_t *event); + + /**************************************************************************/ + /*! + @brief Computes the vector magnitude of a magnetometer reading. + @param event Magnetometer event to evaluate. + @param magnitude Reference to store the computed magnitude (micro Tesla). + @returns True if the magnitude was computed successfully. + */ + /**************************************************************************/ + bool computeMagnitude(const sensors_event_t &event, float &magnitude); + + Adafruit_LIS2MDL *_mag = nullptr; +}; + +#endif // DRV_LIS2MDL_H diff --git a/src/components/i2c/drivers/drvLis3dh.cpp b/src/components/i2c/drivers/drvLis3dh.cpp new file mode 100644 index 000000000..13c8cdd67 --- /dev/null +++ b/src/components/i2c/drivers/drvLis3dh.cpp @@ -0,0 +1,140 @@ +/*! + * @file drvLis3dh.cpp + * + * Driver wrapper for the Adafruit LIS3DH 3-axis accelerometer. + * + */ + +#include "drvLis3dh.h" + +#include +#include + +/******************************************************************************/ +/*! + @brief Destructor for a LIS3DH sensor. +*/ +/******************************************************************************/ +drvLis3dh::~drvLis3dh() { + if (_lis) { + delete _lis; + _lis = nullptr; + } +} + +/******************************************************************************/ +/*! + @brief Initializes the LIS3DH sensor and begins I2C. + @returns True if initialized successfully, False otherwise. +*/ +/******************************************************************************/ +bool drvLis3dh::begin() { + // allocate LIS3DH instance with the I2C bus + _lis = new Adafruit_LIS3DH(_i2c); + + // Attempt to initialize with provided address + if (!_lis->begin(_address)) { + WS_DEBUG_PRINTLN("LIS3DH failed to initialise!"); + return false; + } + + // Set a reasonable range and data rate (use library enums) + _lis->setRange(LIS3DH_RANGE_2_G); // 2G range + // Note: some Adafruit_LIS3DH variants offer setDataRate; if present this + // keeps defaults. Keep configuration minimal to avoid API mismatches. + + // setup interrupt for click detection (boolean event) + _lis->setClick(1, LIS3DH_CLICKTHRESHHOLD); // 0-2 clicks, threshold 50 + delay(100); // ignore any spurious interrupts right after setup + _lis->readAndClearInterrupt(); + + return true; +} + +/******************************************************************************/ +/*! + @brief Gets the LIS3DH's raw sensor event. + @param rawEvent + Pointer to the sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. +*/ +/******************************************************************************/ +bool drvLis3dh::getEventRaw(sensors_event_t *rawEvent) { + if (!_lis) + return false; + WS_DEBUG_PRINTLN("[drvLis3dh] Getting raw event..."); + // Read an Adafruit_Sensor compatible event from the device + sensors_event_t event; + _lis->getEvent(&event); + + // Calculate magnitude of the acceleration vector (m/s^2) and store in + // event->data[0] to be consistent with other drivers that expose "raw" + float mag = sqrtf(event.acceleration.x * event.acceleration.x + + event.acceleration.y * event.acceleration.y + + event.acceleration.z * event.acceleration.z); + rawEvent->data[0] = mag; + WS_DEBUG_PRINT("[drvLis3dh] Raw magnitude: "); + WS_DEBUG_PRINTLN(mag); + return true; +} + +/******************************************************************************/ +/*! + @brief Gets the LIS3DH's boolean sensor event. + @param booleanEvent + Pointer to the sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. +*/ +/******************************************************************************/ +bool drvLis3dh::getEventBoolean(sensors_event_t *booleanEvent) { + if (!_lis) { + return false; + } + WS_DEBUG_PRINTLN("[drvLis3dh] Checking for click event..."); + uint8_t result = _lis->getClick(); + WS_DEBUG_PRINT(" Click result: "); + WS_DEBUG_PRINTHEX(result); + WS_DEBUG_PRINTLN(""); + // does it & 0x30, then 0x20 is double click, 0x10 is single click + WS_DEBUG_PRINTLN("[drvLis3dh] Click result & 0x30: "); + WS_DEBUG_PRINTHEX(result & 0x30); + WS_DEBUG_PRINTLN(""); + uint8_t interruptReason = _lis->readAndClearInterrupt(); + WS_DEBUG_PRINTLN("[drvLis3dh] Interrupt reason: "); + WS_DEBUG_PRINTHEX(interruptReason); + WS_DEBUG_PRINTLN(""); + + // todo: switch on interrupt type - needs driver library expanding + if (interruptReason == 1 && result == 1) { + WS_DEBUG_PRINTLN("[drvLis3dh] Click event detected!"); + } + booleanEvent->data[0] = result ? 1.0f : 0.0f; + return true; +} + +/******************************************************************************/ +/*! + @brief Gets the LIS3DH's accelerometer sensor event (x,y,z in m/s^2). + @param accelEvent + Pointer to the accelerometer sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. +*/ +/******************************************************************************/ +bool drvLis3dh::getEventAccelerometer(sensors_event_t *accelEvent) { + if (!_lis) { + return false; + } + WS_DEBUG_PRINTLN("[drvLis3dh] Getting accelerometer event..."); + // Fill the provided event with sensor data + _lis->getEvent(accelEvent); + return true; +} + +void drvLis3dh::ConfigureDefaultSensorTypes() { + _default_sensor_types_count = 1; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_ACCELEROMETER; +} \ No newline at end of file diff --git a/src/components/i2c/drivers/drvLis3dh.h b/src/components/i2c/drivers/drvLis3dh.h new file mode 100644 index 000000000..832a6b488 --- /dev/null +++ b/src/components/i2c/drivers/drvLis3dh.h @@ -0,0 +1,107 @@ +/*! + * @file drvLis3dh.h + * + * Driver wrapper for the Adafruit LIS3DH 3-axis accelerometer. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Adafruit Industries. + * + * MIT license, all text here must be included in any redistribution. + * + */ +#ifndef DRV_LIS3DH_H +#define DRV_LIS3DH_H + +#include "Wippersnapper_V2.h" +#include "drvBase.h" +#include + +class Adafruit_LIS3DH; // forward + +// Adjust this number for the sensitivity of the 'click' force +// this strongly depend on the range! for 16G, try 5-10 +// for 8G, try 10-20. for 4G try 20-40. for 2G try 40-80 +#define LIS3DH_CLICKTHRESHHOLD 40 + +/**************************************************************************/ +/*! + @brief Class that provides a driver interface for a LIS3DH accelerometer. +*/ +/**************************************************************************/ +class drvLis3dh : public drvBase { +public: + /*******************************************************************************/ + /*! + @brief Constructor for a LIS3DH sensor. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + @param mux_channel + The I2C multiplexer channel. + @param driver_name + The name of the driver. + */ + /*******************************************************************************/ + drvLis3dh(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) {} + + /*******************************************************************************/ + /*! + @brief Destructor for a LIS3DH sensor. + */ + /*******************************************************************************/ + ~drvLis3dh(); + + /*******************************************************************************/ + /*! + @brief Initializes the LIS3DH sensor and begins I2C. + @returns True if initialized successfully, False otherwise. + */ + /*******************************************************************************/ + bool begin() override; + + /******************************************************************************/ + /*! + @brief Gets the LIS3DH's boolean sensor event. + @param booleanEvent + Pointer to the sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. + */ + /******************************************************************************/ + bool getEventBoolean(sensors_event_t *booleanEvent) override; + + /*******************************************************************************/ + /*! + @brief Gets the LIS3DH's raw sensor event (magnitude stored in + event->data[0]). + @param rawEvent + Pointer to the sensor event to fill. + @returns True if the event was obtained successfully, False otherwise. + */ + /*******************************************************************************/ + bool getEventRaw(sensors_event_t *rawEvent) override; + + /*******************************************************************************/ + /*! + @brief Gets the LIS3DH's accelerometer sensor event (x,y,z in m/s^2). + @param accelEvent + Pointer to the accelerometer sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventAccelerometer(sensors_event_t *accelEvent) override; + + void ConfigureDefaultSensorTypes() override; + +protected: + Adafruit_LIS3DH *_lis = nullptr; ///< Pointer to LIS3DH sensor object +}; + +#endif // DRV_LIS3DH_H \ No newline at end of file diff --git a/src/components/i2c/drivers/drvLis3mdl.cpp b/src/components/i2c/drivers/drvLis3mdl.cpp new file mode 100644 index 000000000..68b911b1b --- /dev/null +++ b/src/components/i2c/drivers/drvLis3mdl.cpp @@ -0,0 +1,139 @@ +/*! + * @file drvLis3mdl.cpp + * + * Driver wrapper for the Adafruit LIS3MDL 3-axis magnetometer. + */ + +#include "drvLis3mdl.h" + +#include + +/******************************************************************************/ +/*! + @brief Destructor for a LIS3MDL sensor. +*/ +/******************************************************************************/ +drvLis3mdl::~drvLis3mdl() { + if (_mag) { + delete _mag; + _mag = nullptr; + } +} + +/******************************************************************************/ +/*! + @brief Initializes the LIS3MDL sensor and begins I2C. + @returns True if initialized successfully, False otherwise. +*/ +/******************************************************************************/ +bool drvLis3mdl::begin() { + WS_DEBUG_PRINTLN("[drvLis3mdl] Initialising sensor"); + _mag = new Adafruit_LIS3MDL(); + if (!_mag) + return false; + + if (!_mag->begin_I2C(_address, _i2c)) { + WS_DEBUG_PRINTLN("[drvLis3mdl] Failed to initialise sensor"); + delete _mag; + _mag = nullptr; + return false; + } + + _mag->setPerformanceMode(LIS3MDL_ULTRAHIGHMODE); + _mag->setOperationMode(LIS3MDL_CONTINUOUSMODE); + _mag->setDataRate(LIS3MDL_DATARATE_80_HZ); + _mag->setRange(LIS3MDL_RANGE_4_GAUSS); + _mag->setIntThreshold(500); + _mag->configInterrupt(true, true, true, true, false, true); + + WS_DEBUG_PRINTLN("[drvLis3mdl] Sensor initialised successfully"); + return true; +} + +/******************************************************************************/ +/*! + @brief Reads the LIS3MDL's magnetometer event. + @param event + Pointer to the magnetometer event to populate. + @returns True if the event was obtained successfully, False otherwise. +*/ +/******************************************************************************/ +bool drvLis3mdl::readMagEvent(sensors_event_t *event) { + if (!_mag) + return false; + return _mag->getEvent(event); +} + +/******************************************************************************/ +/*! + @brief Computes the vector magnitude of a magnetometer reading. + @param event + Magnetometer event to evaluate. + @param magnitude + Reference to store the computed magnitude (micro Tesla). + @returns True if the magnitude was computed successfully. +*/ +/******************************************************************************/ +bool drvLis3mdl::computeMagnitude(const sensors_event_t &event, + float &magnitude) { + magnitude = sqrtf(event.magnetic.x * event.magnetic.x + + event.magnetic.y * event.magnetic.y + + event.magnetic.z * event.magnetic.z); + return true; +} + +/******************************************************************************/ +/*! + @brief Gets the LIS3MDL's raw sensor event (magnitude stored in data[0]). + @param rawEvent + Pointer to the sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. +*/ +/******************************************************************************/ +bool drvLis3mdl::getEventRaw(sensors_event_t *rawEvent) { + sensors_event_t magEvent; + if (!readMagEvent(&magEvent)) { + return false; + } + + float magnitude = 0; + computeMagnitude(magEvent, magnitude); + rawEvent->data[0] = magnitude; + return true; +} + +/******************************************************************************/ +/*! + @brief Gets the LIS3MDL's boolean sensor event. + @param booleanEvent + Pointer to the sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. +*/ +/******************************************************************************/ +bool drvLis3mdl::getEventBoolean(sensors_event_t *booleanEvent) { + // TODO(#offline-imu-compass): Reuse the raw magnitude once compass headings + // are supported. For now, magnetometers do not emit boolean events. + booleanEvent->data[0] = 0.0f; + return true; +} + +/******************************************************************************/ +/*! + @brief Gets the LIS3MDL's magnetometer sensor event (x,y,z in uTesla). + @param magEvent + Pointer to the magnetometer sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. +*/ +/******************************************************************************/ +bool drvLis3mdl::getEventMagneticField(sensors_event_t *magEvent) { + return readMagEvent(magEvent); +} + +void drvLis3mdl::ConfigureDefaultSensorTypes() { + _default_sensor_types_count = 1; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_MAGNETIC_FIELD; +} diff --git a/src/components/i2c/drivers/drvLis3mdl.h b/src/components/i2c/drivers/drvLis3mdl.h new file mode 100644 index 000000000..53399aa37 --- /dev/null +++ b/src/components/i2c/drivers/drvLis3mdl.h @@ -0,0 +1,50 @@ +/*! + * @file drvLis3mdl.h + * + * Driver wrapper for the Adafruit LIS3MDL 3-axis magnetometer. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * MIT license, all text here must be included in any redistribution. + */ +#ifndef DRV_LIS3MDL_H +#define DRV_LIS3MDL_H + +#include "Wippersnapper_V2.h" +#include "drvBase.h" +#include + +/**************************************************************************/ +/*! + @brief Class that provides a driver interface for a LIS3MDL magnetometer. +*/ +/**************************************************************************/ +class drvLis3mdl : public drvBase { +public: + drvLis3mdl(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) {} + + ~drvLis3mdl(); + + bool begin() override; + + bool getEventRaw(sensors_event_t *rawEvent) override; + + bool getEventBoolean(sensors_event_t *booleanEvent) override; + + bool getEventMagneticField(sensors_event_t *magEvent) override; + +protected: + void ConfigureDefaultSensorTypes() override; + +private: + bool readMagEvent(sensors_event_t *event); + bool computeMagnitude(const sensors_event_t &event, float &magnitude); + + Adafruit_LIS3MDL *_mag = nullptr; +}; + +#endif // DRV_LIS3MDL_H diff --git a/src/components/i2c/drivers/drvLsm303agr.cpp b/src/components/i2c/drivers/drvLsm303agr.cpp new file mode 100644 index 000000000..414252f6f --- /dev/null +++ b/src/components/i2c/drivers/drvLsm303agr.cpp @@ -0,0 +1,159 @@ +/*! + * @file drvLsm303agr.cpp + * + * Driver wrapper for the Adafruit LSM303AGR combo sensor. + */ + +#include "drvLsm303agr.h" + +#include + +#define LSM303AGR_ACCEL_DEFAULT_ADDR 0x19 ///< LSM303AGR default address +#define LSM303AGR_MAG_DEFAULT_ADDR 0x1E ///< LIS2MDL default address + +/******************************************************************************/ +/*! + @brief Destructor for the LSM303AGR driver wrapper. +*/ +/******************************************************************************/ +drvLsm303agr::~drvLsm303agr() { teardown(); } + +/******************************************************************************/ +/*! + @brief Releases any allocated accelerometer or magnetometer instances. +*/ +/******************************************************************************/ +void drvLsm303agr::teardown() { + if (_accel) { + delete _accel; + _accel = nullptr; + } + if (_mag) { + delete _mag; + _mag = nullptr; + } +} + +/******************************************************************************/ +/*! + @brief Initializes the LSM303AGR accelerometer and LIS2MDL magnetometer. + @returns True if initialization succeeded, False otherwise. +*/ +/******************************************************************************/ +bool drvLsm303agr::begin() { + teardown(); + + _accel = new Adafruit_LSM303_Accel_Unified(); + _mag = new Adafruit_LIS2MDL(); + if (!_accel || !_mag) { + teardown(); + return false; + } + + // TODO: if _address isn't default (or alt), shift mag by same offset. + // to support adress translators. Alternatively compound components. + + WS_DEBUG_PRINT("[drvLsm303agr] Initialising accel @ 0x"); + WS_DEBUG_PRINTHEX(LSM303AGR_ACCEL_DEFAULT_ADDR); + WS_DEBUG_PRINTLN("..."); + if (!_accel->begin(LSM303AGR_ACCEL_DEFAULT_ADDR, _i2c)) { + WS_DEBUG_PRINTLN("[drvLsm303agr] Failed to initialise accelerometer"); + teardown(); + return false; + } + _accel->setRange(LSM303_RANGE_2G); + _accel->setMode(LSM303_MODE_HIGH_RESOLUTION); + + WS_DEBUG_PRINT("[drvLsm303agr] Initialising magnetometer @ 0x"); + WS_DEBUG_PRINTHEX(LSM303AGR_MAG_DEFAULT_ADDR); + WS_DEBUG_PRINTLN("..."); + if (!_mag->begin(LSM303AGR_MAG_DEFAULT_ADDR, _i2c)) { + WS_DEBUG_PRINTLN("[drvLsm303agr] Failed to initialise LIS2MDL"); + teardown(); + return false; + } + _mag->setDataRate(LIS2MDL_RATE_50_HZ); + _mag->enableInterrupts(false); + _mag->interruptsActiveHigh(false); + + WS_DEBUG_PRINTLN("[drvLsm303agr] Sensor initialised successfully"); + return true; +} + +/******************************************************************************/ +/*! + @brief Computes the magnitude of the accelerometer vector. + @param magnitude Reference to store the computed m/s^2 value. + @returns True if the accelerometer event was retrieved successfully. +*/ +/******************************************************************************/ +bool drvLsm303agr::computeAccelMagnitude(float &magnitude) { + if (!_accel) { + return false; + } + sensors_event_t accel_event; + if (!_accel->getEvent(&accel_event)) { + return false; + } + magnitude = sqrtf(accel_event.acceleration.x * accel_event.acceleration.x + + accel_event.acceleration.y * accel_event.acceleration.y + + accel_event.acceleration.z * accel_event.acceleration.z); + return true; +} + +/******************************************************************************/ +/*! + @brief Fills the raw event with the accelerometer magnitude in data[0]. + @param rawEvent Pointer to the destination sensor event. + @returns True if the magnitude was computed successfully. +*/ +/******************************************************************************/ +bool drvLsm303agr::getEventRaw(sensors_event_t *rawEvent) { + float magnitude = 0.0f; + if (!computeAccelMagnitude(magnitude)) { + return false; + } + rawEvent->data[0] = magnitude; + return true; +} + +/******************************************************************************/ +/*! + @brief Retrieves the 3-axis accelerometer event. + @param accelEvent Pointer to the destination sensor event. + @returns True if the event was populated successfully. +*/ +/******************************************************************************/ +bool drvLsm303agr::getEventAccelerometer(sensors_event_t *accelEvent) { + if (!_accel) { + return false; + } + return _accel->getEvent(accelEvent); +} + +/******************************************************************************/ +/*! + @brief Retrieves the 3-axis magnetic field event. + @param magEvent Pointer to the destination sensor event. + @returns True if the event was populated successfully. +*/ +/******************************************************************************/ +bool drvLsm303agr::getEventMagneticField(sensors_event_t *magEvent) { + if (!_mag) { + return false; + } + return _mag->getEvent(magEvent); +} + +/******************************************************************************/ +/*! + @brief Registers the driver's default accelerometer and magnetometer types. +*/ +/******************************************************************************/ +void drvLsm303agr::ConfigureDefaultSensorTypes() { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_ACCELEROMETER; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_MAGNETIC_FIELD; +} diff --git a/src/components/i2c/drivers/drvLsm303agr.h b/src/components/i2c/drivers/drvLsm303agr.h new file mode 100644 index 000000000..7a704700c --- /dev/null +++ b/src/components/i2c/drivers/drvLsm303agr.h @@ -0,0 +1,102 @@ +/*! + * @file drvLsm303agr.h + * + * Driver wrapper for the Adafruit LSM303AGR combo sensor (accel + mag). + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * MIT license, all text here must be included in any redistribution. + */ +#ifndef DRV_LSM303AGR_H +#define DRV_LSM303AGR_H + +#include "Wippersnapper_V2.h" +#include "drvBase.h" + +#include +#include + +/**************************************************************************/ +/*! + @brief Driver interface for the Adafruit LSM303AGR combo sensor. +*/ +/**************************************************************************/ +class drvLsm303agr : public drvBase { +public: + drvLsm303agr(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) {} + + /**************************************************************************/ + /*! + @brief Destructor for the LSM303AGR driver. + */ + /**************************************************************************/ + ~drvLsm303agr(); + + /**************************************************************************/ + /*! + @brief Initializes the accelerometer and magnetometer peripherals. + @returns True if initialization succeeded, False otherwise. + */ + /**************************************************************************/ + bool begin() override; + + /**************************************************************************/ + /*! + @brief Populates a raw magnitude reading into a sensor event. + @param rawEvent Pointer to the destination sensor event. + @returns True if the event was populated successfully. + */ + /**************************************************************************/ + bool getEventRaw(sensors_event_t *rawEvent) override; + + /**************************************************************************/ + /*! + @brief Retrieves the accelerometer vector event. + @param accelEvent Pointer to the destination sensor event. + @returns True if the event was populated successfully. + */ + /**************************************************************************/ + bool getEventAccelerometer(sensors_event_t *accelEvent) override; + + /**************************************************************************/ + /*! + @brief Retrieves the magnetic field vector event. + @param magEvent Pointer to the destination sensor event. + @returns True if the event was populated successfully. + */ + /**************************************************************************/ + bool getEventMagneticField(sensors_event_t *magEvent) override; + +protected: + /**************************************************************************/ + /*! + @brief Registers the default set of virtual sensor types. + */ + /**************************************************************************/ + void ConfigureDefaultSensorTypes() override; + +private: + /**************************************************************************/ + /*! + @brief Releases any allocated sensor instances. + */ + /**************************************************************************/ + void teardown(); + /**************************************************************************/ + /*! + @brief Computes the linear acceleration magnitude in m/s^2. + @param magnitude Reference to store the computed value. + @returns True if the magnitude was computed successfully. + */ + /**************************************************************************/ + bool computeAccelMagnitude(float &magnitude); + + Adafruit_LSM303_Accel_Unified *_accel = nullptr; + Adafruit_LIS2MDL *_mag = nullptr; +}; + +#endif // DRV_LSM303AGR_H diff --git a/src/components/i2c/drivers/drvLsm303dlh.cpp b/src/components/i2c/drivers/drvLsm303dlh.cpp new file mode 100644 index 000000000..2e208d0df --- /dev/null +++ b/src/components/i2c/drivers/drvLsm303dlh.cpp @@ -0,0 +1,166 @@ +/*! + * @file drvLsm303dlh.cpp + * + * Driver wrapper for the legacy Adafruit LSM303DLH combo sensor. + */ + +#include "drvLsm303dlh.h" + +#include + +#define LSM303DLH_ACCEL_DEFAULT_ADDR LSM303_ADDRESS_ACCEL +#define LSM303DLH_MAG_DEFAULT_ADDR 0x1E + +/******************************************************************************/ +/*! + @brief Destructor for the legacy LSM303DLH driver wrapper. +*/ +/******************************************************************************/ +drvLsm303dlh::~drvLsm303dlh() { teardown(); } + +/******************************************************************************/ +/*! + @brief Releases any allocated accelerometer or magnetometer instances. +*/ +/******************************************************************************/ +void drvLsm303dlh::teardown() { + if (_accel) { + delete _accel; + _accel = nullptr; + } + if (_mag) { + delete _mag; + _mag = nullptr; + } +} + +/******************************************************************************/ +/*! + @brief Initializes the LSM303DLH accelerometer and magnetometer helpers. + @returns True if initialization succeeded, False otherwise. +*/ +/******************************************************************************/ +bool drvLsm303dlh::begin() { + WS_DEBUG_PRINTLN("[drvLsm303dlh] Initializing LSM303DLH driver..."); + WS_PRINTER.flush(); + + WS_DEBUG_PRINTLN("[drvLsm303dlh] Tearing down any existing sensor instances..."); + WS_PRINTER.flush(); + teardown(); + + WS_DEBUG_PRINTLN("[drvLsm303dlh] Creating new sensor instances..."); + WS_PRINTER.flush(); + _accel = new Adafruit_LSM303_Accel_Unified(); + WS_DEBUG_PRINTLN("[drvLsm303dlh] Created accelerometer instance, DLH mag next"); + WS_PRINTER.flush(); + _mag = new Adafruit_LSM303DLH_Mag_Unified(); + WS_DEBUG_PRINTLN("[drvLsm303dlh] Created magnetometer instance"); + WS_PRINTER.flush(); + if (!_accel || !_mag) { + teardown(); + return false; + } + WS_DEBUG_PRINT("[drvLsm303dlh] Initialising accelerometer @ 0x"); + WS_DEBUG_PRINTHEX(LSM303DLH_ACCEL_DEFAULT_ADDR); + WS_DEBUG_PRINTLN("..."); + if (!_accel->begin(LSM303DLH_ACCEL_DEFAULT_ADDR, _i2c)) { + WS_DEBUG_PRINTLN("[drvLsm303dlh] Failed to initialise accelerometer"); + teardown(); + return false; + } + _accel->setRange(LSM303_RANGE_2G); + _accel->setMode(LSM303_MODE_HIGH_RESOLUTION); + + WS_DEBUG_PRINT("[drvLsm303dlh] Initialising magnetometer @ 0x"); + WS_DEBUG_PRINTHEX(LSM303DLH_MAG_DEFAULT_ADDR); + WS_DEBUG_PRINTLN("..."); + if (!_mag->begin(LSM303DLH_MAG_DEFAULT_ADDR, _i2c)) { + WS_DEBUG_PRINTLN("[drvLsm303dlh] Failed to initialise LSM303DLH mag"); + teardown(); + return false; + } + _mag->enableAutoRange(true); + _mag->setMagGain(LSM303_MAGGAIN_1_9); + _mag->setMagRate(LSM303_MAGRATE_15); + + WS_DEBUG_PRINTLN("[drvLsm303dlh] Sensor initialised successfully"); + return true; +} + +/******************************************************************************/ +/*! + @brief Computes the magnitude of the accelerometer vector. + @param magnitude Reference to store the computed m/s^2 value. + @returns True if the accelerometer event was retrieved successfully. +*/ +/******************************************************************************/ +bool drvLsm303dlh::computeAccelMagnitude(float &magnitude) { + if (!_accel) { + return false; + } + sensors_event_t accel_event; + if (!_accel->getEvent(&accel_event)) { + return false; + } + magnitude = sqrtf(accel_event.acceleration.x * accel_event.acceleration.x + + accel_event.acceleration.y * accel_event.acceleration.y + + accel_event.acceleration.z * accel_event.acceleration.z); + return true; +} + +/******************************************************************************/ +/*! + @brief Fills the raw event with the accelerometer magnitude in data[0]. + @param rawEvent Pointer to the destination sensor event. + @returns True if the magnitude was computed successfully. +*/ +/******************************************************************************/ +bool drvLsm303dlh::getEventRaw(sensors_event_t *rawEvent) { + float magnitude = 0.0f; + if (!computeAccelMagnitude(magnitude)) { + return false; + } + rawEvent->data[0] = magnitude; + return true; +} + +/******************************************************************************/ +/*! + @brief Retrieves the 3-axis accelerometer event. + @param accelEvent Pointer to the destination sensor event. + @returns True if the event was populated successfully. +*/ +/******************************************************************************/ +bool drvLsm303dlh::getEventAccelerometer(sensors_event_t *accelEvent) { + if (!_accel) { + return false; + } + return _accel->getEvent(accelEvent); +} + +/******************************************************************************/ +/*! + @brief Retrieves the 3-axis magnetic field event. + @param magEvent Pointer to the destination sensor event. + @returns True if the event was populated successfully. +*/ +/******************************************************************************/ +bool drvLsm303dlh::getEventMagneticField(sensors_event_t *magEvent) { + if (!_mag) { + return false; + } + return _mag->getEvent(magEvent); +} + +/******************************************************************************/ +/*! + @brief Registers the driver's default accelerometer and magnetometer types. +*/ +/******************************************************************************/ +void drvLsm303dlh::ConfigureDefaultSensorTypes() { + _default_sensor_types_count = 2; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_ACCELEROMETER; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_MAGNETIC_FIELD; +} diff --git a/src/components/i2c/drivers/drvLsm303dlh.h b/src/components/i2c/drivers/drvLsm303dlh.h new file mode 100644 index 000000000..17f3b65ac --- /dev/null +++ b/src/components/i2c/drivers/drvLsm303dlh.h @@ -0,0 +1,102 @@ +/*! + * @file drvLsm303dlh.h + * + * Driver wrapper for the classic Adafruit LSM303DLH combo sensor. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * MIT license, all text here must be included in any redistribution. + */ +#ifndef DRV_LSM303DLH_H +#define DRV_LSM303DLH_H + +#include "Wippersnapper_V2.h" +#include "drvBase.h" + +#include +#include + +/**************************************************************************/ +/*! + @brief Driver interface for the legacy Adafruit LSM303DLH combo sensor. +*/ +/**************************************************************************/ +class drvLsm303dlh : public drvBase { +public: + drvLsm303dlh(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) {} + + /**************************************************************************/ + /*! + @brief Destructor for the LSM303DLH driver. + */ + /**************************************************************************/ + ~drvLsm303dlh(); + + /**************************************************************************/ + /*! + @brief Initializes the accelerometer and magnetometer peripherals. + @returns True if initialization succeeded, False otherwise. + */ + /**************************************************************************/ + bool begin() override; + + /**************************************************************************/ + /*! + @brief Populates a raw magnitude reading into a sensor event. + @param rawEvent Pointer to the destination sensor event. + @returns True if the event was populated successfully. + */ + /**************************************************************************/ + bool getEventRaw(sensors_event_t *rawEvent) override; + + /**************************************************************************/ + /*! + @brief Retrieves the accelerometer vector event. + @param accelEvent Pointer to the destination sensor event. + @returns True if the event was populated successfully. + */ + /**************************************************************************/ + bool getEventAccelerometer(sensors_event_t *accelEvent) override; + + /**************************************************************************/ + /*! + @brief Retrieves the magnetic field vector event. + @param magEvent Pointer to the destination sensor event. + @returns True if the event was populated successfully. + */ + /**************************************************************************/ + bool getEventMagneticField(sensors_event_t *magEvent) override; + +protected: + /**************************************************************************/ + /*! + @brief Registers the default set of virtual sensor types. + */ + /**************************************************************************/ + void ConfigureDefaultSensorTypes() override; + +private: + /**************************************************************************/ + /*! + @brief Releases any allocated sensor instances. + */ + /**************************************************************************/ + void teardown(); + /**************************************************************************/ + /*! + @brief Computes the linear acceleration magnitude in m/s^2. + @param magnitude Reference to store the computed value. + @returns True if the magnitude was computed successfully. + */ + /**************************************************************************/ + bool computeAccelMagnitude(float &magnitude); + + Adafruit_LSM303_Accel_Unified *_accel = nullptr; + Adafruit_LSM303DLH_Mag_Unified *_mag = nullptr; +}; + +#endif // DRV_LSM303DLH_H diff --git a/src/components/i2c/drivers/drvLsm6ds3.cpp b/src/components/i2c/drivers/drvLsm6ds3.cpp new file mode 100644 index 000000000..647ca337e --- /dev/null +++ b/src/components/i2c/drivers/drvLsm6ds3.cpp @@ -0,0 +1,55 @@ +/*! + * @file drvLsm6ds3.cpp + * + * Driver wrapper for the Adafruit LSM6DS3 6-DoF IMU. + */ + +#include "drvLsm6ds3.h" + +/******************************************************************************/ +/*! @brief Destructor */ +/******************************************************************************/ +drvLsm6ds3::~drvLsm6ds3() { + if (_imu) { + delete _imu; + _imu = nullptr; + } +} + +/******************************************************************************/ +bool drvLsm6ds3::begin() { + if (_imu) { + delete _imu; + _imu = nullptr; + } + + _imu = new Adafruit_LSM6DS3(); + if (!_imu) { + return false; + } + + uint8_t addr = _address == 0 ? LSM6DS_I2CADDR_DEFAULT : (uint8_t)_address; + WS_DEBUG_PRINT("[drvLsm6ds3] Initialising @ 0x"); + WS_DEBUG_PRINTHEX(addr); + WS_DEBUG_PRINTLN("..."); + + if (!_imu->begin_I2C(addr, _i2c)) { + WS_DEBUG_PRINTLN("[drvLsm6ds3] Failed to initialise sensor"); + delete _imu; + _imu = nullptr; + return false; + } + + _imu->setAccelRange(LSM6DS_ACCEL_RANGE_4_G); + _imu->setAccelDataRate(LSM6DS_RATE_104_HZ); + _imu->setGyroRange(LSM6DS_GYRO_RANGE_500_DPS); + _imu->setGyroDataRate(LSM6DS_RATE_104_HZ); + _imu->configInt1(false, false, false, false, true); + _imu->configInt2(false, false, false); + // _imu->enablePedometer(true); + _imu->enableWakeup(true); + + WS_DEBUG_PRINTLN("[drvLsm6ds3] Sensor initialised successfully"); + return true; +} + diff --git a/src/components/i2c/drivers/drvLsm6ds3.h b/src/components/i2c/drivers/drvLsm6ds3.h new file mode 100644 index 000000000..4f7a5d1ef --- /dev/null +++ b/src/components/i2c/drivers/drvLsm6ds3.h @@ -0,0 +1,31 @@ +/*! + * @file drvLsm6ds3.h + * + * Driver wrapper for the Adafruit LSM6DS3 6-DoF IMU. + */ +#ifndef DRV_LSM6DS3_H +#define DRV_LSM6DS3_H + +#include "Wippersnapper_V2.h" +#include "drvBaseAccelLsm6.h" + +#include + +class drvLsm6ds3 : public drvBaseAccelLsm6 { +public: + drvLsm6ds3(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBaseAccelLsm6(i2c, sensorAddress, mux_channel, driver_name) {} + + ~drvLsm6ds3(); + + bool begin() override; + +protected: + Adafruit_LSM6DS *getLSM6Sensor() const override { return _imu; } + +private: + Adafruit_LSM6DS3 *_imu = nullptr; +}; + +#endif // DRV_LSM6DS3_H diff --git a/src/components/i2c/drivers/drvLsm6dso32.cpp b/src/components/i2c/drivers/drvLsm6dso32.cpp new file mode 100644 index 000000000..a6bc7a110 --- /dev/null +++ b/src/components/i2c/drivers/drvLsm6dso32.cpp @@ -0,0 +1,54 @@ +/*! + * @file drvLsm6dso32.cpp + * + * Driver wrapper for the Adafruit LSM6DSO32 6-DoF IMU. + */ + +#include "drvLsm6dso32.h" + +/******************************************************************************/ +drvLsm6dso32::~drvLsm6dso32() { + if (_imu) { + delete _imu; + _imu = nullptr; + } +} + +/******************************************************************************/ +bool drvLsm6dso32::begin() { + if (_imu) { + delete _imu; + _imu = nullptr; + } + + _imu = new Adafruit_LSM6DSO32(); + if (!_imu) { + return false; + } + + uint8_t addr = _address == 0 ? LSM6DS_I2CADDR_DEFAULT : (uint8_t)_address; + WS_DEBUG_PRINT("[drvLsm6dso32] Initialising @ 0x"); + WS_DEBUG_PRINTHEX(addr); + WS_DEBUG_PRINTLN("..."); + + if (!_imu->begin_I2C(addr, _i2c)) { // consider 3rd argument of sensor id, ensure we can run two of these. Could pass mux(+255+muxADDR) add 1000 for bus 1 vs 0 and add sensor addr + WS_DEBUG_PRINTLN("[drvLsm6dso32] Failed to initialise sensor"); + delete _imu; + _imu = nullptr; + return false; + } + + _imu->setAccelRange(LSM6DSO32_ACCEL_RANGE_8_G); + _imu->setGyroRange(LSM6DS_GYRO_RANGE_250_DPS); + _imu->setAccelDataRate(LSM6DS_RATE_416_HZ); + _imu->setGyroDataRate(LSM6DS_RATE_416_HZ); + // _imu->highPassFilter(true, LSM6DS_HPF_ODR_DIV_100); + _imu->configInt1(false, false, false, false, true); + // _imu->configInt2(false, false, false); + _imu->enableWakeup(true); + // _imu->enablePedometer(true); + + WS_DEBUG_PRINTLN("[drvLsm6dso32] Sensor initialised successfully"); + return true; +} + diff --git a/src/components/i2c/drivers/drvLsm6dso32.h b/src/components/i2c/drivers/drvLsm6dso32.h new file mode 100644 index 000000000..be5f257e3 --- /dev/null +++ b/src/components/i2c/drivers/drvLsm6dso32.h @@ -0,0 +1,31 @@ +/*! + * @file drvLsm6dso32.h + * + * Driver wrapper for the Adafruit LSM6DSO32 6-DoF IMU. + */ +#ifndef DRV_LSM6DSO32_H +#define DRV_LSM6DSO32_H + +#include "Wippersnapper_V2.h" +#include "drvBaseAccelLsm6.h" + +#include + +class drvLsm6dso32 : public drvBaseAccelLsm6 { +public: + drvLsm6dso32(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBaseAccelLsm6(i2c, sensorAddress, mux_channel, driver_name) {} + + ~drvLsm6dso32(); + + bool begin() override; + +protected: + Adafruit_LSM6DS *getLSM6Sensor() const override { return _imu; } + +private: + Adafruit_LSM6DSO32 *_imu = nullptr; +}; + +#endif // DRV_LSM6DSO32_H diff --git a/src/components/i2c/drivers/drvLsm9ds1.cpp b/src/components/i2c/drivers/drvLsm9ds1.cpp new file mode 100644 index 000000000..7dbde1430 --- /dev/null +++ b/src/components/i2c/drivers/drvLsm9ds1.cpp @@ -0,0 +1,165 @@ +/*! + * @file drvLsm9ds1.cpp + * + * Driver wrapper for the Adafruit LSM9DS1 9-DOF IMU. + * + */ + +#include "drvLsm9ds1.h" + +#include +#include + +/******************************************************************************/ +/*! + @brief Destructor for a LSM9DS1 sensor. +*/ +/******************************************************************************/ +drvLsm9ds1::~drvLsm9ds1() { + if (_lsm) { + delete _lsm; + _lsm = nullptr; + } +} + +/******************************************************************************/ +/*! + @brief Initializes the LSM9DS1 sensor and begins I2C. + @returns True if initialized successfully, False otherwise. +*/ +/******************************************************************************/ +bool drvLsm9ds1::begin() { + _lsm = new Adafruit_LSM9DS1(_i2c); + // Consumes I2C Addresses 0x1E and 0x6B + if (!_lsm->begin()) { + WS_DEBUG_PRINTLN("LSM9DS1 failed to initialise!"); + return false; + } + + // Mirror the configuration used by the reference example + _lsm->setupAccel(_lsm->LSM9DS1_ACCELRANGE_4G, + _lsm->LSM9DS1_ACCELDATARATE_119HZ); + _lsm->setupMag(_lsm->LSM9DS1_MAGGAIN_4GAUSS); + _lsm->setupGyro(_lsm->LSM9DS1_GYROSCALE_245DPS); + + return true; +} + +bool drvLsm9ds1::readAllEvents(sensors_event_t *accel, sensors_event_t *mag, + sensors_event_t *gyro, sensors_event_t *temp) { + if (!_lsm) { + return false; + } + + return _lsm->getEvent(accel, mag, gyro, temp); +} + +/******************************************************************************/ +/*! + @brief Gets the LSM9DS1's raw sensor event. + @param rawEvent + Pointer to the sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. +*/ +/******************************************************************************/ +bool drvLsm9ds1::getEventRaw(sensors_event_t *rawEvent) { + // TODO: Not yet, but eventually migrate to providing the temperatre data here + WS_DEBUG_PRINTLN("[drvLsm9ds1] Getting raw event..."); + sensors_event_t accel, mag, gyro, temp; + if (!readAllEvents(&accel, &mag, &gyro, &temp)) { + return false; + } + + float mag_accel = sqrtf(accel.acceleration.x * accel.acceleration.x + + accel.acceleration.y * accel.acceleration.y + + accel.acceleration.z * accel.acceleration.z); + rawEvent->data[0] = mag_accel; + WS_DEBUG_PRINT("[drvLsm9ds1] Raw magnitude: "); + WS_DEBUG_PRINTLN(mag_accel); + return true; +} + +/******************************************************************************/ +/*! + @brief Gets the LSM9DS1's accelerometer sensor event (x,y,z in m/s^2). + @param accelEvent + Pointer to the accelerometer sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. +*/ +/******************************************************************************/ +bool drvLsm9ds1::getEventAccelerometer(sensors_event_t *accelEvent) { + WS_DEBUG_PRINTLN("[drvLsm9ds1] Getting accelerometer event..."); + sensors_event_t mag, gyro, temp; + if (!readAllEvents(accelEvent, &mag, &gyro, &temp)) { + return false; + } + return true; +} + +/******************************************************************************/ +/*! + @brief Gets the LSM9DS1's temperature sensor event (not necessarily *C). + @param tempEvent + Pointer to the temperature sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. +*/ +/******************************************************************************/ +bool drvLsm9ds1::getEventAmbientTemp(sensors_event_t *tempEvent) { + WS_DEBUG_PRINTLN("[drvLsm9ds1] Getting temperature event..."); + sensors_event_t accel, mag, gyro; + if (!readAllEvents(&accel, &mag, &gyro, tempEvent)) { + return false; + } + return true; +} + +/******************************************************************************/ +/*! + @brief Gets the LSM9DS1's gyroscope sensor event (x,y,z in rad/s). + @param gyroEvent + Pointer to the gyroscope sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. +*/ +/******************************************************************************/ +bool drvLsm9ds1::getEventGyroscope(sensors_event_t *gyroEvent) { + WS_DEBUG_PRINTLN("[drvLsm9ds1] Getting gyroscope event..."); + sensors_event_t accel, mag, temp; + if (!readAllEvents(&accel, &mag, gyroEvent, &temp)) { + return false; + } + return true; +} + +/******************************************************************************/ +/*! + @brief Gets the LSM9DS1's magnetometer sensor event (x,y,z in uT). + @param magEvent + Pointer to the magnetometer sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. +*/ +/******************************************************************************/ +bool drvLsm9ds1::getEventMagneticField(sensors_event_t *magEvent) { + WS_DEBUG_PRINTLN("[drvLsm9ds1] Getting magnetometer event..."); + sensors_event_t accel, gyro, temp; + if (!readAllEvents(&accel, magEvent, &gyro, &temp)) { + return false; + } + return true; +} + +void drvLsm9ds1::ConfigureDefaultSensorTypes() { + _default_sensor_types_count = 4; + _default_sensor_types[0] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_ACCELEROMETER; + _default_sensor_types[1] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_MAGNETIC_FIELD; + _default_sensor_types[2] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_GYROSCOPE; + _default_sensor_types[3] = + wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE; +} diff --git a/src/components/i2c/drivers/drvLsm9ds1.h b/src/components/i2c/drivers/drvLsm9ds1.h new file mode 100644 index 000000000..eb73bafe2 --- /dev/null +++ b/src/components/i2c/drivers/drvLsm9ds1.h @@ -0,0 +1,128 @@ +/*! + * @file drvLsm9ds1.h + * + * Driver wrapper for the Adafruit LSM9DS1 9-DOF IMU. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Adafruit Industries. + * + * MIT license, all text here must be included in any redistribution. + * + */ +#ifndef DRV_LSM9DS1_H +#define DRV_LSM9DS1_H + +#include "Wippersnapper_V2.h" +#include "drvBase.h" +#include + +class Adafruit_LSM9DS1; // forward + +/**************************************************************************/ +/*! + @brief Class that provides a driver interface for a LSM9DS1 IMU. +*/ +/**************************************************************************/ +class drvLsm9ds1 : public drvBase { +public: + /*******************************************************************************/ + /*! + @brief Constructor for a LSM9DS1 sensor. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + @param mux_channel + The I2C multiplexer channel. + @param driver_name + The name of the driver. + */ + /*******************************************************************************/ + drvLsm9ds1(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, sensorAddress, mux_channel, driver_name) {} + + /*******************************************************************************/ + /*! + @brief Destructor for a LSM9DS1 sensor. + */ + /*******************************************************************************/ + ~drvLsm9ds1(); + + /*******************************************************************************/ + /*! + @brief Initializes the LSM9DS1 sensor and begins I2C. + @returns True if initialized successfully, False otherwise. + */ + /*******************************************************************************/ + bool begin() override; + + /*******************************************************************************/ + /*! + @brief Gets the LSM9DS1's raw sensor event (magnitude stored in + event->data[0]). + @param rawEvent + Pointer to the sensor event to fill. + @returns True if the event was obtained successfully, False otherwise. + */ + /*******************************************************************************/ + bool getEventRaw(sensors_event_t *rawEvent) override; + + /*******************************************************************************/ + /*! + @brief Gets the LSM9DS1's accelerometer sensor event (x,y,z in m/s^2). + @param accelEvent + Pointer to the accelerometer sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventAccelerometer(sensors_event_t *accelEvent) override; + + /*******************************************************************************/ + /*! + @brief Gets the LSM9DS1's temperature sensor event (not necessarily *C). + @param tempEvent + Pointer to the temperature sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventAmbientTemp(sensors_event_t *tempEvent) override; + + /*******************************************************************************/ + /*! + @brief Gets the LSM9DS1's gyroscope sensor event (x,y,z in rad/s). + @param gyroEvent + Pointer to the gyroscope sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventGyroscope(sensors_event_t *gyroEvent) override; + + /*******************************************************************************/ + /*! + @brief Gets the LSM9DS1's magnetometer sensor event (x,y,z in uT). + @param magEvent + Pointer to the magnetometer sensor event. + @returns True if the sensor event was obtained successfully, False + otherwise. + */ + /*******************************************************************************/ + bool getEventMagneticField(sensors_event_t *magEvent) override; + + void ConfigureDefaultSensorTypes() override; + +protected: + Adafruit_LSM9DS1 *_lsm = nullptr; ///< Pointer to LSM9DS1 sensor object + + bool readAllEvents(sensors_event_t *accel, sensors_event_t *mag, + sensors_event_t *gyro, sensors_event_t *temp); + +}; + +#endif // DRV_LSM9DS1_H diff --git a/src/components/i2c/model.cpp b/src/components/i2c/model.cpp index 3003521be..e8cbdd303 100644 --- a/src/components/i2c/model.cpp +++ b/src/components/i2c/model.cpp @@ -210,6 +210,20 @@ GetValueFromSensorsEventOrientation(wippersnapper_sensor_SensorType sensor_type, return value; } +/*! + @brief Returns the boolean event value mapped to a sensor + event. + @param sensor_type + The SensorType. + @param event + The sensors_event_t event. + @returns The value of the SensorType as a boolean. +*/ +bool GetValueFromSensorsEventBoolean( + wippersnapper_sensor_SensorType sensor_type, sensors_event_t *event) { + return event->data[0] > 0.0f; +} + /*! @brief Decodes a I2cDeviceRemove message from an input stream. @param stream @@ -456,6 +470,9 @@ bool I2cModel::AddI2cDeviceSensorEvent( _msg_i2c_device_event .i2c_device_events[_msg_i2c_device_event.i2c_device_events_count] .value.vector_value.z = value_vect.z; + _msg_i2c_device_event + .i2c_device_events[_msg_i2c_device_event.i2c_device_events_count] + .which_value = wippersnapper_sensor_SensorEvent_vector_value_tag; } else if (sensor_type == wippersnapper_sensor_SensorType_SENSOR_TYPE_ORIENTATION || sensor_type == @@ -471,12 +488,27 @@ bool I2cModel::AddI2cDeviceSensorEvent( _msg_i2c_device_event .i2c_device_events[_msg_i2c_device_event.i2c_device_events_count] .value.orientation_value.pitch = value_vect.pitch; + _msg_i2c_device_event + .i2c_device_events[_msg_i2c_device_event.i2c_device_events_count] + .which_value = wippersnapper_sensor_SensorEvent_orientation_value_tag; // TODO: Add color RGB(A) vector support + } else if (sensor_type == + wippersnapper_sensor_SensorType_SENSOR_TYPE_BOOLEAN) { + bool value = GetValueFromSensorsEventBoolean(sensor_type, &event); + _msg_i2c_device_event + .i2c_device_events[_msg_i2c_device_event.i2c_device_events_count] + .value.bool_value = value; + _msg_i2c_device_event + .i2c_device_events[_msg_i2c_device_event.i2c_device_events_count] + .which_value = wippersnapper_sensor_SensorEvent_bool_value_tag; } else { float value = GetValueFromSensorsEvent(sensor_type, &event); _msg_i2c_device_event .i2c_device_events[_msg_i2c_device_event.i2c_device_events_count] .value.float_value = value; + _msg_i2c_device_event + .i2c_device_events[_msg_i2c_device_event.i2c_device_events_count] + .which_value = wippersnapper_sensor_SensorEvent_float_value_tag; } _msg_i2c_device_event.i2c_device_events_count++; diff --git a/src/helpers/ws_helper_macros.h b/src/helpers/ws_helper_macros.h index cfd6d9722..5d1eb79c8 100644 --- a/src/helpers/ws_helper_macros.h +++ b/src/helpers/ws_helper_macros.h @@ -7,11 +7,11 @@ // Define actual debug output functions when necessary. #ifdef WS_DEBUG #define WS_DEBUG_PRINT(...) \ - { WS_PRINTER.print(__VA_ARGS__); } ///< Prints debug output. + { WS_PRINTER.print(__VA_ARGS__);WS_PRINTER.flush();delay(5); } ///< Prints debug output. #define WS_DEBUG_PRINTLN(...) \ - { WS_PRINTER.println(__VA_ARGS__); } ///< Prints line from debug output. + { WS_PRINTER.println(__VA_ARGS__);WS_PRINTER.flush();delay(5); } ///< Prints line from debug output. #define WS_DEBUG_PRINTHEX(...) \ - { WS_PRINTER.print(__VA_ARGS__, HEX); } ///< Prints debug output. + { WS_PRINTER.print(__VA_ARGS__, HEX);WS_PRINTER.flush();delay(5); } ///< Prints debug output. #else #define WS_DEBUG_PRINT(...) \ {} ///< Prints debug output diff --git a/src/provisioning/sdcard/ws_sdcard.cpp b/src/provisioning/sdcard/ws_sdcard.cpp index 0bf7657a7..fdbcacc83 100644 --- a/src/provisioning/sdcard/ws_sdcard.cpp +++ b/src/provisioning/sdcard/ws_sdcard.cpp @@ -1382,23 +1382,24 @@ bool ws_sdcard::LogEventDs18x(wippersnapper_ds18x20_Ds18x20Event *event_msg) { */ bool ws_sdcard::LogEventI2c( wippersnapper_i2c_I2cDeviceEvent *msg_device_event) { - JsonDocument doc; + JsonDocument baseDoc; // Pull the DeviceDescriptor out wippersnapper_i2c_I2cDeviceDescriptor descriptor = msg_device_event->i2c_device_description; char hex_addr[5]; snprintf(hex_addr, sizeof(hex_addr), "0x%02X", descriptor.i2c_device_address); - doc["i2c_address"] = hex_addr; + baseDoc["i2c_address"] = hex_addr; // Using I2C MUX? if (descriptor.i2c_mux_address != 0x00) { snprintf(hex_addr, sizeof(hex_addr), "0x%02X", descriptor.i2c_mux_address); - doc["i2c_mux_addr"] = hex_addr; - doc["i2c_mux_ch"] = descriptor.i2c_mux_channel; + baseDoc["i2c_mux_addr"] = hex_addr; + baseDoc["i2c_mux_ch"] = descriptor.i2c_mux_channel; } // Log each event for (pb_size_t i = 0; i < msg_device_event->i2c_device_events_count; i++) { + JsonDocument doc = baseDoc; // no stale vectors/values doc["timestamp"] = GetTimestamp(); // if mag/vector/colour etc log all value elements if (msg_device_event->i2c_device_events[i].type == @@ -1480,6 +1481,13 @@ bool ws_sdcard::LogEventI2c( if (!LogJSONDoc(doc)) return false; continue; + } else if (msg_device_event->i2c_device_events[i].type == + wippersnapper_sensor_SensorType_SENSOR_TYPE_BOOLEAN) { + doc["value"] = msg_device_event->i2c_device_events[i].value.bool_value; + doc["si_unit"] = + SensorTypeToSIUnit(msg_device_event->i2c_device_events[i].type); + if (!LogJSONDoc(doc)) + return false; } else { // normal scalar float value doc["value"] = msg_device_event->i2c_device_events[i].value.float_value; doc["si_unit"] = diff --git a/src/provisioning/tinyusb/Wippersnapper_FS.cpp b/src/provisioning/tinyusb/Wippersnapper_FS.cpp index d62e3f302..f5f2d3101 100644 --- a/src/provisioning/tinyusb/Wippersnapper_FS.cpp +++ b/src/provisioning/tinyusb/Wippersnapper_FS.cpp @@ -30,6 +30,7 @@ defined(ARDUINO_RASPBERRY_PI_PICO) || \ defined(ARDUINO_RASPBERRY_PI_PICO_2) || \ defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) || \ + defined(ARDUINO_ADAFRUIT_FEATHER_RP2350_HSTX) || \ defined(ARDUINO_ADAFRUIT_METRO_RP2350) || \ defined(ARDUINO_RASPBERRY_PI_PICO_2W) #include "Wippersnapper_FS.h" diff --git a/src/ws_adapters.h b/src/ws_adapters.h index 7e240232b..221cb4672 100644 --- a/src/ws_adapters.h +++ b/src/ws_adapters.h @@ -50,6 +50,7 @@ typedef ws_wifi_ninafw ws_adapter_wifi; #elif defined(ARDUINO_RASPBERRY_PI_PICO_2) || \ defined(ARDUINO_RASPBERRY_PI_PICO) || \ defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) || \ + defined(ARDUINO_ADAFRUIT_FEATHER_RP2350_HSTX) || \ defined(ARDUINO_ADAFRUIT_METRO_RP2350) #define WS_OFFLINE_ADAPTER #include "adapters/offline/ws_offline_pico.h"