Reset a program from a ‘freeze’

While doing a test run on software for an incubator the software did fine, until suddenly on the ninth day weird things started to happen: the LCD showed some odd data and in spite of a low temperature the heating had not kicked in. I resetted the software, wondering what it could be but only an hour later again something off happened. This time in spite of the temperature being well over the upper limit, the heating was not switched off.
I checked my code, which really wasn’t so complicated: Read DSB1820, read DHT11, compare with high and low limit, switch a pin on or off and write the value to an LCD and I couldn’t find a single mistake and don’t forget, it had run flawlessly for 9 days. I suspected my display. This was a 20×4 LCD with I2C module with 4k7 pull up. Nevertheless there might still have been some ‘static’ on the SDA and SCL lines that supposedly can cause the Arduino to freeze.

Obviously that is not good if you are running an incubator as you dont want to check it and find your eggs boiled.
So, other than maybe straightening out the LCD cables a bit, I decided that I needed some software protection against ‘freezes’
The only (and possibly best) way to do this is with the watchdog timer. I dont want to go into the specifics and the background of the watchdog timer, but just keep it on a practical level.
What we do is to set-up the watchdog timer to initiate a system reset after say 4 seconds. Then in our loop we do a reset of the watchdog timer so it starts counting from zero again. So as long as the program tells the watchdog timer “I am still running” nothing will happen. Should the program freeze up, it will not reset the watchdog timer and then after 4 seconds the watchdog timer will reset the entire system.
It is very well possible to use the watchdog timer by manipulating the various registers yourself, but it is much simpler to use the watchdog libary that is part of the avr libraries.
We do this as follows:

#include <avr/wdt.h>

void setup()
{
	wdt_disable();
	//wdt_enable(WDTO_1S);// 1 sec
	wdt_enable(WDTO_2S);// 2 sec
	//wdt_enable(WDTO_4S);// 4 sec
	//wdt_enable(WDTO_8S);// 8 sec
}

void loop()
{
	wdt_reset();
	//  your program
	........
}
Advertisement

Simple EEPROM Module for Arduino or other microcontroller

256 EEPROMs come in handy if you want to store some data without losing it. Many microcontrollers come with some internal EEPROM, but as EEPROMs have a finite (though very large) number of writes before they start becoming faulty, my anal retentive character always had a problem with using that internal EEPROM.
There are other reasons too why you might want to use an external EEPROM: data logging in which you just want to swap an EEPROM rather than having to read out your microcontroller in the field.
Anyway, I just wanted to share a simple 5 minute build EEPROM module that is a bit simpler than a prior one i published.
BOM
1x 24LC256 EEPROM (or other size)
2x 4k7 resistors
stripboard 5 strips of 8
8 pin DIL IC socket (optional)

256pin I am using a 24LC256. That is a 256 kiloBIT EEPROM so in fact only a 32kiloBYTE EEPROM in my traditional way of thinking. These are not to expensive. Can be had for around 80 ct USD.
Although the board can also be used for smaller EEPROMS, like a 24C32, I would advise against that. If that is what you need, buy a 50 ct DS1307 RTC module that includes a 24C32 (which is actually 4kByte).

Anyway, the 24LC256 is an I2C EEPROM, which is pretty standard and which makes use easy
Pins A0, A1 and A2 select the I2C addresses, (A0=pin1, A1=pin1, A2=pin3).
The addressing is as follows

1 0 1 0 A2 A1 A0 x

So if you connect pins A0, A1, A2 to GND the I2C address will be 1010000 = 0x50 in hexadecimal.
If you connect them all to Vcc it will be 1010111=0x57.
As 0x50 is an address that is often used, I decided to connect A2 and A1 to ground and A0 to Vcc, which gives 0x51. It also made the design a tadd simpler.
Pin 7 is the ‘WriteProtect’ pin that needs to be pulled HIGH for ReadOnly and LOW for Read/Write. Obviously I connected it to ground.
The pull up resistors are both 4k7
You will find many EEPROM libraries in the Arduino Playground I tend to use the following code to read and write:

void writeData(int device, unsigned int addr, byte data)
// writes a byte of data 'data' to the chip at I2C address 'device', 
// in memory location 'add'
{
    if ( addr > 65535 )
        addr = addr | B00001000;
    Wire.beginTransmission(device);
    Wire.write((int)(addr >> 8));   // left-part of pointer address
    Wire.write((int)(addr & 0xFF)); // and the right
    Wire.write(data);
    Wire.endTransmission();
    delay(10);
}
byte readData(int device, unsigned int add)
// reads a byte of data from memory location 'add' in chip at I2C address 'device'
{
    byte result; // returned value
    Wire.beginTransmission(device); // these three lines set the pointer 
				    // position in the EEPROM
    Wire.write((int)(add >> 8));    // left-part of pointer address
    Wire.write((int)(add & 0xFF));  // and the right
    Wire.endTransmission();
    Wire.requestFrom(device, 1);    // now get the byte of data...
    result = Wire.read();
    return result; // and return it as a result of the function readData
}

Special Notes if using the 24LC1025

1025

This board can also be used for larger EEPROMS, but……… if you use it for the 24LC1025, you need to make a small adaptation. With this chip A2 MUST be tied to Vcc for it to operate.

The 24LC1025 has an internal addressing boundary limitation that is divided into two segments of 512K bits. Block select bit ‘B0’ to control access to each segment.

The addressing is determined by

1 0 1 0 B0 A1 A0 R/-W  

in which the ‘Block select bit is used to address the lower or higher 512k Block The chip thus has 2 different addresses. with the A0A1 selection as in my board those are:

1010101 =0x55

1010001 =0x51

For memory access from 0..65535 the I2C address for the Memory Chip is 0x51. If you want to access memory between 65536..131071 the Chip address is 0x55

You cannot write across the 65535..65536 byte boundary with breaking the operation into two write() calls. One to chip 0x51, the other to chip 0x55.