Projet

Général

Profil

Wiki » test-float-arduino.ino

Test envoi/réception de float sur le bus I2C (slave) - Tarek Benhnini, 16/12/2015 15:48

 
// ========================================================
// 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
}
}

(4-4/4)