Bonjour,
j'aurais quelques questions sur ce qui se passe exactement lors de la réception de données par un arduino escalve I2C.
Comme base, voici l'exemple Wire/slave_receiver fourni avec l'IDE arduino :
#include <Wire.h> void setup() { Wire.begin(8); // join i2c bus with address #8 Wire.onReceive(receiveEvent); // register event Serial.begin(9600); // start serial for output } void loop() { delay(100); } // function that executes whenever data is received from master // this function is registered as an event, see setup() void receiveEvent(int howMany) { while (1 < Wire.available()) { // loop through all but the last char c = Wire.read(); // receive byte as a character Serial.print(c); // print the character } int x = Wire.read(); // receive byte as an integer Serial.println(x); // print the integer }
Ce qui a attiré mon attention, c'est qu'on ne tient pas compte de la valeur "howMany", mais qu'on utilise Wire.available à la place.
Cela soulève un certain nombre de questions, dont la documentation très restreinte de Wire.onReceive (https://www.arduino....e/WireOnReceive) et de Wire.available (https://www.arduino.cc/en/Reference/WireAvailable) ne donnent pas la réponse :
1) est-ce que Wire.available() est forcément égal à howMany tant qu'on n'a rien lu (dans ce cas, on peut faire une boucle for de 0 à howMany-1 plutôt qu'une boucle while basée sur des appels à Wire.available()
2) est-ce que receiveEvent est appellé à la fin d'une transmission, ou dès qu'au moins un octet est transmit. Si par exemple je transmet par paquets de 5 octets, est ce que je peux être sur que (sauf erreur de communication), j'ai exactement 5 octets à chaque fois? Ou est-ce que je peux avoir par exemple que 3 octets, et 2 autres qui suivent? Ou inversement, avoir 10 octets d'un coup?
3) que ce passe-t-il si un nouveau paquet de données arrive avant qu'on ait quitté la fonction onReceive? les données sont t'elles perdues? Ou disponibles immédiatement (ie Wire.available augmente)? Ou disponibles après la fin de la fonction receiveEvent?
4) Comme se comporte receiveEvent par rapport aux interruptions? Est-ce que c'est une interruption? Est-ce qu'elle bloque les autres interruptions? Que ce passe-t-il si on reçoit des données pendant qu'une autre interruption est en cours?
5) est-ce que je peux me passer de l'évènement "onReceive" et simplement regarder s'il y a des données dispo (avec Wire.available) et les lire avec Wire.read depuis où je veux et quand je veux? (la doc semble dire qu'on est sensé utiliser Wire.available depuis onReceive
Et une question un peu moins liée:
6) est-ce que je peux faire un Wire.write depuis le slave ailleurs que dans onRequest? (le but étant de pouvoir répondre directement aux demandes de lectures de valeurs, plutôt que de devoir préparer les données lors de la reception des infos sur quoi lire puis de les envoyer lors de la requête d'envoi)
Le but de toutes ces questions : construire mon propre "protocole" basé sur l'I2C pour communiquer entre mon raspi et les 8 Atmega328P (microcontroleurs d'arduino) qui controlent les moteurs de mon robot de spéléo.
Une approche "simple" serait de supposer que tout se passe bien, qu'il n'y a jamais d'erreur de transmission et que j'ai toujours le temps de finir de traiter un paquet de données avant l'arrivée du suivant.
Ça marchera bien 99% du temps (enfin, je pense, c'était le cas quand j'ai fait quelque chose de similaire avec de l'uart via USB), mais de temps à autre ça coince : je voudrais donc dessuite partir sur quelque chose de robuste