Friday, January 24, 2020

Permanent storage using EEPROM

For an index to all my stories click this line

I suppose this is something every reader of this weblog has ran into. You are making a project and you want to save some values of variables. Why ? Well every time your program restarts it starts with the initial values. But what if you want to continue where you left last time ?

An example is my Simon game. You can find that in the following blog-posts:
https://lucstechblog.blogspot.com/2018/12/simon.html
https://lucstechblog.blogspot.com/2018/12/simon-part-2.html

My girlfriend really likes this game. But it lacks something. It does not remember the high-score. So she wants me to build a new version with a display that shows the current high-score and the overall high-score.
The problem is that the Arduino, Attiny and the ESP microcontrollers erase their ram memory when they power down and restart. Therfore the overall high-score is never remembered.

The solution is to store the value of your variables in permanent memory.
When you do this, you can safely power down your project. Next time when you power it up again the project can read the values back from the permanent memory. This way your high score is stored safe.
You can use this for any kind of data you want to store permanent. Think about highest and lowest temperature readings, the last color settings of an RGB strip etc. etc.

The Arduino processors have a build-in EEPROM (Electrical Erasable Programmable Read Only Memory) and both the ESP8266 and the ESP32 have flash memory. Let's use that.

Arduino and Attiny85 EEPROM



The Arduino and Attiny processors have an internal EEPROM memory of 512 bytes. So they can store 512 values. As each of these 512 memory places is one byte they can each store a value from 0 to 255.
For the sake of this example I am going to show you how to save 10 values in EEPROM memory. Just look at this example program:



// ======================================
// test program for EEPROM write and read
// adapted by Luc Volders
// ======================================

#include <EEPROM.h>

int value = 0;
int i=0;

void setup()
{
  Serial.begin(9600);
  for (i=1; i<10; i++)
  {
    EEPROM.write(i, i+10);
    delay (100);
  } 
  
  for (i=1; i<10; i++)
  {
    value = EEPROM.read(i);
    Serial.print(i);
    Serial.print("\t");
    Serial.print(value, DEC);
    Serial.println();
  }
  
  
}

void loop()
{
}

I'll explain what is going on.

#include <EEPROM.h>

The first thing you need to do is to import the EEPROM library.

int value = 0;
int i=0;

Two helper variables are defined.

Then the real program is put in the setup. This way it runs only once.

Serial.begin(9600);

The Serial port is activated and we can check what is happening through the serial monitor.

  for (i=1; i<10; i++)
  {
    EEPROM.write(i, i+10);
    delay (100);
  }
 
This is where the magic happens.
The loop counts from 1 to 10. These are the EEPROM bytes where we are going to store our demo values. i is the location in the EEPROM memory where we are storing our values and i+10 is the value we are going to store. You can replace the i+10 value by anything you like as long as the value stays between 0 and 255.

  for (i=1; i<10; i++)
  {
    value = EEPROM.read(i);
    Serial.print(i);
    Serial.print("\t");
    Serial.print(value, DEC);
    Serial.println();
  }

After the values are stored we read them back with EEPROM.read(i). And i is again one of the memory places 1 to 10. The read value is then printed to the serial monitor to see if everything went well.

Now power down your Arduino or Attiny and upload the next program:


// ======================================
// test program for EEPROM read
// adapted by Luc Volders
// ======================================

#include <EEPROM.h>

int value = 0;
int i=0;

void setup()
{
  Serial.begin(9600);
  
  for (i=1; i<10; i++)
  {
    value = EEPROM.read(i);
    Serial.print(i);
    Serial.print("\t");
    Serial.print(value, DEC);
    Serial.println();
  }
}

void loop()
{
}

As you can see it is the same program as the previous but I omitted the writing part. So the only thing that happens is that the program reads the EEPROM memory and prints its values to the Serial monitor.



And this is the Serial Monitor output. As you can see even when the Arduino is powered down and a new program is loaded, the values stored in the EEPROM are still preserved.

ESP8266 and ESP32 EEPROM



Both the ESP8266 and the ESP32 do not have any build in EEPROM memory. But they do have flash memory. That is the same memory you are using in your photocam or phone and that does not looses its info when the power is shut down. So let's use that.

Luckily for us the Arduino EEPROM library has been adapted in such a way that it works for the ESP series controllers. We only have to make a minor adjustment in the program.


#include <EEPROM.h>

#define EEPROM_SIZE 100

int value = 0;
int i=0;

void setup() 
{
  Serial.begin(9600);
  
  EEPROM.begin(EEPROM_SIZE);

    for (i=1; i<10; i++)
  {
    EEPROM.write(i, i+10);
    EEPROM.commit();
    delay (100);
  } 


  for (i=1; i<10; i++)
  {
    value = EEPROM.read(i);
    Serial.print(i);
    Serial.print("\t");
    Serial.print(value, DEC);
    Serial.println();
  }
}

