Node with DS18B20+Relay dies, also with watchdog
-
Hi to all,
I have a node with Atmega 8Mhz that sends temperature and receive on/off for relay. It is powered from wall with a charger and a breadboard power. 3.3v for Atmega (without XTAL) and 5V for the relay. So relay is not powered from Atmega, Atmega give only the "consensus".Sometimes it did hang. So, I did try to add watchdog. This morning on my wakeup I did find it die.
First of all, I need to say you that relay was poweroff for about 2h (I have last temp report about at 00:02 (it did hang from 00:.02 and 00:07, so), relay instead was off from the 22:00), so no interference from it and node was only reading temp every 5 minutes and reporting it to the Domoticz.No more light status blinking (and no responding to the controller). I have at the end of the loop a function that light a led status for 10ms, pause 4990ms (total 5 sec) and repeat this instruction. At the end, restart the loop. So, I have a visual feedback if node is live.
I did note that adding watchdog, also without reset, the watchdog itself is not fired, also with very small times. So I imagine that several Mysensors call "interfere" with watchdog. I can only fire the watchdog if - with a false returning send instruction - I call the "delay" base instructions (you can see it in my code).
My logic: retry to send for max 4 times. If 4th time is false (the send), introduce delay. Watchdog is fired ("finally") and restart coming.
This is the code. Please, someone can help me to render it more stable? I have no idea where it hangs, because is it not connected on the PC but it is "headless".
Thank you in advance!
/** * Sketch for a relay + termostat. * * In test from 27/09/2017 * * * @version 2.1 * */ /** * DEFINE MYSENSORS SECTION */ //#define MY_DEBUG // Enable Basic Debug //#define MY_DEBUG_VERBOSE_SIGNING // Enable Signing Debug #define MY_RADIO_NRF24 #define MY_SIGNING_SOFT #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 #define MY_SIGNING_REQUEST_SIGNATURES #define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x3B,0xF4,0x61,0xDF,0x1E,0x97,0xB1,0x2D,0xEC}}} #define MY_NODE_ID 10 // Default ID #define MY_DEFAULT_LED_BLINK_PERIOD 300 #define MY_WITH_LEDS_BLINKING_INVERSE #define MY_DEFAULT_ERR_LED_PIN 16 #define MY_DEFAULT_TX_LED_PIN 17 #define MY_DEFAULT_RX_LED_PIN 18 /** * Include libraries */ #include <SPI.h> #include <MySensors.h> #include <DallasTemperature.h> #include <OneWire.h> #include <avr/wdt.h> /** * Define section. * * // NAME */ #define SKETCH_NAME "Termostato+Relay" #define SKETCH_VERSION "2.1" // PIN #define PIN_DS18B20 2 #define PIN_RELAY 3 #define PIN_LED_STATUS 19 // CHILD ID #define CHILD_ID_TEMP 0 #define CHILD_ID_RELAY 1 // RELAY SECTION #define RELAY_ON 1 // if inverted, invert here #define RELAY_OFF 0 // if inverted, invert here // WAITs TIMES #define WAIT_LOOPS 60 // The status led flashes ON 10 ms and OFF 4990 ms == 5000 ms of loop. 5000 * WAIT_LOOPS = number of cycles before new read. 60 == 5 minutes // 12 here means 1 minute. 12 * 5000 ms = 60 sec = 1 minute // 60 here means 5 minutes. 60 * 5000 ms = 300 sec = 5 minutes /* * One Wire Section */ OneWire oneWire(PIN_DS18B20); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature. /** * Mysensors message */ // Initialize temperature message MyMessage msg_temperature(CHILD_ID_TEMP , V_TEMP); // Initialize relay message MyMessage msg_relay(CHILD_ID_RELAY , V_STATUS); /** * Before class */ void before() { // Startup up the OneWire library sensors.begin(); } /** * Presentation. * * Presents the child to the controller */ void presentation() { // send sketch name sendSketchInfo(SKETCH_NAME , SKETCH_VERSION); // Present all sensors to controller. // TEMPERATURE present(CHILD_ID_TEMP, S_TEMP); // RELAY present(CHILD_ID_RELAY , S_BINARY); } /** * Our Setup */ void setup() { wdt_enable(WDTO_2S); Serial.println("Start sketch"); // SETUP LED STATUS // Set the LED STATUS as OUTPUT and shutdown it. pinMode(PIN_LED_STATUS , OUTPUT); digitalWrite(PIN_LED_STATUS , LOW); // SETUP RELAY // Set the RELAY PIN as OUTPUT and LOW pinMode(PIN_RELAY , OUTPUT); digitalWrite(PIN_RELAY , RELAY_OFF); // initialize sensors sensors.setWaitForConversion(false); } /** * Our loop */ void loop() { // send the relay state to controller sendRelayStateToController(); // executed the reading loopTemperature(); // light the status led... so wait lightLedStatus(); } /* * Send the state of relay to controller. * * @since 2.1 */ void sendRelayStateToController() { Serial.println("-------------- DEBUG sendRelayStateToController() ---------------"); bool current_state = digitalRead(PIN_RELAY); //current_state = !current_state; // delete if NOT inverted if (current_state == 1) { current_state = RELAY_ON; } else { current_state = RELAY_OFF; } Serial.print("current_state value is "); Serial.println(current_state); bool transmission_was_ok = false; int i = 0; do { transmission_was_ok = send(msg_relay.set(current_state) , true); Serial.print("Variable i is "); Serial.println(i); Serial.print("Variable transmission_was_ok value is "); Serial.println(transmission_was_ok); i++; if ( i > 3 ) { delay(5000); // this delay will call watchdog! } } while (transmission_was_ok == false); Serial.println("------------------------------------------------------------"); } /** * Loop temperature. * Executed inside loop() * * @since 2.0 */ void loopTemperature() { // Fetch temperatures from Dallas sensors // we need sensors.requestTemperatures() to NO BLOCK THE THREAD!!! sensors.requestTemperatures(); float temperature = readTemperature(); Serial.println("-------------- DEBUG loopTemperature() ---------------"); Serial.print("Temperature is now "); Serial.println(temperature); Serial.println("------------------------------------------------------"); sendTemperatureToController(temperature); } /************************************************/ /**** VARIOUS FUNCTION TO SUPPORT *****/ /************************************************/ /** * Receive function * * @since 2.0 */ void receive(const MyMessage &message) { Serial.println("-------------- DEBUG receive() ---------------"); Serial.print("message.type value is "); Serial.println(message.type); Serial.println("------------------------------------------"); Serial.print("message.getCommand() value is "); Serial.println(message.getCommand()); Serial.println("------------------------------------------"); if ( message.isAck() ) { if ( message.type == V_STATUS ) { Serial.println("Relay state transmitted"); } if ( message.type == V_TEMP ) { Serial.println("Temperature transmitted"); } } if ( !message.isAck() ) { if ( message.type == V_STATUS) { if ( message.getCommand() == 1 ) { bool received_state = message.getBool(); Serial.print("received_state value is "); Serial.println(received_state); if ( received_state == 1) { digitalWrite(PIN_RELAY , RELAY_ON); } else { digitalWrite(PIN_RELAY , RELAY_OFF); } } } } Serial.println("--------------------------------------------"); } /** * Read the temperature from DS18B20 * * @since 2.0 */ float readTemperature() { // query conversion time and sleep until conversion completed int16_t conversionTime = millisToWaitForConversion(sensors.getResolution()); wait(conversionTime); // Read temperatures and send them to controller // Fetch and round temperature to one decimal float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(CHILD_ID_TEMP):sensors.getTempFByIndex(CHILD_ID_TEMP)) * 10.)) / 10.; return temperature; } /** * Get the millis to wait before reading based on resolution. * * @since 2.0 */ int16_t millisToWaitForConversion(uint8_t bitResolution) { switch (bitResolution) { case 9: return 94; case 10: return 188; case 11: return 375; default: return 750; } } /** * Send the temperature to controller * * @since 2.0 */ void sendTemperatureToController(float temperature) { if (temperature != -127.00 && temperature != 85.00) { bool transmission_was_ok = false; int i = 0; do { transmission_was_ok = send(msg_temperature.setSensor(CHILD_ID_TEMP).set(temperature,1) , true); Serial.print("Variable i is "); Serial.println(i); Serial.print("Variable transmission_was_ok value is "); Serial.println(transmission_was_ok); i++; if ( i > 3 ) { delay(5000); // this delay will call watchdog! } } while (transmission_was_ok == false); } else { delay(5000); // this call the watchdog! Serial.println("-------------- DEBUG sendTemperatureToController() ---------------"); Serial.println("! ERROR reading temperature"); Serial.println("------------------------------------------------------"); } } /** * Light the LED status * * @since 2.0 */ void lightLedStatus() { int k = 0; for ( k = 0; k < WAIT_LOOPS; k++) { digitalWrite(PIN_LED_STATUS,HIGH); wait(10); // 5 * 1000 millisends = 5 seconds; digitalWrite(PIN_LED_STATUS,LOW); wait(4990); } } }
-
@sineverba I didn't analyse your post in depth yet, but I suffer from effects that sound pretty similar, so here's the link fyi.
-
@rejoe2 Thank you, at least for your sharing.... There is an error in your link, right link is:
https://forum.mysensors.org/topic/7454/rs485-nodes-stop-sending-data-after-some-hours-or-days
(I think that forum has changed a bit your link)....
Btw, tonight the node is still die 2 times. I'm re-arranging it with a Mini. I will update asap.
PS Remain my doubt: how watchdog is implemented inside main functions of MySensors.....
-
@sineverba said in Node with DS18B20+Relay dies, also with watchdog:
PS Remain my doubt: how watchdog is implemented inside main functions of MySensors.....
It isn't. Only deep sleeping uses the watchdog timer to wake up on atmega.
-
@Yveaux thank you. But, why whatchdog is never fired , also without a wtd_reset() in my loop?
I did setup 2 sec, never reset It, but my atmega finish the loop without problem, never resetting itself ....
-
@sineverba See here (bit old, but most is still valid): https://forum.mysensors.org/topic/1004/watchdog-on-ethernet-gateway
MySensors does globally define a watchdog interrupt handler (for sleeping nodes, but always present). Keep that in mind if you want to do something with the interrupt handler.