Resetting Arduino

Hello,

Here is my code:

#include <SD.h>  //http://www.ladyada.net/products/microsd/
#include <Wire.h>
#include <SPI.h>
#include "floatToString.h"
#include "RTClib.h"
#include <avr/pgmspace.h>
#include <math.h>
int CS_pin = 10, SD_led = 8;
RTC_DS1307 RTC;
float COValue = 0, NO2Value = 0, O3Value = 0;
float e_NO2Value = 0, e_NOValue = 0, e_COValue = 0;
float celsius = 0;
int dust_Vout = 0, ledPower = 5, delayTime = 280, delayTime2 = 40;
char date_time[20];
char cel[8];
char e_NO2_Vout[10];
char e_NO_Vout[10];
char e_CO_Vout[10];
char dust[8];
char CO_Vout[10];
char NO2_Vout[10];
char O3_Vout[10];
int _outputserialchar( char c, FILE *t) {
	Serial.write( c );
	return 1;
} 
int pins [3] = {2, 3, 4};

void setup()
{
  for(int i = 2; i<6; i++) pinMode(i, OUTPUT);
  
  fdevopen( &_outputserialchar, 0); 
  Wire.begin();
  Serial.begin(9600);
  SPI.begin();
  Serial.println("Initializing Card");
  pinMode(10, OUTPUT);
  RTC.begin();
  headerW();
  
}

void loop()
{
  dustsensor();  //Dust sensor http://miscellanea.com/how-to-get-more-arduino-analog-inputs/
  E_NO2(); //E_NO2 sensor
  E_CO(); //E_CO sensor
  E_NO(); //E_NO sensor
  MOS();
  temperature(); //Temp sensor
  FtoS();
  DnT();
  SDWrite(); 
  Serial.flush();
}

void temperature() {
  //Read Value of 4051 analog-in 5
  boolean five [3] = {HIGH, LOW, HIGH};
  for(int i=0; i<3; i++) digitalWrite(pins[i], five[i]);
  delay(1);
  int readInFive = analogRead(0);
  float kelvin = readInFive * 0.004882812 * 100;
  celsius = (kelvin - 273.15) - 5;
}

void dustsensor() {
  //Read Value of 4051 analog-in 1
  boolean one [3] = {HIGH, LOW, LOW};
  for(int i=0; i<3; i++) digitalWrite(pins[i], one[i]);
  delay(1);
  digitalWrite(ledPower,LOW);
  delayMicroseconds(delayTime);
  dust_Vout = analogRead(0);
  delayMicroseconds(delayTime2);
  digitalWrite(ledPower,HIGH);
}

void E_NO2() {
  //Read Value of 4051 analog-in 2
  boolean two [3] = {LOW, HIGH, LOW};
  for(int i=0; i<3; i++) digitalWrite(pins[i], two[i]);
  delay(1);
  int readInTwo= analogRead(0);
  e_NO2Value = readInTwo * 0.004882812;
}

void E_CO() {
//Read Value of 4051 analog-in 3
  boolean three [3] = {HIGH, HIGH, LOW};
  for(int i=0; i<3; i++) digitalWrite(pins[i], three[i]);
  delay(1);
  int readInThree= analogRead(0);
  e_COValue = readInThree * 0.004882812;
}

void E_NO() {
//Read Value of 4051 analog-in 4
  boolean four [3] = {LOW, LOW, HIGH};
  for(int i=0; i<3; i++) digitalWrite(pins[i], four[i]);
  delay(1);
  int readInFour= analogRead(0);
  e_NOValue = readInFour * 0.004882812;
}

void MOS() {
  NO2Value = analogRead(1) * 0.004882812;
  COValue = analogRead(2) * 0.004882812;
  O3Value = analogRead(3) * 0.004882812;
}

void FtoS() {
  floatToString(cel, celsius, 0);
  floatToString(dust, dust_Vout, 0);
  floatToString(e_NO2_Vout, e_NO2Value, 5);
  floatToString(e_CO_Vout, e_COValue, 5);
  floatToString(e_NO_Vout, e_NOValue, 5);
  floatToString(CO_Vout, COValue, 5);
  floatToString(NO2_Vout, NO2Value, 5);
  floatToString(O3_Vout, O3Value, 5);
}

void DnT() {
  DateTime now = RTC.now();
  sprintf_P(date_time,PSTR("%d/%d/%d %d:%d:%d"),now.day(),now.month(),now.year(),now.hour(),now.minute(),now.second());
}

