Resetting an arduino through code [SOLVED]

In my project, there is a timer that I have created that starts as soon as the loop section of the code starts running. If there are any hardware errors, I have created a function with a while loop, and as soon as all hardware errors are resolved, the code soft resets and the timer, datalogging etc all reset. It did work for a while, but now it doesn't reset, the reset button on my arduino barely works and the tactile button I have wired to RST barely resets it either. I bought a cheap 'UK' arduino nano knockoff with a CH340 driver, and 3 of the 5 nano's I purchased have already stopped working after a few months. Could someone help me to make sure that it isn't my code that is causing the reset problem? I have taken this project apart and put it back together again about 50 times, so I am sure there are no wiring issues. I just don't want to start altering the code unnecessarily, as I am ordering an arduino nano ESP32 to use instead, and want to have a functional code prior to getting it. This is the code:

/*    _______________________________________________________________________________________________________________________________________________________________________
ㅤㅤ /\             \                                                                                                                                          /            /\
ㅤ ㅤ|_\             \                                                               DATALOGGER                                                               /            /_|
ㅤㅤ |__\             \________________________________     20x4 LCD, SD ADAPTER, DS3231, DS18B20 (5.1kPU), FLOAT SWITCH     ________________________________/            /__| 
ㅤㅤ |___\                                             \____________________________________________________________________/                                            /___|  
ㅤㅤ |____\                                                                                                                                                             /____|
ㅤ ㅤ|_____\                  _______________________________________________________________________________________________________________________                  /_____|
ㅤㅤ \______\                /                                                                                                                       \                /______/                                            
ㅤㅤ  \_____/\______________/  THIS PROGRAM MAY ALSO BE USED AS A GENERAL DATA LOGGER BY MODIFYING THE SENSOR CODE AND INPUTTING THE NECESSARY CODE   \______________/\_____/
ㅤ ㅤ                        \________________________________________________________________________________________________________________________/                     

___________________________________________________________________________________________________________________________________________________________________________________
ㅤ  ㅤ   ㅤ           ㅤ/   (ALL VCC AND GND TO BE WIRED TO VCC AND GND)    \                           /
HARDWARE WIRING LIST: /                                                     \   PROGRAM DESCRIPTION:  /   
_____________________/                                                       \_______________________/
ㅤ                                                      
_________________________________                        _________________________________________________________________
FOR 20X4 LIQUID CRYSTAL DISPLAY: \                      /                                                                 \
............_____________________/                     /  This program is designed to log data from a DS18B20 temperature  \
-VSS GND   /                                           | sensor and read a  float  switch  value.  Once the  SD  card  is  | 
-VDD 5V    \____                                       |  initialised and  the RTC reads the set time, the  program  will  | 
-V0 2k RESISTOR \                                      |  create a file in the SD card and name it according to the  date  | 
-RS PIN A0  ____/                                      |  (the date is retrieved using a DS3231 RTC). once the  file  and  | 
-RW GND    /                                           |  file name is created, 8 data samples from all  DS18B20  sensors  | 
-E PIN A1  |                                           |  are  averaged,  formatted  and  logged   within   the   logging  | 
-D0 X     /                                            |  interval into the created file, as well as the time of the  day  | 
-D1 X    /                                             |  in seconds and the current state of the  float  switch.  If  the | 
-D2 X    \                                             |  program is ran  until  the  next  day,  data  logging  will  be  | 
-D3 X     \                                            |  stopped, and another file will be created and  named  according  | 
-D4 PIN A2 \                                           |  to the date. The liquid  crystal  display  and  serial  monitor  | 
-D5 PIN A3  \                                          |  will show all relevant info, and can be used to ensure that the  | 
-D6 PIN D2  |                                          |  program runs correctly, displaying SD card initialisation,  RTC  | 
-D7 PIN D7  /                                          |  initialisation, the filename the data is writing to,  the  time  | 
-A 10K POT /                                           |  the data started logging in DHHMMSS, and the  current  time  of  | 
-K GND    /                                            \  the RTC. If any Errors occur, the LCD or  serial  monitor  will  / 
_________/                                              \__________________  display an Error message.  __________________/ 
ㅤ                                                                         \___________________________/
____________________________
FOR SD CARD ADAPTER MODULE: \
....................________/
-chipSelect PIN D10 \
-MOSI PIN D11  _____/
-MISO PIN D12 /
-SCK PIN D13 /
____________/

_________________
FOR DS3231 RTC:  \
..................\
-SCL PIN SCL OR A5 \
-SDA PIN SDA OR A4  |
-SQW X  ___________/
_______/

________________________________
FOR DS18B20 TEMPERATURE SENSOR: \
........._______________________/
-POS 5V  \
-NEG GND  \__
-DQ 5.1kPU   \________________
-5.1kPU LINKING PIN D9 AND 5V \______________
-104pF CERAMIC CAPACITOR LIKNING POS AND NEG \
_____________________________________________/

__________________
FOR FLOAT SWITCH: \
............._____/
-POS PIN D4 /
-NEG GND __/
________/

// INCLUDE LIBRARIES AND DEFINED CONSTANTS:                                                                                      
/********************************************************************************************************************************************************************************/