void loop() 
{
}


A short look at the differences from the Arduino program.

#define EEPROM_SIZE 100

For the ESP series we have to define how large the chunk of memory is that we want to put aside as an EEPROM substitute. Here I reserved 100 bytes but you can use as much as 4096 bytes. Quite a lot more as the Arduino allows you.

EEPROM.begin(EEPROM_SIZE);

This line tells the EEPROM library how much memory we want to reserve.

EEPROM.commit();

And this line actually confirms the write to the memory. You NEED to invoke this line after every write to the EEPROM memory.

The rest of the program is the same.

Write limits.

Both the EEPROM memory in the Arduino and the Flash memory in the ESP series have a limited lifespan. You can read as often as you want from the memory but you can write only about 100.000 times before the EEPROM breaks and your Arduino or ESP likely breaks down to.

100.000 times writing boils down to 273 year if you write once a day a value to the EEPROM or Flash memory. If you write a value each hour to the memory the controller will break down after 11 year. Writing every 10 minutes to the EEPROM or Flash memory will bring the lifespan of your controller back to about a year and a half.

Till next time
Have fun

Luc Volders

Friday, January 10, 2020

ESP32 Brownout problem

For an index to all my stories click this text

I have been doing a lot of tests and projects on the ESP32. And just as with the Arduino or ESP8266 you just write a program, upload it from your computer and it works.

And then suddenly I encountered some severe problems.



The programs would not start and the Serial Monitor showed the above text: Brownout Detector was triggered. This did not occur all the time but only when some heavy programming was involved. In my particular case it happened when I was develloping a program that included multiple libraries:


#include <Time.h>
#include <TimeLib.h>

#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUDP.h>

And an extra speech synthesizer library, on which I'll come back in a later story.

Please note that I am using the ESP32 Devkit board V1 from DOIT. This problem might not occur with other boards. I also noted that the problem occured when Wifi was activated (and therefore power consumption was increased).

Brownout detection.

I thought it was strange that this error occured as I knew from the Attiny 85 micro controllers that Brown-out Detection (BOD) is activated when the chip gets to low Voltage. And I had nothing attached to the ESP32. So nothing was drawing power except the ESP32 itself. Therefore the voltage should not get too low for the microcontroller to work.
Nevertheless the ESP32 detected the brownout and kept resetting itself.

Searching the internet revealed that many others encountered the same problem and some solutions were suggested:

- You are using a poor quality USB cable. Try to use a good quality one
- The USB cable is too long. Use a shorter one
- Bad computer USB port. Attach the ESP32 to another port
- Not enough power supplied through the USB port: Use a USB Hub with an external power supply.

I tried all of these suggestions and it did not help.

The solution.

In the end I found a software solution and I do not want to keep that from you.

The solution is to disable the Brown-Out Detection. This is obviously a makeshift solution as there is something wrong with the Devkit ESP32's power supply. But it works like a charm.

Start your program with the following lines:


#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"

#define nobrownout true
#define lowtxpower true

In the start of the setup routine add the following line:


if(nobrownout) WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

This seems to solve the problem.

From the moment I incorporated these lines into my ESP32 programs I did not encounter this problem again.

Solution number 2

I started experimenting and I found another solution.

It occurred to me that the Brow-Out Detection was triggered by a Voltage drop. I was programming my ESP32 from my USB port and when the programming was finished the ESP32 rebooted and started its program. The ESP32 however was still attached to the USB port of my computer. This way I could monitor the proceedings over the Serial Port.

So I decided to program the ESP32 with my computer and then attach the ESP32 to a power bank. I have a big powerbank which has 2 outputs. One supplies 1A and the other port supplies 2A.

Guess what. This solved my problem.
So it seems that the USB port of my computer is not capable of supplying enough power to get the ESP32 fully working.

This also worked with a USB power supply.

The setback is that this is only good when your program is finished as you are not able to monitor anything through the Serial Port.

Solution number 3

This one is a bit tricky, so you have to be absolutely sure of what you are doing.
I decided to use a double power supply for the ESP32.



I plugged the USB port of the ESP32 into my computer and attached a second power USB supply to the V-IN pin of the ESP32 and that worked flawlessly !!! Be aware that the actual connections on your USB breadboard connector might be different as displayed above. GND and VCC might be on different pins !! And I see I mixed up the colors of the wiring. GND should be blue and VCC should be red.

The ESP got enough power to work and at the same time had a connection with my computer so I could monitor data through the Serial Monitor.

If you do this make sure you use a decent 5Volt power supply. You are connecting an external power-supply indirect to the USB port of your computer. If anything fails you are in risk of damaging your computer !! So make absolutely sure that you are using an excellent external power supply, which does not deliver more as 5 volts.

Till next time

Luc Volders