Help with Write/Read to FRAM

Hello all!

Need help with the following code. I have copied code from the samples in the Code Libraries. What I want to accomplish is to write data to the FRAM while the IMP is offline and send it to the agent when it reconnects. I have just received the FRAM breakout board and wanted to test that part before.

I am using:

imp001
Adafruit_FRAM_I2C

PIN connected as follows:
IMP FRAM
PIN 1 to SCL
PIN 2 to SDA
GND to GND
VIN to VCC

`
#require “MB85RC.class.nut:1.0.0”
#require “Serializer.class.nut:1.0.0”

const BASE_I2C_ADDRESS = 0xA0;
numFams <-1

// Configure I2C bus
local i2c = hardware.i2c12;
i2c.configure(CLOCK_SPEED_400_KHZ);

// Configure write-protect pin
local wpin = hardware.pin7;

// Configure FRAM chip
local fram = MB85RC(i2c, BASE_I2C_ADDRESS, 256);

function ReadFram(){
data <- [];

if (fram.readByte(CONTENT_SET_MARKER_ADDRESS) == CONTENT_SET_MARKER) {
// Data stored previously, so read it in
local count = fram.readByte(CONTENT_COUNT_ADDRESS);
for (local i = 0 ; i < count ; ++i) {
local d = fram.readBlob(CONTENT_START_ADDRESS + (i * CONTENT_LENGTH), CONTENT_LENGTH);
data.append(d);
}
}
}

function WriteFram(){
// Back-up the blobs in the data array
local error = 0;
foreach (b in data) {
error = fram.writeBlob(CONTENT_START_ADDRESS + (i * CONTENT_LENGTH), b);
if (error != 0) {
server.log(“Data write error – bailing”);
break;
}
}

if (error == 0) {
// Data written successfully. So record number of items…
fram.writeByte(CONTENT_COUNT_ADDRESS, data.len());

// And record that content has been written
fram.writeByte(CONTENT_SET_MARKER_ADDRESS, CONTENT_SET_MARKER);

}
}

function chk(){
// local fram = frams.framFromIndex(1);
server.log("Checking FRAM chip "+fram.size());
fram.write(0, “James playing with Electric Imp”, 0, 4, 18)
server.log("FRAM size after write "+fram.size());

}

function loop(){
chk();

    imp.wakeup(1.0, loop);

}

loop();
`

I am getting the following error messages:
2016-03-16 21:25:34 UTC-4 [Status] Downloading new code; 13.89% program storage used
2016-03-16 21:25:35 UTC-4 [Device] Checking FRAM chip 32768
2016-03-16 21:25:35 UTC-4 [Device] ERROR: the index ‘seek’ does not exist
2016-03-16 21:25:35 UTC-4 [Device] ERROR: in write …tricimp#mb85rc.class.nut#1.0.0:132
2016-03-16 21:25:35 UTC-4 [Device] ERROR: from chk device_code:54
2016-03-16 21:25:35 UTC-4 [Device] ERROR: from loop device_code:60
2016-03-16 21:25:35 UTC-4 [Device] ERROR: from main device_code:65

James

Your fram.write() call in chk() is being called incorrectly: you’re passing in a string; it expects a blob. I would try changing that line to:

fram.write(0, blob.writestring("James playing with Electric Imp"), 0, 4, 18);

PS. Attached is my FRAM test code. Please feel free to use/abuse as you like.

