Protocole I2C smbus2 communication vers Arduino
Bonjour,
Je souhaite transmettre des informations ( valeurs integer de 0 à 65535 ) en i2c d'un raspberry pi4 vers un arduino MEGA 2560.
J'ai installé smbus2 sur le raspberry et essayé les codes en exemple sur le net (notamment sur pypi.org), mais cela n'a pas l'air de fonctionner.
J'ai aussi bien activé l'i2c sur le rpi. Le cablage entre arduino et Rpi est aussi correct.
Pour info j'arrive bien a faire communiquer en i2c 2 arduinos.
le code utilisé est le suivant :
Code:
1 2 3 4 5
| from smbus2 import SMBus
with SMBus(1) as bus:
data = 45
bus.write_byte_data(8, 0, data) |
l'adresse attribuée à l'arduino est la 8. Est-ce qu'il y a quelque chose que j'aurai oublié ? un paramétrage du raspberry ? existe-t'il une commande qui me permette de vérifier que l'arduino est connecté au raspberry (i2c detect ?) ?
Merci pour votre aide.
raspberry protocole I2C smbus2 communication vers arduino
Bonjour,
Merci pour cette recommandation. Effectivement cela peut être embêtant.
En faisant i2cdetect -y 1 j'ai bien une réponse (tableau à moitié rempli) lorsque l'Arduino est connecté et tableau vide lorsqu'il n'est pas connecté. Mais ce n'est vraiment pas parlant...
Passer par le port série ne serait-il pas plus facile ?
raspberry protocole I2C smbus2 communication vers arduino
bah c'est que non, il n'y a rien à l'adresse 0x08,
mais peut-être qu'il n'est pas bien adressé coté Arduino...
dans mon code Arduino l'attribution des adresse est de la forme :
Code:
1 2
| wire.begin(8)
wire.request(8, ... ) |
8 étant pour moi l'adresse de l'équipement... mais le format n'est peut être pas bon coté Raspberry
raspberry protocole I2C smbus2 communication vers arduino
coté arduino, le code complet, avec la partie communication i2c dans le loop.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| #include <Wire.h>
#define LED_BUILTIN 12
//int pinState = LOW; // etat de la PIN qui sert a générer le signal carré
char prescaler[12]; // variable d'ajustement du prescaler en fonction de la valeur de frequence
unsigned short frequenceInt; // frequenceInt
void setup () {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(2000000); // terminal speed
pinMode (LED_BUILTIN, OUTPUT);
// ======================================================================================================================================================
// Paramétrage du timer1, pour qu'il déclenche une interruption, à chaque fois que sa valeur sera égale à celle qu'on aura indiqué dans le registre OCR1A
// ======================================================================================================================================================
noInterrupts(); // On désactive les interruptions, pour commencer
TCCR1A = 0b00000000;
//TCCR1B = 0b00001001; // TCCR1B = 0b00001001 pour desactiver prescaler et TCCR1B = 0b00001101 pour prescaler = 1024
TIMSK1 = 0b00000010;
bitSet(TIMSK1, OCIE1A); // On met le bit OCIE1A à 1 (contenu dans le registre TIMSK1)
// Enfin, on met le compteur à zéro, on entre la valeur déclenchant l'interruption (nos "31250" coups d'horloge), et on réactive les interruptions
TCNT1 = 0; // Mise du timer1 à zéro
interrupts(); // Et, on ré-active les interruptions
}
// ======================
// Routine d'interruption
// ======================
ISR(TIMER1_COMPA_vect) {
digitalWrite (LED_BUILTIN, !digitalRead(LED_BUILTIN));
TCCR1B = prescaler;
OCR1A = frequenceInt; // mise à jour de la valeur OCR1A en fonction de la valeur envoyée par arduino master (valeur OCR1A calculée en fonction de frequence horloge, prescaler)
}
// =================
// Boucle principale
// =================
void loop () {
Wire.requestFrom(8, 4); // request 6 bytes from peripheral device #8
unsigned long value = 0; // v = value
int i = 0;
while (Wire.available()) { // peripheral may send less than requested
unsigned long c = Wire.read(); // receive a byte and store it in unsigned long so it can be shifted later
value |= (c << (i*8)); // shift the received byte value and store it with the previous value
i++;
}
frequenceInt = value; // value
Serial.println(frequenceInt);
if (value<2430) {
char prescaler[12] = "0b00001101 ";
Serial.println("valeur inferieure à 2430");
Serial.println(prescaler);
}
else {
char prescaler[12] = "0b00001001 ";
Serial.println("valeur supérieure à 2430");
Serial.println(prescaler);
}
} |
raspberry protocole I2C smbus2 communication vers arduino
Le code utilisé pour la communication des arduino provient effectivement de ces sources... mais effectivement je n'ai pas pris en compte l'adresse pour l'arduino slave..
Cela étant, après mise à jour, la commande "i2cdetect -y 1" depuis le terminal du raspberry renvoie bien le tableau avec l'adresse de l'arduino connecté ( 08 ) ==> donc c'est top !
De la même manière, lorsque j'execute le programme d'envoie d'une valeur, le programme me renvoie " transmit " ==> donc ça aussi c'est top !
Par contre, l'arduino ne relit pas la valeur.. enfin pour l'instant. Certainement un problème de type...
En tout cas, merci pour vos conseils et remarques...
raspberry protocole I2C smbus2 communication vers arduino
Bonjour,
Donc l'arduino relit bien une valeur, mais c'est bizarre, quand je suis censé envoyer la valeur 45 depuis le rasperry, l'arduino relit plusieurs valeurs... mais pas 45..
Arduino MEGA 2560 W5500 réception variable par ethernet
Bonjour, en appliquant le code suivant, pour l'arduino 2560 Slave, ça fonctionne. J'envoie la valeur depuis le raspberry et la valeur s'affiche bien sur le moniteur de l'arduino !! cool !
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #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(100);
}
void receiveEvent(int howMany)
{
while(1 < Wire.available())
{
char c = Wire.read();
Serial.print(c);
}
int x = Wire.read();
Serial.println(x);
} |
Arduino MEGA 2560 W5500 réception variable par ethernet
Question,
comment puis-je faire pour transmettre des valeurs de 0 à 65350 ?
Merci.
raspberry protocole I2C smbus2 communication vers arduino
Merci pour vos réponses,
Après essai, le résultat semble similaire, c'est à dire que lorsque j'envoie des valeurs entre 0 et 255 il n'y a pas de soucis (je rappelle que les valeurs sont envoyés avec le programme python du raspberry).
programme d'envoie des valeurs :
Code:
1 2 3 4 5
| with SMBus(1) as bus:
data = 254
bus.write_byte_data(addr, 0, data)
data = 255
bus.write_word_data(addr, 0, data, force=None) |
par contre quand j'envoie des valeurs au dessus de 255 alors ça repart de 0.
par exemple, pour la valeur envoyée 1244, avec le code : ça me retourne les valeurs :
=> value = 220
=> value = 220
=> value = 65535
raspberry :
Code:
1 2 3 4 5
| with SMBus(1) as bus:
data = 1244
bus.write_byte_data(addr, 0, data)
data = 1244
bus.write_word_data(addr, 0, data, force=None) |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <Wire.h>
void setup()
{
Wire.begin(8);
Wire.onReceive(receiveEvent);
Serial.begin(2000000);
}
void loop()
{
delay(100);
}
void receiveEvent(int howMany)
{
while(Wire.available())
{
uint16_t value = Wire.read();
value |= Wire.read();
Serial.print("=> value = ");
Serial.println(value);
}
} |
en testant l'autre config, ça retourne :
=> value = 0
=> value = 56320
=> value = 0
=> value = 56320
=> value = 1024
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <Wire.h>
void setup()
{
Wire.begin(8);
Wire.onReceive(receiveEvent);
Serial.begin(2000000);
}
void loop()
{
delay(100);
}
void receiveEvent(int howMany)
{
while(Wire.available())
{
uint16_t value = Wire.read();
value = value << 8;
Serial.print("=> value = ");
Serial.println(value);
}
} |
Je ne sais pas trop quoi en penser...
raspberry protocole I2C smbus2 communication vers arduino
Bonjour,
Merci pour vos commentaires.
Bon j'ai maintenant bien compris la problématique, mais la ou je bloque c'est comment identifier le 1er byte et le 2d byte dans le message reçu. En effet lorsque je code :
Code:
1 2 3 4 5 6
| void receiveEvent(int howMany)
{
uint16_t r=0;
r = Wire.read();
r = uint16_t(Wire.read());
Serial.println(r); |
je reçois bien les valeurs 220 et 4 et correspondent bien à ce qui est écrit précédemment ... 220 : 1101 1100 et 4 : 0100
et effectivement j'aimerai bien faire 4 | 220 pour obtenir 0000 0100 1101 1100 qui correspond en décimal à la valeur envoyée soit 1244
la ou je galère maintenant c'est "comment identifier et différencier 220 et 4 ??" car en effet je n'arrive pas à écrire seulement 220 ou seulement 4. Le code me renvoi a chaque fois les 2 valeurs, du coup je n'arrive pas à effectuer le 4 | 220... je pense que ça ne doit pas être compliqué, mais pour moi ... cela étant je continue de chercher. Merci et bonne journée.
Arduino MEGA 2560 W5500 réception variable par ethernet
Peut-on utiliser un paramètre pour : " Wire.available() " afin de sélectionner un byte spécifique ? ou bien avec " Wire.onReceive() " ?
Merci.
Arduino MEGA 2560 W5500 réception variable par ethernet
Bonjour,
Je continue a chercher, sans encore arriver à obtenir la valeur de départ. Avec ce code :
Code:
1 2 3 4 5 6 7 8 9 10 11
|
voir receiveEvent(int howMany)
{
if(howMany == 2)
{
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
Serial.println(valeur);
}
} |
rien ne correspondant a ma valeur de départ qui est 1244... enfin je n'arrive pas a recoller les morceaux...