Le Raspberry pi est doté des GPIO, capables de servir d'entrées ou de sorties numériques. On peut donc lire des signaux logiques hauts ou bas (des 0 ou des 1). Il n'est en revanche pas possible de lire directement des valeurs analogiques. Pour cela, il faut utiliser un ADC, pour “Analog to Digital Converter”, ou convertisseur analogique vers numérique en français, dont le Raspberry Pi n'est pas doté. L'objet de ce tutoriel sera justement de connecter une puce, la MCP3008, au Raspberry pi via le bus SPI pour ajouter huit entrées analogiques. A titre d'exemple, nous nous servirons de ces entrées pour pouvoir effectuer la lecture des valeurs d'un capteur simple : le potentiomètre. Il est toujours possible d'accéder à la liste des tutoriels sur le Raspberry pi.
Pour ce tutoriel, nous aurons besoin d'un Raspberry Pi (A, A+, B, B+) configuré, d'une breadboard, de câbles pour breadboard “jumper wire”, d'une puce MCP3008 au format DIP, et de capteurs analogiques pour tester le tout, à savoir un potentiomètre pour cet exemple. Pour pouvoir réaliser ce montage, il est préférable de savoir utiliser les GPIO du Raspberry pi comme entrée.
Avant toute chose, il faut déterminer le “haut” de la puce. Si vous tenez la puce face à vous, les pattes s'éloignant de vous, vous verrez sur le dessus de la puce une petite encoche en forme de demi lune. Elle sert à marquer le haut de la puce. On cherchera à reproduire le câblage suivant : . Télécharger le schéma de câblage du MCP3008 vers le Raspberry pi en PDF
La première étape sera simplement d’alimenter le circuit. pour cela, on connectera le Vdd, qui est la broche 16 (première broche en haut à droite, en rouge sur le schéma) au 3.3V du Raspberry (broche P1-01, en haut à gauche, lorsque la carte SD est vers le haut). Les broches 14 (Agnd, 3eme en haut à droite) et 9 (Dgnd, 8eme broche en partant du haut, colonne de droite) du MCP3008 sont la masse des signaux analogiques et numériques, et seront connectées à la masse du Raspberry pi : la broche P1-06 (3eme en partant du haut, à droite). Il s’agira des fils noirs sur notre schéma. Il faudra ensuite connecter le Vref de notre CI, qui donnera la tension de référence des signaux logiques, au 3.3V du Raspberry. Il s’agit de la broche 15 (2eme en haut à droite) du MCP3008, que vous connecterez au même 3.3V que plus haut (fil rouge sur le schéma). Nous connecterons maintenant 4 broches GPIO de notre Raspberry aux broches CLK, Dout, Din et CS du MCP3008:
On pourra utiliser d'autres GPIO que les 4 utilisés ici, il suffira alors d'ajuster les variables correspondantes dans le code que nous verrons plus bas.
A cette étape, notre MCP3008 est connecté au Raspberry. Toutes les broches de gauche du circuit sont des entrées analogiques que nous pourrons utiliser.
Le “capteur” le plus simple que nous pouvons utiliser immédiatement est un potentiomètre. pour s’en servir, il faudra brancher la première patte du potentiomètre sur le 3.3V(fil rouge en bas), la patte centrale sur une des entrées analogiques (par exemple la broche 1, fil marron), et enfin la dernière patte ira à la masse (fil noir). On obtiendra le montage suivant : Télécharger le schéma de câblage du MCP3008 et du potentiomètre en PDF
Maintenant que notre montage est assemblé, nous pouvons nous intéresser au code. Je me suis basé pour ce code sur l'exemple/tutoriel sur le MCP3008 fourni par Adafruit, et j'ai simplifié quelque peu le code1), que voici :
#!/usr/bin/env python import time import os import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) #fonction lisant les donnees SPI de la puce MCP3008, parmi 8 entrees, de 0 a 7 def readadc(adcnum, clockpin, mosipin, misopin, cspin): if ((adcnum > 7) or (adcnum < 0)): return -1 GPIO.output(cspin, True) GPIO.output(clockpin, False) # start clock low GPIO.output(cspin, False) # bring CS low commandout = adcnum commandout |= 0x18 # start bit + single-ended bit commandout <<= 3 # we only need to send 5 bits here for i in range(5): if (commandout & 0x80): GPIO.output(mosipin, True) else: GPIO.output(mosipin, False) commandout <<= 1 GPIO.output(clockpin, True) GPIO.output(clockpin, False) adcout = 0 # read in one empty bit, one null bit and 10 ADC bits for i in range(12): GPIO.output(clockpin, True) GPIO.output(clockpin, False) adcout <<= 1 if (GPIO.input(misopin)): adcout |= 0x1 GPIO.output(cspin, True) adcout /= 2 # first bit is 'null' so drop it return adcout # ces numeros de pins GPIO doivent etre modifies pour correspondre aux broches utilisées si vous avez utilisé un autre câblage que celui du tutoriel. SPICLK = 18 SPIMISO = 23 SPIMOSI = 24 SPICS = 25 # definition de l'interface SPI GPIO.setup(SPIMOSI, GPIO.OUT) GPIO.setup(SPIMISO, GPIO.IN) GPIO.setup(SPICLK, GPIO.OUT) GPIO.setup(SPICS, GPIO.OUT) #definition du ADC utilise (broche du MCP3008). Cette valeur peut aller de 0 à 7. adcnum = 0 # Lecture de la valeur brute du capteur read_adc0 = readadc(adcnum, SPICLK, SPIMOSI, SPIMISO, SPICS) # conversion de la valeur brute lue en milivolts = ADC * ( 3300 / 1024 ) millivolts = read_adc0 * ( 3300.0 / 1024.0) print "\tvaleur brute : %s" % read_adc0 print "\ttension : %s millivolts" % millivolts
Ce code nous permet de lire la valeur de n'importe laquelle des 8 entrées, il suffira pour cela de changer la valeur de la variable adcnum, pour la faire varier entre 0 et 7 pour lire les entrées 1 à 8. Il est de même possible de lire plusieurs entrées dans le même programme.
Au prix de 4 GPIO, nous ajoutons ainsi 8 entrées analogiques au Raspberry Pi. Toutefois, puisqu'il s'agit du bus SPI, il est techniquement possible d'utiliser ces mêmes broches pour d'autres périphériques, au prix d'un GPIO de plus par périphérique SPI ajouté en plus du premier.
Cette puce permettra dans tous les cas de combler l'absence de convertisseur analogique vers numérique sur le Raspberry pi, permettant ainsi de lire toute une gamme de capteurs. On citera par exemple des capteurs simples pour lesquels nous avons des tutoriels :