#include <OneWire.h>
#include <DallasTemperature.h>
#include <SD.h>
#include <SPI.h>
#include <LiquidCrystal.h>
#include <DS1307RTC.h>
#include <TimeLib.h>
#define BLUE 3
#define floatSw 4
#define GREEN 5
#define RED 6
#define buzzer 8
#define ONE_WIRE_BUS 9
#define chipSelect 10
#define buzzerTogglePin A6
#define year() tmYearToCalendar(tm.Year) - 2000
#define printAll(txt) Serial.println(txt), lcd.print(txt)


// used as general global variables
/********************************************************************************************************************************************************************************/
File dataFile;
LiquidCrystal lcd(A0, A1, A2, A3, 2, 7);
tmElements_t tm;
unsigned long tStart = millis();
unsigned long totMillis;
unsigned long lastMillis = 0;
unsigned long logTm = 10000;
unsigned long sampleTm = 1250;
unsigned long tLog = totMillis + logTm;
unsigned long tSample = totMillis + sampleTm;
int buzzerState = 1;
int BTstate;
char dirName[8] = "TANKLOG";
char fileName[13];
char fullPath[22];


// variables only used for the specific type of datalogging
/********************************************************************************************************************************************************************************/
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// function runs if a hardware error occurs
/********************************************************************************************************************************************************************************/
void hardwareErr() {
  while (!SD.begin(chipSelect) || !RTC.read(tm) || !SD.open(fullPath)) {
    digitalWrite(buzzer, 1);
    delay(100);
    digitalWrite(buzzer, 0);
    delay(1900);
  }

  if(SD.begin(chipSelect) && RTC.read(tm) && SD.open(fullPath)) {
  void (*reset)(void) = 0;
  }
}

