Transmettre un Float/Double par I2C entre Arduino et Raspberry
Nous avons complété notre tutoriel de communication I2C entre Raspberry et Arduino.... cette fois nous nous sommes penchés sur le transport des valeurs décimales.
Tutoriel ArduPi - communication I2C entre Raspberry et Adruino |
Ce complément de tutoriel fut créé pour répondre au besoin spécifique d'un client ayant besoin d'envoyer la température d'une sonde DS18B20 d'un Arduino vers Raspberry-Pi via le bus I2C.
Ce tuto met également en oeuvre le concept des registres sur un Arduino (abordé dans ce tutoriel sur I2C) et déjà exploité dans l'exemple des registres ci-avant.
Dans le tutoriel:
- Raspberry Pi est le MASTER WRITER
Pi est donc le maître de la communication envoyant ses instructions. - Arduino est le SLAVE LISTENER (esclave qui écoute)
Il attend donc les instructions envoyée sur le bus I2C.
Détail du raccordement entre Raspberry Pi et Arduino dans notre tutoriel ArduPi-I2C |
La réponse se trouve ci-dessous (et en détail dans notre tutoriel)?
Côté Arduino
L'envoi d'une valeur décimale (ex: 5.67) se fait à l'aide du type double qui est décomposé en 4 octets.
double valeurDouble; ... valeurDouble = 123.57; Wire_SendDouble( &valeurDouble );
La magie se passe dans la fonction Wire_SendDouble().
La fonction Wire_SendDouble() utilise un struct de type union entre double et byte[4]. Cela permet d'accéder à un même espace mémoire de feux façons différentes:
Les 4 octets/bytes sont accessibles comme un tableau... ou un buffer. Il est donc possible d'utiliser directement la méthode Wire.write() pour envoyer le buffer de 4 octets de long sur le bus I2C.
// Fonction outil décomposant un double en array de Bytes // et envoyant les données sur le bus I2C // // Basé sur le code obtenu ici: // 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 meme espace // memoire union Sharedblock { byte part[4]; // utiliser char parts[4] pour port série double data; } mon_block; mon_block.data = *d; /* pour... mon_block.data = 5.67 le tableau part[x] vaut... mon_block.part[0] = 164; mon_block.part[1] = 112; mon_block.part[2] = 181; mon_block.part[3] = 64; Ce sont les valeurs que l'on doit retrouver de l'autre cote du BUS I2C */ Wire.write( mon_block.part, 4 ); }
La fonction Wire_SendDouble() utilise un struct de type union entre double et byte[4]. Cela permet d'accéder à un même espace mémoire de feux façons différentes:
- une fois pour y stocker une valeur sous le type double,
- Une autres fois pour lire chacun des bytes/octets (tronçons de 8 bits) composant ce "type double" qui stock la valeur numérique.
Les 4 octets/bytes sont accessibles comme un tableau... ou un buffer. Il est donc possible d'utiliser directement la méthode Wire.write() pour envoyer le buffer de 4 octets de long sur le bus I2C.
Côté Raspberry-Pi
En s'appuyant sur la librairie Adafruit_I2C, la réception des bytes se résume à une simple instruction
Et quelques instructions plus loin, la transformation en valeur décimale est presque tout aussi simple:
Tutoriel complet
MCHobby investi du temps et de l'argent dans la réalisation de traduction et/ou documentation. C'est un travail long et fastidieux réalisé dans l'esprit Open-Source... donc gratuit et librement accessible. SI vous aimez nos traductions et documentations ALORS aidez nous à en produire plus en achetant vos produits chez MCHobby.
En s'appuyant sur la librairie Adafruit_I2C, la réception des bytes se résume à une simple instruction
import time import struct from Adafruit_I2C import Adafruit_I2C i2c = Adafruit_I2C( 0x04 ) # --- Demander une valeur décimale --- # Transfert d'un type DOUBLE # demander l'opération de reception d'un float, placer 0x02 dans le # le registre d'exécution 0 i2c.write8( 0x00, 0x02 ) time.sleep(0.100) i2c.debug = True # Lire 4 octets pour recevoir le Float. # Doit recevoir les valeurs [164, 112, 181, 64] # lstData = i2c.readList( 0x00, 4 )
Et quelques instructions plus loin, la transformation en valeur décimale est presque tout aussi simple:
# transformer en string pour unpack sData = '' for aByte in lstData: sData = sData + chr(aByte) f_data, = struct.unpack('<f',sData) print f_data # Affiche la valeur en Float.
Tutoriel complet
- Notre tutoriel ArduPi-I2C complet est accessible sur notre Wiki.
- La transmission de double et/ou float est traité en détail dans cette section.
MCHobby investi du temps et de l'argent dans la réalisation de traduction et/ou documentation. C'est un travail long et fastidieux réalisé dans l'esprit Open-Source... donc gratuit et librement accessible. SI vous aimez nos traductions et documentations ALORS aidez nous à en produire plus en achetant vos produits chez MCHobby.
Écrire un commentaire