Arduino Raspberry communication I2C

Bonjour,

Je galère depuis quelques semaines pour la récupération et relecture des informations envoyées par un raspberry vers un arduino mega 2560.

Jusqu' présent, j'arrive bien à établir la communication I2C, j'arrive bien a envoyer des datas ( 0 à 65535 ), j'arrive à réceptionner des bytes coté arduino. Le problème c'est que je n'arrive pas à réassembler les bytes comme il faut pour reconstruire la valeur envoyée.
En gros lorsque je passe la valeur 1244 coté raspberry , l'arduino reçoit le 1er byter puis le 2d byte, ce qui me donne 220 et 4. Ce que je n'arrive pas a faire c'est le 4 | 220 ...

car en effet : 4 ==> 0100
220 ==> 1101 1100
et 4 | 220 ==> 0100 1101 1100 qui correspond a 1244 en base 10

Je n'arrive pas a "séparer" ces 2 bytes pour pouvoir faire le 4 | 220.

voici mon code arduino :

void receiveEvent(int howMany)
{
  if (howMany == 2)
   {
      uint16_t r = 0;
      r = Wire.read();
      r = Wire.read()<< 8;
      Serial.println(r);
   }
}

J'ai essayé tout un tas de code, sans meilleur résultat...
Merci pour votre aide.

int r1 = Wire.read();
int r2 = Wire.read()
int valeur = r1<<8 + r2;

Merci pour ce bout de code. Je viens de le tester et cela me retourne deux valeurs : 0 et 0

Quand je fais :

int r1 = Wire.read(); qui correspond à 220
int r2 = Wire.read(); qui correspond à 4
int valeur = r2<<8 + r1; ça me retourne -9216 et 1024

Je ne comprends pas pourquoi je n'arrive pas a récupérer 4 | 220....

idem quand je fais :

int r1 = Wire.read();        qui correspond à 220
int valeur = Wire.read()<<8 + r1;       ça me retourne -9216 et 1024

Tu n'es pas très clair
Que valent r1, r2 et valeur?
1024 c'est 4 multiplié par 256 ou 4 << 8
-9216 c'est 220 multiplié par 256 ou 220 << 8

Bonjour, en fait j'envoie la valeur 1244 depuis un raspberry, en faisant :

with SMBus(1) as bus:
    data = 1244
    bus.write_byte_data(addr, 0, data & 0xFF)
    bus.write_word_data(addr, 0, (data & 0xFF)>>8)

coté Arduino, je receptionne les valeurs 220 et 4 ... que je souhaite ré-assembler pour retrouver la valeur envoyée.

Si tu envoies ça

Alors ça doit fonctionner

int r1 = Wire.read();
int r2 = Wire.read()
int valeur = r1 | r2<<8;

Bonjour wawann

r = Wire.read()<< 8;
ne serait pas plutôt
r += Wire.read()<< 8;
sans ça, cette opération "écrase " la valeur de la précédente?

Je ne saurai faire avec un Raspberry, mais, entre 2 Arduino, j'échangerai plutôt une structure contenant les données ça facilite grandement la transmission et, surtout, la réception.

Cordialement
jpbbricole

Alors le 1er code :

#include <Wire.h>

void setup()
{
  Wire.begin(8);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event  
  Serial.begin(2000000);           // start serial for output
}

void loop()
{
  delay(1000);
}

void receiveEvent(int howMany)
{
  if (howMany == 2)
  {
      uint16_t r = 0;
      int r1 = Wire.read();
      int r2 = Wire.read();
      int valeur = r1 | r2<<8;
      Serial.println(valeur);
  }
}

renvoi comme resultat :   -9216  et   1024    pour 1244 envoyé

et le 2d code :

#include <Wire.h>

void setup()
{
  Wire.begin(8);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event  
  Serial.begin(2000000);           // start serial for output
}

void loop()
{
  delay(1000);
}

void receiveEvent(int howMany)
{
  if (howMany == 2)
  {
      uint16_t r = 0;
      r = Wire.read();
      r += Wire.read() <<8;
      Serial.println(r);
  }
}
 

