mardi 16 juillet 2019

Programmer l'ESP32 avec l'IDE Arduino (premiers pas)

Puisque je me suis beaucoup amusé avec l'ESP8266 au cours des derniers mois, il était inévitable que je fasse un jour ou l'autre la connaissance de son cousin, l'ESP32.

En bref, l'ESP32, c'est la même chose que l'ESP8266: un microcontrôleur 32 bits avec WiFi intégré.  Sauf que l'ESP32 est plus rapide et dispose de plus de mémoire, de Bluetooth intégré, de broches GPIO deux fois plus nombreuses, de beaucoup plus d'entrées analogiques, de deux sorties analogiques, d'un capteur à effet Hall intégré... et même s'il est un tout petit peu plus cher que l'ESP8266, l'ESP32 est quand même offert à un prix inexplicablement dérisoire.

Je me suis procuré sur eBay le module de développement photographié ci-dessus (l'annonce était intitulée "ESP-32S ESP32 NodeMCU Development Board").

Le présent billet constitue une marche à suivre pour programmer ce module au moyen de l'IDE Arduino.

Préparation de l'IDE Arduino

Si l'IDE Arduino n'est pas déjà installé sur votre ordinateur, la première étape consiste à l'installer!

Il faut ensuite ajouter des fichiers supplémentaires qui permettent d'utiliser l'IDE Arduino afin de programmer l'ESP32. Pour ce faire, on accède d'abord au dialogue de préférences de l'IDE, grâce au menu Fichier / Préférences.

Au bas du dialogue de Préférences, dans le champ intitulé "URL de gestionnaire de cartes supplémentaires", vous écrivez cette adresse:

https://dl.espressif.com/dl/package_esp32_index.json


S'il y a déjà d'autres adresses dans ce champ, vous pouvez les séparer par des virgules.
On clique évidemment sur le bouton "OK" pour enregistrer les changements.

On se dirige ensuite vers le gestionnaire de carte, en passant par le menu "Outils / Type de carte / Gestionnaire de cartes"


À l'intérieur du gestionnaire de carte, on localise "esp32 by Espressif Systems". Un clic dans cette zone fait apparaître le bouton "Installer", sur lequel nous allons évidemment cliquer.


Le message "Téléchargement des définitions de cartes" devrait s'afficher dans le bas de la fenêtre. Lorsque c'est terminé, la mention "INSTALLED" apparaît à gauche de "esp32 by Espressif Systems". Vous pouvez maintenant fermer le gestionnaire de carte.


Téléversement d'un premier sketch dans l'ESP32

Le temps est venu de brancher le module ESP32 à un port USB de l'ordinateur. Sur ma carte, une LED rouge s'allume pour indiquer qu'elle est alimentée.

Le menu "Outils / Type de carte" nous donne maintenant accès à une rubrique "ESP32 Arduino" qui comporte près d'une soixantaine de cartes ESP32 différentes! Si vous reconnaissez le nom spécifique de votre carte dans la liste, sélectionnez-le, bien sûr, mais si votre carte vous a simplement été vendue sous le nom de ESP32, le premier choix du menu, intitulé "ESP32 Dev Module", fera parfaitement l'affaire.


Si vous êtes curieux de savoir ce qu'implique le choix d'un modèle de carte plutôt qu'un autre, vous pouvez aller jeter un oeil sur le gitHub d'Arduino core for ESP32. Le fichier boards.txt décrit le contenu du menu "Outils" pour chaque carte: certaines cartes offrent plus d'options avancées que d'autres. De plus, le répertoire "variants" comporte les définitions de broches pour chaque carte.

Par exemple, la plupart des cartes définissent la constante "LED_BUILTIN", qui contient le numéro de la broche permettant de contrôler la LED intégrée à la carte. Puisque cette LED n'est pas nécessairement associée à la même broche pour toutes les cartes, notre choix générique "ESP32 Dev Module" ne définit pas cette constante.


Ensuite, c'est la routine habituelle (en supposant que vous êtes déjà familier avec la programmation d'un Arduino): on sélectionne le port série correspondant à notre carte. Dans mon cas, j'ai dû appuyer sur le bouton "BOOT" de ma carte pour que le port devienne disponible dans le menu. J'ai aussi diminué un peu la vitesse de téléversement ("Upload Speed"), car la valeur par défaut de 921600 bauds semble trop optimiste pour la qualité douteuse de mon câble USB.


L'exemple "WiFiScan" (accessible par le menu "Fichier / Exemples / WiFi / WiFiScan" est un bon moyen de vérifier le fonctionnement correct de votre module ESP32, puisqu'aucune modification à ce sketch n'est nécessaire.


Ma première tentative de téléversement a échoué, avec le message d'erreur "A fatal error occured: Failed to connect to ESP32: Timed out waiting for packet header".


