Save the state of the outputs of an Arduino after a power outage

help me please
I want to know how to save the state of the outputs of an Arduino after a power outage

After a power outage? That sounds too late - it is all gone!

My system has an SD card and saves its key memory variables (arrays of data) every hour. You can see today's backup files at http://2wg.co.nz/BACKUPS.DIR/

When my system restarts its gets the current time using UDP and then looks backwards for up to twelve hours for the last backup file. It then reloads it and carries on. (This is largely redundant because my Arduino and ADSL modem are plugged into a UPS and will run for hours if there is a power cut.)

However this system is very useful everytime I recompile and reinstall software updates onto my Arduino. Everytime it restarts it automatically reloads its main memory arrays from the last backup. The system then operates as if nothing has happened - no data appears to have been lost. (Actually new information since the last backup is lost but the loss of that much information is not important to my application - the loss of everything over the last 24 hours however would be significant.)

I hope this helps.

Catweazle NZ

EEPROM is persistent over power outages, but it has finite life and is slow. You don't want to write to it frequently but if your pins only change once every few minutes or something, then it would be quite reasonable to save every state-change.

This is my arduino program that is used to turn the LED’s what I should add to it saves the state of the LED when a power failure occurs

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
// size of buffer used to capture HTTP requests
#define REQ_BUF_SZ 60

// MAC address from Ethernet shield sticker under board
byte mac = { };
IPAddress ip(); // IP address, may need to change depending on network
EthernetServer server(80); // create a server at port 80
File webFile; // the web page file on the SD card
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0; // index into HTTP_req buffer
boolean LED_state[6] = {0}; // stores the states of the LEDs

void setup()
{

Serial.begin(9600); // for debugging

// initialize SD card
Serial.println(“Initializing SD card…”);
if (!SD.begin(4)) {
Serial.println(“ERROR - SD card initialization failed!”);
return; // init failed
}
Serial.println(“SUCCESS - SD card initialized.”);
// check for index.htm file
if (!SD.exists(“index.htm”)) {
Serial.println(“ERROR - Can’t find index.htm file!”);
return; // can’t find index file
}
Serial.println(“SUCCESS - Found index.htm file.”);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);

Ethernet.begin(mac, ip); // initialize Ethernet device
server.begin(); // start to listen for clients
}

void loop()
{
EthernetClient client = server.available(); // try to get client

if (client) { // got client?
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) { // client data available to read
char c = client.read(); // read 1 byte (character) from client
// limit the size of the stored received HTTP request
// buffer first part of HTTP request in HTTP_req array (string)
// leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1)
if (req_index < (REQ_BUF_SZ - 1)) {
HTTP_req[req_index] = c; // save HTTP request character
req_index++;
}
// last line of client request is blank and ends with \n
// respond to client only after last line received
if (c == ‘\n’ && currentLineIsBlank) {
// send a standard http response header
client.println(“HTTP/1.1 200 OK”);
// remainder of header follows below, depending on if
// web page or XML page is requested
// Ajax request - send XML file
if (StrContains(HTTP_req, “ajax_inputs”)) {
// send rest of HTTP header
client.println(“Content-Type: text/xml”);
client.println(“Connection: keep-alive”);
client.println(“Refresh: 15”); // refresh the page automatically every 10 sec
client.println();
SetLEDs();
// send XML file containing input states
XML_response(client);
}
else { // web page request
// send rest of HTTP header
client.println(“Content-Type: text/html”);
client.println(“Connection: keep-alive”);
client.println();
// send web page
webFile = SD.open(“index.htm”); // open web page file
if (webFile) {
while(webFile.available()) {
client.write(webFile.read()); // send web page to client
}
webFile.close();
}
}
// display received HTTP request on serial port
Serial.print(HTTP_req);
// reset buffer index and all buffer elements to 0
req_index = 0;
StrClear(HTTP_req, REQ_BUF_SZ);
break;
}
// every line of text received from the client ends with \r\n
if (c == ‘\n’) {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != ‘\r’) {
// a text character was received from client
currentLineIsBlank = false;
}
} // end if (client.available())
} // end while (client.connected())
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection
} // end if (client)
}

// checks if received HTTP request is switching on/off LEDs
// also saves the state of the LEDs
void SetLEDs(void)
{
// LED 1 (pin 2)
if (StrContains(HTTP_req, “LED1=1”)) {
LED_state[0] = 1; // save LED state
digitalWrite(2, HIGH);
}
else if (StrContains(HTTP_req, “LED1=0”)) {
LED_state[0] = 0; // save LED state
digitalWrite(2, LOW);
}
// LED 2 (pin 3)
if (StrContains(HTTP_req, “LED2=1”)) {
LED_state[1] = 1; // save LED state
digitalWrite(3, HIGH);
}
else if (StrContains(HTTP_req, “LED2=0”)) {
LED_state[1] = 0; // save LED state
digitalWrite(3, LOW);
}
// LED 3 (pin 5)
if (StrContains(HTTP_req, “LED3=1”)) {
LED_state[2] = 1; // save LED state
digitalWrite(5, HIGH);
}
else if (StrContains(HTTP_req, “LED3=0”)) {
LED_state[2] = 0; // save LED state
digitalWrite(5, LOW);
}
// LED 4 (pin 6)
if (StrContains(HTTP_req, “LED4=1”)) {
LED_state[3] = 1; // save LED state
digitalWrite(6, HIGH);
}
else if (StrContains(HTTP_req, “LED4=0”)) {
LED_state[3] = 0; // save LED state
digitalWrite(6, LOW);
}
// LED 5 (pin 7)
if (StrContains(HTTP_req, “LED5=1”)) {
LED_state[4] = 1; // save LED state
digitalWrite(7, HIGH);
}
else if (StrContains(HTTP_req, “LED5=0”)) {
LED_state[4] = 0; // save LED state
digitalWrite(7, LOW);
}
// LED 6 (pin 8)
if (StrContains(HTTP_req, “LED6=1”)) {
LED_state[5] = 1; // save LED state
digitalWrite(8, HIGH);
}
else if (StrContains(HTTP_req, “LED6=0”)) {
LED_state[5] = 0; // save LED state
digitalWrite(8, LOW);
}

}

