Arduino watchdog or automatic RESET in case of freezing

  • Tutorial

It will be about how to keep Arduino always in working condition. The watchdog mechanism is built into Atmega controllers, but, unfortunately, not every Arduino bootloader handles this function correctly. Let's try to deal with this problem.

So what is watchdog? In simple words, this is a built-in timer for a certain time (up to 8 seconds depending on the chip), which can be run programmatically. As soon as the timer "dips" to zero, the controller gives the correct reset signal (RESET) and the whole device goes into a hard reset. Most importantly, this timer can also be reset to the initial state programmatically.

  • The correct reset signal is long enough for the controller to start overloading. Sometimes it is tempting to connect any Arduino digital output to the RST input and set it to 0 when you need to reboot. This is a bad approach to solving the problem, because such a signal may not be enough in time, although it is possible that in some cases this will also work ..
  • hard reboot is a real reboot that occurs when you press the RESET button. The fact is that there is also the concept of soft reset - this is a program transition to the 0-th address. In principle, this is also a useful thing, but with its help it is impossible to reboot a hung Ethernet controller or a doused LCD.

In short, the built-in watchdog is just what you need without additional circuits, soldering and connections.

Watchdog Features


To use Watchdog functions, you need to connect a standard library to the project:
#include 

Now the following three functions are available to us:

1. Starting the watchdog timer:
wdt_enable(WDTO_8S);
/* Возможные значения для константы
  WDTO_15MS
  WDTO_30MS
  WDTO_60MS
  WDTO_120MS
  WDTO_250MS
  WDTO_500MS
  WDTO_1S
  WDTO_2S
  WDTO_4S
  WDTO_8S
*/

The timer will count exactly as specified in the constant. After this time, a reboot will occur.

2. Reset watchdog timer:
wdt_reset();

I think it’s understandable why this function is needed - until you call it, the controller will not reset. As soon as the system freezes and this function ceases to be called, then after a specified period, a reboot will occur.

3. Disabling watchdog:
wdt_disable();

Disabling the watchdog timer.

Actually, this could have ended our story about watchdog ... but the fact is that all this works only in Arduino Uno, and on Arduino Mega, Mini and Nano it all works exactly the opposite, i.e. not working at all :)

Why watchdog doesn't work on most modern Arduino boards


The fact is that after the reboot that was caused by watchdog, the controllers of the latest releases leave watchdog on for a minimum period , i.e. 15ms. This is necessary so that the program somehow finds out that the previous reboot was by watchdog. Therefore, the first task of the loader (or your program, if it starts first) is to save information that the reboot was "unexpected" and immediately turn off watchdog. If this is not done, then the system will go to bootloop, i.e. will forever be overloaded.

As you know, Arduino has a special bootloader that runs primarily after a system reboot. And, unfortunately, the standard bootloader does not reset watchdog! Thus, the system enters a cruel bootloop (“crazy led” state, in which the LED on the 13th pin flashes like crazy).

It all looks something like this:


Ways to solve the problem


If you look at the sources of the standard bootloader (they are supplied with the platform), then the watchdog shutdown code is (!), But this code is conditional compiled and, most likely, the standard bootloader was compiled without watchdog support. At least in the platform package version 1.5.2 (the last at the time of writing), this is the case.

To solve the problem, I even read the platform’s man’s (:) and it seems that this problem is described there and even the code is given that should make everyone happy:

uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
void get_mcusr(void) __attribute__((naked)) __attribute__((section(".init3")));
void get_mcusr(void){
  mcusr_mirror = MCUSR;
  MCUSR = 0;
  wdt_disable();
}

The get_mcusr () function is described here, which should be called immediately after the reset. This is achieved by the macro "__attribute __ ((section (". Init3 "))). I tried to write this function to all sections that are possible - yes, it really starts before the setup () function from the sketch, but, unfortunately, much later than 15ms (the minimum watchdog constant) after reset ...

In short, no matter how I dig the Internet in search of an easy solution to the problem, so nothing was found. I found only one way to make watchdog work - to reflash the bootloader ... which we will do now.

Checking the performance of watchdog


Before flashing something, you need to check - suddenly your Arduino supports watchdog. For this, I wrote a small sketch for the test. Just fill it in, open the port monitor and see what happens.

Testing on watchdog
#include 
void setup() {
  wdt_disable(); // бесполезная строка до которой не доходит выполнение при bootloop
  Serial.begin(9600);
  Serial.println("Setup..");
  Serial.println("Wait 5 sec..");
  delay(5000); // Задержка, чтобы было время перепрошить устройство в случае bootloop
  wdt_enable (WDTO_8S); // Для тестов не рекомендуется устанавливать значение менее 8 сек.
  Serial.println("Watchdog enabled.");
}
int timer = 0;
void loop(){
  // Каждую секунду мигаем светодиодом и значение счетчика пишем в Serial
  if(!(millis()%1000)){
    timer++;
    Serial.println(timer);
    digitalWrite(13, digitalRead(13)==1?0:1); delay(1);
  }
//  wdt_reset();
}


