Need to write a struct fast from and to an 24LC512 chip over i2c

Status
Not open for further replies.

sixeight

Well-known member
This code compiles but gives an ambigious warning:

Code:
struct_test.ino: In function 'void read_cmd_EEPROM(uint16_t, Cmd_struct*)':
struct_test.ino:42:54: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]
In file included from struct_test.ino:2:0:
/Applications/Arduino.app/Contents/Resources/Java/hardware/teensy/avr/libraries/i2c_t3/i2c_t3.h:612:19: note: candidate 1: size_t i2c_t3::requestFrom(int, int)
inline size_t requestFrom(int addr, int len)
^
/Applications/Arduino.app/Contents/Resources/Java/hardware/teensy/avr/libraries/i2c_t3/i2c_t3.h:614:20: note: candidate 2: uint8_t i2c_t3::requestFrom(uint8_t, uint8_t)
inline uint8_t requestFrom(uint8_t addr, uint8_t len)
^

And is it the proper way to send a struct of 11 bytes?
I did not want to use the write anything examples as they seem to write stuff one byte at the time. I wanted to use the block write method.

Code:
#include "My_types.h"
#include <i2c_t3.h>

#define EEPROM_ADDRESS 0x50    //Address of 24LC512 eeprom chip
#define EEPROM_DELAY_LENGTH 5 // time between EEPROM writes (usually 5 ms is OK)
unsigned long WriteDelay = 0;

Cmd_struct cmdIn = { 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6};
Cmd_struct cmdOut;

void write_cmd_EEPROM(uint16_t memloc, Cmd_struct* cmd )
// Writed a command to 24LC512 chip
{
  uint16_t eeaddress = memloc * 16;  // Must write in blocks of 16, to stay within the page size of the memory chip
  const byte* cmdbytes = (const byte*)(const void*)&cmd;
  uint8_t cmdsize = sizeof(cmd);
  
  EEPROM_delay();

  Wire.beginTransmission(EEPROM_ADDRESS);
  Wire.send((int)(eeaddress >> 8));   // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  
  for (uint8_t c = 0; c < cmdsize; c++) {
    Wire.send(*cmdbytes++);
  }
  Wire.endTransmission();
}

void read_cmd_EEPROM(uint16_t memloc, Cmd_struct* cmd )
// Writed a command to 24LC512 chip
{
  uint16_t eeaddress = memloc * 16;  // Must write in blocks of 16, to stay within the page size of the memory chip
  byte* cmdbytes = (byte*)(void*)&cmd;
  uint8_t cmdsize = sizeof(cmd);
  
  Wire.beginTransmission(EEPROM_ADDRESS);
  Wire.send((int)(eeaddress >> 8));   // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  
  Wire.requestFrom (EEPROM_ADDRESS, (uint8_t) cmdsize);
  for (uint8_t c = 0; c < cmdsize; c++) {
    *cmdbytes++ = Wire.receive();
  }
}


void EEPROM_delay() { // Will delay if last message was within EEPROM_DELAY_LENGTH (5 ms)
  while (millis() - WriteDelay <= EEPROM_DELAY_LENGTH) {}
  WriteDelay = millis();
}

void setup () {
 Wire.begin();
 Wire.setClock(I2C_RATE_1200);
 
 write_cmd_EEPROM(0, &cmdIn);
 read_cmd_EEPROM(0, &cmdOut);
 
 Serial.begin(115200);
 Serial.print("OutCmd:");
 Serial.println(String(cmdOut.Type));
}

void loop() {
}

The struct is declared in a seperate MyTypes.h file and is included in the main sketch:

Code:
#ifndef MyTypes_h
#define MyTypes_h

#include <WString.h>

struct Cmd_struct {
  uint8_t Page;
  uint8_t Switch;
  uint8_t Type;
  uint8_t Device;
  uint8_t Data1;
  uint8_t Data2;
  uint8_t Value1;
  uint8_t Value2;
  uint8_t Value3;
  uint8_t Value4;
  uint8_t Value5;
};

#endif

What am I doing wrong?
 
Last edited:
"Fast" and I2C does not match.

Please post the full code and the warning... we don't have magical powers and know which warning it is.
You may think that otherwise you would have posted the "warning"..