`#require "mb85rc.class.nut:1.0.0"
#require "framstore.class.nut:1.0.0"

// GLOBALS

local i2c = null;

// FUNCTIONS

function irand(max) {
  // Generate a pseudo-random integer between 0 and max
  local roll = (1.0 * math.rand() / RAND_MAX) * (max + 1);
  return roll.tointeger();
}

function displayData(chip, from, too, count = 64) {
    // Debugging readout
    local a = from;
    if (too == -1) too = chip.maxAddress();
    for (local j = from ; j < too ; j = j + count) {
        local s = "";
        for (local k = 0 ; k < count ; ++k) {
            if (k + j < too) {
                local b = chip.readByte(j + k);
                s = s + format("%02X ", b[0]);
            }
        }

        s = format("%04X - ", a) + s;
        server.log(s);
        a = a + count;
    }
}

// START

// Configure I2C bus

i2c = hardware.i2c89;
i2c.configure(CLOCK_SPEED_400_KHZ);

// Configure fram chip 1
local fram = MB85RC(hardware.i2c89, 0xA0, 256, hardware.pin7);
if (fram != null) {
    server.log("Checking FRAM chip...");
    local error = fram.checkFramInfo();
    fram.clear(0x01);
}

// Configure fram chip 2
local fram2 = MB85RC(hardware.i2c89, 0xA2, 256);
if (fram2 != null) {
    server.log("Checking FRAM chip...");
    local error = fram2.checkFramInfo();
    //fram2.clear(0x02);
}

// Configure fram chip 3
local fram3 = MB85RC(hardware.i2c89, 0xA4, 256);
if (fram3 != null) {
    server.log("Checking FRAM chip...");
    local error = fram3.checkFramInfo();
    //fram3.clear(0x03);
}

local store = FramStore(fram);
//store.addFrams([fram2, fram3]);
//server.log(store.maxAddress() + ", " + store.chipCount());
//server.log(store.maxAddress() + ", " + store.chipCount());

local pointer = 0;

/*
server.log("Running memory check test");
local count = 0;
local max = 4096;
for (local i = 0 ; i < max ; ++i) {
    local a = irand(store.maxAddress() - 1);
    local b = store.readByte(a);
    local f = store.framFromAddress(a);
    local n = 0;
    if (f == fram) n = 1;
    if (f == fram2) n = 2;
    if (f == fram3) n = 3;
    if (b[0].tointeger() != n) {
        server.log("Discrepancy at address " + a + " (value = " + b[0].tointeger() + ") (FRAM = " + n + ")");
        ++count;
    }
}
server.log("Memory check test done: " + count + " errors out of " + max);


//store.writeString(98300, "Fintlewoodlewicks", true);
//store.writeString(1024, "Wintlefoodleficks", true);

displayData(fram3, 32758, -1);
displayData(fram, 0, 10);

server.log("String: " + store.readString(98300, 11) + store.readString(0, 15));
server.log("String: " + store.readString(1024, 20));

server.log("Done");

agent.on("text.chunk", function(text) {
    store.writeString(pointer, text);
    pointer = pointer + text.len();
});

agent.on("text.start", function(dummy) {
    pointer = 0;
});

*/


//store.writeString(1024, "Fintlewoodlewicks");
local s = "Fintlewoodlewicks";
local b = blob(20);
b.writestring(s);
server.log(b.tostring());
local err = fram.write(1024, b, fram.SPIFLASH_POSTVERIFY);
//local err = fram.writeBlob(1024, b);
if (err != 0) server.log("Error: " + err)
//server.log(format("0x%2X", fram.chipid()) + " " + fram.size());
local b2 = fram.read(1024, 17);
server.log(typeof b2)
server.log(b2.tostring())

displayData(fram, 1024, 2048);`

simttytone

Will try it out and let you know how it went.

Thanks,

James

Ok got it working now with your code. I have to keep a pointer every time data is saved in the fram? Can the pointer be saved in the fram to?

At some level your code needs to know where it can right to in the FRAM. How you organise that is up to you. You could reserve x bytes at the start of the FRAM to store your read/write pointer; your code would read that value, do what it needs to do, then write the new pointer value back if it has been changed.

smittytone:

Here is the final code that I have written. I am saving the last write position to address point 100. The data is written starting from address point 120. This is a sample of the data been written:
"Lat: 18.1234, Lon: -69.1234, Date: 20160202, Time: 12:00:34, Temp: 23.54, LOOP: "+i;

Would this be the more optimal format or should I save to a table? I want to send the data to the agent once the imp connects to wifi.

