JuanPZ
Posts: 8
Joined: Tue Sep 11, 2018 12:13 am

I2C read always get first byte

Thu Sep 13, 2018 10:40 pm

Hello, I have a little problem with I2C

I have an Arduino (Slave) and a PI (Master) connected with I2C. I can send strings through I2C to the Arduino using i2cset:

Code: Select all

[email protected]:~ $ i2cset -y 1 0x08  0x41 0x52 0x47 0x42 0x3a 0x32 0x35 0x35 0x32 0x35 0x35 0x32 0x35 0x35 0x32 0x35 0x35 i
(The message was "ARGB:255255255255", for the arduino that is 255 255 255 255)
But when I try to retrieve a message sent by the Arduino using i2cget, I only get the first Byte

Code: Select all

[email protected]:~ $ i2cget -y 1 0x08
0x32
(The message sent by the arduino was "255255255255", without the ARGB)

I read in Google that if I call the function twice, I should read another byte (0x35), but it's stills being 0x32 ("2"). I can call it a lot of time, but the result is the same.

So I though that it could be the Address parameter, but it's seems that It's ignored, because I can send this:

Code: Select all

[email protected]:~ $ i2cget -y 1 0x08 0xff b
but the result stills 0x32.

If I look i2cdump, I get this:

Code: Select all

[email protected]:~ $ i2cdump -y 1 0x08
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 32 32 32 XX XX XX XX XX XX XX XX XX XX XX XX XX    222XXXXXXXXXXXXX
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
...
f0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX

I don't know If I'm using wrong the i2c, or if this is a bug from the apt-get package (i have the last version from apt-get) but I can't find any solution to read at least 3 bytes
Note: I tried sending a short message (only 3 bytes) from the Arduino, but the result was exactly the same.
Note2: The arduino gets the message correctly from i2cset, so the connection and the setup should be correct

User avatar
joan
Posts: 13582
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: I2C read always get first byte

Thu Sep 13, 2018 11:27 pm

We need to see the Arduino code.

JuanPZ
Posts: 8
Joined: Tue Sep 11, 2018 12:13 am

Re: I2C read always get first byte

Thu Sep 13, 2018 11:31 pm

joan wrote:
Thu Sep 13, 2018 11:27 pm
We need to see the Arduino code.
Sorry, I forget that. Here is (I removed some code to make it simple. Every code related to Wire stills there):

Code: Select all

#include <Wire.h>
int aValue = 0; //0-255
int rValue = 0; //0-255
int gValue = 0; //0-255
int bValue = 0; //0-255

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

  Wire.begin(8);
  Wire.onReceive(OnReceive);
  Wire.onRequest(OnRequest);
}

void OnReceive(int Length) {
  Serial.println("Receiving...");
  String inString = "";
  int pos = 0;
  while (Wire.available() && pos < Length) {
    inString += (char)Wire.read();
    pos++;
  }

  Serial.println(inString);

  if (inString.startsWith("RGB:")) {
    aValue = 255;
    rValue = inString.substring(4, 7).toInt();
    gValue = inString.substring(7, 10).toInt();
    bValue = inString.substring(10, 13).toInt();
  } else if (inString.startsWith("ARGB:")) {
    aValue = inString.substring(5, 8).toInt();;
    rValue = inString.substring(8, 11).toInt();
    gValue = inString.substring(11, 14).toInt();
    bValue = inString.substring(14, 17).toInt();
  }
}

void OnRequest() {
  char ARGBStr[12];
  snprintf(ARGBStr, 12, "%03d%03d%03d%03d", aValue, rValue, gValue, bValue); //this make 255255255255
  Wire.write(ARGBStr);
  Serial.println(ARGBStr);
}

User avatar
joan
Posts: 13582
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: I2C read always get first byte

Fri Sep 14, 2018 7:38 am

I would get rid of the serial prints from within the Arduino interrupt handlers. They could be delaying the I2C bus.

JuanPZ
Posts: 8
Joined: Tue Sep 11, 2018 12:13 am

Re: I2C read always get first byte

Fri Sep 14, 2018 4:48 pm

joan wrote:
Fri Sep 14, 2018 7:38 am
I would get rid of the serial prints from within the Arduino interrupt handlers. They could be delaying the I2C bus.
Hi. I tried that but without success.

I have a question: Do I have to interpetate the Address sent from the Pi in the Arduino?
I mean: If I send 0x1, the arduino has to send the first byte manually (hard-code)?

danjperron
Posts: 3076
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: I2C read always get first byte

Sun Sep 16, 2018 12:07 am

Did you forget that an Arduino UNO is very slow.

you can't use sprintf inside the OnRequest. is too slow