// LED status
void XML_response(EthernetClient cl)
{
cl.print("<?xml version = \"1.0\" ?>");
cl.print("");

// checkbox LED states
// LED1
cl.print("");
if (LED_state[0]) {
cl.print(“checked”);
}
else {
cl.print(“unchecked”);
}
cl.println("");
// LED2
cl.print("");
if (LED_state[1]) {
cl.print(“checked”);
}
else {
cl.print(“unchecked”);
}
cl.println("");
// LED3
cl.print("");
if (LED_state[2]) {
cl.print(“checked”);
}
else {
cl.print(“unchecked”);
}
cl.println("");
// LED4
cl.print("");
if (LED_state[3]) {
cl.print(“checked”);
}
else {
cl.print(“unchecked”);
}
cl.println("");

// LED5
cl.print("");
if (LED_state[4]) {
cl.print(“checked”);
}
else {
cl.print(“unchecked”);
}
cl.println("");

// LED6
cl.print("");
if (LED_state[5]) {
cl.print(“checked”);
}
else {
cl.print(“unchecked”);
}
cl.println("");

cl.print("");
}

// sets every element of str to 0 (clears array)
void StrClear(char *str, char length)
{
for (int i = 0; i < length; i++) {
str = 0;

  • }*
    }
    // searches for the string sfind in the string str
    // returns 1 if string found
    // returns 0 if string not found
    char StrContains(char *str, char *sfind)
    {

  • char found = 0;*

  • char index = 0;*

  • char len;*

  • len = strlen(str);*

  • if (strlen(sfind) > len) {*

  • return 0;*

  • }*

  • while (index < len) {*

  • if (str[index] == sfind[found]) {*

  • found++;*

  • if (strlen(sfind) == found) {*

  • return 1;*

  • }*

  • }*

  • else {*

  • found = 0;*

  • }*

  • index++;*

  • }*

  • return 0;*
    }

You need to read about the EEPROM library.

bilel:
help me please
I want to know how to save the state of the outputs of an Arduino after a power outage

The trick is knowing that power is about to go away so you still have time to save your data. How you are powering your arduino and any external circuitry and how much current is normally drawn are all involved in determining a ‘power is about to fail’ external circuitry. It’s not impossible but does take careful design.

Hi Bilel,

You save my week!
was exactly what I was looking for.
You can pass in the html code too? I need to turn some relays in my house…

Thank you for your help.

bilel:
This is my arduino program that is used to turn the LED’s what I should add to it saves the state of the LED when a power failure occurs

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
// size of buffer used to capture HTTP requests
#define REQ_BUF_SZ 60

// MAC address from Ethernet shield sticker under board
byte mac = { };
IPAddress ip(); // IP address, may need to change depending on network
EthernetServer server(80); // create a server at port 80
File webFile; // the web page file on the SD card
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0; // index into HTTP_req buffer
boolean LED_state[6] = {0}; // stores the states of the LEDs

void setup()
{

Serial.begin(9600); // for debugging

// initialize SD card
Serial.println(“Initializing SD card…”);
if (!SD.begin(4)) {
Serial.println(“ERROR - SD card initialization failed!”);
return; // init failed
}
Serial.println(“SUCCESS - SD card initialized.”);
// check for index.htm file
if (!SD.exists(“index.htm”)) {
Serial.println(“ERROR - Can’t find index.htm file!”);
return; // can’t find index file
}
Serial.println(“SUCCESS - Found index.htm file.”);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);

Ethernet.begin(mac, ip); // initialize Ethernet device
server.begin(); // start to listen for clients
}

Hi my friend @efschuster
This is the html code and you can modify it using the code has arduino Because I have not completed…
Good luck…

.IO_box { float: left; margin: 0 20px 20px 0; border: 1px solid blue; padding: 0 5px 0 5px; width: 120px; } h1 { font-size: 120%; color: blue; margin: 0 0 10px 0; } h2 { font-size: 85%; color: #5734E6; margin: 5px 0 5px 0; } p, form, button { font-size: 80%; color: #252525; } .small_text { font-size: 70%; color: #737373; }

LED 1 (D2)

LED 2 (D3)

LED 3 (D5)

LED 4 (D6)

Islam-peace

If you have some battery backed SRAM, such as is found in RTC chips like DS1307 (56 bytes), or an FRAM chip which has SRAM speed for reading/writing but with EEPROM data retention without data write limitations (thousands of bytes), you can "checkpoint" your data as often as you like, read it back after a reset/powerloss and be right back where you started.

Hi, Thanks a lot…
I’ll make some adjustments and post here the final version.

bilel:
Hi my friend @efschuster
This is the html code and you can modify it using the code has arduino Because I have not completed…
Good luck…

strLED1 = ""; strLED2 = ""; strLED3 = ""; strLED4 = "";

function GetArduinoIO()
{
nocache = “&nocache=” + Math.random() * 1000000;
var request = new XMLHttpRequest();
request.onreadystatechange = function()
{
if (this.readyState == 4) {
if (this.status == 200) {
if (this.responseXML != null) {

// LED 1
if (this.responseXML.getElementsByTagName(‘LED’)[0].childNodes[0].nodeValue === “checked”) {
document.LED_form.LED1.checked = true;
}
else {
document.LED_form.LED1.checked = false;