1

I've used the example code for the Adafruit I2C FRAM breakout board, but I've made it even simpler by just writing the same thing to each byte location and then reading them all off, doing nothing with the data.

I can tell it works because I can read off any byte and get the expected value, but the problem is that it works way too slowly. writing and reading 512 bytes takes almost a full half a second. This just won't work for my application, but I suspect there's something fundamentally wrong with what I'm doing.

I tried calling Wire.setClock(400000);, which supposedly is the maximum speed my Nano can drive an I2c slave at, but no matter what argument I input, the operation takes the same amount of time (498616 microseconds, within about +/- 20 microseconds).

I also tried calling Wire.begin(); TWBR = 10;, because I read that somewhere. But again, I get no difference. Here's my whole code- It's pretty simple

#include <Wire.h>
#include "Adafruit_FRAM_I2C.h"

/* Example code for the Adafruit I2C FRAM breakout */

/* Connect SCL    to analog 5
Connect SDA    to analog 4
Connect VDD    to 5.0V DC
Connect GROUND to common ground */

Adafruit_FRAM_I2C fram = Adafruit_FRAM_I2C();
uint16_t          framAddr = 0;

byte p = 55;   //any old value- just write the same thing into all locations


void setup(void) {
    Serial.begin(153600);
    //Wire.begin();
    //TWBR = 10;
    //Wire.setClock(400000);

    if (fram.begin()) {  
        Serial.println("Found I2C FRAM");
    }
    else {
        Serial.println("I2C FRAM not identified ... check your connections?\r\n");
    }

}


void loop(void) {

    int i = 0;

    long a = micros();


    for (i ; i < 512; i++){  //write 512 bytes to the FRAM board
        fram.write8(i, p);  

    }

    for (i = 0 ; i < 512; i++) {  //read 512 bytes from the FRAM board
        fram.read8(i);

    }

    long b = micros();

    Serial.println(b - a);
    Serial.println("");
}
3
  • You are running at 400000 bits per second, or 200000 per half second you say it takes.
  • You have about 1000 transactions (actually 1024 but for simplicity I will call it 1000)
  • 200000/1000 = 200 bits per transaction.
  • Wire is blocking and not very efficient. So say it is actually only transmitting 25% of the time.

That's 50 bits per transaction. Now I don't know the protocol that chip uses, but if it's like the SPI chips it would need 5 bytes per transaction - 1 for the I2C address, 3 for the FRAM address, and 1 for the byte. With start, ack, etc call it 10 bits per byte.

That makes 50 bits per transaction.

So yes, half a second to write then read it all is perfectly possible.

The slowness stems from the fact that you are working a byte at a time instead of larger blocks of data in one transaction.


Now I am at my computer I can take a look at the datasheet and get some more accurate numbers.

A write of a single byte requires 4 bytes in a transaction. That's 4 bytes, 1 start, 4 ack and 1 stop bit. So (4x8)+1+4+1 = 38 bits.

A read of a single byte, with "repeated start", requires 5 bytes per transaction, with 2 start, 4 acks, 1 nack and 1 stop. That's (5*8)+2+4+1+1 = 48 bits.

So for a read and write it's 38+48 = 86 bits.

Therefore you'd require 86*512 I2C clock cycles to transfer all 512 bytes in both directions - that's 44032 clock cycles.

At 400,000 bits per second it is 44032/400000 = 0.11 seconds, or 110ms of the time spend transferring data, not counting the time it takes to actually process and prepare the data, fill registers, look for status flags, etc.

If it is taking half a second then at 400,000 bits per second you have 44032 / (400000/2) * 100 = 22% of the time it's actually transmitting or receiving data over I2C.

So not a bad guestimate of 25% transmission in my original surmising.

  • Jeez, thanks for the breakdown on that. I wonder what the manufacturer had in mind to be able to do this, since the library only includes the single byte read and write functions. – LegitimateWorkUser Aug 24 '17 at 22:24
  • 2
    The Adafruit library github.com/adafruit/Adafruit_FRAM_I2C has indeed only functions to write and read a single byte. You could add your own functions to write and read 32 bytes. I think that the FRAM is fast enough to keep up with the I2C write or read and I assume that the FRAM itself causes no extra delay. – Jot Aug 24 '17 at 22:25
  • 1
    The manufacturer provides many ways of reading and writing, not just single byte. Adafruit chose to only implement byte reads and writes for simplicity. Read the data sheet and control the chip without the crutch of a library to do more. – Majenko Aug 24 '17 at 22:25
  • 2
    400kHz I2C clock, assuming at least 4k7 pullup resistors and very short wires, trying to write and read 32 bytes... that is hard to calculate, but 100ms is possible and perhaps 50ms. The Wire buffer is 32 bytes, that means when writing data already 2 bytes are taken for the register-address and 30 bytes are left for data. – Jot Aug 24 '17 at 22:37
  • @Jot - If I need two bytes for addressing, does this mean that I won't be able to write a 32 bit float? – LegitimateWorkUser Aug 25 '17 at 15:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.