Pas de panique: ce problème très fréquent indique que le dispositif qui permettrait à ma carte de se mettre en mode programmable ne fonctionne pas correctement. Le remède consiste à appuyer sur le bouton "BOOT" de la carte ESP32 au moment où le messsage "Connecting....." apparaît au bas de la fenêtre, et de maintenir ce bouton enfoncé jusqu'à ce que d'autres messages soient affichés ("Chip is ESP32D0WDQ6 (revision 1)").

Cette fois, ça fonctionne...


Le moniteur série affiche la liste des réseaux WiFi détectés.


Essai d'une broche GPIO

Le premier essai d'un microcontrôleur ne pourrait pas être complet sans le clignotement d'une LED grâce à l'exemple Blink (menu "Fichier / Exemples / 01.Basics / Blink ).

Puisque cet exemple utilise la constante "LED_BUILTIN" qui n'est pas définie pour la carte générique "ESP32 Dev Module" que j'ai sélectionnée, j'ai remplacé dans le sketch l'expression "LED_BUILTIN" par le nombre 2 puisque la LED intégrée à ma carte est branchée à la broche GPIO 2.


Résultat: la LED bleue se met à clignoter sur la carte.


J'ai ensuite branché une LED à une broche choisie au hasard  (celle portant l'identification "D21" sur la carte) et je l'ai fait clignoter avec succès en écrivant "digitalWrite(21, HIGH);" dans le sketch.



Compatibilité des sketches écrits pour l'ESP8266

Un aspect important à considérer lorsqu'on a déjà fait quelques projets impliquant l'ESP8266: nos programmes écrits pour l'ESP8266 fonctionneront-ils sans problème sur l'ESP32?

Je n'ai fait qu'un seul test, mais il s'est avéré encourageant: j'ai fait l'essai de mon sketch qui sert à lire les flux RSS, et la seule modification nécessaire a consisté à remplacer l'instruction #include "ESP8266WiFi.h" par #include "WiFi.h". Pour d'autres sketches, je ne serais pas surpris de devoir modifier quelques numéros de broches de temps à autre mais, à première vue, les modifications requises ne semblent pas très nombreuses.

Yves Pelletier   (TwitterFacebook)

samedi 13 juillet 2019

Livre: Programmer en Java pour le Raspberry Pi 3

Programmer en Java pour le Raspberry Pi 3
par Jean-Bernard Boichat
2019, Éditions Eyrolles, collection Serial Makers

Suite à la récente sortie du Raspberry Pi 4, on pourrait croire que je vous parle d'un vieux livre déjà désuet mais non: il a bel et bien été publié cette année (avec sa regrettable manie de sortir ses nouveaux modèles en prenant soin de ne pas les annoncer à l'avance, la fondation Raspberry Pi ne facilite certainement pas la tâche des éditeurs!).

Donc, comme le titre l'indique, il s'agit d'un livre sur la programmation d'un Rasbperry Pi en langage Java.

Un aspect du livre que j'ai beaucoup apprécié, c'est qu'il accorde une grande importance aux capteurs qu'on peut brancher aux broches GPIO du Raspberry Pi:  LED,  relais, photorésistance,  capteur de mouvement infrarouge (PIR),  buzzer, capteur de température DS18B20, télémètre à ultrason HC-SR04, bouton-poussoir, caméra Raspberry Pi... bref, les mêmes joujoux que j'adore moi-même contrôler avec des scripts en Python. De plus, vous y apprendrez comment programmer un serveur web en java, interagir avec une base de donnée SQLite, envoyer automatiquement une photo par email lorsqu'un mouvement est détecté par un détecteur infrarouge PIR...

Tout ça est clairement expliqué, les schémas Fritzing sont en couleur et, bien entendu, de nombreux exemples de programmes sont fournis.

La démarche préconisée par l'auteur consiste à d'abord tester le fonctionnement correct des capteurs grâce à un script en python, puis ensuite d'écrire un programme plus "professionnel" en Java dans l'environnement de programmation Eclipse (sur un ordinateur autre que le Raspberry Pi, roulant sous Windows 10).

Puisque je ne suis pas du tout familier avec Java, tout ça m'a semblé inutilement compliqué: moi, à partir du moment où ça fonctionne correctement avec un script en Python, je suis pleinement satisfait et je m'arrête là! Mais si vous connaissez déjà un peu Java (ou si vous êtes moins paresseux que moi), ce livre pourrait vous intéresser sérieusement.

Extrait du livre en format pdf.

Yves Pelletier   (TwitterFacebook)

mercredi 10 juillet 2019

Et pendant ce temps, dans un blog près de chez vous...(5)



Encore une fois, un petit tour d'horizons de publications récentes par d'autres blogueurs francophones...

RitonDuino:

iTechnoFrance:

MCHobby:

ProjetsDIY:

IDEHack:
Bonne lecture!

Yves Pelletier   (TwitterFacebook)

jeudi 4 juillet 2019

Mesurer une résistance avec un Raspberry Pi...sans ADC

Dans le présent billet, nous allons mesurer la résistance d'un potentiomètre, d'une photorésistance ou d'une thermistance grâce à un Raspberry Pi, en chronométrant le temps de charge d'un condensateur.

