Arduino Forum

Using Arduino => Programming Questions => Topic started by: PlaneCrazy on Oct 26, 2017, 09:32 am

Title: I2C EEPROM programmer
Post by: PlaneCrazy on Oct 26, 2017, 09:32 am
Greetings, all

Total newbie here.

I have searched on this forum for a while now, looking at all the interesting projects. But I have either not found what I'm looking for, or failed to recognise it when I saw it.

I would like to make an EEPROM programmer. Specifically, the first chip I have to program is an FM24C128.

http://za.rs-online.com/web/p/fram-memory-chips/8282780/ (http://za.rs-online.com/web/p/fram-memory-chips/8282780/)

I have come across several parallel EEPROM programmers using Arduino, but no more than passing mentions of i2c serial programmers - demos and images, even libraries, but no projects.

1. How do I read what's on an EEPROM?
2. How do I save the data to a file on my PC?
3. How do I write the data from my PC onto a chip?

Thank you.
Title: Re: I2C EEPROM programmer
Post by: GautamD on Oct 26, 2017, 09:38 am
Hi, since you are a newbie you should take a look at Nick Gammon's website for I2C and EEPROM. Following is the link: http://gammon.com.au/i2c

Cheers!!
Title: Re: I2C EEPROM programmer
Post by: cyberjupiter on Oct 26, 2017, 10:15 am
1. You find a robust I2C EEPROM library and you read data inside the external eeprom by using the given function in the library built functions, EEPROM.get() or EEPROM.read()

2. You build an application on a PC. That application should be able to communicate serially. You send the saved data in the EEPROM to Arduino serial port. The PC listen using the app and save it to a file.


