Notifications
Clear all

When 30 is an odd number???

29 Posts
3 Users
2 Likes
6,087 Views
(@pugwash)
Sorcerers' Apprentice
Joined: 5 years ago
Posts: 923
Topic starter  

   
Quote
frogandtoad
(@frogandtoad)
Member
Joined: 5 years ago
Posts: 1458
 

@pugwash

Posted by: @pugwash

byte mByte[0x1d]; //0x1d = 30

Umm..., 0x1D == 29 stored numbers, not 30...

Not sure about the rest without some careful study 🙂

 

 

 


   
ReplyQuote
(@pugwash)
Sorcerers' Apprentice
Joined: 5 years ago
Posts: 923
Topic starter  

@frogandtoad

I meant "0x1e" = 30!

Have double checked the code and 0x1e returns the first 30 values stored in EEPROM, and so does 0x1f and 0x20.

I have searched the internet, but come up blank why there seems to be a 30 byte limit! 


   
ReplyQuote
NewburyPi
(@dale)
Member
Joined: 5 years ago
Posts: 97
 

What is the value of idx when it escapes the While loop, at line 53? Has the "while(Wire.available())" actually read anything from those ram locations? Maybe the two zero values were defaulted in the array "mByte[]" when it was initialized. 

You description of the problem and what you've found to date makes me question the wire library. 

 

Just my two cents. 

--
Dale


   
ReplyQuote
NewburyPi
(@dale)
Member
Joined: 5 years ago
Posts: 97
 

I just dug up an LC version of your RAM chip (24LC256), and I'll try to duplicate your issue tonight. 

I've gone over the code and the data sheet and can not find anything obvious. Of course it will be quite obvious once we find it 🙂

--
Dale


   
ReplyQuote
NewburyPi
(@dale)
Member
Joined: 5 years ago
Posts: 97
 

OK, I've duplicated the fault. Sorta. My first observation was that the last two bytes were fixed. However in my case, they were both 255.  Not 0, as you found. I then messed about with making sure the counter were counting properly, Which of course they were. I then made a few changes to your code.  See below. This allowed me to see what happened when I wrote smaller blocks, starting at different addresses. Long story short, when I wrote less than 32 bytes, but wrote on the last two bytes (bytes 31 and 32) the bytes were correctly updated. When I did a 32 byte write, the last two bytes remained as previously set. 

Example:

Starting address: 0
Block size: 32
Values to be stored in EEPROM:
3,212,80,81,61,234,105,237,50,72,144,21,191,17,36,170,54,30,166,106,5,143,86,76,176,147,204,247,84,87,177,56,
Values returned from EEPROM
3,212,80,81,61,234,105,237,50,72,144,21,191,17,36,170,54,30,166,106,5,143,86,76,176,147,204,247,84,87,255,255,
Done

Starting address: 2
Block size: 30
Values to be stored in EEPROM:189,213
212,250,14,157,29,118,78,119,44,36,129,54,141,111,240,74,84,188,104,210,139,9,187,141,62,56,72,239,189,213,
Values returned from EEPROM
212,250,14,157,29,118,78,119,44,36,129,54,141,111,240,74,84,188,104,210,139,9,187,141,62,56,72,239,189,213,
Done

Starting address: 0
Block size: 32
Values to be stored in EEPROM:
189,14,45,68,77,188,192,187,105,18,122,134,116,158,87,217,226,12,137,7,142,6,46,46,5,74,6,107,178,148,154,225,
Values returned from EEPROM
189,14,45,68,77,188,192,187,105,18,122,134,116,158,87,217,226,12,137,7,142,6,46,46,5,74,6,107,178,148,189,213,
Done

Starting address: 30
Block size: 2
Values to be stored in EEPROM:
3,212,
Values returned from EEPROM
3,212,
Done

Starting address: 0
Block size: 32
Values to be stored in EEPROM:
212,250,14,157,29,118,78,119,44,36,129,54,141,111,240,74,84,188,104,210,139,9,187,141,62,56,72,239,189,213,162,41,
Values returned from EEPROM
212,250,14,157,29,118,78,119,44,36,129,54,141,111,240,74,84,188,104,210,139,9,187,141,62,56,72,239,189,213,3,212,
Done

So there's the data, but I haven't found a reason behind it. 

// Include the I2C Wire Library
#include "Wire.h"

// EEPROM I2C Address
#define i2c_eeprom 0x50

#define SIZE 32
#define START_ADDRESS 0

byte mByte[SIZE];

void setup() {

Serial.begin(9600);2
Wire.begin();
randomSeed(analogRead(0));

}

