Aller au contenu


Photo
- - - - -

[Arduino] I2C : réception par l'esclave


6 réponses à ce sujet

#1 Sandro

Sandro

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 1 260 messages
  • Gender:Male

Posté 09 mai 2020 - 03:03

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


Aidez-nous à vous aider : partagez toutes les informations pertinentes : description précise du problème, contexte, schéma de câblage, liens vers la documentation des composants, votre code (ou encore mieux un code minimal reproduisant le bug), ...

Vous recevrez ainsi plus de réponses, et elles seront plus pertinentes.


#2 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 959 messages
  • Gender:Male
  • Location:Anglet

Posté 09 mai 2020 - 04:34

Je pense que ça mériterait des tests ... 

Si on me posait la question comme ça je dirais ( en risquant de me tromper ) : 

1) lors de l'appel du handler oui les deux sont égaux

 

donc sur le principe si on ne reçoit pas plus d'info on pourrait faire une boucle for de 0 à howMany-1 plutôt qu'une boucle while basée sur des appels à Wire.available() ... Mais le truc c'est 3) 
 

2) je pars du principe que tout est possible 

3) je pense que le wire available augmente pendant que tu es dans le handler si tu reçois des infos . D'où l'utilité de faire un wire.available et de partir du principe que tout est possible ... 
Mais il est sans doute possible de fixer la chose ( toujours prendre que la taille que tu sais être bonne etc ... Et ça devrait marcher, a toi de voir si tu veux être plus carré / strict ou bien être plus agile / rapide  )

 

4) Il me semble qu'il y a une partie " stockage matérielle" dans un buffer, qui ne nécéssite pas d'intérruption, mais que le handler lui est une interruption dont le niveau de priorité peut dépendre de ton paramétrage.

 

5) Je pense que ça devrait marcher ... 

6) Un slave n'initie pas de discussion, c'est toujours le master qui demande quelque chose ... Sinon c'est le bordel, les slave pourraient couper la parole au master ou bien à un autre slave. Bref slave bête et discipliné => Dans le rang.

Maintenant à toi de me contredire si je dit une bêtise :P

 


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#3 Sandro

Sandro

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 1 260 messages
  • Gender:Male

Posté 09 mai 2020 - 06:35

Bon, merci.

Du coup, à voir si je pars sur du test ou sur une implémentation ou tout peut arriver.

Le problème du test, c'est qu'à priori on a une interruption, et du coup on ne peut jamais être sur que le code ait tout testé (ie l’interruption a-t-elle eut lieu pile à l'instant précis le plus défavorable).

 

 

Pour 6), je ne pensais pas à une situation où l’esclave parle quand il veut, mais où il répond dès qu'il est prêt.

 

Situation "classique" :

- le maitre envois des données pour dire ce qu'il veut

- l'esclave reçit ses données et prépare la réponse (pendant ce temps le maitre attend)

- le maitre continue à attendre pour être sur que le slave a eut le temps de faire ce qu'il devait

- le maitre demande à l'esclave de lui envoyer des données (ie ce qu'il a préparé)

- l'esclave envoi ces données. (le maitre attend)

- le maître reçoit les données.

 

 

Mais que ce passe-t-il si le maitre demande les données avant que l'esclave ne soit prêt?

Et le maître doit donc attendre plus longtemps que nécessaire la réponse.

 

Une solution plus optimisée serait la suivante :

- le maitre envoi une requête puis attend la réponse

- le slave reçoit la requête, la traite et renvoi la réponse

- le maitre reçoit la réponse (éventuellement avec timeout)


Aidez-nous à vous aider : partagez toutes les informations pertinentes : description précise du problème, contexte, schéma de câblage, liens vers la documentation des composants, votre code (ou encore mieux un code minimal reproduisant le bug), ...

Vous recevrez ainsi plus de réponses, et elles seront plus pertinentes.


#4 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 959 messages
  • Gender:Male
  • Location:Anglet

Posté 09 mai 2020 - 07:03

En fait en général le maitre envoit une requête en spécifiant des paramètres à sa requête, il laisse plus ou moins de temps aux slave de préparer sa réponse ( il peut par exemple préparer une autre requête pour un autre slave ) puis il envoit une micro requête pour dire vas y envoit la réponse et là il attends que le slave lui réponde ...  ( éventuellement avec timeout ) 
 


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#5 Sandro

Sandro

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 1 260 messages
  • Gender:Male

Posté 09 mai 2020 - 09:17

C'est l'impression que j'avais. Mais je trouve que le fait de devoir envoyer la seconde micro-requête (qui sera traité par une autre callback) complique un peu les choses. Mais bon, je ferais avec.


Aidez-nous à vous aider : partagez toutes les informations pertinentes : description précise du problème, contexte, schéma de câblage, liens vers la documentation des composants, votre code (ou encore mieux un code minimal reproduisant le bug), ...

Vous recevrez ainsi plus de réponses, et elles seront plus pertinentes.


#6 Mike118

Mike118

    Staff Robot Maker

  • Administrateur
  • PipPipPipPipPip
  • 9 959 messages
  • Gender:Male
  • Location:Anglet

Posté 10 mai 2020 - 12:02

Il est possible d'envoyer toujours que la même micro requêtes si tu as toujours la même chose à recevoir ... 


Si mon commentaire vous a plus laissez nous un avis  !  :thank_you:

Nouveau sur Robot Maker ? 

Jetez un oeil aux blogs, aux tutoriels, aux ouvrages, au robotscope  aux articles,  à la boutique  et aux différents services disponible !
En attendant qu'une bibliothèque de fichiers 3D soit mise en place n'hésitez pas à demander si vous avez besoin du fichier 3D d'un des produits de la boutique... On l'a peut être ! 
Si vous souhaitez un robot pilotable par internet n'hésitez pas à visiter www.vigibot.com et à lire le sous forum dédié à vigibot!

 

Les réalisations de Mike118  

 

 

 


#7 Sandro

Sandro

    Pilier du forum

  • Modérateur
  • PipPipPipPipPip
  • 1 260 messages
  • Gender:Male

Posté 10 mai 2020 - 12:26

A réfléchir. En soit j'aurais plusieurs infos à renvoyer, mais je pense que je peux tout grouper en une seule frame


Aidez-nous à vous aider : partagez toutes les informations pertinentes : description précise du problème, contexte, schéma de câblage, liens vers la documentation des composants, votre code (ou encore mieux un code minimal reproduisant le bug), ...

Vous recevrez ainsi plus de réponses, et elles seront plus pertinentes.




Répondre à ce sujet



  


0 utilisateur(s) li(sen)t ce sujet

0 members, 0 guests, 0 anonymous users