Dans la suite de l’article je présente l’activation puis l’utilisation du bus I2C sur la carte RaspberryPI (ou tout autre carte qui supporte un bus I2C : Olimex A13 ou iMX233, Beagle/PandaBoard de TI, TQ6410, etc…). L’interrogation des esclaves connectés au bus I2C peut se faire sans aucune programmation ! Cela permet de valider rapidement l’écriture ou la lecture des registres d’un esclave I2C. On peut alors passer à la programmation en C/C++ avec des valeurs validées.
Ressources internet
Une fois n’est pas coutume, je commence par les ressources Internet :
- L’article Wikipédia sur l’I2C : article wikipédia
- Le site de LadyADA : Adafruit Learning System
- Le site eLinux (partie sur l’I2C) : eLinux
- les pages de manuel de l’I2C : i2cdetect, i2cset, i2cget
Brochage du connecteur
Vous trouverez sur Internet de nombreux exemples du brochage du connecteur du RaspberryPI. J’en ai choisi deux parmi d’autres:
Les broches qui nous intéressent ici (pour la V2 revB) :
- GPIO0 (SDA) : broche 3 du connecteur,
- GPIO1 (SCL) : broche 5 du connecteur,
- la masse (GROUND) : broche 6 du connecteur,
- l’alimentation (on prendra des esclaves I2C qui fonctionnent en 3,3V) : broche 1 du connecteur
Utilisation de l’I2C sur le RaspberryPI
Activation de l’I2C
Il faut tout d’abord être « root » pour réaliser les commandes suivantes : sudo su. Il faut éditer le fichier « /etc/modprobe.d/raspi-blacklist.conf » avec l’éditeur nano puis commenter (mettre le caractère #) la ligne « blacklist i2c-bcm2708 ».
Puis rajouter la ligne « i2c-dev » dans le fichier « /etc/modules ». Redémarrez le RaspberryPI avec la commande « reboot ».
Pour vérifier que le pilote de l’I2C est bien chargé, tapez ces deux commandes:
- dmesg | grep i2c : permet de visualiser les messages du noyau se rapportant au bus i2c,
- ls /dev/i2c* : cette commande permet de savoir si le bus i2c est bien accessible depuis « l’espace utilisateur » donc depuis vos programmes.
Voici le résultat de ces deux commandes :
1 2 3 4 5 6 |
root@raspberrypi:/home/pi# dmesg|grep i2c [ 32.803506] bcm2708_i2c bcm2708_i2c.0: BSC0 Controller at 0x20205000 (irq 79) (baudrate 100k) [ 32.832122] bcm2708_i2c bcm2708_i2c.1: BSC1 Controller at 0x20804000 (irq 79) (baudrate 100k) [ 38.616811] i2c /dev entries driver root@raspberrypi:/home/pi# ls /dev/i2c- i2c-0 i2c-1 |
On remarque qu’il y a deux bus i2c reconnus sur la carte. La vitesse de ces bus est ici de 100kHz (mode basse vitesse du bus i2c). Ces deux bus sont accessibles par i2c-0 et i2c-1. En fait un seul bus est disponible sur le connecteur.
Installation des outils I2C
Pour tester si le bus I2C est fonctionnel on connecte une platine avec deux circuits :
- un capteur de température DS1631,
- une horloge temps réel DS3231.
Schéma électrique de la platine et typon (échelle 2) :
Il faut ensuite installer les outils nécessaires pour dialoguer sur le bus i2c sans programmer. En tant qu’utilisateur root, tapez la commande suivante:
1 2 3 4 5 6 7 8 9 10 11 12 |
root@raspberrypi:/home/pi# aptitude install i2c-tools Les NOUVEAUX paquets suivants vont être installés : i2c-tools 0 paquets mis à jour, 1 nouvellement installés, 0 à enlever et 0 non mis à jour. Il est nécessaire de télécharger 59,5 ko d'archives. Après dépaquetage, 223 ko seront utilisés. Prendre : 1 http://mirrordirector.raspbian.org/raspbian/ wheezy/main i2c-tools armhf 3.1.0-2 [59,5 kB] 59,5 ko téléchargés en 1s (56,8 ko/s) Sélection du paquet i2c-tools précédemment désélectionné. (Lecture de la base de données... 60077 fichiers et répertoires déjà installés.) Dépaquetage de i2c-tools (à partir de .../i2c-tools_3.1.0-2_armhf.deb) ... Traitement des actions différées (« triggers ») pour « man-db »... Paramétrage de i2c-tools (3.1.0-2) ... |
L’utilitaire i2cdetect permet de parcourir le bus i2c pour détecter des esclaves reliés à ce bus. Les commandes suivantes permettent de parcourir le bus i2c-0 : raspberry V2revA ou le bus i2c-1 : raspberry V2revB.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
root@raspberrypi:/home/pi# i2cdetect -y 0 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- root@raspberrypi:/home/pi# i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- |
On remarque que sur le bus i2c-1 il y a deux esclaves i2c :
- adresse 0x48 : capteur DS1631 dont les lignes d’adresses A2, A1 et A0 sont reliées à la masse. L’adresse de ce composant est donné dans la documentation : 0b1001A2A1A0 donc 0b1001000 donc en hexadécimal 0x48.
- adresse 0x68 : horloge RTC. Dans la documentation on trouve l’adresse suivante : 0b1101000 soit 0x68.
Le résultat du parcours du bus est donc concluant.
Utilitaires d’interrogation du bus i2c
Nous allons commencer à interroger le capteur de température de l’horloge temps réel. Le résultat de la conversion de température est accessible à l’adresse 0x11 sur deux octets (voir extrait de la documentation ci-dessous ) :
Vous disposez de deux utilitaires pour cela : i2cset et i2cget. Ci-dessous vous trouverez ce que renvoie ces commandes lorsqu’on les lance sans paramètres :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
root@raspberrypi:/home/pi# i2cset Usage: i2cset [-f] [-y] [-m MASK] I2CBUS CHIP-ADDRESS DATA-ADDRESS [VALUE] ... [MODE] I2CBUS is an integer or an I2C bus name ADDRESS is an integer (0x03 - 0x77) MODE is one of: c (byte, no value) b (byte data, default) w (word data) i (I2C block data) s (SMBus block data) Append p for SMBus PEC root@raspberrypi:/home/pi# i2cget Usage: i2cget [-f] [-y] I2CBUS CHIP-ADDRESS [DATA-ADDRESS [MODE]] I2CBUS is an integer or an I2C bus name ADDRESS is an integer (0x03 - 0x77) MODE is one of: b (read byte data, default) w (read word data) c (write byte/read byte) Append p for SMBus PEC |
En gros on remarque qu’il faut spécifier :
- le numéro du bus i2c,
- l’adresse de l’esclave,
- la ou les registres à écrire/lire.
Dans l’exemple qui suit, on lit la température fourni par l’horloge temps réél : adresse 0x68, registres 0x11 et lecture d’un mot (2 octets) :
1 2 3 4 5 6 7 8 |
root@raspberrypi:/home/pi# i2cget 1 0x68 0x11 w WARNING! This program can confuse your I2C bus, cause data loss and worse! I will read from device file /dev/i2c-1, chip address 0x68, data address 0x11, using read word data. Continue? [Y/n] y 0x4013 root@raspberrypi:/home/pi# i2cget -y 1 0x68 0x11 w 0x4013 |
On obtient la valeur hexadécimal 0x4013. La valeur 0x13 correspond au contenu du registre 0x11 (partie entière de la température). La valeur 0x40 correspond à la valeur du registre 0x12 (partie fractionnaire de la température) dont seul les bits B7 B6 nous intéresse. On obtient donc la température suivante : 0x13 = 19 et 0x40 => B7=0 et B6=1. B7 représente 2^-1=0,5°C et B6 représente 2^-2=0,25°C. La température finale est donc de 19,25°C.
Pour initialiser correctement la RTC, il faut écrire la valeur 0x04 dans le registre 0x0E (registre de « control ») et 0x08 dans le registre 0x0F (registre de « status »). Pour la signification de ces valeurs reportez-vous à la documentation officielle. Cela se traduit par les commandes suivantes :
1 2 3 4 5 6 |
root@raspberrypi:/home/pi# i2cset -y 1 0x68 0x0E 0x04 b root@raspberrypi:/home/pi# i2cget -y 1 0x68 0x0F b 0x88 root@raspberrypi:/home/pi# i2cset -y 1 0x68 0x0F 0x08 b root@raspberrypi:/home/pi# i2cget -y 1 0x68 0x0F b 0x08 |
Vous pouvez maintenant lire les secondes, minutes, heures, jour du mois, mois et année. Exemple avec la lecture des secondes et de l’année :
1 2 3 4 |
root@raspberrypi:/home/pi# i2cget -y 1 0x68 0x00 b 0x41 root@raspberrypi:/home/pi# i2cget -y 1 0x68 0x06 b 0x00 |
On obtient donc pour les secondes : 0x41 => 4 x 10s + 1 x 1s = 41s. Pour les années 0 ! La RTC n’est donc pas réglé. Je vous invite à chercher par vous même les commandes pour mettre à l’heure votre horloge RTC.
Bonus : installer une RTC sur le Raspberry
Par défaut, le raspberryPi n’a pas d’horloge RTC. Il récupère la date et l’heure au démarrage à condition d’avoir une connexion Internet. Pour pallier ce défaut on peut connecter au bus i2c une horloge.
Vous trouverez ci-dessous les pilotes gérés par le noyau Linux de la raspberry:
1 2 3 4 5 6 |
root@raspberrypi:/home/pi# ls /lib/modules/3.6.11-rpi-aufs/kernel/drivers/rtc/ rtc-bq32k.ko rtc-ds1672.ko rtc-isl12022.ko rtc-max6900.ko rtc-r9701.ko rtc-rx8581.ko rtc-ds1305.ko rtc-ds3232.ko rtc-isl1208.ko rtc-max6902.ko rtc-rs5c348.ko rtc-s35390a.ko rtc-ds1307.ko rtc-ds3234.ko rtc-m41t80.ko rtc-pcf2123.ko rtc-rs5c372.ko rtc-x1205.ko rtc-ds1374.ko rtc-em3027.ko rtc-m41t93.ko rtc-pcf8563.ko rtc-rv3029c2.ko rtc-ds1390.ko rtc-fm3130.ko rtc-m41t94.ko rtc-pcf8583.ko rtc-rx8025.ko |
Une des plus répandues de ces horloges est certainement la DS1307. Cependant la DS3231 est compatible au niveau des registres de date et d »heure d’une DS1307, elle est plus chère mais aussi beaucoup plus précise. Les commandes suivantes permettent de régler la RTC à partir de l’heure récupérer sur Internet.
1 2 3 4 5 6 7 8 |
root@raspberrypi:/home/pi# echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device root@raspberrypi:/home/pi# hwclock -r sam. 29 mars 2011 15:02:36 CET -0.302646 seconds root@raspberrypi:/home/pi# date samedi 9 février 2013, 16:27:34 (UTC+0100) root@raspberrypi:/home/pi# hwclock -w root@raspberrypi:/home/pi# hwclock -r sam. 09 févr. 2013 16:28:11 CET -0.763037 seconds |
Si l’on détaille les lignes précédentes:
- déclaration d’un nouvel esclave sur le bus i2c : son type (ds1307) et son adresse (0x68),
- lecture de la date dans la RTC : ici la RTC n’est pas à l’heure,
- vérification de l’heure système avec la commande date,
- transfert de l’heure système dans la RTC : paramètre -w de la commande hwclock,
- vérification de l’heure de la RTC.
Pour que l’heure de la RTC soit appliquée au système au démarrage, il faut rajouter les lignes suivantes à la fin du fichier « /etc/rc.local » avant la ligne « exit 0 » :
- « echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device »,
- « sudo hwclock -s ».
Ping : Electronique Innovante » Horloge RTC gérée par le noyau Linux sur RaspberryPi
Ping : Electronique Innovante » RaspberryPi à tout faire…