void loop() {
Serial.print("Starting address: ");
Serial.println(START_ADDRESS);
Serial.print("Block size: ");
Serial.println(SIZE);
int address = START_ADDRESS;
Wire.beginTransmission(i2c_eeprom);
Wire.write((int)(address >> 8)); // MSB
Wire.write((int)(address & 0xFF)); // LSB
Serial.println("Values to be stored in EEPROM:");
for(int i = 0; i < SIZE; i++){
int randomNumber = random(255);
Wire.write(randomNumber);
Serial.print(randomNumber);
Serial.print(",");
}
Wire.endTransmission();

Serial.println();

delay(5);

address = START_ADDRESS;

Wire.beginTransmission (i2c_eeprom);
// Set device to start read reg 0
Wire.write((int)(address >> 8)); // MSB
Wire.write((int)(address & 0xFF)); // LSB
Wire.endTransmission ();

Wire.requestFrom(i2c_eeprom, SIZE);

int idx = 0;

// read the bytes into an array
while(Wire.available()) {

mByte[idx] = Wire.read(); // read each byte from the register and store in the array
idx++;
}

Serial.println("Values returned from EEPROM");
for (int i = 0; i < SIZE; i++){
Serial.print(mByte[i]);
Serial.print(",");
}

Serial.println();
Serial.println("Done");
while(1);
}

 

 

--
Dale


   
ReplyQuote
(@pugwash)
Sorcerers' Apprentice
Joined: 5 years ago
Posts: 923
Topic starter  

@dale

In your first test result block, the last two values of 255 each are because the EEPROM has never before been used, the factory settings for EEPROM are 255. Mine were already zero because I had set the first 120 bytes previously to zero, after previous experimentation with these chips.

In the last block, bytes 31 and 32 had not been overwritten during the while/write loop.

I think you would have to dig deep into the wire.h library and possibly other dependent libraries, to find out if they were responsible for this 30 byte write limit!


   
ReplyQuote
(@pugwash)
Sorcerers' Apprentice
Joined: 5 years ago
Posts: 923
Topic starter  

@dale

What is also interesting is that according to the datasheet attached, it is possible to write 64-byte data blocks to the registers. In the datasheet, they are called "pages".

I am sure that wire.h does not support this method. After looking at the wire.h library, this library is not responsible for read or write actions, I think they are handled by TwoWire.h or stream.h.

It is now getting beyond me ? 


   
ReplyQuote
(@pugwash)
Sorcerers' Apprentice
Joined: 5 years ago
Posts: 923
Topic starter  

Another thing I have discovered is that if you try to write 30 bytes starting at address 60, only the first 4 bytes are written to registers 60, 61, 62 & 63.

Can you confirm this??


   
ReplyQuote
NewburyPi
(@dale)
Member
Joined: 5 years ago
Posts: 97
 

I can try to reproduce a little later. However, that is probably correct operation, as the memory is organized in 64 byte blocks. 

--
Dale


   
ReplyQuote
NewburyPi
(@dale)
Member
Joined: 5 years ago
Posts: 97
 

Problem identified. Solution to follow? I found this tonight...

http://www.hobbytronics.co.uk/eeprom-page-write

This page Identifies the Oddity of "30" as being an issue with the Wire library.  It claims that the buffer in the library is only 32 bytes long, and then when doing a "page write," two of those buffer bytes hold the address data. Hence,  only 30 bytes of data are able to be sent. I've not confirmed it, but my money is on Wire sending a stop after the buffer is empty. I suppose hacking the Wire lib would be the best way to fix it, but that is out of my pay grade. As is writing a compliant I2C driver. Easiest solution may be to have a subroutine that repackages byte blocks longer than 30 bytes and sends Wire the smaller, compliant chunks. 

@pugwash As to your last post...

if you try to write 30 bytes starting at address 60, only the first 4 bytes are written to registers 60, 61, 62 & 63.

The article go on to discuss the issue of writing past page boarders.

 

Hope this helps. 

 

PS: maybe the "chunker" routine could also manage data across these boundries.

--
Dale


   
Pugwash reacted
ReplyQuote
(@pugwash)
Sorcerers' Apprentice
Joined: 5 years ago
Posts: 923
Topic starter  

@dale

Problem identified. Solution to follow? I found this tonight...

http://www.hobbytronics.co.uk/eeprom-page-write

Read it, and it does explain some of the odd things that were happening when using the write() function.

As I mentioned above, I don't think that altering the Wire.h library will have any effect. I believe that the write() function is in one of the underlying libraries invoked by Wire.h, probably stream.h.

These are the functions of the Wire.h library listed in the KEYWORDS file.

begin
setClock
beginTransmission
endTransmission
requestFrom
onReceive
onRequest