make all the computation into a buffer then the OnRequest will works.

you are writing an array but you should write a byte at once.

ex:

Code: Select all

#include <Wire.h>

void setup() {
  Wire.begin(8);
  Wire.onRequest(OnRequest);
}


int index=0;

unsigned char Table[12]={11,10,9,8,7,6,5,4,3,2,99,98};



void OnRequest() {
  Wire.write(Table[index]);
  index= (index + 1) % 12;
}

void loop()
{
  delay(1);
}

Code: Select all

[email protected]:~ $ i2cget -y 1 0x08
0x0b
[email protected]:~ $ i2cget -y 1 0x08
0x0a
[email protected]:~ $ i2cget -y 1 0x08
0x09
[email protected]:~ $ i2cget -y 1 0x08
0x08
[email protected]:~ $ i2cget -y 1 0x08
0x07
[email protected]:~ $ i2cget -y 1 0x08
0x06
[email protected]:~ $ i2cdump -y 1 0x08
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 05 04 03 02 63 62 0b 0a 09 08 07 06 05 04 03 02    ????cb??????????
10: 63 62 0b 0a 09 08 07 06 05 04 03 02 63 62 0b 0a    cb??????????cb??
20: 09 08 07 06 05 04 03 02 63 62 0b 0a 09 08 07 06    ????????cb??????
30: 05 04 03 02 63 62 0b 0a 09 08 07 06 05 04 03 02    ????cb??????????
40: 63 62 0b 0a 09 08 07 06 05 04 03 02 63 62 0b 0a    cb??????????cb??
50: 09 08 07 06 05 04 03 02 63 62 0b 0a 09 08 07 06    ????????cb??????
60: 05 04 03 02 63 62 0b 0a 09 08 07 06 05 04 03 02    ????cb??????????
70: 63 62 0b 0a 09 08 07 06 05 04 03 02 63 62 0b 0a    cb??????????cb??
80: 09 08 07 06 05 04 03 02 63 62 0b 0a 09 08 07 06    ????????cb??????
90: 05 04 03 02 63 62 0b 0a 09 08 07 06 05 04 03 02    ????cb??????????
a0: 63 62 0b 0a 09 08 07 06 05 04 03 02 63 62 0b 0a    cb??????????cb??
b0: 09 08 07 06 05 04 03 02 63 62 0b 0a 09 08 07 06    ????????cb??????
c0: 05 04 03 02 63 62 0b 0a 09 08 07 06 05 04 03 02    ????cb??????????
d0: 63 62 0b 0a 09 08 07 06 05 04 03 02 63 62 0b 0a    cb??????????cb??
e0: 09 08 07 06 05 04 03 02 63 62 0b 0a 09 08 07 06    ????????cb??????
f0: 05 04 03 02 63 62 0b 0a 09 08 07 06 05 04 03 02    ????cb??????????
[email protected]:~ $ 
I prefer to use register on i2C communication. This is easier to get all the register ready first.

JuanPZ
Posts: 8
Joined: Tue Sep 11, 2018 12:13 am

Re: I2C read always get first byte

Sun Sep 16, 2018 12:31 am

danjperron wrote:
Sun Sep 16, 2018 12:07 am
Did you forget that an Arduino UNO is very slow.

you can't use sprintf inside the OnRequest. is too slow

make all the computation into a buffer then the OnRequest will works.

you are writing an array but you should write a byte at once.

ex:

Code: Select all

#include <Wire.h>

void setup() {
  Wire.begin(8);
  Wire.onRequest(OnRequest);
}


int index=0;

unsigned char Table[12]={11,10,9,8,7,6,5,4,3,2,99,98};



void OnRequest() {
  Wire.write(Table[index]);
  index= (index + 1) % 12;
}

void loop()
{
  delay(1);
}

Code: Select all