but no. no magic here.
 
your uint8_t cmdsize = sizeof(cmd); is flawed. cmd is pointer, so it's size will be 4. you want
uint8_t cmdsize = sizeof(struct Cmd_struct);
or uint8_t cmdsize = sizeof(*cmd);


also broken: const byte* cmdbytes = (const byte*)(const void*)&cmd; you want something like
byte* cmdbytes ;
cmdbytes = ( byte*)cmd;


there may be other problems ....
 
Last edited:
What version of IDE and TeensyDuino are installed? What Teensy are you using/compiling for?

Line numbers don't match my .h but I see these three options for two parameters to match parameter types:
Code:
    inline size_t requestFrom(uint8_t addr, size_t len)
    inline size_t requestFrom(int addr, int len)
    inline uint8_t requestFrom(uint8_t addr, uint8_t len)

It is ambiguous because you aren't passing one of those patterms.
 
As defragster notes, Wire.requestFrom ((uint8_t)EEPROM_ADDRESS, (uint8_t) cmdsize); will fix compiler warning
 
Thanks for the great suggestions. I have it working now. I have to put a delay between writing and reading as well, otherwise the data is not read correctly.

I am on Arduino 1.23 on an ancient Macbook running OSX 10.6.8. Can't remember the version of Teensyduino...

"Fast" and I2C does not match.

I know i2C is not fast, but writing the bytes in bulk should be a lot faster than writing them one by one with the addressing bytes in between...

Here is my code:

Code:
#include "My_types.h"
#include <i2c_t3.h>

#define EEPROM_ADDRESS 0x50    //Address of 24LC512 eeprom chip
#define EEPROM_DELAY_LENGTH 5 // time between EEPROM writes (usually 5 ms is OK)
unsigned long WriteDelay = 0;

Cmd_struct cmdIn = { 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6};
Cmd_struct cmdOut;

void write_cmd_EEPROM(uint16_t memloc, Cmd_struct* cmd )
// Writed a command to 24LC512 chip
{
  uint16_t eeaddress = memloc * 16;  // Must write in blocks of 16, to stay within the page size of the memory chip
  //const byte* cmdbytes = (const byte*)(const void*)&cmd;
  byte* cmdbytes = ( byte*)cmd;
  uint8_t cmdsize = sizeof(*cmd);

  EEPROM_delay();

  Wire.beginTransmission(EEPROM_ADDRESS);
  Wire.send((int)(eeaddress >> 8));   // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB

  for (uint8_t c = 0; c < cmdsize; c++) {
    Serial.print(String(*cmdbytes) + " ");
    Wire.send(*cmdbytes++);
  }
  Wire.endTransmission();
  Serial.println();
}

void read_cmd_EEPROM(uint16_t memloc, Cmd_struct* cmd )
// Writed a command to 24LC512 chip
{
  uint16_t eeaddress = memloc * 16;  // Must write in blocks of 16, to stay within the page size of the memory chip
  byte* cmdbytes = ( byte*)cmd;
  uint8_t cmdsize = sizeof(*cmd);

  Wire.beginTransmission(EEPROM_ADDRESS);
  Wire.send((int)(eeaddress >> 8));   // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();

  Wire.requestFrom (EEPROM_ADDRESS, (int) cmdsize);
  for (uint8_t c = 0; c < cmdsize; c++) {
    uint8_t newbyte = Wire.receive();
    *cmdbytes++ = newbyte;
    Serial.print(String(newbyte) + " ");
  }
  Serial.println();
}

void EEPROM_delay() { // Will delay if last message was within EEPROM_DELAY_LENGTH (5 ms)
  while (millis() - WriteDelay <= EEPROM_DELAY_LENGTH) {}
  WriteDelay = millis();
}

void setup () {
  Wire.begin();
  Wire.setClock(I2C_RATE_1200);

  Serial.begin(115200);
  delay(2000);
  Serial.println ("Started debug");

  write_cmd_EEPROM(25, &cmdIn);
  EEPROM_delay();
  read_cmd_EEPROM(25, &cmdOut);
}

void loop() {
}
 
Last edited:
Status
Not open for further replies.
Back
Top