If I knew where the Arduino IDE is hiding the stream.h library, I may be able to confirm it!


   
ReplyQuote
(@pugwash)
Sorcerers' Apprentice
Joined: 5 years ago
Posts: 923
Topic starter  

   
ReplyQuote
NewburyPi
(@dale)
Member
Joined: 5 years ago
Posts: 97
 

@pugwash

Are you getting back all 32 bytes correctly now, or are you having the exact same response.  Just guessing now and will have to run this code later, but...   if all 32 bytes are correct you may be running into the Wire buffer problem again, except this time on the wire.read end.

You could try repeating the section between "// display section****" and the end of the for loop. The second time through set START_ADDRESS to 32. If the write is working properly you should see the remainder of the bytes in the second read part.

Off to do a VV run and some groceries.

--
Dale


   
ReplyQuote
NewburyPi
(@dale)
Member
Joined: 5 years ago
Posts: 97
 

@pugwash

Yep! looks like the 32 byte buffer strikes again. I changed the wire.right part to output incremental data. Then split the wire.read part to first read just the first 32 bytes, then repeat the read on the second 32 bytes. (code below)

Values returned from EEPROM
Register , Value

1 *** , 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 *** 8
9 *** , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 *** 16
17 *** , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 *** 24
25 *** , 24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 *** 32

Values returned from EEPROM
Register , Value

33 *** , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 *** 40
41 *** , 40 , 41 , 42 , 43 , 44 , 45 , 46 , 47 *** 48
49 *** , 48 , 49 , 50 , 51 , 52 , 53 , 54 , 55 *** 56
57 *** , 56 , 57 , 58 , 59 , 60 , 61 , 62 , 63 *** 64

Done

 

// Include the I2C Wire Library
#include "Wire.h"

// EEPROM I2C Address
#define i2c_eeprom 0x50
#define READ_DATA 32
#define START_ADDRESS 0

byte mByte[READ_DATA];

void setup() {

Serial.begin(9600);
Wire.begin();
randomSeed(64);

}

void loop() {

for(int i = 0; i < 64; i++){
byte seed = random(255);
writeEEPROM(i2c_eeprom, i, i );
}

delay(5);

// display section****************************

Wire.beginTransmission (i2c_eeprom);
// Set device to start read reg 0
Wire.write((int)(START_ADDRESS >> 8)); // MSB
Wire.write((int)(START_ADDRESS & 0xFF)); // LSB
Wire.endTransmission ();

Wire.requestFrom(i2c_eeprom, READ_DATA);

int idx = 0;

// read the bytes into an array
// while(Wire.available()) {
for (int i = 0; i < READ_DATA; i++){
mByte[idx] = Wire.read(); // read each byte from the register and store in the array
idx++;
}
Serial.println("\nValues returned from EEPROM");
Serial.println("Register , Value\n");

for (int i = 0; i < READ_DATA; i++){
if ((i)%8 == 0) {
Serial.print(i+1+START_ADDRESS);
Serial.print(" *** ");
}
// Serial.print(i);
Serial.print(" , ");
Serial.print(mByte[i]);
if ((i+1)%8 == 0) {
Serial.print(" *** ");
Serial.println(i+1+START_ADDRESS);
}

}
// second display section****************************

Wire.beginTransmission (i2c_eeprom);
// Set device to start read reg 0
Wire.write((int)((START_ADDRESS+32) >> 8)); // MSB
Wire.write((int)((START_ADDRESS+32) & 0xFF)); // LSB
Wire.endTransmission ();

Wire.requestFrom(i2c_eeprom, READ_DATA);

idx = 0;

// read the bytes into an array
// while(Wire.available()) {
for (int i = 0; i < READ_DATA; i++){
mByte[idx] = Wire.read(); // read each byte from the register and store in the array
idx++;
}
Serial.println("\nValues returned from EEPROM");
Serial.println("Register , Value\n");

for (int i = 0; i < READ_DATA; i++){
if ((i)%8 == 0) {
Serial.print(i+1+START_ADDRESS+READ_DATA);
Serial.print(" *** ");
}
// Serial.print(i);
Serial.print(" , ");
Serial.print(mByte[i]);
if ((i+1)%8 == 0) {
Serial.print(" *** ");
Serial.println(i+1+START_ADDRESS+READ_DATA);
}
}
Serial.println();
Serial.println("Done");
while(1);
}

//write one single byte of data

void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data )
{
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddress >> 8)); // MSB
Wire.write((int)(eeaddress & 0xFF)); // LSB
Wire.write(data);
Wire.endTransmission();

delay(5);
}

 

--
Dale


   
ReplyQuote
Page 1 / 2