|
// ========================================================
|
|
// Communication Arduino et Raspberry Pi via le bus I2C
|
|
// ========================================================
|
|
//
|
|
// S'utilise avec le programme test-float-raspi.py
|
|
// Ce programme attend des instructions dans le registre de commande
|
|
// registre 0x00: registre d'exécution (commande à exécuter)
|
|
// commande 0x00 - nop
|
|
// commande 0x01 - demande de numéro de version (retourne un octet) -- non utilisé
|
|
// commande 0x02 - retourne un float avec la valeur 5.67
|
|
// commande 0x03 -
|
|
// registre 0x01: opérant 1 - non utilisé ici
|
|
// registre 0x02: opérant 2 - non utilisé ici
|
|
|
|
# include <Wire.h>
|
|
|
|
// déclaration des registrs
|
|
byte regs[3];
|
|
int regIndex = 0; // registre à lire ou à écrire
|
|
|
|
// copie de la dernière instruction d'exécution écrite dans
|
|
// le registre reg0 pour le traitement asynchrone de
|
|
// requestEvent (demande de bytes)
|
|
|
|
void setup() {
|
|
// put your setup code here, to run once:
|
|
// 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 l'adresse #4
|
|
Wire.begin(4)
|
|
// Enregistrer l'évènement: lorsque des données sont écrites par la raspi (maître)
|
|
Wire.onReceive(receiveEvent);
|
|
// Enregistrer l'évènement: lorsqu'il y a demande de lecture de bytes par la raspi
|
|
Wire.onRequest(requestEvent);
|
|
|
|
// Démarrer une communication série
|
|
Serial.begin(9600);
|
|
Serial.println( F("Bus I2C pret") );
|
|
|
|
}
|
|
|
|
void loop() {
|
|
// put your main code here, to run repeatedly:
|
|
// Si NOP alors rien à faire
|
|
if( regs[0] == 0x00 ) {
|
|
delay(100);
|
|
return;
|
|
}
|
|
|
|
// Exécution de l'opération
|
|
/* Serial.println( F("--- Traitement Requete ---") );
|
|
* Serial.println( F("reg0 = ") );
|
|
* Serial.print( regs[0], DEC );
|
|
* Serial.println( F("reg1 = ") );
|
|
* Serial.print( regs[1], DEC );
|
|
* Serial.println( F("reg2 = ") );
|
|
* Serial.print( regs[2], DEC );
|
|
*/
|
|
|
|
// reset to NOP
|
|
regs[0] = 0x00;
|
|
}
|
|
|
|
// Fonction qui est exécutée lorsque des données sont envoyées par la raspi
|
|
// Cette fonction est enregistrée comme un évènement, cf la fonction setup()
|
|
void receiveEvent(int howMany)
|
|
{
|
|
int byteCounter = 0;
|
|
|
|
// Debug
|
|
/* Serial.println( F("--- READING ---") );
|
|
* Serial.println( F("Nombre d'octets") );
|
|
* 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 à 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;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// Fonction outil décomposant un double en array de bytes
|
|
// et envoyant les données sur le bus I2C
|
|
// Basé sur le code: http://stackoverflow.com/questions/12664826/sending-float-type-data-from-arduino-to-python
|
|
|
|
void Wire_SendDouble (double *, d) {
|
|
|
|
// Permet de partager deux types distinct sur un même espace mémoire
|
|
union Sharedblock {
|
|
byte part[4]; / utiliser char parts[4] pour port série
|
|
double data;
|
|
} mon_bloc;
|
|
|
|
mon_bloc.data = *d;
|
|
|
|
/* pour mon_bloc.data = 5.67
|
|
* le tableau part[x] vaut
|
|
* mon_bloc.part[0] = 164;
|
|
* mon_bloc.part[1] = 112;
|
|
* mon_bloc.part[2] = 181;
|
|
* mon_bloc.part[3] = 64;
|
|
* Ce sont les valeurs qui seront envoyées sur le bus I2C, on doit les retrouver sur la raspi
|
|
*/
|
|
|
|
Wire.write( mon_bloc.part, 4);
|
|
}
|
|
|
|
double valeurDouble;
|
|
|
|
// Fonction activée lorsque la raspi fait une demande de lecture
|
|
|
|
void requestEvent() {
|
|
/*Debug (warning: peut perturber l'échange I2C fortement)
|
|
* Serial.println ( "Lecture registre: ");
|
|
* Serial.println( regIndex );
|
|
*/
|
|
|
|
// Quel registre est-il lu ?
|
|
switch( regIndex ) {
|
|
|
|
case 0x00: // lecture registre 0
|
|
// la réponse dépend de la dernière opération d'exécution demandée
|
|
// par l'intermédiaire du registre d'exécution 0x00
|
|
switch( lastExecReq ) {
|
|
case 0x01: // demande de version
|
|
Wire.write( 0x11 );
|
|
break;
|
|
|
|
case 0x02: // retourne un float
|
|
valeurDouble = 5.67;
|
|
// décompose la valeur en bytes et l'envoie sur l'I2C
|
|
Wire_SendDouble( &valeurDouble );
|
|
break;
|
|
default:
|
|
Wire.write( 0xFF ); // écrire 255 --> il y a un problème
|
|
}
|
|
break;
|
|
default: // lecture autre registre
|
|
Wire.write( 0xFF ); // écrire 255 --> re problème
|
|
}
|
|
|
|
}
|
|
|