Node with DS18B20+Relay dies, also with watchdog


  • Hardware Contributor

    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".

    alt text

    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.


  • Hardware Contributor

    @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.....


  • Mod

    @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.


  • Hardware Contributor

    @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 ....


  • Mod

    @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.


Log in to reply
 

Suggested Topics

  • 1
  • 5
  • 2
  • 2
  • 10
  • 198

0
Online

11.2k
Users

11.1k
Topics

112.5k
Posts