diff --git a/.gitignore b/.gitignore index 7e7cc694..51449c2d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ .vscode/ipch out/ .direnv/ +.DS_Store +.vscode/settings.json diff --git a/src/helpers/SensorManager.h b/src/helpers/SensorManager.h index a5d53939..8d3d4aef 100644 --- a/src/helpers/SensorManager.h +++ b/src/helpers/SensorManager.h @@ -2,11 +2,18 @@ #include -#define TELEM_PERM_BASE 0x01 // 'base' permission includes battery -#define TELEM_PERM_LOCATION 0x02 +#define TELEM_PERM_BASE 0x01 // 'base' permission includes battery +#define TELEM_PERM_LOCATION 0x02 +#define TELEM_PERM_ENVIRONMENT 0x04 // permission to access environment sensors #define TELEM_CHANNEL_SELF 1 // LPP data channel for 'self' device +#define TELEM_INA3221_ADDRESS 0x42 // INA3221 3 channel current, voltage, power sensor I2C address +#define TELEM_INA3221_SHUNT_VALUE 0.100 // most variants will have a 0.1 ohm shunts +#define TELEM_INA3221_SETTING_CH1 "INA3221 Channel 1" +#define TELEM_INA3221_SETTING_CH2 "INA3221 Channel 2" +#define TELEM_INA3221_SETTING_CH3 "INA3221 Channel 3" + class SensorManager { public: double node_lat, node_lon; // modify these, if you want to affect Advert location diff --git a/variants/promicro/platformio.ini b/variants/promicro/platformio.ini index 5599cdd8..98e9c719 100644 --- a/variants/promicro/platformio.ini +++ b/variants/promicro/platformio.ini @@ -36,7 +36,8 @@ build_flags = ; -D MESH_DEBUG=1 lib_deps = ${Faketec.lib_deps} adafruit/RTClib @ ^2.1.3 - + robtillaart/INA3221 @ ^0.4.1 + [env:Faketec_room_server] extends = Faketec build_src_filter = ${Faketec.build_src_filter} diff --git a/variants/promicro/target.cpp b/variants/promicro/target.cpp index 212e3b25..304bb54a 100644 --- a/variants/promicro/target.cpp +++ b/variants/promicro/target.cpp @@ -10,7 +10,7 @@ WRAPPER_CLASS radio_driver(radio, board); VolatileRTCClock fallback_clock; AutoDiscoverRTCClock rtc_clock(fallback_clock); -SensorManager sensors; +PromicroSensorManager sensors; #ifndef LORA_CR #define LORA_CR 5 @@ -74,3 +74,85 @@ mesh::LocalIdentity radio_new_identity() { RadioNoiseListener rng(radio); return mesh::LocalIdentity(&rng); // create new random identity } + +INA3221 INA_3221(TELEM_INA3221_ADDRESS, &Wire); + +bool PromicroSensorManager::begin() { + if (INA_3221.begin() ) { + Serial.print("Found INA3221 at address "); + Serial.print(INA_3221.getAddress()); + Serial.println(); + Serial.print(INA_3221.getDieID(), HEX); + Serial.print(INA_3221.getManufacturerID(), HEX); + Serial.print(INA_3221.getConfiguration(), HEX); + Serial.println(); + + for(int i = 0; i < 3; i++) { + INA_3221.setShuntR(i, TELEM_INA3221_SHUNT_VALUE); + } + INA3221initialized = true; + } + else { + INA3221initialized = false; + Serial.print("INA3221 was not found at I2C address "); + Serial.print(TELEM_INA3221_ADDRESS, HEX); + Serial.println(); + } + return true; +} + +bool PromicroSensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) { + if (requester_permissions && TELEM_PERM_ENVIRONMENT) { + if (INA3221initialized) { + for(int i = 0; i < 3; i++) { + // add only enabled INA3221 channels to telemetry + if (INA3221_CHANNEL_ENABLED[i]) { + telemetry.addVoltage(INA3221_CHANNELS[i], INA_3221.getBusVoltage(i)); + telemetry.addCurrent(INA3221_CHANNELS[i], INA_3221.getCurrent(i)); + telemetry.addPower(INA3221_CHANNELS[i], INA_3221.getPower(i)); + } + } + } + } + + return true; +} + +int PromicroSensorManager::getNumSettings() const { + return NUM_SENSOR_SETTINGS; +} + +const char* PromicroSensorManager::getSettingName(int i) const { + if (i >= 0 && i < NUM_SENSOR_SETTINGS) { + return INA3221_CHANNEL_NAMES[i]; + } + return NULL; +} + +const char* PromicroSensorManager::getSettingValue(int i) const { + if (i >= 0 && i < NUM_SENSOR_SETTINGS) { + return INA3221_CHANNEL_ENABLED[i] ? "1" : "0"; + } + return NULL; +} + +bool PromicroSensorManager::setSettingValue(const char* name, const char* value) { + for (int i = 0; i < NUM_SENSOR_SETTINGS; i++) { + if (strcmp(name, INA3221_CHANNEL_NAMES[i]) == 0) { + int channelEnabled = INA_3221.getEnableChannel(i); + if (strcmp(value, "1") == 0) { + INA3221_CHANNEL_ENABLED[i] = true; + if (!channelEnabled) { + INA_3221.enableChannel(i); + } + } else { + INA3221_CHANNEL_ENABLED[i] = false; + if (channelEnabled) { + INA_3221.disableChannel(i); + } + } + return true; + } + } + return false; +} \ No newline at end of file diff --git a/variants/promicro/target.h b/variants/promicro/target.h index b2c4f9d2..225afd4d 100644 --- a/variants/promicro/target.h +++ b/variants/promicro/target.h @@ -8,14 +8,39 @@ #include #include #include +#include + +#define NUM_SENSOR_SETTINGS 3 extern PromicroBoard board; extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; -extern SensorManager sensors; + bool radio_init(); uint32_t radio_get_rng_seed(); void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); void radio_set_tx_power(uint8_t dbm); mesh::LocalIdentity radio_new_identity(); + + +class PromicroSensorManager: public SensorManager { + bool INA3221initialized = false; + + // INA3221 channels in telemetry + int INA3221_CHANNELS[NUM_SENSOR_SETTINGS] = {TELEM_CHANNEL_SELF + 1, TELEM_CHANNEL_SELF + 2, TELEM_CHANNEL_SELF+ 3}; + char * INA3221_CHANNEL_NAMES[NUM_SENSOR_SETTINGS] = { TELEM_INA3221_SETTING_CH1, TELEM_INA3221_SETTING_CH2, TELEM_INA3221_SETTING_CH3}; + bool INA3221_CHANNEL_ENABLED[NUM_SENSOR_SETTINGS] = {true, true, true}; + +public: + PromicroSensorManager(){}; + bool begin() override; + bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; + int getNumSettings() const override; + const char* getSettingName(int i) const override; + const char* getSettingValue(int i) const override; + bool setSettingValue(const char* name, const char* value) override; +}; + + +extern PromicroSensorManager sensors; \ No newline at end of file