Différences entre versions de « ArduPi-I2C-Registre-CodeArduino »
Ligne 23 : | Ligne 23 : | ||
N'oubliez pas d'ouvrir le moniteur série d'Arduino, car une communication série est initialisée pour permettre l'affichage de quelques informations utiles. | N'oubliez pas d'ouvrir le moniteur série d'Arduino, car une communication série est initialisée pour permettre l'affichage de quelques informations utiles. | ||
− | <nowiki></nowiki> | + | {{ambox-stop|text=Avant de démarrer le programme MasterRegisterWriter.py sur votre Raspberry, assurez-vous de voir le message "Bus I2C pret" apparaitre sur le moniteur série d'Arduino IDE.}} |
+ | |||
+ | <nowiki>// === ArduPi-I2C ================================================ | ||
+ | // Communication entre Arduino et Raspberry Pi via le BUS I2C | ||
+ | // =============================================================== | ||
+ | // Tutoriel: http://mchobby.be/wiki/index.php?title=ArduPi-I2C | ||
+ | // | ||
+ | // Programme Esclave qui Recoit les données données envoyées par Raspberry Pi | ||
+ | // S'utilise avec le programme Arduino MasterRegisterWriter.py | ||
+ | // | ||
+ | // Ce programme attend des instructions dans le registre de commande | ||
+ | // registre 0x00: registre d'exécution (commande a exécuter) | ||
+ | // commande 0x00 - nop | ||
+ | // Commande 0x01 - demande de numero de version (retourne un byte) | ||
+ | // Commande 0x02 - Addition. Additionne les valeurs du registre 0x01 et 0x02 | ||
+ | // retourne un byte. | ||
+ | // Commande 0x03 - Allume/eteind led Pin 13 en fonction de la valeur du registre 0x01 (1 ou 0) | ||
+ | // registre 0x01: opérant 1 pour addition POUR instruction exec = 0x02 | ||
+ | // Status Pin 13 (allumé/éteind) POUR instruction exe = 0x03 | ||
+ | // registre 0x02: opérant 2 pour addition | ||
+ | // | ||
+ | // Ecrit par D. Meurisse pour MCHobby.be | ||
+ | // www.mchobby.be - Vente de kit et composant Arduino et Raspberry Pi | ||
+ | // Licence CC-BY-SA | ||
+ | // | ||
+ | // Basé sur l'exemple de Nicholas Zambetti <http://www.zambetti.com> | ||
+ | // | ||
+ | #include <Wire.h> | ||
+ | |||
+ | // déclaration des registres | ||
+ | byte regs[3]; | ||
+ | int regIndex = 0; // Registre à lire ou à écrire. | ||
+ | |||
+ | // copie de la dernière instruction d execution écrite dans | ||
+ | // le registre reg0 pour le traitement asynchrone de | ||
+ | // requestEvent (demande de bytes) | ||
+ | byte lastExecReq = 0x00; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | // Initialisation des registres | ||
+ | regs[0] = 0x00; // reg0 = registre d'exécution | ||
+ | // valeur 0x00 = NOP - No Operation = rien à faire | ||
+ | regs[1] = 0x00; | ||
+ | regs[2] = 0x00; | ||
+ | |||
+ | // Joindre le Bus I2C avec adresse #4 | ||
+ | Wire.begin(4); | ||
+ | // enregistrer l'événement | ||
+ | // Lorsque des données sont écrites par le maitre et reçue par l'esclave | ||
+ | Wire.onReceive(receiveEvent); | ||
+ | // enregistrer l'événement | ||
+ | // Lorsque le Maitre demande de lecture de bytes | ||
+ | Wire.onRequest(requestEvent); | ||
+ | |||
+ | // Démarrer une communication série | ||
+ | Serial.begin(19200); | ||
+ | Serial.println( F("Bus I2C pret") ); | ||
+ | |||
+ | // Definir la broche 13 en sortie | ||
+ | pinMode( 13, OUTPUT ); | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | // Si NOP alors rien à faire | ||
+ | if( regs[0] == 0x00 ) { | ||
+ | delay(100); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | // Exécution de l'opération | ||
+ | /* Serial.println( F("--- Traitement Requete ---") ); | ||
+ | Serial.print( F("reg0 = ") ); | ||
+ | Serial.println( regs[0], DEC ); | ||
+ | Serial.print( F("reg1 = ") ); | ||
+ | Serial.println( regs[1], DEC ); | ||
+ | Serial.print( F("reg2 = ") ); | ||
+ | Serial.println( regs[2], DEC ); | ||
+ | */ | ||
+ | |||
+ | switch( regs[0] ){ | ||
+ | case 0x01 : // demande de version (rien à faire) | ||
+ | break; | ||
+ | case 0x02 : // demande d'addition (rien à faire, l'addition est exécutée à la demande de réponse) | ||
+ | break; | ||
+ | case 0x03 : // Activer/désactiver Pin 13 en fct de la valeur du registre 0x01 | ||
+ | if( regs[1] > 0 ) | ||
+ | digitalWrite( 13, HIGH ); | ||
+ | else | ||
+ | digitalWrite( 13, LOW ); | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | // reset to NOP | ||
+ | regs[0] = 0x00; | ||
+ | } | ||
+ | |||
+ | // Fonction qui est exécutée lorsque des données sont envoyées par le Maître. | ||
+ | // Cette fonction est enregistrée comme une événement ("event" en anglais), voir la fonction setup() | ||
+ | void receiveEvent(int howMany) | ||
+ | { | ||
+ | int byteCounter = 0; | ||
+ | |||
+ | // Pour faire du debug... mais attention cela peut planter | ||
+ | // la réception! | ||
+ | // | ||
+ | //Serial.println(F("---- LECTURE ---")); | ||
+ | //Serial.print(F("Numbre de Bytes: ")); | ||
+ | //Serial.println( howMany ); | ||
+ | |||
+ | // Lire tous les octets sauf le dernier | ||
+ | while( byteCounter < howMany ) | ||
+ | { | ||
+ | // lecture de l'octet | ||
+ | byte b = Wire.read(); | ||
+ | byteCounter += 1; | ||
+ | |||
+ | //Serial.println( b, DEC ); | ||
+ | |||
+ | if( byteCounter == 1 ){ // Byte #1 = Numéro de registre | ||
+ | regIndex = b; | ||
+ | } | ||
+ | else { // Byte #2 = Valeur a stocker dans le registre | ||
+ | switch(regIndex) { | ||
+ | case 0: | ||
+ | regs[0] = b; | ||
+ | // maintenir une copie du dernier reg0 pour | ||
+ | // traitement d'une réponse via requestEvent (demande de byte) | ||
+ | lastExecReq = b; | ||
+ | break; | ||
+ | case 1: | ||
+ | regs[1] = b; | ||
+ | break; | ||
+ | case 2: | ||
+ | regs[2] = b; | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | } // fin WHILE | ||
+ | } | ||
+ | |||
+ | // Fonction est activé lorsque le Maitre fait une demande de lecture. | ||
+ | // | ||
+ | void requestEvent() | ||
+ | { | ||
+ | // Deboggage - Activer les lignes suivantes peut perturber fortement | ||
+ | // l'échange I2C... a utiliser avec circonspection. | ||
+ | // | ||
+ | // Serial.print( "Lecture registre: " ); | ||
+ | // Serial.println( regIndex ); | ||
+ | |||
+ | // Quel registre est-il lu??? | ||
+ | switch( regIndex ){ | ||
+ | |||
+ | case 0x00: // lecture registre 0 | ||
+ | // la réponse depend de la dernière opération d'exécution demandée | ||
+ | // par l'intermédiaire du registre d'exécution (reg 0x00). | ||
+ | switch( lastExecReq ) { | ||
+ | case 0x01: // demande de version | ||
+ | // current version = v3 | ||
+ | Wire.write( 0x03 ); | ||
+ | break; | ||
+ | |||
+ | case 0x02: // Addition reg1 + reg2 | ||
+ | Wire.write( regs[1]+regs[2] ); | ||
+ | break; | ||
+ | |||
+ | default: | ||
+ | Wire.write( 0xFF ); // ecrire 255 = il y a un problème! | ||
+ | } | ||
+ | break; | ||
+ | |||
+ | default: // lecture autre registre | ||
+ | Wire.write( 0xFF ); // ecrire 255 = il y a un problème | ||
+ | } | ||
+ | |||
+ | }</nowiki> | ||
{{ArduPi-I2C-TRAILER}} | {{ArduPi-I2C-TRAILER}} |
Version actuelle datée du 15 avril 2013 à 20:17
Arduino
Voici ensuite le programme Arduino.
Cette fois-ci, il est sensiblement plus compliqué car il implémente un système de registre de façon logiciel.
Comme déjà précisé, c'est un Slave Listener (esclave qui écoute). Il reçoit des informations en provenance du Raspberry-Pi sur le bus I2C.
Programme SlaveRegister
Le programme Arduino fonctionne comme suit:
- Il reçoit un avis de transmission d'instruction par l'intermédiaire de l'évènement receiveEvent
(lorsque le maître "Raspberry" envoi des données).- Il s'agit d'instructions permettant de stocker une valeur dans un des registres.
- De surcroît le stockage dans le registre 0x00 déclenche l'exécution de tâches
particulières (par exemple l'activation de la LED). - Finalement, on mémorisé également le premier octet dans la variable regIndex
ce premier octet c'est N° du registre ;-)
- Les demandes de lecture de registres est composé de deux évènements distinct:
- La réception d'une instruction via receiveEvent réduite à un seul octet
qui est le numéro de registre à lire.
Ce numéro sera stocké dans la variable regIndex (voir ci-dessus). - La demande de lecture d'octet par le maître est intercepté par
l'évènement requestEvent qui renverra l'information demandée. - Il va de soit que le maître (Raspberry Pi) doit demander le bon nombre d'octets.
- La réception d'une instruction via receiveEvent réduite à un seul octet
N'oubliez pas d'ouvrir le moniteur série d'Arduino, car une communication série est initialisée pour permettre l'affichage de quelques informations utiles.
Avant de démarrer le programme MasterRegisterWriter.py sur votre Raspberry, assurez-vous de voir le message "Bus I2C pret" apparaitre sur le moniteur série d'Arduino IDE. |
// === ArduPi-I2C ================================================ // Communication entre Arduino et Raspberry Pi via le BUS I2C // =============================================================== // Tutoriel: http://mchobby.be/wiki/index.php?title=ArduPi-I2C // // Programme Esclave qui Recoit les données données envoyées par Raspberry Pi // S'utilise avec le programme Arduino MasterRegisterWriter.py // // Ce programme attend des instructions dans le registre de commande // registre 0x00: registre d'exécution (commande a exécuter) // commande 0x00 - nop // Commande 0x01 - demande de numero de version (retourne un byte) // Commande 0x02 - Addition. Additionne les valeurs du registre 0x01 et 0x02 // retourne un byte. // Commande 0x03 - Allume/eteind led Pin 13 en fonction de la valeur du registre 0x01 (1 ou 0) // registre 0x01: opérant 1 pour addition POUR instruction exec = 0x02 // Status Pin 13 (allumé/éteind) POUR instruction exe = 0x03 // registre 0x02: opérant 2 pour addition // // Ecrit par D. Meurisse pour MCHobby.be // www.mchobby.be - Vente de kit et composant Arduino et Raspberry Pi // Licence CC-BY-SA // // Basé sur l'exemple de Nicholas Zambetti <http://www.zambetti.com> // #include <Wire.h> // déclaration des registres byte regs[3]; int regIndex = 0; // Registre à lire ou à écrire. // copie de la dernière instruction d execution écrite dans // le registre reg0 pour le traitement asynchrone de // requestEvent (demande de bytes) byte lastExecReq = 0x00; void setup() { // Initialisation des registres regs[0] = 0x00; // reg0 = registre d'exécution // valeur 0x00 = NOP - No Operation = rien à faire regs[1] = 0x00; regs[2] = 0x00; // Joindre le Bus I2C avec adresse #4 Wire.begin(4); // enregistrer l'événement // Lorsque des données sont écrites par le maitre et reçue par l'esclave Wire.onReceive(receiveEvent); // enregistrer l'événement // Lorsque le Maitre demande de lecture de bytes Wire.onRequest(requestEvent); // Démarrer une communication série Serial.begin(19200); Serial.println( F("Bus I2C pret") ); // Definir la broche 13 en sortie pinMode( 13, OUTPUT ); } void loop() { // Si NOP alors rien à faire if( regs[0] == 0x00 ) { delay(100); return; } // Exécution de l'opération /* Serial.println( F("--- Traitement Requete ---") ); Serial.print( F("reg0 = ") ); Serial.println( regs[0], DEC ); Serial.print( F("reg1 = ") ); Serial.println( regs[1], DEC ); Serial.print( F("reg2 = ") ); Serial.println( regs[2], DEC ); */ switch( regs[0] ){ case 0x01 : // demande de version (rien à faire) break; case 0x02 : // demande d'addition (rien à faire, l'addition est exécutée à la demande de réponse) break; case 0x03 : // Activer/désactiver Pin 13 en fct de la valeur du registre 0x01 if( regs[1] > 0 ) digitalWrite( 13, HIGH ); else digitalWrite( 13, LOW ); break; } // reset to NOP regs[0] = 0x00; } // Fonction qui est exécutée lorsque des données sont envoyées par le Maître. // Cette fonction est enregistrée comme une événement ("event" en anglais), voir la fonction setup() void receiveEvent(int howMany) { int byteCounter = 0; // Pour faire du debug... mais attention cela peut planter // la réception! // //Serial.println(F("---- LECTURE ---")); //Serial.print(F("Numbre de Bytes: ")); //Serial.println( howMany ); // Lire tous les octets sauf le dernier while( byteCounter < howMany ) { // lecture de l'octet byte b = Wire.read(); byteCounter += 1; //Serial.println( b, DEC ); if( byteCounter == 1 ){ // Byte #1 = Numéro de registre regIndex = b; } else { // Byte #2 = Valeur a stocker dans le registre switch(regIndex) { case 0: regs[0] = b; // maintenir une copie du dernier reg0 pour // traitement d'une réponse via requestEvent (demande de byte) lastExecReq = b; break; case 1: regs[1] = b; break; case 2: regs[2] = b; break; } } } // fin WHILE } // Fonction est activé lorsque le Maitre fait une demande de lecture. // void requestEvent() { // Deboggage - Activer les lignes suivantes peut perturber fortement // l'échange I2C... a utiliser avec circonspection. // // Serial.print( "Lecture registre: " ); // Serial.println( regIndex ); // Quel registre est-il lu??? switch( regIndex ){ case 0x00: // lecture registre 0 // la réponse depend de la dernière opération d'exécution demandée // par l'intermédiaire du registre d'exécution (reg 0x00). switch( lastExecReq ) { case 0x01: // demande de version // current version = v3 Wire.write( 0x03 ); break; case 0x02: // Addition reg1 + reg2 Wire.write( regs[1]+regs[2] ); break; default: Wire.write( 0xFF ); // ecrire 255 = il y a un problème! } break; default: // lecture autre registre Wire.write( 0xFF ); // ecrire 255 = il y a un problème } }
Ecrit par Meurisse D. pour mchobby.be
Toute référence, mention ou extrait de cette traduction doit être explicitement accompagné du texte suivant : « Traduction par MCHobby (www.MCHobby.be) - Vente de kit et composants » avec un lien vers la source (donc cette page) et ce quelque soit le média utilisé.
L'utilisation commercial de la traduction (texte) et/ou réalisation, même partielle, pourrait être soumis à redevance. Dans tous les cas de figures, vous devez également obtenir l'accord du(des) détenteur initial des droits. Celui de MC Hobby s'arrêtant au travail de traduction proprement dit.