Un convertisseur analogique/numérique? Pas besoin!

Lorsqu'on désire lire la valeur d'une résistance avec un Arduino, par exemple, la méthode classique consiste à insérer la résistance inconnue dans un diviseur de tension, puis mesurer le potentiel au moyen d'une entrée analogique (l'entrée analogique étant équipée d'un convertisseur analogique-numérique, ou ADC pour analog-digital converter).

Le Raspberry Pi, toutefois, ne comporte pas d'ADC. Pour mesurer une résistance de cette façon, il faut ajouter un module ADC externe au Raspberry Pi (voir à ce sujet mes billets sur le MCP3008 ou le PCF8591).

La méthode que nous explorons aujourd'hui ne nécessite pas l'utilisation d'un ADC externe.

Le circuit

Le circuit schématisé ci-dessous est présenté dans le livre Raspberry Pi Cookbook, par Simon Monk. En plus de la résistance qu'on désire mesurer au moyen du Raspberry Pi (ici: un potentiomètre de 10 kΩ), le circuit est constitué de deux résistances de 1 kΩ et d'un condensateur de 220 nF.


Comme l'indique le schéma, une des 3 broches du potentiomètre n'est pas branchée au circuit. 

Vous pouvez très bien remplacer le potentiomètre par un autre capteur résistif comme, par exemple, une photorésistance ou une thermistance. Il pourrait être approprié de modifier la capacité du condensateur si votre résistance variable prend des valeurs qui ne sont pas de l'ordre du kΩ.

Principe de fonctionnement

Les entrées du Raspberry Pi sont numériques, ce qui signifie qu'on mesure un niveau logique BAS lorsque la tension est nulle, et un niveau logique HAUT si la tension est de 3,3 V. Mais qu'arrive-t-il si la tension varie de façon à passer progressivement de 0 à 3,3 V? Le niveau logique, initialement BAS, deviendra HAUT à un certain moment pendant l'augmentation de la tension. Le seuil entre BAS et HAUT est d'environ 1,2 V sur le Raspberry Pi que j'ai utilisé, mais ça peut varier d'un Raspberry Pi à l'autre.

Au départ, le condensateur n'est pas chargé, et le potentiel mesuré par l'entrée GPIO 23 du Raspberry Pi est donc nulle. On règle la sortie GPIO 18 au niveau logique HAUT, ce qui a pour effet d'amourcer la charge du condensateur. Plus la résistance du potentiomètre est élevée, plus le condensateur prend du temps à se charger.  À un certain point pendant la charge du condensateur, la tension mesurée par l'entrée GPIO 23 atteint la valeur à partir de laquelle le niveau logique est HAUT. Il s'agit de chronométrer le temps nécessaire pour que le niveau logique de l'entrée GPIO 23 passe de BAS à HAUT pour obtenir une valeur proportionnelle à la résistance du potentiomètre.

Il faut ensuite décharger le condensateur en vue de la prochaine mesure. Pour ce faire, la broche GPIO 23 devient une entrée (son impédance est alors très grande) et la broche GPIO 18 devient une sortie (faible impédance) au niveau logique BAS. Le condensateur se décharge donc à travers la broche GPIO 18.

La résistance de 1 kΩ  branchée à la broche GPIO 18 évite de court-circuiter cette broche si la résistance du potentiomètre devient trop basse. La résistance de 1 kΩ branchée à la broche GPIO 23 protège cette broche en évitant que la décharge du condensateur soit trop rapide.

Script en Python

Toutes les secondes, ce script affiche le nombre de microsecondes nécessaires pour que le condensateur se charge jusqu'à provoquer le niveau logique HAUT sur la broche GPIO 23.


Résultats

En faisant tourner le potentiomètre d'une position extrême à l'autre, j'obtiens un temps de charge qui varie entre 230 microsecondes et 1140 microsecondes environ. La position du potentiomètre a donc un effet évident sur la valeur mesurée.


Lorsque je ne change pas la position du potentiomètre, les résultats sont un peu fluctuants: à une extrémité, on peut lire 230, puis 317 à la lecture suivante...


À l'autre extrémité, on peut aussi bien avoir 1130 que 1228.


Ces fluctuations peuvent s'avérer problématiques si vous avez besoin d'une valeur très précise (il faut alors prendre quelques mesures consécutives et éliminer les valeurs aberrantes). Mais dans de nombreuses applications, ça n'aura pas d'impact majeur.

Une courbe d'étalonnage

Je me suis ensuite amusé à étalonner mon dispositif, afin d'afficher à l'écran la valeur de la résistance en ohms (ce qui est rarement utile, remarquez...). Pour ce faire, j'ai remplacé le potentiomètre par une résistance de valeur connue, et j'ai noté le temps de charge affiché par mon script.

Résistance (kΩ)
Temps (µs)
1,0
230
2,2
320
3,3
436
4,7
580
5,6
680
6,8
820
8,2
965
10
1150