3. Same as (2) but this time the app send data from PC to Arduino serial port. Arduino will perform the job to write the data into the EEPROM, again by using the function provided by the I2C EEPROM library. built functions, EEPROM.put or EEPROM.write()
Title: Re: I2C EEPROM programmer
Post by: PlaneCrazy on Oct 26, 2017, 09:05 pm
My thanks to both of you.
Title: Re: I2C EEPROM programmer
Post by: cyberjupiter on Oct 27, 2017, 01:50 am
To be honest, I think this is a cool project. Though, I am sure this project has been done before. But I don't know if there is a library for I2C external eeprom that has the same functions as the official internal EEPROM library. If you could get a library that has the same function as EEPROM.put() or EEPROM.write(), this project is quite easy.
Title: Re: I2C EEPROM programmer
Post by: PlaneCrazy on Oct 27, 2017, 12:03 pm
Jack Christensen (http://adventuresinarduinoland.blogspot.co.za/2014/07/an-arduino-library-for-external-i2c.html) has a library for external i2c EEPROMs. I think I'll start there.
Title: Re: I2C EEPROM programmer
Post by: PlaneCrazy on Jan 28, 2018, 03:46 pm
Greetings, all

I have found many links on how to transfer data using wire.h to an I2C device. However, when I simulate it using Proteus I apparently get nothing.

Using the code from this reference page (https://www.arduino.cc/en/Reference/WireWrite), and running the sketch in Proteus, the only change in bits that I see are these:

(https://i.imgur.com/gkx4E9K.jpg)

Changing the data to an array (as I ultimately need to write a 16 kiB array to my EEPROM) to the following:

Code: [Select]
#include <Wire.h>

byte test[] = {1,2,3,4};

void setup()
{
  Wire.begin(); // join i2c bus
}

void loop()
{
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
                              // device address is specified in datasheet
  Wire.write(test,4); 
  Wire.endTransmission();     // stop transmitting

  delay(500);
}
 

I get exactly the same display on Proteus's oscilloscope.

Why am I only seeing 44? Where is the data that I'm supposed to be sending? How do I know my code is working?

Thank you

Title: Re: I2C EEPROM programmer
Post by: GolamMostafa on Jan 28, 2018, 05:53 pm
Quote
1. How do I read what's on an EEPROM?
2. How do I save the data to a file on my PC?
3. How do I write the data from my PC onto a chip?
1. You may collect an Arduino UNO which will hopefully answer your above questions.
2. Build the following circuit between UNO, 24C128, and I2C LCD. (I2C LCD is given as a bonus!).
(http://www.krdcbd.com/twiconxy.png)

3. Store (write) 0x23 into location 0x1234 of the EEPROM; read it back, and show it on Serail Monitor and LCD.

Code: [Select]
#include<Wire.h>
#define eeDeviceAddress 0b1010010
#define adrLocUbyte 0x12
#define adrLocLbyte 0x34
#define dataByte 0x23

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  
  Wire.beginTransmission(eeDeviceAddress); //select EEPROM by doing a roll call
  Wire.write(adrLocUbyte);        //select (point) EEPROM location 1234h
  Wire.write(adrLocLbyte);
  Wire.write(dataByte);          //data byte 23h fro the location 1234h
  Wire.endTransmission();        //end all the above queued data and STOP
  delay(5);                      //wait for the data byte to get written into EEPROM location                
  //-------------------------------
  Wire.beginTransmission(eeDeviceAddress); //select EEPROM by doing a roll call
  Wire.write(adrLocUbyte);        //select (point) EEPROM location 1234h
  Wire.write(adrLocLbyte);
  Wire.endTransmission();        //end all the above queued data and STOP
  //--------------------------------------  
  Wire.requestFrom(eeDeviceAddress, 1); //read 1 byte data from location 1234 and save in buffer
  byte x = Wire.read();                 //bring data byte from buffer into x
  Serial.println(x, HEX);               //show value on Serial Monitor ; shows: 23
}

void loop()
{
  
}


Tested for: 24C512. The program should also be working for 24128 as 24C512 and 24C128 are pin-compatible and TWI-bus compatible chips.
Title: Re: I2C EEPROM programmer
Post by: cattledog on Jan 28, 2018, 06:46 pm
You are leaving out the eeprom memory location from your code.

Code: [Select]
void writeBytes(int device, unsigned int Address, byte* data, byte len)
{
  Wire.beginTransmission(device);
  Wire.write(Address >>8 ); //MSB
  Wire.write(Adderess& 0xFF); // LSB
  Wire.write(data,len);
  Wire.endTransmission();
  delay(5);//small delay for eeprom to save data
 }


You need to be careful of page boundaries with block writes to an external eeprom. I would echo the sentiments of reply#5 and consider using the Christensen library.
Title: Re: I2C EEPROM programmer
Post by: PlaneCrazy on Feb 01, 2018, 06:54 am
OK, pardon me for being really new and really dumb (I am, after all, but a humble mechanical engineer), but I am failing to understand anything I see. And I really need to get my radio working.

Here is the J Christensen example, as per you recommendations:

Code: [Select]

//Test extEEPROM library.
//Writes the EEPROM full of 32-bit integers and reads them back to verify.
//Wire a button from digital pin 6 to ground, this is used as a start button
//so the sketch doesn't do unnecessary EEPROM writes every time it's reset.
//Jack Christensen 09Jul2014

#include <extEEPROM.h>    //http://github.com/JChristensen/extEEPROM/tree/dev
#include <Streaming.h>    //http://arduiniana.org/libraries/streaming/
#include <Wire.h>         //http://arduino.cc/en/Reference/Wire

//Two 24LC256 EEPROMs on the bus
const uint32_t totalKBytes = 64;         //for read and write test functions
extEEPROM eep(kbits_256, 2, 64);         //device size, number of devices, page size

const uint8_t btnStart = 6;              //start button

void setup(void)
{
    pinMode(btnStart, INPUT_PULLUP);
    Serial.begin(115200);
    uint8_t eepStatus = eep.begin(extEEPROM::twiClock400kHz);   //go fast!
    if (eepStatus) {
        Serial << endl << F("extEEPROM.begin() failed, status = ") << eepStatus << endl;
        while (1);
    }
   
    Serial << endl << F("Press button to start...") << endl;
    while (digitalRead(btnStart) == HIGH) delay(10);    //wait for button push

    uint8_t chunkSize = 64;    //this can be changed, but must be a multiple of 4 since we're writing 32-bit integers
//    eeErase(chunkSize, 0, totalKBytes * 1024 - 1);
    eeWrite(chunkSize);
    eeRead(chunkSize);

    dump(0, 16);            //the first 16 bytes
    dump(32752, 32);        //across the device boundary
    dump(65520, 16);        //the last 16 bytes
}

void loop(void)
{
}

//write test data (32-bit integers) to eeprom, "chunk" bytes at a time
void eeWrite(uint8_t chunk)
{
    chunk &= 0xFC;                //force chunk to be a multiple of 4
    uint8_t data[chunk];
    uint32_t val = 0;
    Serial << F("Writing...") << endl;
    uint32_t msStart = millis();
   
    for (uint32_t addr = 0; addr < totalKBytes * 1024; addr += chunk) {
        if ( (addr &0xFFF) == 0 ) Serial << addr << endl;
        for (uint8_t c = 0; c < chunk; c += 4) {
            data[c+0] = val >> 24;
            data[c+1] = val >> 16;
            data[c+2] = val >> 8;
            data[c+3] = val;
            ++val;
        }
        eep.write(addr, data, chunk);
    }
    uint32_t msLapse = millis() - msStart;
    Serial << "Write lapse: " << msLapse << " ms" << endl;
}

//read test data (32-bit integers) from eeprom, "chunk" bytes at a time
void eeRead(uint8_t chunk)
{
    chunk &= 0xFC;                //force chunk to be a multiple of 4
    uint8_t data[chunk];
    uint32_t val = 0, testVal;
    Serial << F("Reading...") << endl;
    uint32_t msStart = millis();
   
    for (uint32_t addr = 0; addr < totalKBytes * 1024; addr += chunk) {
        if ( (addr &0xFFF) == 0 ) Serial << addr << endl;
        eep.read(addr, data, chunk);
        for (uint8_t c = 0; c < chunk; c += 4) {
            testVal =  ((uint32_t)data[c+0] << 24) + ((uint32_t)data[c+1] << 16) + ((uint32_t)data[c+2] << 8) + (uint32_t)data[c+3];
            if (testVal != val) Serial << F("Error @ addr ") << addr+c << F(" Expected ") << val << F(" Read ") << testVal << F(" 0x") << _HEX(testVal) << endl;
            ++val;
        }
    }
    uint32_t msLapse = millis() - msStart;
    Serial << "Last value: " << --val << " Read lapse: " << msLapse << " ms" << endl;
}

//write 0xFF to eeprom, "chunk" bytes at a time
void eeErase(uint8_t chunk, uint32_t startAddr, uint32_t endAddr)
{
    chunk &= 0xFC;                //force chunk to be a multiple of 4
    uint8_t data[chunk];
    Serial << F("Erasing...") << endl;
    for (int i = 0; i < chunk; i++) data[i] = 0xFF;
    uint32_t msStart = millis();
   
    for (uint32_t a = startAddr; a <= endAddr; a += chunk) {
        if ( (a &0xFFF) == 0 ) Serial << a << endl;
        eep.write(a, data, chunk);
    }
    uint32_t msLapse = millis() - msStart;
    Serial << "Erase lapse: " << msLapse << " ms" << endl;
}

//dump eeprom contents, 16 bytes at a time.
//always dumps a multiple of 16 bytes.
void dump(uint32_t startAddr, uint32_t nBytes)
{
    Serial << endl << F("EEPROM DUMP 0x") << _HEX(startAddr) << F(" 0x") << _HEX(nBytes) << ' ' << startAddr << ' ' << nBytes << endl;
    uint32_t nRows = (nBytes + 15) >> 4;

    uint8_t d[16];
    for (uint32_t r = 0; r < nRows; r++) {
        uint32_t a = startAddr + 16 * r;
        eep.read(a, d, 16);
        Serial << "0x";
        if ( a < 16 * 16 * 16 ) Serial << '0';
        if ( a < 16 * 16 ) Serial << '0';
        if ( a < 16 ) Serial << '0';
        Serial << _HEX(a) << ' ';
        for ( int c = 0; c < 16; c++ ) {
            if ( d[c] < 16 ) Serial << '0';
            Serial << _HEX( d[c] ) << ( c == 7 ? "  " : " " );
        }
        Serial << endl;
    }
}


If I compile and export this, nothing happens. That is because no data has been given yet.

I have 16384 bytes of data to upload. How, explicitly, and where do I give the address(es) that I need to upload to, and how, explicitly, do I specify the data in the above sketch? How many bytes can I upload at a time?

Do I create an array with data bytes in hex format? Do I break it up into smaller chunks? If so, how small? (I know the sketch also breaks data up in chunks, but does it break up an entire array into chunks of 32 bits?) Do I create a counter to count down the addresses and put them in a loop?

Thank you for your patience with me.
Title: Re: I2C EEPROM programmer
Post by: GolamMostafa on Feb 01, 2018, 07:22 am
1. It is assumed that your set up is: UNO and 24C128 EEPROM (capacity 16384 bytes; address range: 0000 - 3FFF).

2.  You wish to write 16384 bytes data into the EEPROM.

3. You can follow page write mode or byte write mode for the storage of data into the EEPROM. In page mode, 24C128 EEPROM allows 64-byte data (page size) to be written in ONE GO (within 5 ms time -- the data write time). In byte mode, data are written byte-by-byte, and it will require 16384x5 ms ~= 82 sec time to finish writing in stead of 256x5 = 1.3 sec time (in page mode).

4.  It is recommended that the 16834 bytes data to be kept in a byte/page oriented array.

5.  Post#7/Post#8 could be followed to store data into the EEPROM.
Title: Re: I2C EEPROM programmer
Post by: cattledog on Feb 01, 2018, 08:37 am
Quote
I would like to make an EEPROM programmer. Specifically, the first chip I have to program is an FM24C128.
http://za.rs-online.com/web/p/fram-memory-chips/8282780/
The link is to a FRAM storage device FM24V01-G Serial-I2C FRAM  while FM24C128 is a conventional EEPROM. The FRAM does not have page boundaries, the EEPROM does.

Which one are you trying to fill with data?

Quote
I have 16384 bytes of data to upload.
Where does this data file reside, what format is it in, and how do you plan to transfer the data to the Arduino?

Are you still working with Proteus? Do you have an EEPROM and an Arduino?  Can you read and write data to and from the EEPROM using the Wire library commands? You can work up to large block writes and optimized speed with the Christensen library after you work through the basics of byte read/write or small transfers of 4 byte blocks which will always work with page boundaries.


Quote
And I really need to get my radio working.
What does the radio have to do with the transfer of data into an EEPROM or FRAM?
What are you trying to do with your project?
Title: Re: I2C EEPROM programmer
Post by: PlaneCrazy on Feb 01, 2018, 09:39 am
I couldn't get the FM24V01, so I purchased 24LC128 instead. I have already checked that these two are compatible for my application.

The background is this: I purchased a radio for my car. The car is a 1995 model, but the radio is a 2014 OEM from another manufacturer. As it turns out, this radio was never commissioned, so instead of asking me for a passcode, it requests a diagnostic tool.

The cure for this is to collect a dump file for the radio, then burn it onto the radio's EEPROM. This OEM radio is quite a popular alternative to the garish aftermarket stuff we can buy.

I have the dump file in binary format. But I also have a text file with the addresses and bytes in hex format (https://forum.arduino.cc/index.php?topic=511233.0).

I decided to practice on EEPROMs that I purchased, rather than accidentally destroying the radio. For this purpose I have purchased several EEPROMs. I have built the circuitry, but I want to know that the code works.

This is the short-term goal. I have longer term goals and projects as well, but this radio was my excuse for finally getting into Arduino.

Now, Proteus.

I can simulate writing an EEPROM. But I cannot (to my knowledge) simulate reading an already written EEPROM, so I can't simulate first writing the EEPROM and then reading it to check a) that all the data is there and b) all the data is where I expect them to be. So I would expect to at least detect on the oscilloscope which bytes are active when, right?
Title: Re: I2C EEPROM programmer
Post by: cattledog on Feb 01, 2018, 08:33 pm
It sounds like you have some eeproms to use, so I would forget about proteus and just use an eeprom and the Arduino. You can write and read from the test eeprom before you try and program the radio eeprom.

Your test eeproms are 128Kbits (16Kbytes). What is the size of the eeprom in the radio? Is the eeprom in the radio addressable with i2c? How did you obtain the "dump file?

Quote
ultimately need to write a 16 kiB array to my EEPROM
In your link to the "dump file" you show 720 bytes of data. Is that the data you have? Where does the 16K bytes come in? Is all data after the 720 either 0x00 or 0xFF or is there real data to deal with?

I am asking this because originally whey you talked about an eeprom programmer it was not clear that you had only one eeprom to write, and you were not developing a production tool. With 720 bytes, of actual data you don't need to develop a tool set to deal with large files and use a write procedure which is optimized for speed.

With 720 bytes, you should be able to hand input a 2 dimensional array 45x16 which contains all the data. Writing that data to eeprom and reading it back will be very simple, even without the Christensen library. You should be able to use the Wire library with the wire.write(data,16) and avoid any page boundary issues.

Title: Re: I2C EEPROM programmer
Post by: cattledog on Feb 01, 2018, 10:22 pm
Here is some code which demonstrates how to set  up block data and write it to eeprom. You should be able to adapt it to your data.

Code: [Select]

//possible page boundary issue unless all writes at 16 bytes
#include <Wire.h>
#define ADDRESS 0x50 //Address of EEPROM

unsigned int memAddress = 0;//starting eeprom address
int totalBytes = 720;//total byte number multiple of 16
const byte blockLength = 16; //will avoid page boundary in eeprom
const byte numberOfBlocks = totalBytes/blockLength;

//test data visuallyto confirm pattern
//EDIT: correct declaration of byte fileData
byte fileData[][blockLength] =
{
  {0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0},
};

void setup() {
  Serial.begin(115200);
  Wire.begin();

  for (int i = 0; i <= numberOfBlocks - 1; i++)
  {
    writeBytes( ADDRESS, memAddress, fileData[i], blockLength);
    memAddress += blockLength;
  }

  memAddress = 0;//reset address for read

  for (int i = 0; i <= numberOfBlocks - 1; i++)
  {
    readBytes(ADDRESS, memAddress, blockLength);
    memAddress += blockLength;
  }
}

void loop() {}

void writeBytes(int device, unsigned int Address, byte* data, byte len)
{
  Wire.beginTransmission(device);
  Wire.write(Address >> 8 ); //MSB
  Wire.write(Address & 0xFF); // LSB
  Wire.write(data, len);
  Wire.endTransmission();
  delay(5);//small delay for eeprom to save data
}

void readBytes(int device, unsigned int Address, byte len )
{
  byte readBuffer[len];
  Wire.beginTransmission(device); // I2C address
  Wire.write(Address >> 8); // bit shift for high byte of pointer address
  Wire.write(Address & 0xFF); // mask for the low byte
  Wire.endTransmission();
  Wire.requestFrom(device, len);
  Wire.readBytes(readBuffer, len);
  for (byte j = 0; j < 16; j++)
  {
    Serial.print(readBuffer[j], HEX);
    Serial.print(" ");
  }
  Serial.println();
}


OUTPUT
Code: [Select]
FF 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 FF 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 FF 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 FF 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 FF 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 FF 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 FF 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 FF 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 FF 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 FF 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 FF 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 FF 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 FF 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 FF 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 FF 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 FF
0 0 0 0 0 0 0 0 0 0 0 0 0 0 FF 0
0 0 0 0 0 0 0 0 0 0 0 0 0 FF 0 0
0 0 0 0 0 0 0 0 0 0 0 0 FF 0 0 0
0 0 0 0 0 0 0 0 0 0 0 FF 0 0 0 0
0 0 0 0 0 0 0 0 0 0 FF 0 0 0 0 0
0 0 0 0 0 0 0 0 0 FF 0 0 0 0 0 0
0 0 0 0 0 0 0 0 FF 0 0 0 0 0 0 0
0 0 0 0 0 0 0 FF 0 0 0 0 0 0 0 0
0 0 0 0 0 0 FF 0 0 0 0 0 0 0 0 0
0 0 0 0 0 FF 0 0 0 0 0 0 0 0 0 0
0 0 0 0 FF 0 0 0 0 0 0 0 0 0 0 0
0 0 0 FF 0 0 0 0 0 0 0 0 0 0 0 0
0 0 FF 0 0 0 0 0 0 0 0 0 0 0 0 0
0 FF 0 0 0 0 0 0 0 0 0 0 0 0 0 0
FF 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 FF 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 FF 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 FF 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 FF 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 FF 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 FF 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 FF 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 FF 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 FF 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 FF 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 FF 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 FF 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 FF 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 FF 0
Title: Re: I2C EEPROM programmer
Post by: PlaneCrazy on Feb 02, 2018, 08:08 am
Your test eeproms are 128Kbits (16Kbytes). What is the size of the eeprom in the radio? Is the eeprom in the radio addressable with i2c? How did you obtain the "dump file?
The dump files can be easily obtained by searching Google for "AGC-1220RF dump file".

The radio appears to be equipped with an FM24V01 chip, which is i2c, 128kib. However, this chip seems to be getting hard to find. I have seen several dump files for this radio listed as 24C128 dump files.

In your link to the "dump file" you show 720 bytes of data. Is that the data you have? Where does the 16K bytes come in? Is all data after the 720 either 0x00 or 0xFF or is there real data to deal with?
Each of the binary files is 16kiB, including the file I intend to use.

Maybe I'm too proud, but I deliberately didn't include the actual binary file since I really want to learn to do this myself.

Thank you for showing interest in this project. I should mention that, while I am a newby, this isn't my first Arduino project. Since I acquired my Arduino, I've been spending my December holiday chasing down projects after working through the examples in the booklet. I am surprised that the i2c EEPROM stuff is so difficult for me.
Title: Re: I2C EEPROM programmer
Post by: GolamMostafa on Feb 02, 2018, 11:21 am
+1 for the beautiful demonstration of Post#14, which I have tested and worked fine! (The Compiler IDE-1.8.0 does not like byte fileData[numberOfBlocks][blockLength]; but, it takes byte fileData[45][16] or byte fileData[][blockLength] or byte fileData[][].)
Title: Re: I2C EEPROM programmer
Post by: cattledog on Feb 02, 2018, 06:47 pm
Quote
Each of the binary files is 16kiB, including the file I intend to use.
If you are going to hand enter the data like the example provided, you can use multiple entered arrays and just manage the eeprom address where the storage takes place. There will be memory issues if your array blocks get too large.

Alternatively, you can put all the arrays in PROGMEM to store the data in flash (program) memory instead of SRAM, but that adds another level of complication to read them. https://forum.arduino.cc/index.php?topic=478466.0 (https://forum.arduino.cc/index.php?topic=478466.0)

If you indeed have 1000 unique lines of 16 byte data fields, you may want to develop a tool to get the data from the computer into the Arduino line by line. Google will be your friend here, and you will probably explore "Processing" and "GoBetweeno". If you are entering new territory here(like I am) it may be faster to brute force and hand code the solution.

If the data is on an SD card, there may be examples of how to read line by line into an Arduino in the SdFat library examples.

At this point, you don't have an eeprom problem, you have a data file management and pc/arduino problem. I'm not very familiar with this area so can't be of much help. Google is your friend. Good luck.

Quote
The background is this: I purchased a radio for my car. The car is a 1995 model, but the radio is a 2014 OEM from another manufacturer. As it turns out, this radio was never commissioned, so instead of asking me for a passcode, it requests a diagnostic tool.
I don't understand this. If the radio is not stolen, I would think that the manufacture should be able to supply a passcode based on the serial number. What does "never commissioned" mean?
Title: Re: I2C EEPROM programmer
Post by: PlaneCrazy on Feb 03, 2018, 09:37 am
I don't understand this. If the radio is not stolen, I would think that the manufacture should be able to supply a passcode based on the serial number. What does "never commissioned" mean?
The radio is not stolen, I just purchased it without buying a car from the dealership. This means the radio has never been installed in a car. I have the passcode, but the radio doesn't ask for a passcode yet. And the car I'm hoping to install the radio in is too old to have a CAN bus. The dealership also informed me that they cannot commission the radio unless it is in a car - and they refuse to temporarily install the radio in one of the cars in their workshop...

The radio has the ability to communicate with other systems on the car, such as hands-free phone, rear view cameras or park distance sensors, vehicle speed sensors, navigation etc. But these have to be activated based on the specification of the car. Hence the need for commissioning. 
Title: Re: I2C EEPROM programmer
Post by: GolamMostafa on Feb 03, 2018, 11:15 am
@PlaneCrazy 

Have you executed the program of Post#14 on your Arduino? Have you seen any error message reported by the Compiler on this declaration: byte fileData[numberOfBlocks][blockLength];?
Title: Re: I2C EEPROM programmer
Post by: cattledog on Feb 03, 2018, 04:57 pm
Quote
Have you executed the program of Post#14 on your Arduino? Have you seen any error message reported by the Compiler on this declaration: byte fileData[numberOfBlocks][blockLength];?
@GolamMostafa  You are correct about the compiler error. I tested the program with byte fileData [45][16] and then made it more generic when I was done. I tested with fileData[][16], and probably made the final code change without compiling. my bad.

I've edited my original post. Thanks for picking this up.
Title: Re: I2C EEPROM programmer
Post by: GolamMostafa on Feb 04, 2018, 06:29 am
Thanks for for taking care of our observations.
Title: Re: I2C EEPROM programmer
Post by: PlaneCrazy on Feb 09, 2018, 07:18 am
Well, this sucks...

Code: [Select]
Arduino: 1.8.5 (Windows 7), Board: "Arduino/Genuino Uno"

Sketch uses 20190 bytes (62%) of program storage space. Maximum is 32256 bytes.
Global variables use 16787 bytes (819%) of dynamic memory, leaving -14739 bytes for local variables. Maximum is 2048 bytes.
Not enough memory; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing your footprint.
Error compiling for board Arduino/Genuino Uno.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.


So, as I understand it, the code in Post #14 works with 720 bytes. But if I give it all 16kiB of data, the program is too big. I guess I'll have to divide it up into 1kiB chunks.
Title: Re: I2C EEPROM programmer
Post by: PlaneCrazy on Feb 09, 2018, 05:52 pm
I have verified and uploaded the code from Post #14, and I'm not liking what I'm seeing...

Here is the serial monitor output. I have not changed the code to include my data yet, I am using the code from Post #14 exactly.

Code: [Select]
0 0 CF 0 1 1 1 0 9C 0 0 4 3F E6 3F


Here is a screenshot. I don't understand why it isn't copying everything.

(https://i.imgur.com/HIb6mMD.jpg)

What am I doing wrong?

Title: Re: I2C EEPROM programmer
Post by: DrAzzy on Feb 09, 2018, 06:05 pm
This should 100% be straightforward to do - I don't have time to dissect your code and figure out why it's not working...

But I question this approach...

Are you aware that there are USB devices (based on the CH341T) that you can plug into your USB port, pop an I2C or SPI eeprom or SPI flash chip into, and read/write with a desktop application? With some searching, I was even able to find a desktop application with the UI in english!

That they used an FM24V01 instead of a normal 128kbit EEPROM should set off blaring alarm bells in your head. Why did they do that? The FRAM chips cost like an order of magnitude more per bit than EEPROM, maybe more. You don't use a part that much more expensive for no reason.

Either they needed it because they had to do no-delay writes (eeprom has a delay after writing a page), or they were going to rewrite it many many times.

 (FRAM has effectively infinite rewrite limit - even if you rewrote it 1000 times a second, its specs indicate it would last over 3000 years. An eeprom page being rewritten 200 times per second (the fastest it's capable of, for at24c128) would reach it's spec'ed write limit in an hour and a half)


I was planning to make an EEPROM read/writing sketch, until I discovered there was an off-the-shelf EEPROM read/writer available on ebay for a few bucks, with the GUI control software already written.
Title: Re: I2C EEPROM programmer
Post by: PlaneCrazy on Feb 09, 2018, 08:02 pm
I wouldn't know which programmer to get. Some come with software, some don't. Some are compatible with 24-series, some are compatible with 25-series...

Besides, all that I saw for purchase cost more than the Arduino. Which is also why I bought the Arduino first. But I'm not completely against the idea.
Title: Re: I2C EEPROM programmer
Post by: cattledog on Feb 09, 2018, 11:05 pm
First, run this i2c scanner program, and verify that you can see the address of the eeprom and it is what the code expects which is 0x50.

I am very confused by the output, which is only 15 bytes wide. Even with the wrong address or no eeprom connected I see output 16 bytes wide on the printout. What baud rate setting do you have on the monitor when you run the code in #14?

EDIT: Are you trying to read/write a new and unused 24LC128 eeprom? How is the WP(write protect) pin connected?

Code: [Select]
// I2C Scanner
// Written by Nick Gammon
// Date: 20th April 2011

#include <Wire.h>

void setup() {
  Serial.begin (115200);

  // Leonardo: wait for serial port to connect
  while (!Serial)
    {
    }

  Serial.println ();
  Serial.println ("I2C scanner. Scanning ...");
  byte count = 0;
  
  Wire.begin();
  for (byte i = 8; i < 120; i++)
  {
    Wire.beginTransmission (i);
    if (Wire.endTransmission () == 0)
      {
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);
      Serial.println (")");
      count++;
      delay (1);  // maybe unneeded?
      } // end of good response
  } // end of for loop
  Serial.println ("Done.");
  Serial.print ("Found ");
  Serial.print (count, DEC);
  Serial.println (" device(s).");
}  // end of setup

void loop() {}
Title: Re: I2C EEPROM programmer
Post by: DrAzzy on Feb 09, 2018, 11:52 pm
I wouldn't know which programmer to get. Some come with software, some don't. Some are compatible with 24-series, some are compatible with 25-series...

Besides, all that I saw for purchase cost more than the Arduino. Which is also why I bought the Arduino first. But I'm not completely against the idea.
https://www.ebay.com/itm/CH341A-STC-FLASH-24-25-EEPROM-BIOS-Writer-USB-Programmer-SPI-USB-to-TTL/201316582787
 (https://www.ebay.com/itm/CH341A-STC-FLASH-24-25-EEPROM-BIOS-Writer-USB-Programmer-SPI-USB-to-TTL/201316582787)
This is the same as mine (unfortunately, I paid like $14 for mine) - different manufacturer, but same chip, likely both clones of the same thing. $2.50 with shipping (more expensive ones with faster shipping exist). That's two dollars and fifty cents - sub-cup-of-coffee pricing.

Would bet money that that could read the FRAM chip too if you tell it it's an eeprom of same size.
Title: Re: I2C EEPROM programmer
Post by: cattledog on Feb 10, 2018, 12:05 am
Useful video on how to use one of the CH341A EEPROM reader/writer. Links to software, and explanation of how to enable english language within the gui.

https://www.youtube.com/watch?v=L0ChYNwunUE (https://www.youtube.com/watch?v=L0ChYNwunUE)

Dr Azzy-- Have you used your programmer?
Title: Re: I2C EEPROM programmer
Post by: PlaneCrazy on Feb 14, 2018, 06:14 am
I'm sorry for taking so long to get back, especially since you're all so kind to help me. But I really only have weekends to learn the Arduino.

I am very confused by the output, which is only 15 bytes wide. Even with the wrong address or no eeprom connected I see output 16 bytes wide on the printout. What baud rate setting do you have on the monitor when you run the code in #14?
The baud rate on the serial monitor is at its default rate of 9600. What is a baud rate, anyway? Why is it important?

EDIT: Are you trying to read/write a new and unused 24LC128 eeprom? How is the WP(write protect) pin connected?
Yes. I purchased new EEPROMs to play with to ensure that I can actually transfer the data correctly. The WP pin is connected to ground. That's correct, isn't it? If it were connected to +5V, write protect would be enabled. I basically followed the 24LC128' data sheet and the Sparkfun website.
Title: Re: I2C EEPROM programmer
Post by: cattledog on Feb 14, 2018, 07:42 am
Quote
The baud rate on the serial monitor is at its default rate of 9600. What is a baud rate, anyway? Why is it important?
The baud rate is  the data rate in bits per second (baud) for serial communication sent between the Arduino and the serial monitor. The rate set in the sketch with Serial.begin(baud rate) must match the rate set in the lower right hand corner of the serial monitor window. If the rate of the arduino and the rate of the serial monitor don't match, the output shown is not valid.

The sketch was written with Serial.begin(115200). Either set the monitor to that speed, or change the sketch to Serial.begin(9600) if that's what you are going to use in the monitor.

Quote
The WP pin is connected to ground. That's correct, isn't it? If it were connected to +5V, write protect would be enabled. I basically followed the 24LC128' data sheet and the Sparkfun website.
You are correct. When tied to ground write operations are enabled.

I was uncertain why the sketch did not work properly for you and was searching for possible explanations. 

The baud rate mismatch was the root cause.

Title: Re: I2C EEPROM programmer
Post by: PlaneCrazy on Feb 16, 2018, 09:12 am
Thank you, cattledog. Adjusting the baud rate worked. I have confirmed that the chip is written correctly, by also verifying it with a separate I2C read program from sparkfun.

Thanks again also to all of your contributions.