Use threads for your watchdog

By:
Posted: 2nd December 2018
Category: Arduino
Comments: 0

I have been playing around with the Arduino Nano to build a framework with a small footprint that I could deploy in remote locations (deep in the garden or scattered out the warehouse etc). So first thing is to keep that device running as reliable as possible (good case, solid power supply - the whole thing). However the issue that used to plague the Nano was the fact that the build-in watchdog did not work and you had to do some firmware flashing to get that functionality up and running. For those who are not familiar with the term - in short a watchdog allows to restart your hardware when the software decides to hang for whatever reason. Very handy indeed.

Once you get the Nano to work with the watchdog I found that it kind of forces me into a specific way of programming which I really did not like much. This became much more apparent when I started experimenting with the "mother" Arduino Uno / Mega that I wanted to use as a little server that will store all the sensor data. I understand that having a proper server would be a much more prefered solution - but that can introduce much more complexity to what I want to achieve at the moment (more on that another time). So... the watchdog can technically only work with 8 seconds before it needs to be reset (otherwise your NANO will just restart). Not very flexible when you use delays is it? However, this library comes along with the ability to introduce "threads" into my project. In short you will have to stop relying on the delay function. Now "threads" are the "new" kid in town! Here is a little sample code that came with the library (I have bend it to my will a tiny bit):

#include <Thread.h>
#include <ThreadController.h>

// Watchdog library !
#include <avr/wdt.h>

// ThreadController that will controll all threads
ThreadController controll
= ThreadController();

//My Thread (as a pointer)
Thread
* myThread = new Thread();
//His Thread (not pointer)
Thread hisThread
= Thread();

// callback for myThread
void niceCallback()
{
Serial
.print("Thread running... ");
Serial
.println(millis());
}

// callback for hisThread
void resetWatchDog()
{
wdt_reset
(); // reset the WDT timer
Serial
.print("Watchdog RESET... ");
Serial
.println(millis());
}

void setup()
{
// immediately disable watchdog timer so that you can prevent any potential issues and infinity loops which are nasty
wdt_disable
();

Serial
.begin(9600);
wdt_enable
(WDTO_8S);

// Configure myThread

myThread
->onRun(niceCallback);
myThread
->setInterval(2000);

// Configure myThread
hisThread
.onRun(resetWatchDog);
hisThread
.setInterval(5000);

// Adds both threads to the controller
controll
.add(myThread);
controll
.add(&hisThread); // & to pass the pointer to it

Serial
.println("Setup process complete..");
}


void loop()
{
// run ThreadController
// this will check every thread inside ThreadController,
// if it should run. If yes, he will run it;
controll
.run();
// Rest of my code... Ethernet web server ?

}

This sketch will trigger two threads when they are due. Obviously in this example I want to reset the watchdog every 5 seconds - you can just copy this code and adjust it to whatever you require. It should be a good method to expand this idea into grabbing sensor data every X seconds... (and I am thinking here about few. One every 3 seconds, second every 5 seconds and the third every 20 seconds - you get the picture). Here is a screenshot from the serial output:


I believe that the above screenshot is self-explanatory. It hopefully will give someone another method of getting the watchdog reset activated and not rely on the usual linear writing style. The git page for this library has some interesting notes and suggestions on how to utilise/fine tune the "thread" idea. I would not deploy this code "as is" in any production environment (test your code before you do that!) however this has proven to be very stable when combined with my UDP Server project I am currently working on. It gathers data from the network sensors (cough cough Arduino Nano cough cough) and stores it on the SD card and even maybe upload it from time to time to a proper server. And sure, there are other libraries that have implemented similar functionality as this one (I have no favorite so whatever floats your boat).

On a side note... I have also discovered relays (yeah, was not aware of their existence until like 6 weeks ago....). I think I will have a fun idea how to use them to build a rather "odd" watchdog....

Hope this helps!

Hey, like this? Why not share it with a buddy?