Le résultat est linéaire. Je peux maintenant convertir le temps de charge en résistance en faisant ce calcul:     R = 0,00955 * t - 0,957

(notez que cette équation pourrait ne pas être valable sur un autre Raspberry Pi)

Script en Python donnant la valeur en 

J'ai donc modifié mon script pour qu'il affiche la valeur de la résistance en  plutôt que le temps de charge en µs.



Conclusion

La méthode fonctionne très bien. Les avantages par rapport à l'utilisation d'un module ADC externe sont surtout d'ordre économique: un condensateur et deux résistance, ça ne coûte pratiquement rien.

Certains inconvénients pourraient s'avérer problématiques pour certaines applications:

  • Les valeurs obtenues sont un peu fluctuantes et, occasionnellement, des lectures sont carrément aberrantes.
  • Le temps de charge, pour une résistance de 10 kΩ, est de l'ordre de la milliseconde, et on laisse le condensateur se décharger pendant 5 millisecondes: c'est beaucoup plus lent que la vitesse de lecture typique d'un ADC.
  • La plage des valeurs mesurées demeure inconnue avant d'en avoir fait l'essai, contrairement aux résultats d'un ADC (qui varient de 0 à 1023, par exemple, pour un ADC à 10 bits).
  • Les résultats pourraient être très différents d'un Raspberry Pi à l'autre, puisque la tension constituant la frontière entre l'état logique BAS et l'état logique HAUT n'est pas le même pour deux exemplaires différents.

Yves Pelletier   (TwitterFacebook)

vendredi 28 juin 2019

Étude de CI: le compteur binaire 74LS193

Comme son nom peut le laisser deviner, un compteur est un circuit intégré qui compte le nombre d'impulsions reçues sur sa broche d'entrée.  Cette fonction peut sembler banale en cette époque où un microcontrôleur bas de gamme peut accomplir des tâches beaucoup plus complexes, mais il y a quelque années, c'était impressionnant! De plus, l'utilisation d'un compteur demeure encore pertinente  de nos jours si la fréquence des impulsions à compter est élevée (jusqu'à 32 MHz, dans le cas du compteur que nous étudiants aujourd'hui).

Il existe un grand nombre de compteurs. Nous en avons même déjà construit un à partir de quelques bascules (flip flops) CD4013. Le 74LS193 de Texas Instruments, que nous étudions aujourd'hui, est un compteur binaire synchrone de 4 bits, qui peut compter de façon ascendante et descendante. Il se présente sous la forme d'un circuit intégré comportant 16 broches.  Comme à mon habitude, je vous encourage à expérimenter avec le circuit intégré, pour vérifier qu'il se comporte bien de la façon décrite dans la fiche technique.


Broches d'alimentations

Commençons par les broches numéros 8 et 16: elles servent à alimenter le circuit intégré, qui est conçu pour fonctionner à une tension de 5 V. Ces deux broches doivent obligatoirement être branchées à une alimentation continue de 5 V, sinon le circuit intégré ne fonctionnera pas.

2 broches d'entrée

La broche numéro 4 "DOWN" et la broche numéro 5 "UP" sont les entrées.  Chaque fois que la broche "UP" retourne à une tension de 5 V après avoir brièvement été soumise à une tension nulle, la valeur du compteur augmente d'une unité. Pour la broche "DOWN", c'est la même chose, sauf que la valeur du compteur diminue d'une unité.

4 broches de sortie

La valeur du compteur est accessible sous la forme d'un nombre binaire à 4 bits grâce aux broches QA, QB, QC et QD. QD est le bit de poids fort, alors que QA est le bit de poids faible. Ainsi, si QA, QB et QC sont à 0 V pendant que QD est à 5 V, le compteur affiche le nombre binaire 1000 qui correspond à 8 en notation décimale.

Un premier circuit exploratoire

Pour tester le 74LS193, nous devons l'alimenter avec une tension de 5 V, soumettre sa broche "UP" à des impulsions de 5 V, et lire la tension de ses 4 broches de sortie: tout ça peut facilement être accompli par un Arduino Uno, c'est pourquoi je vous propose le montage illustré ci-dessous.


  • Les broches 4, 11 et 16 du 74LS193 sont branchées à la sortie 5 V de l'Arduino.
  • Les broches 8 et 14 du 74LS193 sont branchées à une des broches GND de l'Arduino.
  • Les sorties QA, QB, QC et QD (broches 3, 2, 6, 7) du 74LS193 sont branchées respectivement aux broches 2, 3, 4 et 5 de l'Arduino.
  • La broche 5 (entrée UP) du 74LS193 est branchée à la broche 6 de l'Arduino.
  • Les broches 1, 9, 10, 12, 13 et 15 du 74LS193 ne sont pas branchées (nous les utiliserons plus tard).
Le sketch n'est pas très long: il consiste à envoyer chaque seconde une impulsion sur l'entrée UP du compteur, puis de lire la tension de chacune de ses 4 sorties afin d'afficher le résultat sur le moniteur série de l'IDE Arduino.