// initialises most of the hardware
/********************************************************************************************************************************************************************************/
void initialisation() {
  sensors.begin();
  sensors.setWaitForConversion(false);
  lcd.begin(20, 4);
  lcd.clear();
  sensors.requestTemperatures();
  pinMode(buzzer, OUTPUT);
  pinMode(buzzerTogglePin, INPUT);
  buzzerState = 1;
  pinMode(floatSw, INPUT_PULLUP);
  pinMode(RED, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(BLUE, OUTPUT);
  Serial.begin(115200);
  SD.begin(chipSelect);
  RTC.get();
  Serial.print(F(""));
  if (!SD.begin(chipSelect)) {
    printAll(F("SD Card Failed."));
    hardwareErr();
  }
  if (!RTC.read(tm)) {
    printAll(F("RTC failed."));
    hardwareErr();
  }
}

// creates the file and name, and prints lcd info if the file is available to write to
/*******************************************************************************************************************************************************************************/
void createFileAndName() {
  sprintf(fileName, "%02d-%02d-%d.txt", tm.Day, tm.Month, year());
  strlcpy(fullPath, dirName, sizeof fullPath);
  strlcat(fullPath, "/", sizeof fullPath);
  strlcat(fullPath, fileName, sizeof fullPath);
  SD.mkdir(dirName);

  // INITIALISE LCD DISPLAY DATA
  /********************************************************************************************************************************************************************************/
  Serial.println(fullPath);
  lcd.print(dirName);
  lcd.print("     ");
  lcd.print(fileName);
  lcd.setCursor(0, 1);
  lcd.print(F("TEMP:"));
  lcd.setCursor(0, 2);
  lcd.print(F("TANK LVL:"));
  lcd.setCursor(17, 2);
}

void firstWrite() {
  dataFile = SD.open(fullPath, FILE_WRITE);
  dataFile.close();
  dataFile = SD.open(fullPath, FILE_WRITE);
  if (!dataFile) {
    printAll("First Write Error.");
    hardwareErr();
  }
  dataFile.println("#Time Sw Temp");
  dataFile.close();
}

//  DATA AND DIAGNOSTICS:
/********************************************************************************************************************************************************************************/
void DatalogAndDiagnostics() {

  // TIME INFO:
  /********************************************************************************************************************************************************************************/
  char displayTime[21];
  if (!RTC.read(tm)) {
    lcd.clear();
    printAll(F("RTC failed"));
    printAll(F("RTC failed"));
    hardwareErr();
  }
  if (tm.Hour == 0 && tm.Minute == 0 && tm.Second == 0) {
    createFileAndName();
    delay(750);
  }
  unsigned long totMillis = millis() - tStart;
  unsigned long totSeconds = (millis() - tStart) / 1000;
  unsigned long totMinutes = totSeconds / 60;
  unsigned long totHours = totMinutes / 60;
  unsigned long totDays = totHours / 24;
  totSeconds %= 60;
  totMinutes %= 60;
  totHours %= 24;
  totDays %= 7;
  char charDays[2];
  char charHours[3];
  char charMinutes[3];
  char charSeconds[3];
  dtostrf(totDays, 1, 0, charDays);
  dtostrf(totHours, 2, 0, charHours);
  dtostrf(totMinutes, 2, 0, charMinutes);
  dtostrf(totSeconds, 2, 0, charSeconds);
  sprintf(displayTime, "%02d:%02d:%02d %sd%02sh%02sm%02ss", tm.Hour, tm.Minute, tm.Second, charDays, charHours, charMinutes, charSeconds);
  lcd.setCursor(0, 3);
  lcd.print(displayTime);
  unsigned long hToM = tm.Hour * 60;
  unsigned long hToS = hToM * 60;
  unsigned long mToS = (tm.Minute * 60);
  unsigned long sToS = tm.Second;
  unsigned long tmDayInS = hToS + mToS + sToS;

  //SPECIFIC DATALOGGING CODE:
  /********************************************************************************************************************************************************************************/
  static int floatSwState;
  static byte nSample = 0;
  const int highTempTm = 1000;
  const int tempErrTm = 1500;
  const int floatSwTm = 500;
  static bool highTempErrState = 0;
  static bool hardwareErrState = 0;
  static bool floatSwErrState = 0;
  lcd.setCursor(10, 2);
  if (digitalRead(floatSw) == 1) {
    lcd.print("OK    ");
    floatSwState = 1;
    floatSwErrState = 0;
  } else if (digitalRead(floatSw == 0)) {
    lcd.print("NOT OK");
    floatSwState = 0;
    floatSwErrState = 1;
    if (totMillis - lastMillis > floatSwTm) {
      lastMillis = totMillis;
      if (buzzerState == 1) {
        digitalWrite(buzzer, 1);
      }
      digitalWrite(RED, 0);
      digitalWrite(GREEN, 0);
      digitalWrite(BLUE, 1);

    } else {
      digitalWrite(buzzer, 0);
    }
  }
  lcd.setCursor(6, 1);
  sensors.getTempCByIndex(0);
  lcd.print(sensors.getTempCByIndex(0));
  lcd.print("\337C");
  sensors.requestTemperatures();
  if (sensors.getTempCByIndex(0) >= 0 && sensors.getTempCByIndex(0) <= 22) {
    digitalWrite(RED, 0);
    digitalWrite(GREEN, 1);
    digitalWrite(BLUE, 0);
    highTempErrState = 0;
  } else if (sensors.getTempCByIndex(0) > 22 && sensors.getTempCByIndex(0) <= 23) {
    analogWrite(RED, 255);
    analogWrite(GREEN, 255);
    digitalWrite(BLUE, 0);
    highTempErrState = 0;
  } else if (sensors.getTempCByIndex(0) > 23 && sensors.getTempCByIndex(0) <= 24) {
    analogWrite(RED, 255);
    analogWrite(GREEN, 90);
    digitalWrite(BLUE, 0);
    highTempErrState = 0;
  } else if (sensors.getTempCByIndex(0) > 24 && sensors.getTempCByIndex(0) <= 25) {
    digitalWrite(RED, 1);
    digitalWrite(GREEN, 0);
    digitalWrite(BLUE, 0);
    highTempErrState = 0;
  } else if (sensors.getTempCByIndex(0) > 25) {
    highTempErrState = 1;
    if (totMillis - lastMillis > highTempTm) {
      lastMillis = totMillis;
      if (buzzerState == 1) {
        digitalWrite(buzzer, 1);
      }
      digitalWrite(RED, 1);
      digitalWrite(GREEN, 0);
      digitalWrite(BLUE, 0);
    } else {
      digitalWrite(buzzer, 0);
      digitalWrite(RED, 0);
      digitalWrite(GREEN, 0);
      digitalWrite(BLUE, 0);
    }
  } else {
    hardwareErrState = 1;
    if (totMillis - lastMillis > tempErrTm) {
      lastMillis = totMillis;
      if (buzzerState == 1) {
        digitalWrite(buzzer, 1);
      }
      digitalWrite(RED, 1);
      digitalWrite(GREEN, 1);
      digitalWrite(BLUE, 1);
    } else {
      digitalWrite(buzzer, 0);
      digitalWrite(RED, 0);
      digitalWrite(GREEN, 0);
      digitalWrite(BLUE, 0);
    }
  }
  static float aveT1 = sensors.getTempCByIndex(0);
  static float totT1 = aveT1;
  static char charAveT1[9];
  static char charTotT1[9];
  static char charTemp[9];
  dtostrf(aveT1, 7, 2, charAveT1);
  dtostrf(totT1, 8, 2, charTotT1);
  dtostrf(sensors.getTempCByIndex(0), 7, 2, charTemp);
  if (totMillis > tSample) {
    nSample += 1;
    aveT1 = totT1 / nSample;
    totT1 += sensors.getTempCByIndex(0);
    sensors.requestTemperatures();
    char sampleData[70];
    sprintf(sampleData, "Sample: %d Sw: %d temp(°C):%s Ave:%s Tot:%s",
            nSample, floatSwState, charTemp, charAveT1, charTotT1);
    Serial.println(sampleData);
    tSample += sampleTm;
  }

  if (highTempErrState == 0 && hardwareErrState == 0 && floatSwErrState == 0) {

    digitalWrite(buzzer, 0);
  }

  // OPEN FILE:
  /********************************************************************************************************************************************************************************/
  char aveData[20];
  char charTmDayInS[7];
  dtostrf(tmDayInS, 5, 0, charTmDayInS);
  sprintf(aveData, "%ls %d%s", charTmDayInS, floatSwState, charAveT1);
  dataFile = SD.open(fullPath, FILE_WRITE);
  if (dataFile) {
    if (totMillis > tLog) {
      dataFile.println(aveData);
      Serial.println("#Time Sw Temp");
      Serial.println(aveData);
      tLog += logTm;
    }
    if (nSample > 7) {
      nSample = 0;
      totT1 = sensors.getTempCByIndex(0);
    }
  } else {
    printAll(F("File write Err"));
    lcd.clear();
    printAll(F("File write Err"));
    hardwareErr();
  }

  // ALARM
  /********************************************************************************************************************************************************************************/
  static bool lastBTstate = 0;
  unsigned long lastDebounceTime = 0;
  const byte debounceDelay = 50;
  lcd.setCursor(13, 1);
  lcd.print("  ALARM");
  int newBTstate = analogRead(buzzerTogglePin) < 500 ? 1 : 0;
  if (newBTstate != lastBTstate) {
    lastDebounceTime = totMillis;
  }
  if ((totMillis - lastDebounceTime) > debounceDelay) {
    if (newBTstate != BTstate) {
      BTstate = newBTstate;
      if (BTstate == 1) {
        buzzerState = !buzzerState;
      }
    }
  }
  lcd.setCursor(17, 2);
  if (buzzerState == 1) {

    lcd.print(" ON");
  }

  else if (buzzerState == 0) {

    lcd.print("OFF");
  }
  lastBTstate = newBTstate;

  dataFile.close();
}

// SETUP() FUNCTION
/********************************************************************************************************************************************************************************/
void setup() {
  initialisation();
  createFileAndName();
  firstWrite();
  tStart = millis();
}

// LOOP() FUNCTION
/********************************************************************************************************************************************************************************/
void loop() {
  DatalogAndDiagnostics();
}

// END OF PROGRAM
/********************************************************************************************************************************************************************************/

Please post schematics.

Could you explain how you do the reset in your code?

If a hardware error occurs, then the device goes into a while loop that beeps an alarm and checks if the SD card begins, the file opens and the RTC gets the time. Once all the hardware is working again, the code breaks out of the while loop and runs:

void (*reset)(void) = 0;

This isn't exactly a system reset, as it only calls the reset vector at address 0, but it is pretty close. It worked before ( about a week or so ago) but now it doesn't work.

I think I'm just going to use a watchdog timer, as I've gotten my arduino ESP32 nano, which has a lot more program storage ( the main issue for my old nano was that i was using most of it's storage)

void hardwareErr() {
  while (!SD.begin(chipSelect) || !RTC.read(tm) || !SD.open(fullPath)) {
    digitalWrite(buzzer, 1);
    delay(100);
    digitalWrite(buzzer, 0);
    delay(1900);
  }

  if(SD.begin(chipSelect) && RTC.read(tm) && SD.open(fullPath)) {
  void (*reset)(void) = 0;
  }
}

This code does not look correct. You appear to be declaring the reset function and not calling it.
The reset function declaration needs to declared separately, and then called.

void(* resetFunc) (void) = 0;
 
void setup() {     
  Serial.begin(9600);
  Serial.println("How to Reset Arduino Programmatically");
  delay(200);
}

void loop() 
{
  Serial.println("A");
  delay(1000);               
  Serial.println("B");
  delay(1000);               
  Serial.println("Now we are Resetting Arduino Programmatically");
  Serial.println();
  delay(1000);
  resetFunc();
  Serial.println("Arduino will never reach there.");
 
}

Using the watchdog timer is a better method.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.