Lire les informations du contrôleur T’REX
Protocole de communication avec le T’REX
Le bus I²C nous permet d’échanger une série d’octet entre 2 cartes, mais ne propose pas de protocole de communication à proprement parler. Le code d’exemple du T’REX propose un protocole pour la réception d’informations :
Le T’REX peut transmettre 24 octets qui contient :
- Un indicateur d’erreur
- La tension de la batterie
- L’intensité des moteurs
- Le compteur des encodeurs (non installés par défaut sur le Wild Thumper)
- Les informations brutes de l’accéléromètre
- Une détection d’impact
Certaines de ces informations sont contenues sur 16 bits. Nous devons combiner deux octets pour récupérer la valeur.
Octet | Nom | Position | Description |
---|---|---|---|
1 | Start byte | Cet octet doit être 0x0F (15 décimal) | |
2 | Error flag | 0x00 indique qu’il n’y a pas d’erreur. Sinon, il faut regarder le/les bits qui sont à 1 :
|
|
3 | Battery voltage | High byte | Un entier qui correspond à la tension de la batterie x 100, en volt. Par exemple, une valeur de 1527 correspond à 15,27V |
4 | Low byte | ||
5 | Left motor current | High byte | Intensité utilisée par les moteurs gauche, en mA |
6 | Low byte | ||
7 | Left encoder count | High byte | Valeur de l’encodeur du côté gauche (D6). En activant le frein gauche avec la vitesse gauche à 0, cette valeur se réinitialise |
8 | Low byte | ||
9 | Right motor current | High byte | Intensité utilisée par les moteurs droit, en mA |
10 | Low byte | ||
11 | Right encoder count | High byte | Valeur de l’encodeur du côté droit (D5). En activant le frein droit avec la vitesse droite à 0, cette valeur se réinitialise |
12 | Low byte | ||
13 | Accelerometer X-axis | High byte | Données brutes de l’accéléromètre qui peut être utilisée pour déterminer l’angle et l’accélération du robot |
14 | Low byte | ||
15 | Accelerometer Y-axis | High byte | |
16 | Low byte | ||
17 | Accelerometer Z-axis | High byte | |
18 | Low byte | ||
19 | Impact X-axis | High byte | La carte lit les valeurs de l’accéléromètre toutes les 2 ms pour déterminer s’il y a un changement significatif de valeur. Si un impact est détecté, l’octet correspondant à l’axe concerné change de valeur. |
20 | Low byte | ||
21 | Impact Y-axis | High byte | |
22 | Low byte | ||
23 | Impact Z-axis | High byte | |
24 | Low byte |
Communication avec Python
Dans cet article je fais souvent référence au protocole I²C, mais l’implémentation que l’on rencontre sur les systèmes monocartes sous Linux (Raspberry Pi, BeagleBone Black, etc.) est plutôt un dérivé de ce protocole nommée SMBus. Les différences essentielles sont des limitations dans les tensions autorisées (3.3V max) ou les fréquences de communication (10 à 100 kHz seulement).
Pigpio
Il existe une bibliothèque Python (python-smbus
) permettant d’utiliser directement le protocole dans un script Python. Mais avec cette bibliothèque, je n’ai pas réussi à récupérer les 24 octets de statut. J’ai contourné ce problème en utilisant la bibliothèque pigpio
Pour l’installer, il faut installer les paquets suivants :
sudo apt-get update sudo apt-get install pigpio python-pigpio python3-pigpio
Pour vérifier qu’il s’est bien installé, on vérifie la version :
pigpiod -v
Il faut que le daemon pigpiod soit démarré pour pouvoir l’utiliser. On peut soit la démarrer manuellement avec
sudo pigpiod
ou le lancer au démarrage du système avec
sudo systemctl enable pigpiod
Source :
http://abyz.me.uk/rpi/pigpio/download.html
Le code
#!/usr/bin/python # -*- coding: utf-8 -*- from __future__ import division # Pour division float import pigpio # Cablage TREX_ADDRESS = 0x07 SDA=2 # Pin no 3 SCL=3 # Pin no 5 # Connexion de pigpiod pigpio = pigpio.pi() # Connect to Pi. def __trex_status(): ''' Envoi une requête de statut au T'REX Retourne une liste d'octet ''' # Vérification de la connexion de pigpiod if not pigpio.connected: exit(0) # Préparation de la requête Bit Bang pigpio.bb_i2c_open(SDA, SCL, baud=100000) # 4, TREX_ADDRESS : Set I2C adress to TREX_ADDRESS # 2 : Start condition # 6, 24 : Read 24 bytes of data # 3 : Stop condition # 0 No more commands (count, data) = pigpio.bb_i2c_zip(SDA, [4, TREX_ADDRESS, 2, 6, 24, 3, 0]) # Fin de la requête Bit Bang pigpio.bb_i2c_close(SDA) # Déconnexion de pigpiod pigpio.stop() if not data: print("Impossible de communiquer avec le T'REX") exit(0) return data def __hight_low_int(hight_byte, low_byte): ''' Convertit deux octets (high et low) en entier ''' result = (hight_byte << 8) + low_byte # Gestion des entiers signés if result > 32768 : result -= 65536 return result def trex_status(): ''' Envoi une requête de statut au T'REX Return tuple: battery_voltage, left_motor_current, left_motor_encoder, right_motor_current, right_motor_encoder, accelerometer_x, accelerometer_y, accelerometer_z, impact_x, impact_y, impact_z ''' b = __trex_status() # pprint(b) battery_voltage = (__hight_low_int(b[2], b[3])/100) left_motor_current = __hight_low_int(b[4], b[5]) left_motor_encoder = __hight_low_int(b[6], b[7]) right_motor_current = __hight_low_int(b[8], b[9]) right_motor_encoder = __hight_low_int(b[10], b[11]) accelerometer_x = __hight_low_int(b[12], b[13]) accelerometer_y = __hight_low_int(b[14], b[15]) accelerometer_z = __hight_low_int(b[16], b[17]) impact_x = __hight_low_int(b[18], b[19]) impact_y = __hight_low_int(b[20], b[21]) impact_z = __hight_low_int(b[22], b[23]) return battery_voltage, left_motor_current, left_motor_encoder, right_motor_current, right_motor_encoder, accelerometer_x, accelerometer_y, accelerometer_z, impact_x, impact_y, impact_z if __name__ == '__main__': battery_voltage, left_motor_current, left_motor_encoder, right_motor_current, right_motor_encoder, accelerometer_x, accelerometer_y, accelerometer_z, impact_x, impact_y, impact_z = trex_status() print("Battery voltage: " + str(battery_voltage) + " V") print("Left motor current: " + str(left_motor_current) + " mA") print("Left motor encoder: " + str(left_motor_encoder)) print("Right motor current: " + str(right_motor_current) + " mA") print("Right motor encoder: " + str(right_motor_encoder)) print("Accelerometer X-axis: " + str(accelerometer_x)) print("Accelerometer Y-axis : " + str(accelerometer_y)) print("Accelerometer Z-axis : " + str(accelerometer_z)) print("Impact X-axis: " + str(impact_x)) print("Impact Y-axis: " + str(impact_y)) print("Impact Z-axis: " + str(impact_z))
Source :
GNU Linux magazine HS n°75
https://www.raspberrypi.org/forums/viewtopic.php?t=129678
Documentation de pigpio
Troubleshooting
Can’t connect to pigpio at localhost(8888)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Can't connect to pigpio at localhost(8888) Did you start the pigpio daemon? E.g. sudo pigpiod Did you specify the correct Pi host/port in the environment variables PIGPIO_ADDR/PIGPIO_PORT? E.g. export PIGPIO_ADDR=soft, export PIGPIO_PORT=8888 Did you specify the correct Pi host/port in the pigpio.pi() function? E.g. pigpio.pi('soft', 8888) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Le daemon n’est pas démarré. Démarrez le avec sudo pigpiod
ou au démarrage du système avec sudo systemctl enable pigpiod
pigpio.error: ‘GPIO already in use’
Il n’y a pas eu de bb_i2c_close(SDA)
Il faut kill le daemon avec sudo killall pigpiod
, puis le relancer avec sudo pigpiod