void headerW() {
  if (!SD.begin(CS_pin))
  {
      Serial.println("Card Failure");
      return;
  }
  Serial.println("Card Ready");
  
  //Write Log File Header
  File logFile = SD.open("ARD1.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(", , , , , , , ,"); //Just a leading blank line, incase there was previous data
    String header = "Date_Time, Temp, e_NO2_Vout, e_NO_Vout, e_CO_Vout, CO_Vout, NO2_Vout, O3_Vout, Dust_Vout";
    logFile.println(header);
    logFile.close();
    Serial.println(header);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }
}

void SDWrite() {
  String dataString = String(date_time) + ", " + String(cel) + ", " + String(e_NO2_Vout) + ", " + String(e_NO_Vout) + ", " + String(e_CO_Vout) + ", " + String(CO_Vout) + ", " + String(NO2_Vout) + ", " + String(O3_Vout) + ", " + String(dust_Vout);
  
  File logFile = SD.open("ARD1.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(dataString);
    logFile.close();
    //Serial.println(dataString); // testing if the data string is correct
    printf_P(PSTR("%s, %s, %s, %s, %s, %s, %s, %s, %s\r\n"), date_time, cel, e_NO2_Vout, e_NO_Vout, e_CO_Vout, CO_Vout, NO2_Vout, O3_Vout, dust); 
    pinMode(SD_led, OUTPUT);
    digitalWrite(SD_led, HIGH);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }
  
  delay(29000);
  digitalWrite(SD_led, LOW);
  delay(1000);
}

Here SD_led lights ON when data is getting written on SD card and if there is a problem, it turns off.
Based on SD_led, I want to reset Arduino.
My idea is:
Reset Arduino when SD_led is OFF.

Please suggest how is it possible.

Thanks.

Best,
Z

Well the first thing we usually ask is "Why do you need to reset the Arduino?"

That's normally a sign of bad program structure.


Rob

If there is a failure to write to the SD card, what makes you think that a reboot of the Arduino will fix the problem?

Graynomad:
Well the first thing we usually ask is “Why do you need to reset the Arduino?”

PaulS:
If there is a failure to write to the SD card, what makes you think that a reboot of the Arduino will fix the problem?

After some hours of operation, a few arduinos get hanged (not all every time, I have 5). This I figure out looking at the SD led.
They again start working when I press the reset button and led turns on.

That’s why I want to soft reset the Arduino based on led activity.

Please suggest what needs to be done.

Thanks.

Best,
Z

Surely, it’s better to find out why it’s hanging?

I am not sure why, probably heating? For now, I want to solve this quickly with resetting the board. Do you know what I can do here?

Thanks.

http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_softreset

If you do go the WDT route, be warned that some arduino bootloaders don't set the WDT off. If it doesn't and you set the WDT on, you could put your arduino in a state only recoverable by an ISP.

WizenedEE: http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_softreset

If you do go the WDT route, be warned that some arduino bootloaders don't set the WDT off. If it doesn't and you set the WDT on, you could put your arduino in a state only recoverable by an ISP.

Thanks. How would I know that my boards do/don't support WDT off? Or should I connect a digital pin with reset pin?

Which way is better?

Thanks.

Best, Z

The pin connection is not recommended, as has been discussed here many times.

The WDT with a long timeout should be fine (eg. 8 seconds). Just "pat the dog" in the main loop, when things are going fine and the watchdog will reset it after 8 seconds if not.

Besides you can work around the bootloader issue by holding down reset while you power on the board, and letting go when the power is on and the sketch starts to upload.

