This is what I recently created to enclose newbie PCB with two AA batteries.
https://www.thingiverse.com/thing:3228067
Michał Kozak
@Michał Kozak
Best posts made by Michał Kozak
-
Newbie PCB (not only) housing in different sizes
-
RE: Need help to understand basic communication API: send, receive, ACK
@mfalkvidd that's helped me a lot to better understand what is happening during send! Thanks!
-
RE: sendBatteryLevel is not published to MQTT
I'm still investigating my problem
I checked logs from gateway and I can't see received messages with battery level, so looks like message is not reaching a gateway at all.
Situation improved a bit when I started using sendBatteryLevel with ACK, but it is still not perfect :).
I suspect that because sendBatteryLevel is a first message send after arduino wakes up maybe it could be that transport layer is not initilized yet? Maybe I should wait few sec after wake up before I start sending messages? What do you think?
Latest posts made by Michał Kozak
-
Newbie PCB (not only) housing in different sizes
This is what I recently created to enclose newbie PCB with two AA batteries.
https://www.thingiverse.com/thing:3228067 -
RE: !TSM:FPAR:NO REPLY
Hmmm.... today I managed to connect this node to gateway. I just rebooted gateway...
-
RE: !TSM:FPAR:NO REPLY
@alowhum said in !TSM:FPAR:NO REPLY:
MY_TRANSPORT_WAIT_READY_MS
I must admit that now I'm in "experimenting mode" trying every idea and see whether it helps.
Maybe you are right but the default is 0ms (see MyConfig.h) -
RE: !TSM:FPAR:NO REPLY
Looks like I stared facing simillar issues
Logs from node (assembled on NewbiPCB) with 100uF cap.
111382 !TSM:FPAR:NO REPLY 111384 TSM:FPAR 111421 TSF:MSG:SEND,4-4-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK: 113430 !TSM:FPAR:NO REPLY 113432 TSM:FPAR 113469 TSF:MSG:SEND,4-4-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK: 115478 !TSM:FPAR:NO REPLY 115480 TSM:FPAR 115517 TSF:MSG:SEND,4-4-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK: 117526 !TSM:FPAR:FAIL 117528 TSM:FAIL:CNT=7 117530 TSM:FAIL:DIS 117532 TSF:TDI:TSL
Gateway
Sep 29 21:30:17 DEBUG !TSF:MSG:SEND,0-0-4-4,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=NACK:0 Sep 29 21:30:18 DEBUG TSF:MSG:READ,4-4-255,s=255,c=3,t=7,pt=0,l=0,sg=0: Sep 29 21:30:18 DEBUG TSF:MSG:BC Sep 29 21:30:18 DEBUG TSF:MSG:FPAR REQ,ID=4 Sep 29 21:30:18 DEBUG TSF:CKU:OK,FCTRL Sep 29 21:30:18 DEBUG TSF:MSG:GWL OK Sep 29 21:30:19 DEBUG !TSF:MSG:SEND,0-0-4-4,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=NACK:0 Sep 29 21:30:20 DEBUG TSF:MSG:READ,4-4-255,s=255,c=3,t=7,pt=0,l=0,sg=0: Sep 29 21:30:20 DEBUG TSF:MSG:BC Sep 29 21:30:20 DEBUG TSF:MSG:FPAR REQ,ID=4 Sep 29 21:30:20 DEBUG TSF:CKU:OK,FCTRL Sep 29 21:30:20 DEBUG TSF:MSG:GWL OK Sep 29 21:30:21 DEBUG !TSF:MSG:SEND,0-0-4-4,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=NACK:0 Sep 29 21:30:22 DEBUG TSF:MSG:READ,4-4-255,s=255,c=3,t=7,pt=0,l=0,sg=0: Sep 29 21:30:22 DEBUG TSF:MSG:BC Sep 29 21:30:22 DEBUG TSF:MSG:FPAR REQ,ID=4 Sep 29 21:30:22 DEBUG TSF:CKU:OK,FCTRL Sep 29 21:30:22 DEBUG TSF:MSG:GWL OK Sep 29 21:30:23 DEBUG !TSF:MSG:SEND,0-0-4-4,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=NACK:0
Today I'm on development branch. I switched from 2.3.0 which had simillar issues hoping the problem will be resolved.
My sketch which isn't clean because I'm experimenting, trying to find solution
#define MY_DEBUG //#define MY_PASSIVE_NODE #define MY_TRANSPORT_WAIT_READY_MS 1 #define MY_RADIO_NRF24 #define MY_NODE_ID 4 //#define MY_PARENT_NODE_ID 0 //#define MY_PARENT_NODE_IS_STATIC //#define MY_RF24_PA_LEVEL RF24_PA_MAX #include <MySensors.h> // MYSENSORS_LIBRARY_VERSION // https://github.com/finitespace/BME280 #include <BME280I2C.h> typedef struct BatteryStatus { float voltage; int level; BatteryStatus() { voltage = 0; level = 0; } } BatteryStatus; typedef struct Weather { float temperature; float humidity; float baro; Weather() { temperature = -127.0; humidity = -127.0; baro = -127.0; } } Weather; const uint32_t SLEEP_TIME = 15*60*1000ul; const bool DEBUG = true; const float VBAT_FULL = 2.8; const float VBAT_EMPTY = 2.0; const byte BATTERY_VOLTAGE_SENSOR_ID = 3; const byte TEMPERATURE_SENSOR_ID = 1; const byte HUMIDITY_SENSOR_ID = 2; const byte BARO_SENSOR_ID = 4; // current sensors readings BatteryStatus batteryStatus; Weather weather; // define mysensors messages MyMessage vbatMsg(BATTERY_VOLTAGE_SENSOR_ID, V_VOLTAGE); MyMessage temperatureMsg(TEMPERATURE_SENSOR_ID, V_TEMP); MyMessage humidityMsg(HUMIDITY_SENSOR_ID, V_HUM); MyMessage baroMsg(BARO_SENSOR_ID, V_PRESSURE); // configure BME280 sensor BME280I2C::Settings settings( BME280::OSR_X1, BME280::OSR_X1, BME280::OSR_X1, BME280::Mode_Forced, // Forced sample. After taking the measurement the chip goes back to sleep. BME280::StandbyTime_1000ms, BME280::Filter_Off, BME280::SpiEnable_False, 0x76 // I2C address. I2C specific. ); BME280I2C bme(settings); BME280::TempUnit temperatureUnit(BME280::TempUnit_Celsius); BME280::PresUnit baroUnit(BME280::PresUnit_hPa); void readBatteryStatus(BatteryStatus& batteryStatus) { int val = analogRead(A0); float voltage = val * 0.0033464521; int level; if (voltage > VBAT_FULL) { level = 100; } else if (voltage < VBAT_EMPTY) { level = 0; } else { level = (int) ((voltage - VBAT_EMPTY) * 100.0 / (VBAT_FULL - VBAT_EMPTY)); } if (DEBUG) { Serial.print("readBatteryStatus: "); Serial.print("val="); Serial.print(val); Serial.print(", level="); Serial.print(level); Serial.print("%, "); Serial.print("voltage="); Serial.print(voltage); Serial.print("V"); Serial.println(); } batteryStatus.voltage = voltage; batteryStatus.level = level; } void readWeather(Weather& weather) { bme.read(weather.baro, weather.temperature, weather.humidity, temperatureUnit, baroUnit); if (DEBUG) { Serial.print("readWeather: "); Serial.print("temperature="); Serial.print(weather.temperature); Serial.print("C"); Serial.print(", humidity="); Serial.print(weather.humidity); Serial.print("%"); Serial.print(", baro="); Serial.print(weather.baro); Serial.println("hPa"); } } void send(Weather& weather) { //send_hard(temperatureMsg.set(weather.temperature, 1)); //send_hard(humidityMsg.set(weather.humidity, 1)); //send_hard(baroMsg.set(weather.baro, 1)); } void send(BatteryStatus& batteryStatus) { //send_hard(vbatMsg.set(batteryStatus.voltage, 2)); sendBatteryLevel(batteryStatus.level); } void send_hard(MyMessage& msg) { int retry = 5; while (retry--) { if (send(msg)) { return; } Serial.println("RETRY"); wait(50); // TODO: Add some random value to send } } void setup() { // configure analog pin and do the first read // looks like first read always returns MAX value, // subsequent reads seems to be accurate analogReference(INTERNAL); analogRead(A0); int bmeRetry = 10; while(!bme.begin() && bmeRetry > 0) { Serial.println("Could not find BME280I2C sensor!"); delay(1000); bmeRetry--; } } void presentation() { sendSketchInfo("Weather", "1.0"); present(BATTERY_VOLTAGE_SENSOR_ID, S_MULTIMETER, "BAT/VOLTAGE"); present(BARO_SENSOR_ID, S_BARO, "BARO"); present(TEMPERATURE_SENSOR_ID, S_TEMP, "TEMPERATURE"); present(HUMIDITY_SENSOR_ID, S_HUM, "HUMIDITY"); Serial.println("mmmmmmm"); } void loop() { readWeather(weather); send(weather); readBatteryStatus(batteryStatus); send(batteryStatus); if (DEBUG) { Serial.print("batteryStatus.level="); Serial.print(batteryStatus.level); Serial.print("%, batteryStatus.voltage="); Serial.print(batteryStatus.voltage); Serial.println("V"); Serial.print("weather: "); Serial.print("temperature="); Serial.print(weather.temperature); Serial.print("C"); Serial.print(", humidity="); Serial.print(weather.humidity); Serial.print("%"); Serial.print(", baro="); Serial.print(weather.baro); Serial.println("hPa"); Serial.println(); } if (DEBUG) { wait(10*1000ul); } else { wait(SLEEP_TIME); } }
-
RE: Need help to understand basic communication API: send, receive, ACK
@mfalkvidd that's helped me a lot to better understand what is happening during send! Thanks!
-
Need help to understand basic communication API: send, receive, ACK
Looks like I have a problem to understand how sending exactly works? I read the docs, examples, I created sketches for 4 nodes but I'm still not sure wether I use the function send correctly.
The function returns boolean which according to documentation:
Returns true if message reached the first stop on its way to destination.
My doubts here:- If I send without ACK, how does a node "knows" that the "message reached the first stop on its way" ? How to interpret the returned boolean in such case? If I get false should I repeat sending?
- If I want to use ACK, does the send function call blocks execution until ACK is received then it returns true? Do I need to implement receive function and handle ACK by myself?
-
RE: sendBatteryLevel is not published to MQTT
I'm still investigating my problem
I checked logs from gateway and I can't see received messages with battery level, so looks like message is not reaching a gateway at all.
Situation improved a bit when I started using sendBatteryLevel with ACK, but it is still not perfect :).
I suspect that because sendBatteryLevel is a first message send after arduino wakes up maybe it could be that transport layer is not initilized yet? Maybe I should wait few sec after wake up before I start sending messages? What do you think?
-
RE: sendBatteryLevel is not published to MQTT
Example massages published to MQTT
mysensors-out/3/3/1/0/38 2.65 mysensors-out/3/1/1/0/0 37.9 mysensors-out/3/2/1/0/0 29.2
As you can see voltage is published (mysensors-out/3/3/1/0/38 2.65) so looking into my sketch I would expect that battery level also is published because I send battery level and voltage in sendBatteryStatus function.
-
RE: sendBatteryLevel is not published to MQTT
@rozpruwacz I haven't checked that.
@mfalkvidd here it is my complete sketch. Battery level should be published to MQTT together with battery voltage. I can see battery voltage in MQTT but not battery level.//#define MY_DEBUG #define MY_RADIO_NRF24 #define MY_NODE_ID 3 #define MY_RF24_PA_LEVEL RF24_PA_MAX #include <MySensors.h> #include <DallasTemperature.h> #include <OneWire.h> typedef struct BatteryStatus { float voltage; int level; } BatteryStatus; typedef struct Temperatures { float top; float bottom; } Temperatures; const byte TOP_SENSOR_ID = 1; const byte BOTTOM_SENSOR_ID = 2; const byte BATTERY_VOLTAGE_SENSOR_ID = 3; const uint32_t SLEEP_TIME = 600000UL; const bool DEBUG = false; const bool DO_SEARCH_DEVICES = false; const float VBAT_FULL = 2.8; const float VBAT_EMPTY = 2.0; BatteryStatus batteryStatus; BatteryStatus currentBatteryStatus; Temperatures temperatures; Temperatures currentTemperatures; // define oneWire communication OneWire oneWire(3); DallasTemperature sensors(&oneWire); DeviceAddress topThermometer = {0x28,0xFF,0xF8,0x5,0x1A,0x4,0x0,0x4A}; DeviceAddress bottomThermometer = {0x28,0xFF,0x71,0xF,0x12,0x4,0x0,0x4C}; // define mysensors messages MyMessage tempTopMsg(TOP_SENSOR_ID, V_TEMP); MyMessage tempBottomMsg(BOTTOM_SENSOR_ID, V_TEMP); MyMessage vbatMsg(BATTERY_VOLTAGE_SENSOR_ID, V_VOLTAGE); void getBatteryStatus(BatteryStatus *batteryStatus) { int val = analogRead(A0); float voltage = val * 0.00325458871; int level; if (voltage > VBAT_FULL) { level = 100; } else if (voltage < VBAT_EMPTY) { level = 0; } else { level = (int) ((voltage - VBAT_EMPTY) * 100.0 / (VBAT_FULL - VBAT_EMPTY)); } if (DEBUG) { Serial.print("getBatteryStatus: "); Serial.print("val="); Serial.print(val); Serial.print(", level="); Serial.print(level); Serial.print("%, "); Serial.print("voltage="); Serial.print(voltage); Serial.print("V"); Serial.println(); } batteryStatus->voltage = voltage; batteryStatus->level = level; } void sendBatteryStatus(BatteryStatus *batteryStatus) { sendBatteryLevel(batteryStatus->level); vbatMsg.set(batteryStatus->voltage, 2); send(vbatMsg); } bool isTemperatureValid(float temp) { return temp != -127.00 && temp != 85.00; } bool getTemperatures(Temperatures *temperatures) { sensors.requestTemperatures(); int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution()); sleep(conversionTime); temperatures->top = sensors.getTempC(topThermometer); temperatures->bottom = sensors.getTempC(bottomThermometer); if (DEBUG) { Serial.print("getTemperatures: "); Serial.print("top="); Serial.print(temperatures->top); Serial.print(", bottom="); Serial.print(temperatures->bottom); Serial.println(); } return isTemperatureValid(temperatures->top) && isTemperatureValid(temperatures->bottom); } void sendTemperatures(Temperatures *temperatures) { tempTopMsg.set(temperatures->top, 1); tempBottomMsg.set(temperatures->bottom, 1); send(tempTopMsg); send(tempBottomMsg); } void searchDevices() { Serial.print("Locating devices..."); int deviceCount = sensors.getDeviceCount(); Serial.print("found "); Serial.print(deviceCount, DEC); Serial.println(" devices."); for (int deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++) { DeviceAddress addr; if (sensors.getAddress(addr, deviceIndex)) { Serial.print("Device "); Serial.print(deviceIndex, DEC); Serial.print(" = {"); for (uint8_t i = 0; i < 8; i++) { Serial.print("0x"); Serial.print(addr[i], HEX); if (i + 1 < 8) { Serial.print(","); } } Serial.print("}"); Serial.println(); } else { Serial.print("Unable to find address for Device "); Serial.println(deviceIndex, DEC); } } } void before() { sensors.begin(); if (DO_SEARCH_DEVICES) { searchDevices(); } } void setup() { // configure analog pin and do the first read // looks like first read always returns MAX value, // subsequent reads seems to be accurate analogReference(INTERNAL); analogRead(A0); batteryStatus.level = 0; batteryStatus.voltage = 0; temperatures.top = -127.00; temperatures.bottom = -127.00; // configure temperature readings to not block current thread sensors.setWaitForConversion(false); } void presentation() { sendSketchInfo("CWU", "1.2"); present(TOP_SENSOR_ID, S_TEMP, "Top temp"); present(BOTTOM_SENSOR_ID, S_TEMP, "Bottom temp"); present(BATTERY_VOLTAGE_SENSOR_ID, S_MULTIMETER, "Vbat"); } void loop() { if (DEBUG) { Serial.print("batteryStatus.level="); Serial.print(batteryStatus.level); Serial.print("%, batteryStatus.voltage="); Serial.print(batteryStatus.voltage); Serial.println("V"); Serial.print("temperatures.top="); Serial.print(temperatures.top); Serial.print(", temperatures.bottom="); Serial.print(temperatures.bottom); Serial.println(); } getBatteryStatus(¤tBatteryStatus); if (batteryStatus.level != currentBatteryStatus.level || batteryStatus.voltage != currentBatteryStatus.voltage) { if (DEBUG) { Serial.println("Sending battery status"); } batteryStatus = currentBatteryStatus; sendBatteryStatus(&batteryStatus); } if (getTemperatures(¤tTemperatures)) { if (temperatures.top != currentTemperatures.top || temperatures.bottom != currentTemperatures.bottom) { if (DEBUG) { Serial.println("Sending temperatures"); } temperatures = currentTemperatures; sendTemperatures(&temperatures); } } sleep(SLEEP_TIME); }
-
sendBatteryLevel is not published to MQTT
This is my setup:
- mysgw (2.3.0 release) connecting to mosquitto MQTT
- one node with 3 sensors (node compiled using 2.3.0 Arduino lib)
Node uses sendBatteryLevel function to send current battery level. I can see that when node when starts, then "prenests" itself to gateway battery level is published to MQTT. Then node goes to sleep for 10min, then wakes up and sends battery level again (amoung other sensor values). Each sensor value is published to MQTT but battery level not.