retourne comme résultat : 56320 et 1024 ... pour 1244 envoyé..

Désolé mais c'est impossible.
Tu ne fais fais imprimer qu'un seul nombre c'est valeur donc tu ne peux pas avoir 2 nombres.

Tu n'as pas répondu à ça

Fais imprimer r1, r2 et valeur pour que l'on comprenne (et toi aussi au passage) ce que tu reçois.

Je crois que j'ai compris le problème. Tu vas lire alors qu'il ne doit y avoir aucune valeur à récupérer.
Regarde de ce coté

ok, je vais regarder "available".
Pour répondre à la question, voici les retours pour le code :


void receiveEvent(int howMany)
{
  if (howMany == 2)
  {
      uint16_t r = 0;
      int r1 = Wire.read();
      int r2 = Wire.read();
      int valeur = r1 | r2<<8;
      Serial.print("r1 = ");
      Serial.println(r1);
      Serial.print("r2 = ");
      Serial.println(r2);
      Serial.print("valeur = ");
      Serial.println(valeur);
  }
}

r1 = 0
r2 = 220
valeur = -9216
r1 = 0
r2 = 4
valeur = 1024

Bonjour wawann

et si tu fais:

      r = Wire.read()  <<8;
      r += Wire.read();

En lisant MSB puis LSB.

Cordialement
jpbbricole

Donc en fait tu ne reçois pas les 2 octets en une fois mais en 2 fois donc cela vaut peut-être le coup d'utiliser available et de tester si tu as bien reçu 2 octets.

Ou alors cette ligne n'envoie pas 1 seul octet mais 2.

Ok, alors en faisant :

Serial.print(Wire.available());

la commande retourne la valeur 2.

Et quand je désactive l'une ou l'autre des lignes bus.write

    data = 1244
    bus.write_byte_data(addr, 0, data & 0xFF)
    bus.write_word_data(addr, 0, (data & 0xFF)>>8)

la commande Serial.print(Wire.available()) retourne toujours 2...

Bonjour,

Ceci envoie 0
bus.write_word_data(addr, 0, (data & 0xFF)>>8)

Je suppose que tu veux faire
bus.write_word_data(addr, 0, (data>>8) & 0xFF)

Bonjour, bon voila le mystère est résolu... Merci à tous pour votre aide, conseil, remarques....
Voici les codes :

#CODE POUR RASPBERRY

from smbus 2 import SMBus
addr = 0x08

with SMBus(1) as bus:
   data = 43265
   bus.write_word_data(addr, 0, data)
   print ("transmit word")
   print (data)

et

// CODE POUR ARDUINO

#include <Wire.h>

void setup()
{
  Wire.begin(8);
  Wire.onReceive(reveiveEvent);
  Serial.begin(2000000);
}

void loop()
{
  delay(500)
}

void receiveEvent(int howMany)
{
  if (howMany > 0)
   {
      uint16_t r1 = Wire.read();
      uint16_t r2 = Wire.read();
      uint16_t r3 = Wire.read();
      uint16_t valeur = r2 | r3 <<8;
      Serial.print("valeur= ");
      Serial.println(valeur);
   }
}

Bonjour,
Je reviens sur ce sujet car quand je réalise mes tests, avec un raspberry qui récupère une valeur, qui la convertie et qui la transmet en I2C vers l'arduino, ça fonctionne pendant environ 20secondes, puis coté raspberry j'ai le message d'erreur :

Traceback (most recent call last):
  File "/home/pi/./speedsimulator.py", line 21, in <module>
    bus.write_word_data(addr, 0, data, force=None)                      #ecriture et transmission de la valeur OCR1A
  File "/home/pi/.local/lib/python3.9/site-packages/smbus2/smbus2.py", line 496, in write_word_data
    ioctl(self.fd, I2C_SMBUS, msg)
OSError: [Errno 121] Remote I/O error

que je ne sais pas interpréter. Auriez vous une idée du pourquoi ?

En vous remerciant.