Introduction: Working With Adafruit FRAM Memory
I purchased an Adafruit I2C FRAM memory chip to be able to save some variables between reboots on an Arduino Camera Slider project I was working on. Adafruit has 2 FRAM memory chips. One works with SPI bus and the other uses I2C. I2C model is a little slower, but I was already familiar with I2C, so after making sure the address didn't interfere with my LCD and Motor control boards, I ordered one to try.
There was an example supplied with the library, but it had very little information about how to store numbers larger than 256. I did some study and experimentation and cobbled a way to store and retrieved numbers as large as 65535. I thought this might be interesting to others who want to save a value on occasion.
Step 1: Build a Test Board
I used a 5V Arduino Mini Pro with the IC2 FRAM breakout, since this was the processor on my camera slider and the FRAM chip can use either 3.3v or 5v logic. Be aware that the A4 and A5 pins used to drive the I2C are not available on the edge of the Mini chip, but are located in the center of the chip. You will need to add wires to access these (or just use an Uno for testing).
Wiring is simple. Connect A4 on the Arduino to SDA on the FRAM, A5 to SCL. Add connections for Ground and 5V (Vcc) and you are ready to program.
Note: Just because you are using I2C for the memory chip does not mean that you can't use it also to drive your LCD screen and/or motor shield. Just make sure the addresses for each of your assemblies are different. If you bought it all from the same manufacturer, you are probably OK. Otherwise, you may need to change an address. Most boards have a way to do this fairly easily.
Step 2: Programming the Arduino
Download and install the library Adafruit library here and have a look at their example.
The example that comes with FRAM library is pretty simple, but you may want to run it to show that everything is working properly. After you are sure it's working properly, you can upload my sketch to try.
The two functions that I added take care of saving the values and retrieving them. The writeMem() function takes the value to be saved and the save address as inputs. Next, the value is divided by 256. That number (MSB = Most Significant Byte) and the remainder or modulo (LSB = Least Significant Byte) are stored in 2 separate memory address. The address that you pass the function ( I use address 10 in my example) and the next sequential address, 11, store the 2 bytes. If you are going to pass multiple values for storage, be sure you skip an address between them so you don't overwrite the 2nd byte of your first number.
readMem() is called with the first of the 2 address. Again, my example uses address 10. The MSB and LSB are retrieved and the full value is reconstituted by multiplying the MSB by 256 and adding it to the LSB.
No binary or hex math needed.... Store it and retrieve it... THATS IT!
Step 3: Running the Example
In my example, I use a for loop to store a value to a pair of address, then retrieve those values, reconstitute the original value, and then display it. I then increment the value and do this again. I send every 1000th value that is stored and retrieved to the Serial Monitor, so open the monitor to see what is happening. According to Adafruit, the memory on this chip is good for a lifetime of reads and writes. This is unlike the memory on the Arduino, which has a limited number of R/W cycles.
The method I devised will only hold a value up to 65355. You can see what happens if you change the values in the for loop to go above 65355.
One of the issues that I encountered was dealing with the various variable data types and their limitations. The re-constructed value kept thinking it was an Integer, so it would only hold half of the unsigned Integer before rolling to a negative numbe. By writing as a function and passing values back and forth, I found my data type changed with unexpected results, so be a bit careful in your data handling.
I left Adafruit's memory dump example in the sketch, but made a function of it. If you want it to run, uncomment the " //#define dumpMemory" line near the top of the sketch and it will SLOWLY dump your memory to the monitor in hex, no less.
Thanks to the Adafruit guys and gals for writing the library and for the example that I used as a starting point.