[email protected]:~ $ i2cget -y 1 0x08
0x0b
[email protected]:~ $ i2cget -y 1 0x08
0x0a
[email protected]:~ $ i2cget -y 1 0x08
0x09
[email protected]:~ $ i2cget -y 1 0x08
0x08
[email protected]:~ $ i2cget -y 1 0x08
0x07
[email protected]:~ $ i2cget -y 1 0x08
0x06
[email protected]:~ $ i2cdump -y 1 0x08
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 05 04 03 02 63 62 0b 0a 09 08 07 06 05 04 03 02    ????cb??????????
10: 63 62 0b 0a 09 08 07 06 05 04 03 02 63 62 0b 0a    cb??????????cb??
20: 09 08 07 06 05 04 03 02 63 62 0b 0a 09 08 07 06    ????????cb??????
30: 05 04 03 02 63 62 0b 0a 09 08 07 06 05 04 03 02    ????cb??????????
40: 63 62 0b 0a 09 08 07 06 05 04 03 02 63 62 0b 0a    cb??????????cb??
50: 09 08 07 06 05 04 03 02 63 62 0b 0a 09 08 07 06    ????????cb??????
60: 05 04 03 02 63 62 0b 0a 09 08 07 06 05 04 03 02    ????cb??????????
70: 63 62 0b 0a 09 08 07 06 05 04 03 02 63 62 0b 0a    cb??????????cb??
80: 09 08 07 06 05 04 03 02 63 62 0b 0a 09 08 07 06    ????????cb??????
90: 05 04 03 02 63 62 0b 0a 09 08 07 06 05 04 03 02    ????cb??????????
a0: 63 62 0b 0a 09 08 07 06 05 04 03 02 63 62 0b 0a    cb??????????cb??
b0: 09 08 07 06 05 04 03 02 63 62 0b 0a 09 08 07 06    ????????cb??????
c0: 05 04 03 02 63 62 0b 0a 09 08 07 06 05 04 03 02    ????cb??????????
d0: 63 62 0b 0a 09 08 07 06 05 04 03 02 63 62 0b 0a    cb??????????cb??
e0: 09 08 07 06 05 04 03 02 63 62 0b 0a 09 08 07 06    ????????cb??????
f0: 05 04 03 02 63 62 0b 0a 09 08 07 06 05 04 03 02    ????cb??????????
[email protected]:~ $ 
I prefer to use register on i2C communication. This is easier to get all the register ready first.
Thanks for the explanation.
Actually, I change a little bit the way to comunicate. Sadly I didn't had time to write a reply (in fact, right now I'm not in my house), but the way that I fix it was like this:

1) First, the message is being built when I change a variable instead in OnRequested.
2) In my Pi side, I send a i2cget with address (the Arduino get that address in OnReceived) and I store that in a global variable.
3) After OnReceived, the arduino will Call the OnRequested function, where it's sends the X char of the string (which is also a Global Variable)
4) Repeat the steps 2 until I receive all the bytes (in the Pi Side there is a variable that store the count of byte that there should be).

Tomorrow I will update with the code of both the Pi side (.php) and the arduino side (.ino)

danjperron
Posts: 3076
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: I2C read always get first byte

Sun Sep 16, 2018 12:52 am

1) First, the message is being built when I change a variable instead in OnRequested.
2) In my Pi side, I send a i2cget with address (the Arduino get that address in OnReceived) and I store that in a global variable.
3) After OnReceived, the arduino will Call the OnRequested function, where it's sends the X char of the string (which is also a Global Variable)
4) Repeat the steps 2 until I receive all the bytes (in the Pi Side there is a variable that store the count of byte that there should be).
Perfect! This is more or less what I ask you to do!

JuanPZ
Posts: 8
Joined: Tue Sep 11, 2018 12:13 am

Re: I2C read always get first byte

Sun Sep 16, 2018 11:21 pm

Here is my code:

Pi side (.php)

Code: Select all

function GetActualLightColor() {
    $lights = read_string(12);
    //Proccess the data
}

function read_register($address) {
    $cmd = 'i2cget -y ' . $GLOBALS['i2c_bus'] . ' ' . $GLOBALS['2ic_first_slave_address'] . ' ' . $address . ' b';
    return trim(shell_exec($cmd));
}
function read_string($strLen) {
	$result = "";
	for($i = 0; $i < $strLen; $i++) {
		$intVal = intval(read_register($i), 16);
		$result = $result.chr($intVal);
		usleep(25 * 1000);
	}
	return $result;
}
This is the Arduino code:

Code: Select all

#include <Wire.h>

#define Rpin 9
#define Gpin 5
#define Bpin 6

#define ARGBStrLen 13 //I use snprintf so the lenght must be N+1

int aValue = 0; //0-255
int rValue = 0; //0-255
int gValue = 0; //0-255
int bValue = 0; //0-255

int posToSend = 0;
char ARGBStr[12];

void OnReceive(int Length) {
  Serial.println("Receiving...");
  if(Length == 1) {
    posToSend = Wire.read();
    Serial.print("New pos: ");
    Serial.println(posToSend);
    return;
  }
  //...
  snprintf(ARGBStr, ARGBStrLen, "%03d%03d%03d%03d", aValue, rValue, gValue, bValue);
}

void OnRequest() {
  Wire.write(ARGBStr[posToSend]);
  Serial.println(ARGBStr);
}
Note: I deleted a lot of code to make it simple. the xValue variables from arduino I proccess in another part NOT included in the example code


Anyway, thanks for the help!

Return to “Interfacing (DSI, CSI, I2C, etc.)”