Choosing an MCU with a small amount of RAM (e.g., the ATmega328p MCU has only 2KB RAM), and programming it by using dynamic memory allocation (e.g., by using malloc
) may cause memory fragmentation having as side effect strange MCU behavior. In such cases, observing the "real free" amount of RAM and rebooting the device whenever a dangerously low level is detected may be the only (or the simplest) solution for having the project running for a long amount of time.
We present three currently available and simple methods which allow to programmatically reset an Arduino.
Watchdog Reset - The Recommended Method
Whenever possible, this is the method one should use. Not only that was designed and implemented by the chip manufacturer, but also produces a clean reset, with the same results as when you freshly power the Arduino (or the custom Arduino-brained project board). Think on a watchdog as on a kind of guardian for the micro-controller, able to power it off then back on. Once a watchdog was started, the program must emit signals (also named reset signals) within specified time slots, and in the absence of the correct signal, it simply produces a reset. The specific time periods are called prescallers and are normally defined as constants. For Atmel MCUs found in the Arduino boards, the following prescaller constants were defined: WDTO_15MS
, WDTO_30MS
, WDTO_60MS
, WDTO_120MS
, WDTO_250MS
, WDTO_500MS
, WDTO_1S
, WDTO_2S
, WDTO_4S
, and WDTO_8S
. Their names are suggestive, indicating possible time slots between 15 milliseconds and 8 seconds.
The following code shows how to use the watchdog to reset the Arduino on-demand:
#include <avr/wdt.h>
void softwareReset( uint8_t prescaller) {
wdt_enable( prescaller);
while(1) {}
}
void setup() {
void loop() {
softwareReset( WDTO_60MS);
}
We have discussed about how use a watchdog for auto-reset purposes, but it has many other use cases, such as waking-up the MCU from power-down states or debugging.
Program Restart - The Unclean Method
This method does not really perform a MCU reboot, but rather a program restart. The obvious negative effect is that the MCU hardware states remains mostly unchanged. This includes the pin modes, their current HIGH
or LOW
states and so on. The following code shows how to implement the softwareReset
method by using assembly language and executing a jump to the address where the program starts:
void softwareReset( unsigned long delayMillis) {
uint32_t resetTime = millis() + delayMillis;
while ( resetTime > millis()) {
}
asm volatile ( "jmp 0");
}
Enforce Hardware Reset - The Hacker's Method
This method requires to connect one of the digital pins (e.g., digital pin 7) to the reset pin of the Arduino via a 1kOhm or 2.2kOhm resistor. Then set the digital pin as OUTPUT
and keep it HIGH
as long as no reboot/reset is required. Once a reboot is needed, just set the digital pin to LOW
. This method works because by putting the reset pin to a LOW
state, the micro-controller receives a "hardware reset signal". The following Arduino sketch code shows how to implement and use this method:
void softwareReset( uint8_t prescaller) {
uint32_t resetTime = millis() + delayMillis;
while ( resetTime > millis()) { }
digitalWrite( 7, LOW);
}
void setup() {
pinMode( 7, OUTPUT);
digitalWrite( 7, HIGH);
}
void loop() {
softwareReset( 60);
}
Unfortunately, this method can't be used on all Arduino boards and also not with every Atmel MCU. The main problem is that the digital pins goes in a LOW
state when set to OUTPUT
thus resulting in a reset loop which may require to remove the connection with the reset pin before being able to reprogram the MCU. We confirm that Arduino UNO and Arduino MEGA2560 boards can be safely used with this method.
While Arduino was mostly in our discussion (so, Atmel MCUs), there are many other MCUs designed and produced by various manufacturers where the above presented methods work in the same way. However, different code may be required and in case of using "the hacker method", one may need also to study the chip datasheet for being able to correctly use the reset and I/O pins and even may have to use a different resistor value.