š¬ NodeManager
-
@ksga said in š¬ NodeManager:
Pretty sure I have to use the other library - tried using Adafruit's examples, and it claims no BME is attached...
Thanks for digging into it! I just want to be sure with the Adafruit library I'm using you can get the sensor working before evaluating and integrating the other library. As far as I remember during my tests I got a similar issue and if I'm not wrong this is because the chinese version of the BME sensor is on the 0x76 address instead of the 0x77 Adafruit's. Try if you don't mind with the plain Adafruit example and passing the address to begin() to see if you get better results. Thanks!
@user2684
Tried again with adafruits library and got it working changing the address.
But still can't get any useful data from it using NodeManager.Did a bit of copy/paste and got this code working (with adafruit and the alternative library):
#define MY_RADIO_NRF24 #include <MySensors.h> #include <SPI.h> #include <BH1750.h> #include <Wire.h> #include <BME280I2C.h> #define BARO_CHILD 0 #define TEMP_CHILD 1 #define HUM_CHILD 2 #define CHILD_ID_LIGHT 3 #define R1 687000 #define R2 222000 #define VMIN 3.30 #define VMAX 4.18 #define ADC_PRECISION 1023 #define VREF 1.107 unsigned long SLEEP_TIME = 300000; const float ALTITUDE = 10; BME280I2C bme; BH1750 lightSensor; MyMessage pressureMsg(BARO_CHILD, V_PRESSURE); MyMessage tempMsg(TEMP_CHILD, V_TEMP); MyMessage humMsg(HUM_CHILD, V_HUM); MyMessage lightMsg(CHILD_ID_LIGHT, V_LEVEL); float lastbaro = -1; float lasttemp = -1; float lasthum = -1; float lastlux = -1; float oldBatteryPcnt = -1; int BATTERY_SENSE_PIN = A0; void setup() { lightSensor.begin(); bme.begin(); analogReference(INTERNAL); pinMode(BATTERY_SENSE_PIN, INPUT); delay(100); } void presentation() { sendSketchInfo("BME280_BH1750", "1.1"); present(BARO_CHILD, S_BARO); present(TEMP_CHILD, S_TEMP); present(HUM_CHILD, S_HUM); present(CHILD_ID_LIGHT, S_LIGHT_LEVEL); } void loop() { float baro_local = bme.pres() / 100.0; float baro = ( baro_local / pow((1.0 - ( ALTITUDE / 44330.0 )), 5.255)); if (baro != lastbaro) { send(pressureMsg.set(baro,2)); lastbaro = baro; } float temp = bme.temp(); if (temp != lasttemp) { send(tempMsg.set(temp,1)); lasttemp = temp; } float hum = bme.hum(); if (hum != lasthum) { send(humMsg.set(hum,1)); lasthum = hum; } float lux = lightSensor.readLightLevel(); if (lux != lastlux) { send(lightMsg.set(lux,0)); lastlux = lux; } float batteryPcnt = getBatteryPercentage(); if (oldBatteryPcnt != batteryPcnt) { // Power up radio after sleep sendBatteryLevel(batteryPcnt); oldBatteryPcnt = batteryPcnt; } sleep(SLEEP_TIME); } float getBatteryPercentage() { delay(500); int inputValue = analogRead(BATTERY_SENSE_PIN); float voltageDividerFactor = (R1 + R2) / R2; float maxValue = voltageDividerFactor * VREF; float voltsPerBit = maxValue / ADC_PRECISION; float batteryVoltage = voltsPerBit * inputValue; float batteryPercentage = ((batteryVoltage-VMIN)/(VMAX-VMIN))*100; return batteryPercentage; } -
@user2684
Tried again with adafruits library and got it working changing the address.
But still can't get any useful data from it using NodeManager.Did a bit of copy/paste and got this code working (with adafruit and the alternative library):
#define MY_RADIO_NRF24 #include <MySensors.h> #include <SPI.h> #include <BH1750.h> #include <Wire.h> #include <BME280I2C.h> #define BARO_CHILD 0 #define TEMP_CHILD 1 #define HUM_CHILD 2 #define CHILD_ID_LIGHT 3 #define R1 687000 #define R2 222000 #define VMIN 3.30 #define VMAX 4.18 #define ADC_PRECISION 1023 #define VREF 1.107 unsigned long SLEEP_TIME = 300000; const float ALTITUDE = 10; BME280I2C bme; BH1750 lightSensor; MyMessage pressureMsg(BARO_CHILD, V_PRESSURE); MyMessage tempMsg(TEMP_CHILD, V_TEMP); MyMessage humMsg(HUM_CHILD, V_HUM); MyMessage lightMsg(CHILD_ID_LIGHT, V_LEVEL); float lastbaro = -1; float lasttemp = -1; float lasthum = -1; float lastlux = -1; float oldBatteryPcnt = -1; int BATTERY_SENSE_PIN = A0; void setup() { lightSensor.begin(); bme.begin(); analogReference(INTERNAL); pinMode(BATTERY_SENSE_PIN, INPUT); delay(100); } void presentation() { sendSketchInfo("BME280_BH1750", "1.1"); present(BARO_CHILD, S_BARO); present(TEMP_CHILD, S_TEMP); present(HUM_CHILD, S_HUM); present(CHILD_ID_LIGHT, S_LIGHT_LEVEL); } void loop() { float baro_local = bme.pres() / 100.0; float baro = ( baro_local / pow((1.0 - ( ALTITUDE / 44330.0 )), 5.255)); if (baro != lastbaro) { send(pressureMsg.set(baro,2)); lastbaro = baro; } float temp = bme.temp(); if (temp != lasttemp) { send(tempMsg.set(temp,1)); lasttemp = temp; } float hum = bme.hum(); if (hum != lasthum) { send(humMsg.set(hum,1)); lasthum = hum; } float lux = lightSensor.readLightLevel(); if (lux != lastlux) { send(lightMsg.set(lux,0)); lastlux = lux; } float batteryPcnt = getBatteryPercentage(); if (oldBatteryPcnt != batteryPcnt) { // Power up radio after sleep sendBatteryLevel(batteryPcnt); oldBatteryPcnt = batteryPcnt; } sleep(SLEEP_TIME); } float getBatteryPercentage() { delay(500); int inputValue = analogRead(BATTERY_SENSE_PIN); float voltageDividerFactor = (R1 + R2) / R2; float maxValue = voltageDividerFactor * VREF; float voltsPerBit = maxValue / ADC_PRECISION; float batteryVoltage = voltsPerBit * inputValue; float batteryPercentage = ((batteryVoltage-VMIN)/(VMAX-VMIN))*100; return batteryPercentage; }@ksga I have no problem in adding this other alternative library in NodeManager but it is really strange it is working for you with the adafruit library but not in NodeManager which is using the same library :-/ Did you set the same address in NodeManager's as well? Can you share the sketch you got it working with the Adafruit library so I can compare the code and see what I do differently in NodeManager preventing it to work for you? Thanks!
-
I have a BMP280 sensor (as far as i know, they are quite similar). At first it seemed like the sensor was not detected. After inspecting the datasheet, i found out that the address could be selected (one of 2 possibilities).
Here's the text from the datasheet:Connecting SDO to GND results in slave
address 1110110 (0x76); connection it to VDDIO results in slave address 1110111 (0x77)Some people change the library code, but (like in my case), i only needed to connect the SDO pin to +3.3V.
At first i did not connect the SDO pin at all, and my sensor was not reporting at all. That was because of this:
The SDO pin cannot be left floating; if left floating, the
I²C address will be undefined.Perhaps those issues can be the cause of your problems ksga?
-
I have a BMP280 sensor (as far as i know, they are quite similar). At first it seemed like the sensor was not detected. After inspecting the datasheet, i found out that the address could be selected (one of 2 possibilities).
Here's the text from the datasheet:Connecting SDO to GND results in slave
address 1110110 (0x76); connection it to VDDIO results in slave address 1110111 (0x77)Some people change the library code, but (like in my case), i only needed to connect the SDO pin to +3.3V.
At first i did not connect the SDO pin at all, and my sensor was not reporting at all. That was because of this:
The SDO pin cannot be left floating; if left floating, the
I²C address will be undefined.Perhaps those issues can be the cause of your problems ksga?
@core_c this is what I was thinking of as well. Right now in NodeManager the only way to change the i2c address is to change the core code under registerSensor() in NodeManager.cpp which is not handy. I need to find out how to provide an easy way to set it. The problem is registerSensor() takes a fixed number of parameters (and I want it to stay in this way) and it is responsible to create the bmp/bme object, passing it to the 2-3 child sensors. I can provide a setAddress() function but the user needs just after to retrieve each sensor (temperature, humidity, pressure, etc.) and set it manually which is not not great.
I've opened https://github.com/mysensors/NodeManager/issues/85 for this which is needed regardless. Thanks -
@core_c this is what I was thinking of as well. Right now in NodeManager the only way to change the i2c address is to change the core code under registerSensor() in NodeManager.cpp which is not handy. I need to find out how to provide an easy way to set it. The problem is registerSensor() takes a fixed number of parameters (and I want it to stay in this way) and it is responsible to create the bmp/bme object, passing it to the 2-3 child sensors. I can provide a setAddress() function but the user needs just after to retrieve each sensor (temperature, humidity, pressure, etc.) and set it manually which is not not great.
I've opened https://github.com/mysensors/NodeManager/issues/85 for this which is needed regardless. Thanks@core_c found a great way to to let NodeManager identifying automatically which i2c address the sensor is using without the need for the user to change anything in the code. This is done by requesting the chip_id for the two i2c address and comparing it with the expected one to identify the right address. I've implemented it for both the BME280 and BMP085/BMP180 sensors and it is available in 1.5-dev3 (https://github.com/mysensors/NodeManager/tree/702a05c7e2f4425c188d5abf62b4a119fea29bc8). Also, under the hood, I've created a SensorBosch class which is not exposed but helps providing common functionalities to the two sensors without duplicating the code.
Finally, specifically for your problem @ksga, I found a critical bug in the BME280 class. I wonder how I've missed it so far. For some unknown reasons, the bme object created by registerSensor and passed to the SensorBME280 class, was not stored by the latter. This means it was calling e.g. readTemperature on a null pointer which I even wonder why was not crashing everything. It has been fixed in 1.5-dev3 so if you would like to give it a try, I'm more confident it will work just fine finally :-)
-
Do you think would make any sense to add NodeManager among the Arduino's examples? So that from the IDE one can select Examples, MySensors and NodeManager would show up like MotionSensor and the others. However I'd expect new versions of NM to be released more frequently than updates to the core code so it might happen an outdated version to be available there...
-
I've added a rain gauge out-out-the-box sensor for the latest dev release called 1.5-dev5 (https://github.com/mysensors/NodeManager/tree/126812a9d01311640416222be8225fdcca1e7266). This is intended to be the last enhancement for the upcoming v1.5 version but of course I'll wait for some additional days to collect (and fix) any issue all the new sensors might have.
The implementation of the rain gauge sensor has to be different than the one from the build section for a good number of reasons and limitations. All the details here: https://github.com/mysensors/NodeManager/issues/90.
-
Hi, nice work!
I have changed the code for REBOOT so there is no need for a reboot-pin.
like this...else if (strcmp(message, "REBOOT") == 0) {
#if DEBUG == 1
Serial.println(F("REBOOT"));
#endif
// Software reboot with watchdog timer
// Enter Watchdog Configuration mode:
WDTCSR |= (1<<WDCE) | (1<<WDE);
// Reset enable
WDTCSR= (1<<WDE);
// Infinite loop until watchdog reset after 16 ms
while(true){}
} -
Hi, nice work!
I have changed the code for REBOOT so there is no need for a reboot-pin.
like this...else if (strcmp(message, "REBOOT") == 0) {
#if DEBUG == 1
Serial.println(F("REBOOT"));
#endif
// Software reboot with watchdog timer
// Enter Watchdog Configuration mode:
WDTCSR |= (1<<WDCE) | (1<<WDE);
// Reset enable
WDTCSR= (1<<WDE);
// Infinite loop until watchdog reset after 16 ms
while(true){}
}@Dencan interesting thanks! I initially thought there were two use cases, one is to reboot with a remote command and the other is by using a pin (e.g. when having physical access is easier than sending out a message). But I think you're right, if you have physical access, well, hitting the reset button is way easier than connecting the reboot pin to RST ;-)
I'll use this snippet for the version about to be released (https://github.com/mysensors/NodeManager/issues/101). Thanks! -
Hi, nice work!
I have changed the code for REBOOT so there is no need for a reboot-pin.
like this...else if (strcmp(message, "REBOOT") == 0) {
#if DEBUG == 1
Serial.println(F("REBOOT"));
#endif
// Software reboot with watchdog timer
// Enter Watchdog Configuration mode:
WDTCSR |= (1<<WDCE) | (1<<WDE);
// Reset enable
WDTCSR= (1<<WDE);
// Infinite loop until watchdog reset after 16 ms
while(true){}
}@Dencan That is a method i never even thought about Dencan.
Cool.. You tought me something. Thanks. I have to try it out for myself. :)
My first thought was jumping to the address of the RESET interrupt vector in memory.
It's located in the very first bytes at address 0.__asm__ __volatile__ ("jmp 0"); -
Version 1.5 of NodeManager is finally available here!
https://github.com/mysensors/NodeManagerI've done my best to implement most of the requests received so far since unfortunately I'm expecting starting from June very little spare time to spend here so I tried to hurry up a bit :-) The result is a pretty long change log and a total of 26 between ad-hoc and generic out-of-the-box sensors supported up to this release:
- Added support for ACS712 current sensor
- Added support for HC-SR04 distance sensor
- Added support for BMP085/BMP180 temperature and pressure sensor
- Added support for Sonoff smart switch
- Added support for Rain Gauge sensor
- Added support for MCP9808 temperature sensor
- Added forecast output to all Bosch sensors
- Added I2C address auto-discovery for all Bosch sensors
- Added support for running as a gateway
- Added option to retrieve the latest value of a sensor from outside NodeManager
- Remote reboot now does not need a reboot pin configured
- A heartbeat is now sent also when waking up from a wait cycle
- When waking up for an interrupt, only the code of the sensor expecting that interrupt is executed
- Added capability to retrieve the time from the controller
- Optimized battery life for DS18B20 sensors
- SLEEP_MANAGER has been deprecated (now always enabled) and setMode() replaces setSleepMode()
- New mode ALWAYS_ON to let the node staying awake and executing each sensors' loop
- ESP8266WiFi.h has to be included in the main sketch if MY_GATEWAY_ESP8266 is defined
- Added receiveTime() wrapper in the main sketch
- Fixed the logic for output sensors
- Added common gateway settings in config.h
I've added upgrade instructions as well in the documentation. Generally speaking to upgrade it is safe to just replace the existing NodeManager.h and NodeManager.cpp files but with this release I had to do some minor changes to the main sketch as well, as documented in the release notes.
Thanks everybody for all the advice and for reporting any issue always in a constructive way :-)
-
Hi, I've added a "How to contribute" section in the documentation of the dev release in case anybody is interested to contribute to this project: https://github.com/mysensors/NodeManager/tree/development#contributing.
I'm not a git expert so I hope those instructions to have some sense :)
-
Very good job @user2684 ! I like it very much.
Only one thing, how I can create a simple DHT22 node? I activated MODULE_DHT, and registered like this:/* Register below your sensors */ int sensorDHT_Id = nodeManager.registerSensor(SENSOR_DHT22,4); SensorDHT* sensorDHT = (SensorDHT*)nodeManager.getSensor(sensorDHT_Id); sensorDHT->setSamples(5); sensorDHT->setTackLastValue(true); sensorDHT->setForceUpdate(5); /* Register above your sensors */But when compiling it throws:
'DHT11' was not declared in this scopeI have the DHT library installed by the env, and a copy at the projects libraries folder (portable) and also at the same project folder (when opening the sketch also opens the library), but still complains.
??
-
Very good job @user2684 ! I like it very much.
Only one thing, how I can create a simple DHT22 node? I activated MODULE_DHT, and registered like this:/* Register below your sensors */ int sensorDHT_Id = nodeManager.registerSensor(SENSOR_DHT22,4); SensorDHT* sensorDHT = (SensorDHT*)nodeManager.getSensor(sensorDHT_Id); sensorDHT->setSamples(5); sensorDHT->setTackLastValue(true); sensorDHT->setForceUpdate(5); /* Register above your sensors */But when compiling it throws:
'DHT11' was not declared in this scopeI have the DHT library installed by the env, and a copy at the projects libraries folder (portable) and also at the same project folder (when opening the sketch also opens the library), but still complains.
??
@Sergio-Rius thanks! Are you sure you are using the DHT library from the arduino IDE ( https://github.com/adafruit/DHT-sensor-library) and not the one from the MySensors example folder? Thanks
-
@Sergio-Rius thanks! Are you sure you are using the DHT library from the arduino IDE ( https://github.com/adafruit/DHT-sensor-library) and not the one from the MySensors example folder? Thanks
@user2684
AH! You're right, you got me. I'll change and test it. Anyways the one I was using was failing frecuently reading the sensor.But you could also make your wrapper compatible with the MyS one. The difference between both is that the later places its declarations inside the class. You can make it work by fully qualifying the calls like the example:
NodeManager.cpp @1949: int dht_type = sensor_type == SENSOR_DHT11 ? _dht.DHT11 : _dht.DHT22;It could be interesting if there are anyone really needing the MyS DHT library. And also it seems more memory optimized. The adafruit's are two in one and also needs another library helper in cascade.
-
@user2684
AH! You're right, you got me. I'll change and test it. Anyways the one I was using was failing frecuently reading the sensor.But you could also make your wrapper compatible with the MyS one. The difference between both is that the later places its declarations inside the class. You can make it work by fully qualifying the calls like the example:
NodeManager.cpp @1949: int dht_type = sensor_type == SENSOR_DHT11 ? _dht.DHT11 : _dht.DHT22;It could be interesting if there are anyone really needing the MyS DHT library. And also it seems more memory optimized. The adafruit's are two in one and also needs another library helper in cascade.
@Sergio-Rius great idea! Will prevent people to get crazy with compile errors, thanks!
I'll track this with https://github.com/mysensors/NodeManager/issues/144 -
@Sergio-Rius great idea! Will prevent people to get crazy with compile errors, thanks!
I'll track this with https://github.com/mysensors/NodeManager/issues/144@user2684 Nevermid! I'm still struggling trying to make the TH sensor :sweat_smile:
That's the serial output I get and nothing at domoticz.REG I=1 P=4 P=6 T=0 REG I=2 P=4 P=7 T=1 NodeManager v1.5 INT1 M=255 INT2 M=255 RADIO OK PRES I=200, T=23 PRES I=201, T=30 BATT V=2.95 P=50 SEND D=0 I=201 C=0 T=38 S= I=0 F=2.95 PRES I=1 T=6 PRES I=2 T=7 READY MY I=3 M=1 -
@user2684 Nevermid! I'm still struggling trying to make the TH sensor :sweat_smile:
That's the serial output I get and nothing at domoticz.REG I=1 P=4 P=6 T=0 REG I=2 P=4 P=7 T=1 NodeManager v1.5 INT1 M=255 INT2 M=255 RADIO OK PRES I=200, T=23 PRES I=201, T=30 BATT V=2.95 P=50 SEND D=0 I=201 C=0 T=38 S= I=0 F=2.95 PRES I=1 T=6 PRES I=2 T=7 READY MY I=3 M=1@Sergio-Rius ok, this is kind of a standard startup with the temperature and humidity sensors presented as child 1 and 2, so far so good.
PRES I=1 T=6 PRES I=2 T=7By default no data is reported unless the node enters in a cycle. You would like to add:
nodeManager.setSleep(SLEEP, 10, MINUTES);Or
nodeManager.setSleep(WAIT, 10, MINUTES);To start getting periodically the data out. Alternatively you can send a REQ message to the child id with the appropriate V_type
-
@Sergio-Rius ok, this is kind of a standard startup with the temperature and humidity sensors presented as child 1 and 2, so far so good.
PRES I=1 T=6 PRES I=2 T=7By default no data is reported unless the node enters in a cycle. You would like to add:
nodeManager.setSleep(SLEEP, 10, MINUTES);Or
nodeManager.setSleep(WAIT, 10, MINUTES);To start getting periodically the data out. Alternatively you can send a REQ message to the child id with the appropriate V_type
@user2684 Mmmmm what if you have a motion sensor in the same node? (I'm trying to migrate my own sketch)
-
@user2684
AH! You're right, you got me. I'll change and test it. Anyways the one I was using was failing frecuently reading the sensor.But you could also make your wrapper compatible with the MyS one. The difference between both is that the later places its declarations inside the class. You can make it work by fully qualifying the calls like the example:
NodeManager.cpp @1949: int dht_type = sensor_type == SENSOR_DHT11 ? _dht.DHT11 : _dht.DHT22;It could be interesting if there are anyone really needing the MyS DHT library. And also it seems more memory optimized. The adafruit's are two in one and also needs another library helper in cascade.
@Sergio-Rius said in š¬ NodeManager:
The difference between both is that the later places its declarations inside the class.
Please don't waste your time as they are not compatible. In my stupidity didn't make sure that my lib wasn't "personalized".
What a pity.