[quote author=Nick Gammon link=topic=113936.msg858087#msg858087 date=1342132147] The WDT with a long timeout should be fine (eg. 8 seconds). Just "pat the dog" in the main loop, when things are going fine and the watchdog will reset it after 8 seconds if not. [/quote]

Thanks Nick. I have 30 sec of delay in my main loop. Will it affect soft resetting? Probably I don't understand this 8 sec of wait, I am having a doubt that this will reset while Arduino is in waiting loop of 30 sec. Please clarify.

Thanks.

Best, Z

Well, what do you think?

Better make the 30 second wait to be 5 x 6 seconds with a “pat the dog” for each one (or 30 x 1 second, as long as you don’t get too close to 8 seconds). eg.

for (int i = 0; i < 30; i++)
  {
  wdt_reset();  // pat the dog
  delay (1000);
  }

(edit) Changed delay(1) to delay(1000). Thanks wildbill for pointing it out. :slight_smile:

Thanks Nick. I think 5x6sec is a better option.

If you just want to use the WDT for reset, you should disable it completely in setup (or, ideally, the bootloader) and only enable it when you want to reset. Unless, of course, you want an actual watchdog for your rc car or transformer or whatever.

Unfortunately, WDT didn’t work in resetting Arduino.
Here is the code:

#include <SD.h>  //http://www.ladyada.net/products/microsd/
#include <Wire.h> //to reset http://www.forums.adafruit.com/viewtopic.php?f=8&t=15435
#include <SPI.h>
#include "floatToString.h"
#include "RTClib.h"
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <math.h>
int CS_pin = 10, SD_led = 8;
RTC_DS1307 RTC;
float COValue = 0, NO2Value = 0, O3Value = 0;
float e_NO2Value = 0, e_NOValue = 0, e_COValue = 0;
float celsius = 0;
int dust_Vout = 0, ledPower = 5, delayTime = 280, delayTime2 = 40;
char date_time[20];
char cel[8];
char e_NO2_Vout[10];
char e_NO_Vout[10];
char e_CO_Vout[10];
char dust[8];
char CO_Vout[10];
char NO2_Vout[10];
char O3_Vout[10];
int _outputserialchar( char c, FILE *t) {
	Serial.write( c );
	return 1;
} 
int pins [3] = {2, 3, 4};

void setup()
{
  for(int i = 2; i<6; i++) pinMode(i, OUTPUT);
  
  fdevopen( &_outputserialchar, 0); 
  Wire.begin();
  wdt_disable();
  Serial.begin(9600);
  SPI.begin();
  Serial.println("Initializing Card");
  pinMode(10, OUTPUT);
  RTC.begin();
  headerW();
  
}

void loop()
{
  dustsensor();  //Dust sensor http://miscellanea.com/how-to-get-more-arduino-analog-inputs/
  E_NO2(); //E_NO2 sensor
  E_CO(); //E_CO sensor
  E_NO(); //E_NO sensor
  MOS();
  temperature(); //Temp sensor
  FtoS();
  DnT();
  SDWrite(); 
  Serial.flush();
}

void temperature() {
  //Read Value of 4051 analog-in 5
  boolean five [3] = {HIGH, LOW, HIGH};
  for(int i=0; i<3; i++) digitalWrite(pins[i], five[i]);
  delay(1);
  int readInFive = analogRead(0);
  float kelvin = readInFive * 0.004882812 * 100;
  celsius = (kelvin - 273.15) - 5;
}

void dustsensor() {
  //Read Value of 4051 analog-in 1
  boolean one [3] = {HIGH, LOW, LOW};
  for(int i=0; i<3; i++) digitalWrite(pins[i], one[i]);
  delay(1);
  digitalWrite(ledPower,LOW);
  delayMicroseconds(delayTime);
  dust_Vout = analogRead(0);
  delayMicroseconds(delayTime2);
  digitalWrite(ledPower,HIGH);
}

void E_NO2() {
  //Read Value of 4051 analog-in 2
  boolean two [3] = {LOW, HIGH, LOW};
  for(int i=0; i<3; i++) digitalWrite(pins[i], two[i]);
  delay(1);
  int readInTwo= analogRead(0);
  e_NO2Value = readInTwo * 0.004882812;
}

void E_CO() {
//Read Value of 4051 analog-in 3
  boolean three [3] = {HIGH, HIGH, LOW};
  for(int i=0; i<3; i++) digitalWrite(pins[i], three[i]);
  delay(1);
  int readInThree= analogRead(0);
  e_COValue = readInThree * 0.004882812;
}

void E_NO() {
//Read Value of 4051 analog-in 4
  boolean four [3] = {LOW, LOW, HIGH};
  for(int i=0; i<3; i++) digitalWrite(pins[i], four[i]);
  delay(1);
  int readInFour= analogRead(0);
  e_NOValue = readInFour * 0.004882812;
}

void MOS() {
  NO2Value = analogRead(1) * 0.004882812;
  COValue = analogRead(2) * 0.004882812;
  O3Value = analogRead(3) * 0.004882812;
}

void FtoS() {
  floatToString(cel, celsius, 0);
  floatToString(dust, dust_Vout, 0);
  floatToString(e_NO2_Vout, e_NO2Value, 5);
  floatToString(e_CO_Vout, e_COValue, 5);
  floatToString(e_NO_Vout, e_NOValue, 5);
  floatToString(CO_Vout, COValue, 5);
  floatToString(NO2_Vout, NO2Value, 5);
  floatToString(O3_Vout, O3Value, 5);
}

void DnT() {
  DateTime now = RTC.now();
  sprintf_P(date_time,PSTR("%d/%d/%d %d:%d:%d"),now.day(),now.month(),now.year(),now.hour(),now.minute(),now.second());
}

void headerW() {
  if (!SD.begin(CS_pin))
  {
      Serial.println("Card Failure");
      return;
  }
  Serial.println("Card Ready");
  
  //Write Log File Header
  File logFile = SD.open("ARD1.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(", , , , , , , ,"); //Just a leading blank line, incase there was previous data
    String header = "Date_Time, Temp, e_NO2_Vout, e_NO_Vout, e_CO_Vout, CO_Vout, NO2_Vout, O3_Vout, Dust_Vout";
    logFile.println(header);
    logFile.close();
    Serial.println(header);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }
}

void SDWrite() {
  String dataString = String(date_time) + ", " + String(cel) + ", " + String(e_NO2_Vout) + ", " + String(e_NO_Vout) + ", " + String(e_CO_Vout) + ", " + String(CO_Vout) + ", " + String(NO2_Vout) + ", " + String(O3_Vout) + ", " + String(dust_Vout);
  
  File logFile = SD.open("ARD1.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(dataString);
    logFile.close();
    //Serial.println(dataString); // testing if the data string is correct
    printf_P(PSTR("%s, %s, %s, %s, %s, %s, %s, %s, %s\r\n"), date_time, cel, e_NO2_Vout, e_NO_Vout, e_CO_Vout, CO_Vout, NO2_Vout, O3_Vout, dust); 
    pinMode(SD_led, OUTPUT);
    digitalWrite(SD_led, HIGH);
  }
  else
  {
    Serial.println("Couldn't open log file");
  }
  
  delay(6000);
  wdt_enable(WDTO_8S);
  wdt_reset();
  
  delay(6000);
  wdt_enable(WDTO_8S);
  wdt_reset();
  
  delay(6000);
  wdt_enable(WDTO_8S);
  wdt_reset();
  
  delay(6000);
  wdt_enable(WDTO_8S);
  wdt_reset();
  
  delay(6000);
  wdt_enable(WDTO_8S);
  wdt_reset();
}

But pressing the reset button or re-plugging A/C adopter does restart the device.

Please suggest how can I overcome the problem.

Thanks.

Best,
Z

Someone?

But pressing the reset button or re-plugging A/C adopter does restart the device.

Ummm, well it would do wouldn't it. Kind of like telling us that the sky is normally blue.

Unfortunately, WDT didn't work in resetting Arduino.

You don't expect it to until there's an error do you? As far as I can see that code is designed specifically NOT to have a WD reset.

Try increasing one of the delays to 10000 to verify that the WD works.

Also why do wdt_enable(WDTO_8S); every time, surely you do that once in setup.


Rob

I ran into a similar problem when I was working with getting my Arduino to work with WiFi. The WiFi module would sometimes crash due to a buggy library, and the best way to fix it was to reset the whole board. (This was for a class project that had to be done in one semester.) In the end, it was easier to build a little reset hardware than to completely debug a someone else's library.

I made a small reset board that plugs directly into the Arduino. It uses a 555 timer to send a ~1ms pulse to the Arduino's reset pin. Since it's a hardware solution, you don't have to worry about checking the watchdog. All you have to do is pull the A0 pin high to get the reset board to reset your Arduino.

I've linked my project below. It's complete with a bill of materials, schematics, board files, build instructions, notes on how to use it, and an Arduino sketch. http://www.openhardwarehub.com/projects/49-Arduino-Hardware-Reset-Circuit-PCB

If the code has crashed how do you apply the reset pulse to the 555? Or do you detect that the WiFi board has crashed but your code is OK?

In the case of zeus2kx I gather that he can't detect the problem so presumably his code has crashed, if he could detect the problem there's a there are easy ways to restart the code. If that's the case he needs a real watchdog. Maybe modify your design to require a constant pulse to stop it from resetting the Arduino.

That said the WD should work if used properly.


Rob

In my situation, the WiFi module would get into a bad state and wouldn't reconnect. I could figure out it was in a bad state because I couldn't send/receive data. When that happened, I'd just hit the reset switch to get it to reconnect.

I'm not sure if this is still true, but the old Arduino bootloaders were not compatible with using the watchdog. That was my main reason for using a hardware solution rather than a software solution. http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1278573986