After rebooting (or connecting the monitor to the port), the built-in LED will blink, indicating that the bootloader has started. Next, in the setup section, watchdog is turned on with a timer for 8 seconds. After that, the LED will count us this time and a reboot should occur.

Then the fun part begins - if the reboot occurred and everything repeats in the same sequence, then you have Arduino in your hands, in which the bootloader correctly processes watchdog. If, after a reboot, the LED on the 13th pin starts flashing endlessly, then the bootloader does not support watchdog. Here, even the reset button will not help. For subsequent firmware, you need to disconnect the board from the power supply and after switching on have time to flash before the first reboot.

I tested 4 types of boards and only the bootloader in Arduino Uno worked as it should:

Arduino Boards

Monitor Results
Watchdog is not supported by the bootloader:
image
Watchdog is supported by the bootloader:



What is the easiest way to flash a new bootloader?


You can flash the bootloader in Arduino using separate programmers, or you can build your own programmer using the same Arduino. Those. any Arduino board can be turned into a programmer, filling in a special sketch.

In this article I will not describe all the wisdom of creating an Arduino-based programmer, because This topic is described in some detail on the Internet . As a programmer, I used Arduino Uno. As you know, firmware is produced through a separate ICSP connector, which is on almost all boards. In the case of firmware Arduino Pro Mini, which does not have ICSP, the connection is made directly to the conclusions .

Connection for bootloader firmware
image
image

Where can I get a bootloader that supports watchdog?


This chapter is reminiscent of dancing with a tambourine and most likely you can make everything somehow simpler, but, alas, I didn’t manage in a different way.

It is recommended that you use the bootloaders from the optiboot package. In principle, these bootloaders go into the installation of the Arduino platform itself, but it is better to download and install the latest version of optiboot from here . Installation consists of two steps (perhaps this can be done somehow differently):

  1. The bootloaders \ optiboot folder is overwritten in C: \ Program Files (x86) \ Arduino \ hardware \ arduino \ avr \ bootloaders \ optiboot
  2. The boards.txt file is appended to the file C: \ Program Files (x86) \ Arduino \ hardware \ arduino \ avr \ boards.txt

Naturally, the Arduino platform installation folder may be different for you.

Next, the development environment is overloaded and in the Service / Board menu, you can observe new boards marked [optiboot]. Unfortunately, when choosing these boards, some strange compilation errors occur and all sorts of other oddities appear ... so we make it even easier. Open the file C: \ Program Files (x86) \ Arduino \ hardware \ arduino \ avr \ boards.txt in any text editor and change the following lines:

For Arduino Nano:
menu.cpu.nano.atmega328.bootloader.file = optiboot / optiboot_atmega328 .hex

For Arduino Mini:
menu.cpu.mini.atmega328.bootloader.file = optiboot / optiboot_atmega328.hex

The next problem is that the optiboot bootloader for the Arduino Mega board does not existin nature, as Mega has more memory and uses a different protocol. Therefore, we use a standard but modified bootloader, which we download from here . Rename the file to stk500boot_v2_mega2560_2.hex and write it to the folder C: \ Program Files (x86) \ Arduino \ hardware \ arduino \ avr \ bootloaders \ stk500v2.

Next, we change the following line in the already familiar boards.txt file:
mega2560.bootloader.file = stk500v2 / stk500boot_v2_mega2560_2.hex

Do not be afraid that the file for the modified firmware for Mega is 2 times smaller than the standard one - as it should be.

Firmware process


After all the changes, you can flash the bootloaders by choosing ordinary boards in the board menu (not [optiboot]!). In this case, it will be the hex files that we specified in the board.txt file that will be flashed.
The firmware process may not start and an error is issued:
avrdude: stk500_getsync(): not in sync: resp=0x00

To solve this problem, open the programmer sketch and in the setup section select a different serial port speed.
During pouring in Arduino Mega, an error may appear that should be ignored:
avrdude: verification error, first mismatch at byte 0x3e000
                               0x0d != 0xff
                      avrdude: verification error; content mismatch 

Final manipulations


The optiboot bootloaders have another feature - they increase the speed of loading sketches, so when using boards with optiboot, you need to make the appropriate changes to boards.txt:

For Arduino Nano:
menu.cpu.nano.atmega328.upload.speed = 115200
For Arduino Mini:
menu .cpu.mini.atmega328.upload.speed = 115200 The

previous port speed is also better to remember, because it will need to be used on boards with standard bootloaders. If you do not make such changes, an error will be generated during the sketching process, such as this:
avrdude: stk500_getsync(): not in sync: resp=0x00

References, literature


Optiboot package Bootloader
firmware
How to flash bootloader in Arduino Pro Mini

Also popular now: