WDT doesnt reset the mcu

I have this code for sampling from a dht22 every 30 minutes and using wdt to keep an eye out for hangs. I know im using delay() when I should be using millis, but I want to understand why it failed because inthis case, I believe the wdt should actually work despite the use of delay().

  1. I disable and enable wdt in the setup() method

  2. I pat the dog a few times in loop() after sampling and after posting HTTP Request, neither of which should take more than 8s.

  3. Then comes the bad part (I know), I use a delay of 30 minutes after patting the dog, which should trigger the reboot of the mcu.

So I set up the code this morning, loaded it onto the nano and it posted the first HTTP Request at 7am, nothing else got posted after that and when I came back at 1130am, nothing else was printed in the Serial Monitor and the LED on the nano was flickering at a very high rate, obviously stuck.

Why would that happen?

#include "SoftwareSerial.h"
#include <avr/wdt.h>
#include "DHT.h"
#define DHTPIN A1     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE);

String ssid ="myssid";
String password="mypwd";
String server = "santiapps.com";//"santiapps.com";
String uri = "/emoncms/input/post";
String pwd = "mykey";

byte dat [5];
String temp ,hum;
String data;
char dataString[20];
char tempString[20];
char humString[20];

SoftwareSerial esp(6, 7);// RX, TX

void setup() {
  esp.begin(9600);
  Serial.begin(9600);
  Serial.println("setup");
  reset();
  uint8_t lastReset = wdt_clear();//*****************DISABLE WDT******************
  Serial.print(F("MCUSR: "));
  Serial.println(lastReset);
  connectWifi();
  wdt_enable(WDTO_8S);//***********************ENABLE WDT*******************
}

void reset() {
  Serial.println("reset");
  esp.println("AT+RST");
  delay(1000);
  if(esp.find("OK") ) Serial.println("Module Reset");
}

void connectWifi() {
  Serial.println("connect to wifi");  
  String cmd = "AT+CWJAP=\"" +ssid+"\",\"" + password + "\"";
  esp.println(cmd);
  delay(400);
  while (esp.available()){
     String inData = esp.readStringUntil('\n');
     Serial.println("Got reponse from ESP8266: " + inData);
  }


  if(esp.find("OK")) {
    Serial.println("Connected!");
  } else {
    connectWifi();
    Serial.println("Cannot connect to wifi"); }
}


void start_test () {
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  dtostrf(t, 4, 2, tempString);  //convert flat to char  
  dtostrf(h, 4, 2, humString);  //convert flat to char
}

void loop(){
  Serial.println("loop");
  start_test();
  wdt_reset(); // path the dog just in case***********************************************
  httppost();
  wdt_reset(); // path the dog just in case***********************************************

  //millis code..........
  delay(1800000);//100k ms = 100s or ~ 1.8m
}

uint8_t wdt_clear(void){
    uint8_t nResetReg = MCUSR;
    MCUSR = 0;
    wdt_disable();
    return nResetReg;
}

void httppost () {
  esp.println("AT+CIPSTART=\"TCP\",\"" + server + "\",80");//start a TCP connection.
  if( esp.find("OK")) {
    Serial.println("TCP connection ready");
  }

  String finalData="/emoncms/input/post.json?apikey=" + pwd + "&node=fortnite&json={\"t\":" + tempString + ",\"h\":" + humString + "}";
  Serial.println(finalData); 
  delay(1000);
  String getRequest="GET " + finalData + " HTTP/1.1\r\n" + "Host: " + server + "\r\n" + "Connection: keep-alive\r\n\r\n";
  Serial.println("getRequest");
  Serial.println(getRequest);
  
  String sendCmd = "AT+CIPSEND=";//determine the number of caracters to be sent.
  esp.print(sendCmd);
  esp.println(getRequest.length());
  delay(1000);
  if(esp.find(">")) { 
    Serial.println("Sending.."); 
    esp.print(getRequest);
    if(esp.find("SEND OK")) { 
      Serial.println("Packet sent");
      while (esp.available()) {
        String tmpResp = esp.readString();
        Serial.println(tmpResp);
      }
      // close the connection
      esp.println("AT+CIPCLOSE");
    }
  }
}

For the millis code Illl do:

void loop(){
  Serial.println("loop");
  wdt_reset(); //pat the dog so he doesnt bite before heavylifting

  //millis code..........
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis <= interval) {
    Serial.println("keepAlive"); // do nothing
  } else { //if deltaTimeElapsed is GREATER than target interval, spin
    previousMillis = currentMillis; //sets previous-0 to current-3600
    start_test(); //sample
    wdt_reset(); //pat the dog
    httppost();  //post
}
}

You have the "old bootloader" in Nano? This is the reason why it was retired. Optiboot - the 'new' bootloader disables WDT.

try to call wdt_clear() as first line in setup(). you have only 8 secs from MCU start to call wdt_clear().

Yes it has the old bootloader.

the call to wdt_clear() is this one:

  uint8_t lastReset = wdt_clear();

its like the third line, i think it would be called under 8 seconds no?

I tried it, same thing. :frowning:

What can I do?

Just confirming, is this what I want?

https://www.google.hn/search?q=upgrade+bootloader+on+arduino+nano&oq=upgrade+bootloader+on+arduino+nano&aqs=chrome..69i57j0l2.4440j0j7&sourceid=chrome&ie=UTF-8#kpvalbx=1

In IDE 1.8.5+ flash the bootloader to Nano. It should flash the 'new' bootloader.
I changed the bootloader in my Nano a year ago. I flashed it as Uno. It is the same Optiboot bootloader.

So i just plug in the nano with the old bootloader into the usb and click on Flash Bootloader?

Cause in the video it seems you have to get it from another nano that has the new bl.

The weird thing is that this one I have is a clone Arduino Nano, so its understandable that its the old bl. But I just went to an original arduino nano and connected it to the ide and i cant upload sketches to that one either with the 328P option, i have to resort to the 328P (Old Bootloader) option or i get the sync error. I guess it could be explained if the original nano came out when the new BL wasnt available. It says V3.0 on it but I guess that doesnt refer necessarily to the new BL.

But the other weird thing is that I just tried one of those clones with the old bootloader and uploaded a sketch that uses wdt on it and it works fine.

Marciokoko:
So i just plug in the nano with the old bootloader into the usb and click on Flash Bootloader?

Cause in the video it seems you have to get it from another nano that has the new bl.

The weird thing is that this one I have is a clone Arduino Nano, so its understandable that its the old bl. But I just went to an original arduino nano and connected it to the ide and i cant upload sketches to that one either with the 328P option, i have to resort to the 328P (Old Bootloader) option or i get the sync error. I guess it could be explained if the original nano came out when the new BL wasnt available. It says V3.0 on it but I guess that doesnt refer necessarily to the new BL.

But the other weird thing is that I just tried one of those clones with the old bootloader and uploaded a sketch that uses wdt on it and it works fine.

the 'new' Nano bootloader thing is only some months old. there are many new Nanos with old bootloader at shops

to burn the booltloader, you need to use a programmer or another Arduino with the "Arduino as ISP" sketch. but the Nano with old bootloader is not suitable because of long wait-for-the-sketch time after reset (you could inhibit auto reset with a cap, then it will work).

ok i still dont fully understand.

i dont have a programmer, i have other arduino boards, but the other nanos i have all have the old bootloader.

what else can i do?

Marciokoko:
ok i still dont fully understand.

i dont have a programmer, i have other arduino boards, but the other nanos i have all have the old bootloader.

what else can i do?

the only problem with old bootloader is that is has a much longer time of testing if a new sketch is uploaded. it is not good for use of the "Arduino as ISP" sketch, because IDE doesn't wait after connecting to port and sending the bootloader to programmer (which is the arduino board in this case). but the Arduino autoresets on usb connection. (the programmers don't do that).
so you need to supress the autoreset of the Nano. in the linked article is a trick with capacitor on reset pin

ok ill just buy a new nano with the new bootloader, but here is the thing...im not sure thats the problem. I have 3 types of nanos:

  1. originals
  2. generic clones
  3. tinysine tosduino clones

Im using this dht22/wdt code on the tosduino clone. But i have another wdt/avr code running on a generic clone and it works fine. Although all three types require me to use the Nano => 328P (Old Bootloader) option from the IDE in order to upload sketches.

I think its more something about the code. Ill try the millis code instead...

Marciokoko:
ok ill just buy a new nano with the new bootloader, but here is the thing...im not sure thats the problem. I have 3 types of nanos:

  1. originals
  2. generic clones
  3. tinysine tosduino clones

Im using this dht22/wdt code on the tosduino clone. But i have another wdt/avr code running on a generic clone and it works fine. Although all three types require me to use the Nano => 328P (Old Bootloader) option from the IDE in order to upload sketches.

I think its more something about the code. Ill try the millis code instead...

could be a diffrent version of old bootloader. does it work without wdt_clear()?

OK so is getting a new nano with the new bootloader the only way to get the new bootloader onto the old nano?

Marciokoko:
OK so is getting a new nano with the new bootloader the only way to get the new bootloader onto the old nano?

see comment #8

Sorry I didn't really understand the answer.

Marciokoko:
OK so is getting a new nano with the new bootloader the only way to get the new bootloader onto the old nano?

No, you can burn the new bootloader via ISP to any. The bootloader is a part of IDE. To burn the bootloader you will need some kind of ISP programmer. Another Nano can be used as ISP programmer. ArduinoISP sketch is for that purpose.

Marciokoko:
Sorry I didn't really understand the answer.

did you read the linked article "Arduino as ISP"?