`
#require “mb85rc.class.nut:1.0.0”
#require “framstore.class.nut:1.0.0”

// GLOBALS

local i2c = null;
pointer <-0;
fpointer <- null;
POINTER_SAVE_POINT <-100;
DEFUALT_POINTER_START_POINT <-120;

// FUNCTIONS

function irand(max) {
// Generate a pseudo-random integer between 0 and max
local roll = (1.0 * math.rand() / RAND_MAX) * (max + 1);
return roll.tointeger();
}

function displayData(chip, from, too, count = 64) {
// Debugging readout
local a = from;
if (too == -1) too = chip.maxAddress();
for (local j = from ; j < too ; j = j + count) {
local s = “”;
for (local k = 0 ; k < count ; ++k) {
if (k + j < too) {
local b = chip.readByte(j + k);
s = s + format("%02X ", b[0]);
}
}

    s = format("%04X - ", a) + s;
    server.log(s);
    a = a + count;
}

}

// START

// Configure I2C bus

i2c = hardware.i2c12;
i2c.configure(CLOCK_SPEED_400_KHZ);

// Configure fram chip 1
local fram = MB85RC(hardware.i2c12, 0xA0, 256, hardware.pin7);
if (fram != null) {
//server.log(“Checking FRAM chip1…”);
local error = fram.checkFramInfo();
//fram.clear(0x01);
}
/*
// Configure fram chip 2
local fram2 = MB85RC(hardware.i2c12, 0xA2, 256);
if (fram2 != null) {
server.log(“Checking FRAM chip2…”);
local error = fram2.checkFramInfo();
//fram2.clear(0x02);
}

// Configure fram chip 3
local fram3 = MB85RC(hardware.i2c12, 0xA4, 256);
if (fram3 != null) {
server.log(“Checking FRAM chip3…”);
local error = fram3.checkFramInfo();
//fram3.clear(0x03);
}
*/
local store = FramStore(fram);
//store.addFrams([fram2, fram3]);
//server.log(store.maxAddress() + ", " + store.chipCount());
//server.log(store.maxAddress() + ", " + store.chipCount());

/*
server.log(“Running memory check test”);
local count = 0;
local max = 4096;
for (local i = 0 ; i < max ; ++i) {
local a = irand(store.maxAddress() - 1);
local b = store.readByte(a);
local f = store.framFromAddress(a);
local n = 0;
if (f == fram) n = 1;
//if (f == fram2) n = 2;
//if (f == fram3) n = 3;
if (b[0].tointeger() != n) {
server.log("Discrepancy at address " + a + " (value = " + b[0].tointeger() + ") (FRAM = " + n + “)”);
++count;
}
}
server.log("Memory check test done: " + count + " errors out of " + max);
*/

//store.writeString(98300, “Fintlewoodlewicks”, true);
//store.writeString(1024, “Wintlefoodleficks”, true);

//displayData(fram3, 32758, -1);
//server.log(“displayData fram, 0, 10”)
//displayData(fram, 0, 10);

//server.log("String: " + store.readString(98300, 11) + store.readString(0, 15));
//server.log("String: " + store.readString(1024, 20));

//server.log(“Done”);

agent.on(“text.chunk”, function(text) {
store.writeString(pointer, text);
pointer = pointer + text.len();
});

agent.on(“text.start”, function(dummy) {
pointer = 0;
});
// Format the pointer to 000000 for simple read from FRAM
function formatPointer(s){
fpointer = format("%06u", s);
}

// GET INITIAL POSITION
local p = store.readString(POINTER_SAVE_POINT, 6);
// IF NO POSITION SET A BASE POSITION
if (p == "      ") {
    server.log("initial reading  "+p);
    local s = DEFUALT_POINTER_START_POINT;
    formatPointer(s)
    s = fpointer
    local b = blob(20);
    b.writestring(s);
    local err = fram.write(POINTER_SAVE_POINT, b, fram.SPIFLASH_POSTVERIFY);
}
else {
    server.log("current pointer is:  "+p);
}


// Get Pointer
function getPointer(){
    local b2 = fram.read(POINTER_SAVE_POINT, 6);
          pointer = b2.tostring();
          pointer = pointer.tointeger();
          // local p = store.readString(0, 6);
          server.log("p "+pointer);
}

// POINTER SAVE
function savePointer(newPoint){
local s = newPoint;
formatPointer(s)
s = fpointer
local b = blob(20);
b.writestring(s);
local err = fram.write(POINTER_SAVE_POINT, b, fram.SPIFLASH_POSTVERIFY);

}

function saveData2FRAM(data){
         server.log("Entered Save Data")
         getPointer();
         local s = data;
         local dataLength = s.len();
         local new_pointer = pointer + dataLength;
         server.log("new_pointer: "+new_pointer);
         local b = blob(20);
         b.writestring(s);
         savePointer(new_pointer);
         server.log("Data and Pointer Saved...")
         local err = fram.write(new_pointer, b, fram.SPIFLASH_POSTVERIFY);

}

// displayData(fram, 100, -1);
local d=“lat: 18.2345, lon: -69.2345, date: 20161231 time: 23:59:59 temp: 123.44”;
saveData2FRAM(d);
getPointer();

local size = pointer - DEFUALT_POINTER_START_POINT;
server.log("size is: "+size);
local b2 = fram.read(pointer, size);
//server.log("type of read "+typeof b2)
server.log(b2.tostring());
displayData(fram, pointer, size);

// displayData(fram, 0, -1);
for(local i = 0; i < 10; i++){
// imp.sleep(0.01);
server.log(" loop count is "+ i );
local read = "Lat: 18.1234, Lon: -69.1234, Date: 20160202, Time: 12:00:34, Temp: 23.54, LOOP: "+i;
saveData2FRAM(read);

    // pointer("g");
    // local b2 = fram.read(pointers, readLen);
    // server.log(" readLen= "+readLen);
    // server.log(" read data "+b2.tostring());
}

`