diff --git a/src/configuration.h b/src/configuration.h index 32d99295e..1615600f6 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -193,6 +193,15 @@ along with this program. If not, see . // ----------------------------------------------------------------------------- #define FT6336U_ADDR 0x48 +// ----------------------------------------------------------------------------- +// RAK12035VB Soil Monitor (using RAK12023 up to 3 RAK12035 monitors can be connected) +// - the default i2c address for this sensor is 0x20, and users are instructed to +// set 0x21 and 0x22 for the second and third sensor if present. +// ----------------------------------------------------------------------------- +#define RAK120351_ADDR 0x20 +#define RAK120352_ADDR 0x21 +#define RAK120353_ADDR 0x22 + // ----------------------------------------------------------------------------- // BIAS-T Generator // ----------------------------------------------------------------------------- diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index 72184db69..1e91933a9 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -70,6 +70,7 @@ class ScanI2C DFROBOT_RAIN, DPS310, LTR390UV, + RAK12035, TCA8418KB, PCT2075, } DeviceType; diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index e2ba78a92..ba7b66793 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -423,9 +423,21 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) logFoundDevice("BMA423", (uint8_t)addr.address); } break; + case TCA9535_ADDR: + case RAK120352_ADDR: + case RAK120353_ADDR: + registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x02), 1); + if (registerValue == addr.address) { // RAK12035 returns its I2C address at 0x02 (eg 0x20) + type = RAK12035; + logFoundDevice("RAK12035", (uint8_t)addr.address); + } else { + type = TCA9535; + logFoundDevice("TCA9535", (uint8_t)addr.address); + } + + break; SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3", (uint8_t)addr.address); - SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535", (uint8_t)addr.address); SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555", (uint8_t)addr.address); SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700", (uint8_t)addr.address); SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591", (uint8_t)addr.address); diff --git a/src/main.cpp b/src/main.cpp index 7a11ca2e0..792e87360 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -732,6 +732,7 @@ void setup() scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DFROBOT_RAIN, meshtastic_TelemetrySensorType_DFROBOT_RAIN); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::LTR390UV, meshtastic_TelemetrySensorType_LTR390UV); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DPS310, meshtastic_TelemetrySensorType_DPS310); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::RAK12035, meshtastic_TelemetrySensorType_RAK12035); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::PCT2075, meshtastic_TelemetrySensorType_PCT2075); i2cScanner.reset(); diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index 6d29fecb2..aaab8d0e6 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -19,8 +19,8 @@ #include #if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL -// Sensors +// Sensors #include "Sensor/CGRadSensSensor.h" #include "Sensor/RCWL9620Sensor.h" #include "Sensor/nullSensor.h" @@ -101,6 +101,13 @@ SHTC3Sensor shtc3Sensor; NullSensor shtc3Sensor; #endif +#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1 +#include "Sensor/RAK12035Sensor.h" +RAK12035Sensor rak12035Sensor; +#else +NullSensor rak12035Sensor; +#endif + #if __has_include() #include "Sensor/VEML7700Sensor.h" VEML7700Sensor veml7700Sensor; @@ -173,6 +180,7 @@ NullSensor pct2075Sensor; RCWL9620Sensor rcwl9620Sensor; CGRadSensSensor cgRadSens; + #endif #ifdef T1000X_SENSOR_EN #include "Sensor/T1000xSensor.h" @@ -182,6 +190,7 @@ T1000xSensor t1000xSensor; #include "Sensor/IndicatorSensor.h" IndicatorSensor indicatorSensor; #endif + #define FAILED_STATE_SENSOR_READ_MULTIPLIER 10 #define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true @@ -288,6 +297,11 @@ int32_t EnvironmentTelemetryModule::runOnce() result = rak9154Sensor.runOnce(); #endif +#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1 + if (rak12035Sensor.hasSensor()) { + result = rak12035Sensor.runOnce(); + } +#endif #endif } // it's possible to have this module enabled, only for displaying values on the screen. @@ -625,6 +639,14 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m valid = valid && rak9154Sensor.getMetrics(m); hasSensor = true; #endif +#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && \ + RAK_4631 == \ + 1 // Not really needed, but may as well just skip at a lower level it if no library or not a RAK_4631 + if (rak12035Sensor.hasSensor()) { + valid = valid && rak12035Sensor.getMetrics(m); + hasSensor = true; + } +#endif #endif return valid && hasSensor; } @@ -679,6 +701,9 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly) LOG_INFO("Send: radiation=%fµR/h", m.variant.environment_metrics.radiation); + LOG_INFO("Send: soil_temperature=%f, soil_moisture=%u", m.variant.environment_metrics.soil_temperature, + m.variant.environment_metrics.soil_moisture); + sensor_read_error_count = 0; meshtastic_MeshPacket *p = allocDataProtobuf(m); @@ -850,8 +875,17 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule if (result != AdminMessageHandleResult::NOT_HANDLED) return result; } +#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && \ + RAK_4631 == \ + 1 // Not really needed, but may as well just skip it at a lower level if no library or not a RAK_4631 + if (rak12035Sensor.hasSensor()) { + result = rak12035Sensor.handleAdminMessage(mp, request, response); + if (result != AdminMessageHandleResult::NOT_HANDLED) + return result; + } +#endif #endif return result; } -#endif \ No newline at end of file +#endif diff --git a/src/modules/Telemetry/Sensor/RAK12035Sensor.cpp b/src/modules/Telemetry/Sensor/RAK12035Sensor.cpp new file mode 100644 index 000000000..e4fa473bd --- /dev/null +++ b/src/modules/Telemetry/Sensor/RAK12035Sensor.cpp @@ -0,0 +1,107 @@ +#include "configuration.h" +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1 + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "RAK12035Sensor.h" + +RAK12035Sensor::RAK12035Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_RAK12035, "RAK12035") {} + +int32_t RAK12035Sensor::runOnce() +{ + if (!hasSensor()) { + return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; + } + + // TODO:: check for up to 2 additional sensors and start them if present. + sensor.set_sensor_addr(RAK120351_ADDR); + delay(100); + sensor.begin(nodeTelemetrySensorsMap[sensorType].first); + + // Get sensor firmware version + uint8_t data = 0; + sensor.get_sensor_version(&data); + if (data != 0) { + LOG_INFO("Init sensor: %s", sensorName); + LOG_INFO("RAK12035Sensor Init Succeed \nSensor1 Firmware version: %i, Sensor Name: %s", data, sensorName); + status = true; + } else { + LOG_INFO("Init sensor: %s \n", sensorName); + LOG_ERROR("RAK12035Sensor Init Failed"); + status = false; + } + sensor.sensor_sleep(); + return initI2CSensor(); +} + +void RAK12035Sensor::setup() +{ + // Set the calibration values + // Reading the saved calibration values from the sensor. + // TODO:: Check for and run calibration check for up to 2 additional sensors if present. + uint16_t zero_val = 0; + uint16_t hundred_val = 0; + uint16_t default_zero_val = 550; + uint16_t default_hundred_val = 420; + sensor.sensor_on(); + delay(200); + sensor.get_dry_cal(&zero_val); + sensor.get_wet_cal(&hundred_val); + delay(200); + if (zero_val == 0 || zero_val <= hundred_val) { + LOG_INFO("Dry calibration value is %d", zero_val); + LOG_INFO("Wet calibration value is %d", hundred_val); + LOG_INFO("This does not make sense. You can recalibrate this sensor using the calibration sketch included here: " + "https://github.com/RAKWireless/RAK12035_SoilMoisture."); + LOG_INFO("For now, setting default calibration value for Dry Calibration: %d", default_zero_val); + sensor.set_dry_cal(default_zero_val); + sensor.get_dry_cal(&zero_val); + LOG_INFO("Dry calibration reset complete. New value is %d", zero_val); + } + if (hundred_val == 0 || hundred_val >= zero_val) { + LOG_INFO("Dry calibration value is %d", zero_val); + LOG_INFO("Wet calibration value is %d", hundred_val); + LOG_INFO("This does not make sense. You can recalibrate this sensor using the calibration sketch included here: " + "https://github.com/RAKWireless/RAK12035_SoilMoisture."); + LOG_INFO("For now, setting default calibration value for Wet Calibration: %d", default_hundred_val); + sensor.set_wet_cal(default_hundred_val); + sensor.get_wet_cal(&hundred_val); + LOG_INFO("Wet calibration reset complete. New value is %d", hundred_val); + } + sensor.sensor_sleep(); + delay(200); + LOG_INFO("Dry calibration value is %d", zero_val); + LOG_INFO("Wet calibration value is %d", hundred_val); +} + +bool RAK12035Sensor::getMetrics(meshtastic_Telemetry *measurement) +{ + // TODO:: read and send metrics for up to 2 additional soil monitors if present. + // -- how to do this.. this could get a little complex.. + // ie - 1> we combine them into an average and send that, 2> we send them as separate metrics + // ^-- these scenarios would require different handling of the metrics in the receiving end and maybe a setting in the + // device ui and an additional proto for that? + measurement->variant.environment_metrics.has_soil_temperature = true; + measurement->variant.environment_metrics.has_soil_moisture = true; + + uint8_t moisture = 0; + uint16_t temp = 0; + bool success = false; + + sensor.sensor_on(); + delay(200); + success = sensor.get_sensor_moisture(&moisture); + delay(200); + success &= sensor.get_sensor_temperature(&temp); + delay(200); + sensor.sensor_sleep(); + + if (success == false) { + LOG_ERROR("Failed to read sensor data"); + return false; + } + measurement->variant.environment_metrics.soil_temperature = ((float)temp / 10.0f); + measurement->variant.environment_metrics.soil_moisture = moisture; + + return true; +} +#endif diff --git a/src/modules/Telemetry/Sensor/RAK12035Sensor.h b/src/modules/Telemetry/Sensor/RAK12035Sensor.h new file mode 100644 index 000000000..2c32a840d --- /dev/null +++ b/src/modules/Telemetry/Sensor/RAK12035Sensor.h @@ -0,0 +1,28 @@ +#pragma once + +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include() && defined(RAK_4631) +#ifndef _MT_RAK12035VBSENSOR_H +#define _MT_RAK12035VBSENSOR_H +#endif + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "RAK12035_SoilMoisture.h" +#include "TelemetrySensor.h" +#include + +class RAK12035Sensor : public TelemetrySensor +{ + private: + RAK12035 sensor; + + protected: + virtual void setup() override; + + public: + RAK12035Sensor(); + virtual int32_t runOnce() override; + virtual bool getMetrics(meshtastic_Telemetry *measurement) override; +}; +#endif diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index f2d68e704..ee134e87a 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -18,6 +18,7 @@ lib_deps = melopero/Melopero RV3028@^1.1.0 https://github.com/RAKWireless/RAK13800-W5100S/archive/1.0.2.zip rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2 + beegee-tokyo/RAK12035_SoilMoisture@^1.0.4 https://github.com/RAKWireless/RAK12034-BMX160/archive/dcead07ffa267d3c906e9ca4a1330ab989e957e2.zip ; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) @@ -51,4 +52,4 @@ lib_deps = upload_protocol = stlink ; eventually use platformio/tool-pyocd@^2.3600.0 instad ;upload_protocol = custom -;upload_command = pyocd flash -t nrf52840 $UPLOADERFLAGS $SOURCE \ No newline at end of file +;upload_command = pyocd flash -t nrf52840 $UPLOADERFLAGS $SOURCE diff --git a/variants/rak4631/variant.h b/variants/rak4631/variant.h index 0da1c04ea..46a6140f3 100644 --- a/variants/rak4631/variant.h +++ b/variants/rak4631/variant.h @@ -90,6 +90,8 @@ static const uint8_t A7 = PIN_A7; // Other pins #define PIN_AREF (2) #define PIN_NFC1 (9) +#define WB_IO5 PIN_NFC1 +#define WB_IO4 (4) #define PIN_NFC2 (10) static const uint8_t AREF = PIN_AREF; @@ -223,6 +225,7 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG // enables 3.3V periphery like GPS or IO Module // Do not toggle this for GPS power savings #define PIN_3V3_EN (34) +#define WB_IO2 PIN_3V3_EN // RAK1910 GPS module // If using the wisblock GPS module and pluged into Port A on WisBlock base @@ -276,4 +279,4 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG * Arduino objects - C++ only *----------------------------------------------------------------------------*/ -#endif \ No newline at end of file +#endif diff --git a/variants/rak4631_epaper/platformio.ini b/variants/rak4631_epaper/platformio.ini index 7c8a299bb..47e4451c7 100644 --- a/variants/rak4631_epaper/platformio.ini +++ b/variants/rak4631_epaper/platformio.ini @@ -16,6 +16,7 @@ lib_deps = melopero/Melopero RV3028@^1.1.0 rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2 beegee-tokyo/RAKwireless RAK12034@^1.0.0 + beegee-tokyo/RAK12035_SoilMoisture@^1.0.4 debug_tool = jlink ; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) ;upload_protocol = jlink diff --git a/variants/rak4631_epaper/variant.h b/variants/rak4631_epaper/variant.h index 0bb97498c..c1e11bee5 100644 --- a/variants/rak4631_epaper/variant.h +++ b/variants/rak4631_epaper/variant.h @@ -90,6 +90,8 @@ static const uint8_t A7 = PIN_A7; // Other pins #define PIN_AREF (2) #define PIN_NFC1 (9) +#define WB_IO5 PIN_NFC1 +#define WB_IO4 (4) #define PIN_NFC2 (10) static const uint8_t AREF = PIN_AREF; @@ -188,6 +190,7 @@ static const uint8_t SCK = PIN_SPI_SCK; // enables 3.3V periphery like GPS or IO Module #define PIN_3V3_EN (34) +#define WB_IO2 PIN_3V3_EN // RAK1910 GPS module // If using the wisblock GPS module and pluged into Port A on WisBlock base @@ -231,4 +234,4 @@ static const uint8_t SCK = PIN_SPI_SCK; * Arduino objects - C++ only *----------------------------------------------------------------------------*/ -#endif \ No newline at end of file +#endif diff --git a/variants/rak4631_epaper_onrxtx/platformio.ini b/variants/rak4631_epaper_onrxtx/platformio.ini index c749fc686..52a13f2a7 100644 --- a/variants/rak4631_epaper_onrxtx/platformio.ini +++ b/variants/rak4631_epaper_onrxtx/platformio.ini @@ -18,6 +18,7 @@ lib_deps = melopero/Melopero RV3028@^1.1.0 rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2 beegee-tokyo/RAKwireless RAK12034@^1.0.0 + beegee-tokyo/RAK12035_SoilMoisture@^1.0.4 debug_tool = jlink ; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) ;upload_protocol = jlink diff --git a/variants/rak4631_epaper_onrxtx/variant.h b/variants/rak4631_epaper_onrxtx/variant.h index 5888cff33..1f8257e8e 100644 --- a/variants/rak4631_epaper_onrxtx/variant.h +++ b/variants/rak4631_epaper_onrxtx/variant.h @@ -69,7 +69,9 @@ static const uint8_t A7 = PIN_A7; // Other pins #define PIN_AREF (2) -// #define PIN_NFC1 (9) +#define PIN_NFC1 (9) +#define WB_IO5 PIN_NFC1 +#define WB_IO4 (4) // #define PIN_NFC2 (10) static const uint8_t AREF = PIN_AREF; @@ -160,6 +162,7 @@ static const uint8_t SCK = PIN_SPI_SCK; // enables 3.3V periphery like GPS or IO Module #define PIN_3V3_EN (34) +#define WB_IO2 PIN_3V3_EN // NO GPS #undef GPS_RX_PIN @@ -202,4 +205,4 @@ static const uint8_t SCK = PIN_SPI_SCK; * Arduino objects - C++ only *----------------------------------------------------------------------------*/ -#endif \ No newline at end of file +#endif diff --git a/variants/rak4631_eth_gw/variant.h b/variants/rak4631_eth_gw/variant.h index bc5541336..c8a2f83ae 100644 --- a/variants/rak4631_eth_gw/variant.h +++ b/variants/rak4631_eth_gw/variant.h @@ -90,6 +90,8 @@ static const uint8_t A7 = PIN_A7; // Other pins #define PIN_AREF (2) #define PIN_NFC1 (9) +#define WB_IO5 PIN_NFC1 +#define WB_IO4 (4) #define PIN_NFC2 (10) static const uint8_t AREF = PIN_AREF; @@ -217,6 +219,7 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG // enables 3.3V periphery like GPS or IO Module // Do not toggle this for GPS power savings #define PIN_3V3_EN (34) +#define WB_IO2 PIN_3V3_EN // RAK1910 GPS module // If using the wisblock GPS module and pluged into Port A on WisBlock base @@ -270,4 +273,4 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG * Arduino objects - C++ only *----------------------------------------------------------------------------*/ -#endif \ No newline at end of file +#endif diff --git a/variants/rak_wismeshtap/platformio.ini b/variants/rak_wismeshtap/platformio.ini index 6ed97c7ad..bfb3ea927 100644 --- a/variants/rak_wismeshtap/platformio.ini +++ b/variants/rak_wismeshtap/platformio.ini @@ -22,6 +22,7 @@ lib_deps = bodmer/TFT_eSPI beegee-tokyo/RAKwireless RAK12034@^1.0.0 beegee-tokyo/RAK14014-FT6336U @ 1.0.1 + beegee-tokyo/RAK12035_SoilMoisture@^1.0.4 debug_tool = jlink ; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm) ;upload_protocol = jlink diff --git a/variants/rak_wismeshtap/variant.h b/variants/rak_wismeshtap/variant.h index 1980dc4a1..f961ddf6e 100644 --- a/variants/rak_wismeshtap/variant.h +++ b/variants/rak_wismeshtap/variant.h @@ -90,6 +90,8 @@ static const uint8_t A7 = PIN_A7; // Other pins #define PIN_AREF (2) #define PIN_NFC1 (9) +#define WB_IO5 PIN_NFC1 +#define WB_IO4 (4) #define PIN_NFC2 (10) static const uint8_t AREF = PIN_AREF; @@ -176,11 +178,11 @@ static const uint8_t SCK = PIN_SPI_SCK; // No reason not to have the RAK Wireless pin defs here too. This allows code from example RAK sketches to run without // modification. -static const uint8_t WB_IO1 = 17; // SLOT_A SLOT_B -static const uint8_t WB_IO2 = 34; // SLOT_A SLOT_B -static const uint8_t WB_IO3 = 21; // SLOT_C -static const uint8_t WB_IO4 = 4; // SLOT_C -static const uint8_t WB_IO5 = 9; // SLOT_D +static const uint8_t WB_IO1 = 17; // SLOT_A SLOT_B +static const uint8_t WB_IO2 = 34; // SLOT_A SLOT_B +static const uint8_t WB_IO3 = 21; // SLOT_C +// static const uint8_t WB_IO4 = 4; // SLOT_C <- already defined above (ln. 94) +// static const uint8_t WB_IO5 = 9; // SLOT_D <- already defined above (ln. 93) static const uint8_t WB_IO6 = 10; // SLOT_D static const uint8_t WB_SW1 = 33; // IO_SLOT static const uint8_t WB_A0 = 5; // IO_SLOT @@ -314,4 +316,4 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG * Arduino objects - C++ only *----------------------------------------------------------------------------*/ -#endif \ No newline at end of file +#endif