Tel que prévu, chaque fois qu'une impulsion est détectée par la broche UP, la valeur binaire présentée par les sorties QA, QB, QC et QD augmente d'une unité. Lorsque la valeur maximale "1111" (qui est l'équivalent de 15 en décimal) est atteinte, le compteur recommence à zéro.

Réglage de la valeur du compteur

Il est parfois utile de régler la valeur du compteur. Pour ce faire, nous plaçons les entrées A, B, C et D du compteur aux valeurs désirées, puis nous plaçons brièvement la broche LOAD (broche #11) à 0 V pour enregistrer le résultat.

Par exemple, si vous désirez régler le compteur à la valeur "0100", vous mettez D à 0 V, C à 5 V, B à 0 V et A à 0 V, puis vous envoyez une impulsion sur la broche LOAD pour enregistrer le résultat.

Modifions notre circuit afin de pouvoir régler la valeur du compteur (nous en profiterons également pour activer la broche DOWN, ce qui nous permettra de diminuer la valeur du compteur.


Il s'agit donc du même circuit que plus haut, sauf que maintenant:
  • La broche DOWN (#4) du 74LS193 est branchée à la broche 7 de l'Arduino (et non à 5 V).
  • La broche LOAD (#11) du 74LS193 est branchée à la broche 8 de l'Arduino (et non à 5 V).
  • La broche A (#15) du 74LS193 est branchée à la broche 9 de l'Arduino.
  • La broche B (#1) du 74LS193 est branchée à la broche 10 de l'Arduino.
  • La broche C (#10) du 74LS193 est branchée à la broche 11 de l'Arduino.
  • La broche D (#9) du 74LS193 est branchée à la broche 12 de l'Arduino.
Le sketch ci-dessous règle le compteur à la valeur "0111", puis envoie 4 signaux de soustraction par la broche "DOWN" avant de régler le compteur à "0101" et d'envoyer 4 signaux d'addition.




Notez que si vous désirez mettre le compteur à zéro, vous pouvez aussi placer temporairement la broche CLR du compteur à 5 V, puis la remettre à 0 V.

Détection des débordements

Il ne nous reste plus que 2 dernières broches du 74LS193 à explorer:  BO et CO. Ces deux sorties sont généralement à 5 V, mais leur tension devient brièvement nulle lorsque le compteur "déborde". Par exemple, lorsque vous ajoutez "1" au compteur alors qu'il se trouve à la valeur maximale "1111", la broche CO prend brièvement une valeur nulle juste avant que le compteur n'affiche "0000". De la même façon, si vous soustrayez "1" du compteur alors qu'il se trouve à la valeur minimale "0000", la tension de la broche BO devient momentanément nulle avant que le compteur n'affiche "1111".

Pour tester ces deux broches, j'ai branché CO (#12) à la broche A0 de l'Arduino, et BO (#13) à A1.


Le sketch ci-dessous effectue 25 additions, en nous alertant à chaque débordement, puis 25 soustraction, en nous alertant à chaque débordement.




Plusieurs compteurs en cascade

Grâce aux sorties CO et BO, il est facile de relier plusieurs compteurs en cascade. En reliant la sortie CO du premier compteur à l'entrée UP du deuxième, et en reliant la sortie BO du premier compteur à l'entrée DOWN du deuxième, vous obtenez un compteur binaire à 8 bits, capable de compter de 0 à 255.

Un circuit vintage, sans microcontrôleur

Évidemment, le 74LS193 peut être utilisé sans le moindre microcontrôleur.  Dans le circuit ci-dessous, les impulsions transmises à l'entrée UP du compteur sont générées par un timer 555 (en mode astable), et chacune des 4 sorties du compteur contrôle une LED.

Voici ce que ça donne:



Yves Pelletier   (TwitterFacebook)

samedi 22 juin 2019

Fabrication d'une boussole avec le module HMC5883L (Arduino)


Le HMC5883L est un capteur qui permet de mesurer les 3 composantes orthogonales du champ magnétique dans lequel il se trouve (je vous l'avais brièvement présenté il y a quelques années). Dans ce billet, je vous propose la fabrication d'une boussole constituée d'un capteur HMC5883, d'un Arduino et d'un afficheur LCD de type "Nokia".

Dans le produit final, l'écran LCD affichera une flèche qui pointera obstinément vers le nord.



Le champ magnétique terrestre 

Notre planète est un gigantesque aimant: elle produit un champ magnétique. Ce champ magnétique comporte une composante verticale (orientée vers le haut si vous vous trouvez dans l'hémisphère sud, et vers le bas si vous êtes dans l'hémisphère nord) et une composante horizontale orientée vers le nord magnétique.

Le HMC5883L comporte 3 capteurs de champ magnétique: il mesure le champ magnétique dans la direction x (le sens de x est indiqué sur le capteur), dans la direction y (également indiquée sur le capteur), et dans la direction z (perpendiculaire au module).

Pour l'utilisation comme boussole, il s'agit de placer le capteur à l'horizontale (bien à plat sur une table, par exemple). L'orientation horizontale du champ magnétique (donc l'orientation de la résultante des composantes x et y) représente l'angle que fait l'axe x du capteur par rapport au nord.

Branchement du capteur HMC5883L à l'Arduino Uno

Commençons par brancher le module HCM5883L à l'Arduino. Comme nous le verrons, il sera utile de tester et de calibrer ce capteur, et ce n'est qu'ensuite que j'ajouterai l'afficheur LCD.


Mon module HMC5833 comporte un régulateur de tension et des résistances de tirage, il se branche donc à l'Arduino de la façon suivante:

VCC du module HMC5833 ----- 5V de l'Arduino
GND du module HMC5833 ---- GND de l'Arduino
SCL du module HMC5833 ---- A5 de l'Arduino Uno
SDA du module HMC5833 ----- A4 de l'Arduino Uno
RDY du module HMC5833 ---- pas connectée

Calibration nécessaire!

Faisons un petit test pour vérifier la fiabilité des mesures prises par le capteur: on place le capteur à plat sur une table: on le fait lentement tourner sur lui-même sur au moins un tour complet tout en mesurant les 3 composantes du champ magnétique. J'ai utilisé le sketch ci-dessous (basé sur un sketch publié par l'équipe de Sparkfun) pour enregistrer les 3 composantes du champ magnétique, que j'ai ensuite copiées dans un tableur.



Si les mesures sont correctes, le graphique de la composante y en fonction de la composante x devrait former un cercle centré autour de la valeur 0. Quant à la composante z, elle devrait demeurer constante.

Mais voici ce que j'ai obtenu:


Ça ne va pas du tout!  Les données forment une ellipse plutôt qu'un cercle, ce qui signifie qu'un même champ magnétique ne génère pas la même valeur numérique selon qu'il est mesuré par le capteur x ou par le capteur y. De plus, les mesures du capteur x ne sont pas réparties de façon symétrique autour de 0, ce qui signifie qu'un même champ magnétique ne génère pas la même mesure (en valeur absolue) selon qu'il est orienté dans le sens positif ou dans le sens négatif de l'axe.

Dans ce cas précis, x a varié entre -561 et -63, alors que y a varié entre -263 et +242. Quant à la composante z, qu'on ne voit pas sur le graphique, elle est demeurée presque constante, tel que prévu, fluctuant entre -613 et -587.

Pour faciliter la prise des mesures utiles à la calibration, j'ai légèrement modifié le sketch afin qu'il affiche la valeur minimale et la valeur maximale de x et y pendant une rotation complète du module:


En faisant à nouveau tourner le capteur à plat sur une table, ce deuxième sketch a affiché les informations suivantes:

xmin: -564     xmax: -62     ymin: -277     ymax: 254     zmin: -616     zmax: -606

(ce qui confirme approximativement les valeurs constatées dans le test précédent).

Nous pouvons maintenant utiliser la fonction "map" d'Arduino pour redistribuer nos valeurs entre une valeur minimale de -1000 et une valeur maximale de 1000, selon les deux axes (cette valeur de 1000 est arbitraire, mais nous ne nous intéressons qu'à l'orientation du champ magnétique; nous devons simplement nous assurer que l'échelle est la même dans les 2 directions):

       xcalibree = map(xbrut, xmin, xmax, -1000, 1000);
       ycalibree = map(ybrut, ymin, ymax, -1000, 1000);

En utilisant à nouveau le premier sketch de ce billet, nous réglons la constante "calibration" à 1, et nous assignons les valeurs qui conviennent à notre capteur pour les constantes xmin, xmax, ymin et ymax.




Nouvelle prise de mesure, et transfert des données dans un tableur, après calibration:


Voilà qui est beaucoup mieux: après calibration, les deux capteurs x et y mesurent un champ magnétique maximal de 1000. La résultante de x et y (le rayon du cercle) est la même peu importe l'orientation du module. Lorsque la valeur en x est maximale, celle en y est nulle, etc.

Ajout de l'afficheur LCD

Pour créer notre boussole, il ne reste plus qu'à ajouter l'afficheur LCD; le circuit est le même que lors de mes utilisations précédentes de cet afficheur; j'utilise un circuit intégré 4050 pour abaisser à 3,3 V la communication entre l'Arduino et l'afficheur.



  • La broche VCC de l'afficheur et la broche 1 du 4050 sont branchés à la sortie 3.3 V de l'Arduino.
  • La broche GND de l'afficheur et la broche 8 du 4050 sont branchés à la broche GND de l'Arduino.
  • La broche 3 de l'Arduino est branchée à la broche 3 du 4050
  • La broche 4 de l'Arduino est branchée à la broche 5 du 4050
  • La broche 5 de l'Arduino est branchée à la broche 7 du 4050
  • La broche 11 de l'Arduino est branchée à la broche 14 du 4050
  • La broche 13 de l'Arduino est branchée à la broche 11 du 4050
  • La broche SCE ou CS de l'afficheur est branchée à la broche 4 du 4050
  • La broche RST de l'afficheur est branchée à la broche 2 du 4050
  • La broche D/C de l'afficheur est branchée à la broche 6 du 4050
  • La broche DN (MOSI) ou DIN de l'afficheur est branchée à la broche 15 du 4050
  • La broche SCLK ou CLK de l'afficheur est branchée à la broche 12 du 4050
  • La broche LED de l'afficheur n'est pas branchée (je n'avais pas besoin du rétroéclairage).

Rien n'a changé en ce qui concerne le capteur magnétique:

  • VCC du module HMC5833 ----- 5V de l'Arduino
  • GND du module HMC5833 ---- GND de l'Arduino
  • SCL du module HMC5833 ---- A5 de l'Arduino Uno
  • SDA du module HMC5833 ----- A4 de l'Arduino Uno
  • RDY du module HMC5833 ---- pas connectée


Sketch de la boussole

Ce dernier sketch est assez similaire aux précédents, mais plutôt qu'afficher les composantes du champ magnétique dans le moniteur série, ces composantes servent à tracer sur l'écran LCD une flèche qui pointe vers le nord (le sketch est conçu en supposant que l'axe x du capteur pointe vers le côté droit du LCD).

Attention: pour que la boussole fonctionne correctement, il est important que vous écriviez les constantes appropriées pour la calibration de votre capteur HMC5883 (xmin, xmax, ymin, ymax). Vous devez également trouver l'angle de déclinaison de l'endroit où vous vous trouvez, et mettre la bonne valeur (en radians) dans la constante "declinaison".



Modifications envisageables:

Il est possible que le module HMC5883L nécessite de fréquentes recalibrations: on pourrait envisager d'insérer la procédure de calibration à l'intérieur du sketch de la boussole. En appuyant sur un bouton (où à chaque démarrage du sketch), on afficherait un message à l'écran demandant d'effectuer une rotation complète de la boussole afin de redéfinir les valeurs à utiliser lors du calcul de calibration. De plus, on pourrait surveiller la composante z du champ magnétique pour s'assurer que la boussole est bien tenue à l'horizontale (l'écran pourrait indiquer que la boussole est trop inclinée pour que la mesure soit fiable).

Yves Pelletier   (TwitterFacebook)

jeudi 13 juin 2019

Contrôler plusieurs LEDs avec Arduino: multiplexing et charlieplexing

Multi quoi??? Charlie qui???

Le multiplexing et le charliplexing sont des façon de brancher des LEDs à l'Arduino (ou tout autre microcontrôleur) de façon à utiliser le moins de broches possible. Par exemple, si vous désirez contrôler 30 LEDs, vous auriez besoin, en principe, de 30 sorties de l'Arduino, ce qui exigerait donc l'ajout de sorties supplémentaires par l'entremise, par exemple, de registres à décalage. Mais grâce au multiplexing, vous pourrez contrôler individuellement chacune de ces 30 LEDs avec seulement 11 sorties de l'Arduino. Si vous optez pour le charlieplexing, 6 sorties de l'Arduino suffiront pour contrôler les 30 LEDs.

Pour explorer tout ça, je vous propose une petite expérience consistant à contrôler 6 LEDs au moyen d'un Arduino Uno. Pour contrôler ces 6 LEDs, nous allons successivement procéder de 3 façons différentes: branchement direct, multiplexing et charlieplexing.

Les 6 LEDs sont disposées sur une breadboard de façon à former un rectangle (2 LEDs de largeur, 3 LEDs de hauteur). Pour chacune des trois versions du programme, la routine consistera à allumer chaque LED individuellement pendant une demi seconde, puis allumer les LEDs par groupes de deux, ensuite allumer les LEDs par groupe de 3, et finalement allumer toutes les LEDs.  Vous pouvez voir le résultat dans la vidéo ci-dessous.




Connexion directe

La façon classique de faire les choses consiste à brancher chaque LED en série avec une résistance de protection, et de l'insérer entre une sortie de l'Arduino et la masse (GND) (sur le schéma, A, B, C, D, E et F représentent les 6 broches de l'Arduino qui sont utilisées pour contrôler nos 6 LEDs).

Cette méthode accapare beaucoup de sorties, mais le fonctionnement est simple: pour allumer la LED L1, vous placez la broche A au niveau logique HAUT. Pour éteindre la LED L1, vous placez la broche A au niveau logique BAS. Et ainsi de suite pour les 5 autres LEDs.
Voici donc le sketch correspondant à ce circuit (les broches 3 à 8 de l'Arduino sont utilisées). Comme ce sera le cas dans les autres programmes de ce billet, les 12 motifs qui seront successivement affichés par les 6 LEDs sont définis dès le départ dans un tableau bidimensionnel ("1" quand la LED est allumée, "0" quand elle est éteinte).


Multiplexing

Essayons maintenant le multiplexing, qui consiste à associer une broche de l'Arduino pour chaque ligne, ainsi qu'une broche de l'Arduino pour chaque colonne de notre matrice de LEDs. Puisque nos 6 LEDs forment un rectangle de 2 LEDs de largeur et de 3 LEDs de hauteur, nous avons 2 colonnes et 3 lignes, donc un total de 5 broches sont nécessaires (d'accord, ce n'est qu'une broche de moins que pour le montage précédent, mais plus contrôlez un grand nombre de LEDs, plus l'économie de broches sera substantiel).

Cette fois, nous ne branchons rien à la masse (GND). Si vous désirez allumer la LED L1 dans le schéma ci-dessous, vous devez mettre la broche A au niveau logique HAUT, et la broche C au niveau logique BAS, ce qui fera circuler un courant de A vers C. Si la broche B est au niveau logique BAS, et les broches D et E sont au niveau logique HAUT, toutes les autres LEDs demeureront éteintes (soit parce qu'il n'y a pas de différence de potentiel, soit parce que le courant essaie sans succès de circuler dans le sens bloquant de la diode).
Le tableau ci-dessous montre l'état logique que doit avoir chacune des 5 broches pour allumer chaque LED individuellement.

LED
A
B
C
D
E
L1
HAUT
BAS
BAS
HAUT
HAUT
L2
BAS
HAUT
BAS
HAUT
HAUT
L3
HAUT
BAS
HAUT
BAS
HAUT
L4
BAS
HAUT
HAUT
BAS
HAUT
L5
HAUT
BAS
HAUT
HAUT
BAS
L6
BAS
HAUT
HAUT
HAUT
BAS

Là où les choses se corsent un peu, c'est si vous désirez allumer plusieurs LEDs à la fois. Par exemple, supposons que vous désirez allumer L1 et L4 en même temps, pendant que toutes les autres LEDs demeurent éteintes. Vous pourriez penser que la solution consiste à placer la broche A au niveau logique HAUT et la broche C au niveau logique BAS pour allumer L1, tout en plaçant la broche B au niveau logique HAUT et la broche D au niveau logique BAS pour allumer L4.  Mais si vous procédez de cette façon, 2 autres LEDs vont s'allumer: L2 (puisque B est HAUT et C est bas) et L3 (puisque A est HAUT et D est BAS).

Pour ne pas perdre le contrôle, en multiplexing, on n'allume qu'une seule LED à la fois. On peut par contre donner l'illusion que plusieurs LEDs sont allumées en même temps grâce à la persistance rétinienne: si vous allumer L1, puis ensuite L4, puis ensuite L1, etc., très rapidement, le clignotement rapide des LEDs sera imperceptible à l'oeil nu, et les deux LEDs sembleront allumées en même temps (alors qu'elles ne le sont pas vraiment).

Voici ce que ça donne comme sketch: c'est un tout petit peu plus complexe que le précédent. Par exemple, on ne peut pas se contenter d'allumer deux LEDs et de paralyser le processus au moyen d'un delay(): en attendant le prochain changement de motif, on doit continuer d'allumer par alternance les LEDs qui doivent l'être.

Il faut également s'assurer que l'intensité lumineuse de chaque LED demeurera la même peu importe le nombre de LEDs allumées: si la LED 1 doit paraître allumée pendant que toutes les autres sont éteintes, elle sera en réalité allumée une fois sur six, soit la même fréquence que lorsque toutes les LEDs semblent allumées en même temps.


Charlieplexing

Le schéma ci-dessous montre 6 LEDs connectées à la façon charlieplexing: cette fois, 3 broches de l'Arduino seront suffisantes pour contrôler chacune de nos 6 LEDs.

Par exemple, pour allumer la LED L1, il faut que la broche B soit au niveau logique haut, et que la broche A soit au niveau logique bas. Mais attention: la broche C ne doit pas être au niveau logique haut (sinon L5 va s'allumer aussi), ni au niveau logique bas (sinon L4 va s'allumer aussi)! Il faut plutôt la régler en mode INPUT (entrée), ce qui aura pour effet de lui procurer une très grande impédance (équivalent d'un circuit ouvert) et pour cette raison aucun courant ne la traversera.
Le tableau ci-dessous montre l'état que doit avoir chacune des trois broches A, B et C pour allumer chaque LED individuellement.

LED
A
B
C
L1
BAS
HAUT
ENTREE
L2
HAUT
BAS
ENTREE
L3
ENTREE
BAS
HAUT
L4
ENTREE
HAUT
BAS
L5
BAS
ENTREE
HAUT
L6
HAUT
ENTREE
BAS

Tout comme c'est le cas en multiplexing, nous allumons les LEDs une à la fois, et c'est le phénomène de persistance rétinienne qui nous donne l'illusion que plusieurs LEDs sont allumées en même temps.


Yves Pelletier   (TwitterFacebook)

Related Posts Plugin for WordPress, Blogger...