Thanks budvar10.

So I found this article online and I did the following steps:

  1. uploaded the Arduino ISP sketch from the examples folder in the Arduino IDE.
  2. connected the Arduino Uno to the nano via the ICSP headers.
  3. I selected the Arduino nano 328 board and selected Arduino as ISP and then clicked on burn boot loader.

I think it worked because I am able to upload sketches now to the Arduino nano(old bl) using the 328P option instead of the 328 old boot loader option. I tried uploading the blink sketch and it worked fine however when I ran my watchdog timer code I still get the same error where the LED blinks really fast after a while so something must be wrong with my code.

I tried running this wdt code and it works perfectly (it reboots after 8s):

#include <avr/wdt.h>
//#define RESETWATCHDOG

void setup(){
  wdt_disable();
	  Serial.begin(57600);
          Serial.println("");
          Serial.println ("------->Arduino Rebooted");
          Serial.println("");
          wdt_enable(WDTO_8S);
}

void loop(){
#ifdef RESETWATCHDOG
	wdt_reset(); //pat the dog
#endif
	Serial.println("Arduino Running");
	delay(1000);
}

Oh btw I modified the code for millis, here is the hanging code:

#include "SoftwareSerial.h"
#include <avr/wdt.h>
#include "DHT.h"
#define DHTPIN A1     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE);

String ssid ="myssid";
String password="mypwd";
String server = "myserver.com";
String uri = "/emoncms/input/post";
String pwd = "mykey";

byte dat [5];
String temp ,hum;
String data;
char dataString[20];
char tempString[20];
char humString[20];

unsigned long previousMillis = 0;        // will store last time was updated
const long interval = 180000;

SoftwareSerial esp(6, 7);// RX, TX

void setup() {
  wdt_disable();

  esp.begin(9600);
  Serial.begin(9600);
  Serial.println("setup");
  reset();
  connectWifi();
  wdt_enable(WDTO_8S);
}

void reset() {
  Serial.println("reset");
  esp.println("AT+RST");
  delay(1000);
  if(esp.find("OK") ) Serial.println("Module Reset");
}

void connectWifi() {
  Serial.println("connect to wifi");  
  String cmd = "AT+CWJAP=\"" +ssid+"\",\"" + password + "\"";
  esp.println(cmd);
  delay(400);
  while (esp.available()){
     String inData = esp.readStringUntil('\n');
     Serial.println("Got reponse from ESP8266: " + inData);
  }


  if(esp.find("OK")) {
    Serial.println("Connected!");
  } else {
    connectWifi();
    Serial.println("Cannot connect to wifi"); }
}


void start_test () {
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  dtostrf(t, 4, 2, tempString);  //convert flat to char  
  dtostrf(h, 4, 2, humString);  //convert flat to char
}

void loop(){
  wdt_reset(); // path the dog just in case***********************************************

  //millis code..........
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis <= interval) { //when time elapsed is LESS than interval
    wdt_reset(); // path the dog just in case***********************************************
  } else { //if deltaTimeElapsed is GREATER than target interval, sample and post...
    previousMillis = currentMillis; 
    connectWifi();
    wdt_reset(); // path the dog just in case***********************************************
    start_test(); //sample
    wdt_reset(); // path the dog just in case***********************************************
    httppost();
  }
}

void httppost () {
  esp.println("AT+CIPSTART=\"TCP\",\"" + server + "\",80");//start a TCP connection.
  if( esp.find("OK")) {
    Serial.println("TCP connection ready");
  }
  wdt_reset(); // path the dog just in case***********************************************

//  //CODE USED TO BUILD COMPLETE STRING
  String finalData="/emoncms/input/post.json?apikey=" + pwd + "&node=fortnite&json={\"t\":" + tempString + ",\"h\":" + humString + "}";
  Serial.println(finalData); 
  wdt_reset(); // path the dog just in case***********************************************

  delay(1000);
  String getRequest="GET " + finalData + " HTTP/1.1\r\n" + "Host: " + server + "\r\n" + "Connection: keep-alive\r\n\r\n";
  //String requestLength = String(getRequest.length());
  Serial.println("getRequest");
  Serial.println(getRequest);
  
  String sendCmd = "AT+CIPSEND=";//determine the number of caracters to be sent.
  esp.print(sendCmd);
  esp.println(getRequest.length());
  wdt_reset(); // path the dog just in case***********************************************

  delay(1000);
  if(esp.find(">")) { 
    Serial.println("Sending.."); 
    esp.print(getRequest);
    if(esp.find("SEND OK")) { 
      Serial.println("Packet sent");
      while (esp.available()) {
        String tmpResp = esp.readString();
        Serial.println(tmpResp);
      }
      // close the connection
      esp.println("AT+CIPCLOSE");
    }
  }
  wdt_reset(); // path the dog just in case***********************************************

}