I2C Write Issues

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hi there,

   

I've been (slowly) making progress on reading and writing between the CY5674 module and a Raspberry Pi 3B. I'm able to read the PRoC buffer fine, but no matter what I do I can't get the Pi to write to the PRoC module.

   

I'm using the python smbus library, and I've tried all of these commands with no luck (my slave address is 0x2D with a 3 byte buffer):

   
        
  • write_byte(int addr,char val)
  •     
  • write_byte_data(int addr,char cmd,char val)
  •     
  • write_word_data(int addr,char cmd,int val)
  •     
  • write_block_data(int addr,char cmd,long vals[])
  •     
  • write_i2c_block_data(int addr,char cmd,long vals[])
  •    
   

I'm using 0 for cmd. The single byte commands don't return an error, but don't write anything predictable.

   

The block commands give me an error 121 (remote i/o error).

   

 

   

After some research, this 3 year old post noted a problem with repeated start and Rpi: 

   

http://stackoverflow.com/questions/17317317/using-python-smbus-on-a-raspberry-pi-confused-with-synta...

   

​The last comment gives a solution for explicitly turning on repeated start support, but this is for the bcm2708 which is deprecated. The Pi I'm using is brand new and has a bcm2835, for which I can't ind any parameter settings.

   

 

   

Does anyone have experience with this, or have any ideas to point me in the right direction? Help would be greatly appreciated.

   

Thanks!

0 Likes
1 Solution
Anonymous
Not applicable

Hi Madhu, thanks for your response. I solved the issue.

   

it comes down to the structure of the i2c functions... most of the libraries out there that I saw use a format similar to the following for i2c write: write_i2c_block_data(int addr,char cmd,long vals[]) Sometimes I've seen a "register" argument in place of the "cmd". The PRoC devices don't seem to be register addressed so I was putting 0 for this.

   

Anyways, what was happening was that my i2c block write was sending an extra "0" byte in front of the 3 bytes I wanted to send. So the PRoC was expecting 3 bytes but actually getting 4, then concluding with a "NACK". To get around this, I put the first byte I want to send in the "cmd" position, and the rest of them in the "vals" array.

   

If you're interested, I'm actually using the PIGPIO library which works with a similar workaround.

   

Here is the format for i2c block write:

   

int i2cWriteI2CBlockData(unsigned handle, unsigned i2cReg, char*buf, unsigned count)

   

This writes 1 to 32 bytes to the specified register of the device associated with handle. 
handle: >=0, as returned by a call to i2cOpen
i2cReg: 0-255, the register to write
buf: the data to write
count: 1-32, the number of bytes to write

   

So using this function, if I want to write the bytes [0x1F,0x3C,0x4D] to my PRoC, I have to call the function like so:

   

char writeBuf[2] = {0x3c, 0x4d};

   

i2cWriteI2CBlockData(handle, 0x1f, writeBuf, 2);

   

Then it works perfectly. 

View solution in original post

0 Likes
2 Replies
Anonymous
Not applicable

Hi,

   

Did you probe the lines using a scope? Do they indicate that the proper data is being transferred?

   

Regards,

   

- Madhu Sudhan

0 Likes
Anonymous
Not applicable

Hi Madhu, thanks for your response. I solved the issue.

   

it comes down to the structure of the i2c functions... most of the libraries out there that I saw use a format similar to the following for i2c write: write_i2c_block_data(int addr,char cmd,long vals[]) Sometimes I've seen a "register" argument in place of the "cmd". The PRoC devices don't seem to be register addressed so I was putting 0 for this.

   

Anyways, what was happening was that my i2c block write was sending an extra "0" byte in front of the 3 bytes I wanted to send. So the PRoC was expecting 3 bytes but actually getting 4, then concluding with a "NACK". To get around this, I put the first byte I want to send in the "cmd" position, and the rest of them in the "vals" array.

   

If you're interested, I'm actually using the PIGPIO library which works with a similar workaround.

   

Here is the format for i2c block write:

   

int i2cWriteI2CBlockData(unsigned handle, unsigned i2cReg, char*buf, unsigned count)

   

This writes 1 to 32 bytes to the specified register of the device associated with handle. 
handle: >=0, as returned by a call to i2cOpen
i2cReg: 0-255, the register to write
buf: the data to write
count: 1-32, the number of bytes to write

   

So using this function, if I want to write the bytes [0x1F,0x3C,0x4D] to my PRoC, I have to call the function like so:

   

char writeBuf[2] = {0x3c, 0x4d};

   

i2cWriteI2CBlockData(handle, 0x1f, writeBuf, 2);

   

Then it works perfectly. 

0 Likes