diff --git a/CMakeLists.txt b/CMakeLists.txt index fe45c1f..1ddaef3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,14 @@ add_executable(ei_rp2040_firmware src/main.cpp ) +# Define options for different boards +OPTION(BOARD_MICROMOD "Select MicroMod board" OFF) + +# Conditionally define macros based on the selected board +if (BOARD_MICROMOD) + target_compile_definitions(ei_rp2040_firmware PRIVATE BOARD_MICROMOD=1) +endif() + OPTION(DEFINE_PIN_UART "Only use TX/RX pins and not USB UART" OFF) @@ -100,6 +108,7 @@ target_include_directories(ei_rp2040_firmware PRIVATE ThirdParty/Seeed_Arduino_UltrasonicRanger ThirdParty/Wire/src ThirdParty/Arduino_LSM6DSOX/src + ThirdParty/LIS2DH12/src ThirdParty/rp2040_DHT11_lib ThirdParty/PDM/src/include ) diff --git a/ThirdParty/LIS2DH12/src/LIS2DH12.cpp b/ThirdParty/LIS2DH12/src/LIS2DH12.cpp new file mode 100644 index 0000000..4fd4ee6 --- /dev/null +++ b/ThirdParty/LIS2DH12/src/LIS2DH12.cpp @@ -0,0 +1,161 @@ +/* Include ----------------------------------------------------------------- */ +#include "LIS2DH12.h" + +/* Constant defines -------------------------------------------------------- */ +// Registers +#define LIS2DH12_STATUS_REG_AUX 0x07U +#define LIS2DH12_OUT_TEMP_L 0x0CU +#define LIS2DH12_WHO_AM_I_REG 0X0FU +#define LIS2DH12_TEMP_CFG_REG 0x1FU +#define LIS2DH12_CTRL_REG1 0x20U +#define LIS2DH12_CTRL_REG4 0x23U +#define LIS2DH12_STATUS_REG 0x27U +#define LIS2DH12_OUT_X_L 0x28U + +// Register masks +#define LIS2DH12_STATUS_REG_ZYXOR_MASK 0x80u +#define LIS2DH12_STATUS_REG_AUX_TDA_MASK 0x04u + +LIS2DH12Class::LIS2DH12Class(TwoWire& wire, uint8_t slaveAddress) : + _wire(&wire), + _slaveAddress(slaveAddress) +{ +} + +LIS2DH12Class::~LIS2DH12Class() { /* Nothing to do */ } + +int LIS2DH12Class::begin() +{ + int8_t type; + uint8_t ret; + _wire->begin(); + + type = readRegister(LIS2DH12_WHO_AM_I_REG); + if (type != MOTION_SENSOR_LIS2DH12) { + return 0; + } + + // Data rate: 100Hz, enable all axis, high-resolution mode + writeRegister(LIS2DH12_CTRL_REG1, 0x57); + + //Enable block data update, full-scale 2g, hr 1 + writeRegister(LIS2DH12_CTRL_REG4, 0x88); + + //Enable temperature sensor + writeRegister(LIS2DH12_TEMP_CFG_REG, 0xC0); + + return type; +} + +void LIS2DH12Class::end() +{ + _wire->end(); +} + +int LIS2DH12Class::readAcceleration(float& x, float& y, float& z) +{ + int16_t data[3]; + + if (!readRegisters(LIS2DH12_OUT_X_L, (uint8_t*)data, sizeof(data))) { + x = NAN; + y = NAN; + z = NAN; + + return 0; + } + + /* First convert fs2 hr to mg and then to g */ + x = ((data[0] / 16.0f) * 1.0f) / 1000.0f; + y = ((data[1] / 16.0f) * 1.0f) / 1000.0f; + z = ((data[2] / 16.0f) * 1.0f) / 1000.0f; + + return 1; +} + +int LIS2DH12Class::accelerationAvailable() +{ + uint8_t data; + if (readRegisters(LIS2DH12_STATUS_REG, &data, 1) != 1) { + return 0; + } + + return (data & LIS2DH12_STATUS_REG_ZYXOR_MASK) ? 1 : 0; +} + +float LIS2DH12Class::accelerationSampleRate() +{ + return 100.0F; +} + +int LIS2DH12Class::readTemperature(int & temperature_deg) +{ + /* Read the raw temperature from the sensor. */ + int16_t temperature_raw = 0; + + if (readRegisters(LIS2DH12_OUT_TEMP_L, reinterpret_cast(&temperature_raw), sizeof(temperature_raw)) != 1) { + return 0; + } + + temperature_deg = (((float)temperature_raw / 64.0f ) / 4.0f ) + 25.0f; + + return 1; +} + +int LIS2DH12Class::temperatureAvailable() +{ + uint8_t data; + + if (readRegisters(LIS2DH12_STATUS_REG_AUX, &data, 1) != 1) { + return 0; + } + return (data & LIS2DH12_STATUS_REG_AUX_TDA_MASK) ? 1 : 0; +} + +int LIS2DH12Class::readRegister(uint8_t address) +{ +uint8_t value; + +if (readRegisters(address, &value, sizeof(value)) != 1) { + return -1; +} + +return value; +} + +int LIS2DH12Class::readRegisters(uint8_t address, uint8_t* data, size_t length) +{ + if (length > 1) + { + //For multi byte reads we must set the first bit to 1 + address |= 0x80; + } + + _wire->beginTransmission(_slaveAddress); + _wire->write(address); + + if (_wire->endTransmission(false) != 0) { + return -1; + } + + if (_wire->requestFrom(_slaveAddress, length) != length) { + return 0; + } + + for (size_t i = 0; i < length; i++) { + *data++ = _wire->read(); + } + return 1; +} + +int LIS2DH12Class::writeRegister(uint8_t address, uint8_t value) +{ + _wire->beginTransmission(_slaveAddress); + _wire->write(address); + _wire->write(value); + if (_wire->endTransmission() != 0) { + return 0; + } + return 1; +} + +LIS2DH12Class MOTION(Wire, LIS2DH12_ADDRESS); diff --git a/ThirdParty/LIS2DH12/src/LIS2DH12.h b/ThirdParty/LIS2DH12/src/LIS2DH12.h new file mode 100644 index 0000000..5c53371 --- /dev/null +++ b/ThirdParty/LIS2DH12/src/LIS2DH12.h @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include + +#define MOTION_SENSOR_LIS2DH12 0x33 +#define LIS2DH12_ADDRESS 0x19U + +class LIS2DH12Class { + public: + LIS2DH12Class(TwoWire& wire, uint8_t slaveAddress); + ~LIS2DH12Class(); + + int begin(); + void end(); + + // Accelerometer + int readAcceleration(float& x, float& y, float& z); + float accelerationSampleRate(); + int accelerationAvailable(); + + // Temperature + int readTemperature(int & temperature_deg); + int temperatureAvailable(); + + private: + int readRegister(uint8_t address); + int readRegisters(uint8_t address, uint8_t* data, size_t length); + int writeRegister(uint8_t address, uint8_t value); + + + private: + TwoWire* _wire; + uint8_t _slaveAddress; +}; + +extern LIS2DH12Class MOTION; diff --git a/ThirdParty/PDM/src/PDM.cpp b/ThirdParty/PDM/src/PDM.cpp index e8ba3c1..9b78695 100644 --- a/ThirdParty/PDM/src/PDM.cpp +++ b/ThirdParty/PDM/src/PDM.cpp @@ -240,4 +240,4 @@ void PDMClass::IrqHandler(bool halftranfer) } } -PDMClass PDM(22, 23, -1); +PDMClass PDM(DIN_PIN, CLK_PIN, -1); diff --git a/ThirdParty/PDM/src/include/PDM.h b/ThirdParty/PDM/src/include/PDM.h index 647c462..500405a 100644 --- a/ThirdParty/PDM/src/include/PDM.h +++ b/ThirdParty/PDM/src/include/PDM.h @@ -24,6 +24,14 @@ #include "PDMDoubleBuffer.h" +#ifdef BOARD_MICROMOD +#define DIN_PIN 2 +#define CLK_PIN 3 +#else +#define DIN_PIN 22 +#define CLK_PIN 23 +#endif + class PDMClass { public: diff --git a/ThirdParty/Wire/src/Wire.h b/ThirdParty/Wire/src/Wire.h index 9db4868..de6e919 100644 --- a/ThirdParty/Wire/src/Wire.h +++ b/ThirdParty/Wire/src/Wire.h @@ -46,12 +46,19 @@ constexpr uint32_t __bitset(const int (&a)[N], size_t i = 0U) { #define WIRE_BUFFER_SIZE 128 #endif +#ifdef BOARD_MICROMOD +#define SDA 4 +#define SCL 5 +#define PIN_WIRE1_SDA 26 +#define PIN_WIRE1_SCL 27 +#else // Wire #define SDA 12 #define SCL 13 #define PIN_WIRE1_SDA 6 #define PIN_WIRE1_SCL 7 +#endif class TwoWire { public: diff --git a/edge-impulse/ingestion-sdk-platform/sensors/ei_motionsensor.cpp b/edge-impulse/ingestion-sdk-platform/sensors/ei_motionsensor.cpp new file mode 100644 index 0000000..6b412bb --- /dev/null +++ b/edge-impulse/ingestion-sdk-platform/sensors/ei_motionsensor.cpp @@ -0,0 +1,46 @@ +/* Include ----------------------------------------------------------------- */ +#include +#include + +#include "ei_motionsensor.h" +#include + +#include "ei_device_raspberry_rp2040.h" +#include "sensor_aq.h" + +/* Constant defines -------------------------------------------------------- */ +#define CONVERT_G_TO_MS2 9.80665f + +static float motion_data[MOTION_AXIS_SAMPLED]; + +bool ei_motion_sensor_init(void) +{ + uint8_t acc_type = MOTION.begin(); + + if ((acc_type == 0) || (acc_type != MOTION_SENSOR_LIS2DH12)) { + return false; + } + + ei_add_sensor_to_fusion_list(motion_sensor); + return true; +} + +float *ei_fusion_motion_sensor_read_data(int n_samples) +{ + if (MOTION.accelerationAvailable()) + { + MOTION.readAcceleration(motion_data[0], motion_data[1], motion_data[2]); + + motion_data[0] *= CONVERT_G_TO_MS2; + motion_data[1] *= CONVERT_G_TO_MS2; + motion_data[2] *= CONVERT_G_TO_MS2; + } + +#ifdef DEBUG + for (int i = 0; i < MOTION_AXIS_SAMPLED; i++) { + ei_printf("%f ", motion_data[i]); + } + ei_printf("\n"); +#endif + return motion_data; +} diff --git a/edge-impulse/ingestion-sdk-platform/sensors/ei_motionsensor.h b/edge-impulse/ingestion-sdk-platform/sensors/ei_motionsensor.h new file mode 100644 index 0000000..e51b22e --- /dev/null +++ b/edge-impulse/ingestion-sdk-platform/sensors/ei_motionsensor.h @@ -0,0 +1,32 @@ +#ifndef _EI_MOTIONSENSOR_H +#define _EI_MOTIONSENSOR_H + +/* Include ----------------------------------------------------------------- */ +#include "ei_fusion.h" +#include "ei_sampler.h" + +/** Number of axis used and sample data format */ +#define MOTION_AXIS_SAMPLED 3 + +/* Function prototypes ----------------------------------------------------- */ +bool ei_motion_sensor_init(void); +float *ei_fusion_motion_sensor_read_data(int n_samples); + +static const ei_device_fusion_sensor_t motion_sensor = { + // name of sensor module to be displayed in fusion list + "Motion", + // number of sensor module axis + MOTION_AXIS_SAMPLED, + // sampling frequencies + { 100.0f, 62.5f, 20.0f }, + // axis name and units payload (must be same order as read in) + { + { "accX", "m/s2" }, + { "accY", "m/s2" }, + { "accZ", "m/s2" }, + }, + // reference to read data function + &ei_fusion_motion_sensor_read_data +}; + +#endif /* _EI_MOTIONSENSOR_H */ diff --git a/firmware-sdk/sensor_aq.h b/firmware-sdk/sensor_aq.h index 2d62036..58493da 100644 --- a/firmware-sdk/sensor_aq.h +++ b/firmware-sdk/sensor_aq.h @@ -22,10 +22,10 @@ /* Include ----------------------------------------------------------------- */ #include "QCBOR/inc/qcbor.h" #include +#include // detect POSIX, and use FILE* in that case #if !defined(EI_SENSOR_AQ_STREAM) && (defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))) -#include #define EI_SENSOR_AQ_STREAM FILE #elif !defined(EI_SENSOR_AQ_STREAM) // most targets don't need a file handle diff --git a/src/main.cpp b/src/main.cpp index ce9c4aa..560f054 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,6 +35,7 @@ #include "ei_dht11sensor.h" #include "ei_inertialsensor.h" +#include "ei_motionsensor.h" #include "ei_analogsensor.h" #include "ei_ultrasonicsensor.h" @@ -69,6 +70,11 @@ void ei_init(void) ei_printf("Inertial sensor communication error occurred\r\n"); } + /* Setup the motion sensor */ + if (ei_motion_sensor_init() == false) { + ei_printf("Motion sensor communication error occurred\r\n"); + } + /* Setup the temp&humidity sensor */ if (ei_dht11_sensor_init() == false) { ei_printf("DHT11 initialization failed\r\n"); @@ -105,7 +111,7 @@ void ei_main(void *pvParameters) ei_init(); while(true) { - /* handle command comming from uart */ + /* handle command coming from uart */ char data = ei_get_serial_byte(); while (data != 0xFF) {