L'objectif de cet atelier est de vous faire découvrir la programmation avancée du micro-contrôleur ATmega328P que l'on retrouve sur les cartes Arduino Uno et Nano. Nous nous intéresserons ici aux registres internes et aux vecteurs d'interruption de l'ATmega328P. Autrement dit, le code que nous allons écrire dans le cadre de cet atelier est très spécifique à l'ATmega328P et ne pourra donc fonctionner que sur ce micro-contrôleur.
![]() |
![]() |
Je vous propose de reprendre le petit circuit électronique que nous avions réalisé dans le cadre de l'atelier sur le contrôle d'un chenillard à 8 LEDs par un bouton poussoir, que nous allons adapter et compléter par un transducteur ultrasonique HC-SR04 pour nous permettre de mesurer des distances en utilisant directement les registres et les vecteurs d'interruption de l'ATmega328P.
J'utilise ici une carte Arduino Nano, mais vous pouvez tout à fait réaliser le même montage avec une carte Arduino Uno. Le raccordement des LEDs, du bouton poussoir et du capteur HC-SR04 sur les broches d'entrées-sorties numériques est exactement le même sur ces deux cartes Arduino.
-
Les anodes de chaque LED sont respectivement reliées aux broches D12 à D5 de la carte Arduino. Les cathodes sont reliée à la masse (broche GND de la carte Arduino) au travers d'une résistance de 220 Ω pour limiter l'intensité du courant à environ 15 mA.
-
Le bouton poussoir est inséré entre la broche D3 et la ligne d'alimentation 5V de la carte Arduino. La broche de lecture D3 est également ramenée à la masse (broche GND de la carte Arduino) par une résistance pull-down de 10 kΩ.
-
Le transducteur HC-SR04, quant à lui, dispose de 4 broches :
-
VCC qui est reliée à la ligne d'alimentation 5V de la carte Arduino,
-
GND qui est reliée à la masse (broche GND de la carte Arduino),
-
TRIG qui est reliée à la broche D4 de la carte Arduino,
-
ECHO qui est reliée :
- à la broche D2 de la carte Arduino,
- ainsi qu'à la masse (broche GND de la carte Arduino) par une résistance pull-down de 10 kΩ.
-
Voici une petite expérimentation que nous allons réaliser dans le cadre d'un exercice, qui met en œuvre l'utilisation du transducteur ultrasonique pour effectuer une mesure graduée de proximité sur la rampe de LEDs :
Pour la mise en œuvre des exercices qui vous sont proposés dans cet atelier, il vous sera utile de vous référer aux documentations suivantes :
- Documentation technique de l'ATmega328P
- Plans détaillés des entrées-sorties de la carte Arduino Uno
- Plans détaillés des entrées-sorties de la carte Arduino Nano
- Documentation technique du transducteur HC-SR04
Le transducteur HC-SR04 fournit en sortie, sur sa broche ECHO, une impulsion dont la durée ∆t en microsecondes permet de déduire la distance à laquelle se trouve l'objet qui a réfléchi le train d'ondes ultrasoniques à partir de la vitesse du son dans l'air. Cette vitesse varie en fonction de la pression atmosphérique, de la température et, dans de très faibles proportions, de l'humidité de l'air. En supposant que nos expérimentations sont effectuées au niveau de la mer, à pression atmosphérique normale, on peut se contenter d'évaluer la vitesse du son dans l'air en fonction de la température ambiante.
Pour vous faciliter la tâche, j'ai mis à votre disposition un petit outil en ligne qui effectue les calculs à votre place. Il fournit notamment la formule de calcul de la distance de l'obstacle en centimètres en fonction de ∆t. Dans les exercices proposés, nous considérerons que la température ambiante est de 25°C.
Ce petit calculateur nous permettra d'implémenter facilement la fonction de conversion us2cm()
:
/**
* @brief Constante de conversion durée => distance pour le capteur HC-SR04
*
* @note Cette constante permet de calculer la distance d'un obstacle réfléchissant
* le train d'ondes ultrasoniques en fonction de sa durée de propagation.
* Elle incorpore de manière implicite la vitesse du son dans l'air.
*
* La constante de conversion que nous utiliserons ici correspond à la
* vitesse du son dans l'air à 25°C évaluée à 346.68 m/s.
*/
constexpr float US_TO_CM = .017334f;
/**
* @brief Conversion durée => distance pour le capteur HC-SR04
*
* @param us Durée de propagation du train d'ondes ultrasoniques exprimée en microsecondes
* @return La distance de l'obstacle réfléchissant exprimée en centimètres
*/
float us2cm(float us) {
return us * US_TO_CM;
}
La configuration du projet est définie par les directives inscrites dans le fichier platformio.ini
:
; --------------------------------------------------------------------------------
; Atelier de programmation Robotic 974
; © 2021 Stéphane Calderoni
; --------------------------------------------------------------------------------
; Registres internes et interruptions de l'ATmega328P
; --------------------------------------------------------------------------------
[env:workshop]
platform = atmelavr
board = nanoatmega328new
framework = arduino
monitor_speed = 9600
Le projet est ici configuré pour être téléversé sur une carte Arduino Nano. Si, de votre côté, vous utilisez une carte Arduino Uno, vous devez remplacer la désignation de la carte board
par la valeur uno
:
board = uno
Les solutions des exercices se trouvent dans le répertoire src
:
src
├── 01-blink.cpp
├── 02-switch.cpp
├── 03-switch-int-v1.cpp
├── 04-switch-int-v2.cpp
├── 05-switch-debouncing.cpp
├── 06-binary-counter-v1.cpp
├── 07-binary-counter-v2.cpp
├── 08-hc-sr04.cpp
├── 09-hc-sr04-button.cpp
└── 10-proximity-sensor.cpp
Chaque fichier doit être compilé en excluant tous les autres avec la directive src_filter
dans le fichier de configuration platformio.ini
. Par exemple, pour compiler la solution de l'exercice n°10 :
; --------------------------------------------------------------------------------
; Atelier de programmation Robotic 974
; © 2021 Stéphane Calderoni
; --------------------------------------------------------------------------------
; Registres internes et interruptions de l'ATmega328P
; --------------------------------------------------------------------------------
[env:workshop]
platform = atmelavr
board = nanoatmega328new
framework = arduino
monitor_speed = 9600
src_filter = -<*> +<10-proximity-sensor.cpp>
Faire clignoter la LED connectée à la broche D12 à la manière de l'instruction suivante :
digitalWrite(12, millis() % 1024 < 512);
Solution : 01-blink.cpp
Allumer la LED connectée à la broche D12 lorsqu'on appuie sur le bouton poussoir, et l'éteindre lorsqu'on relâche le bouton. Autrement dit, cela revient à réécrire :
digitalWrite(12, digitalRead(3));
Solution : 02-switch.cpp
Allumer puis éteindre alternativement la LED connectée à la broche D12 à chaque pression sur le bouton poussoir. On cherchera ici à détecter les pressions sur le bouton par le déclenchement d'une interruption armée par la fonction attachInterrupt()
.
Remarque : on ne cherchera pas ici à éliminer l'effet rebond.
Solution : 03-switch-int-v1.cpp
Même exercice que le précédent mais, cette fois, sans utiliser la fonction attachInterrupt()
. On lui préfèrera l'usage direct du vecteur d'interruption INT1
, activé par la broche D3.
Remarque : on ne cherchera pas ici à éliminer l'effet rebond.
Solution : 04-switch-int-v2.cpp
Même exercice que le précédent mais, cette fois, en neutralisant l'effet rebond.
Solution : 05-switch-debouncing.cpp
Incrémenter un compteur entier codé sur 8 bits à chaque pression sur le bouton poussoir, et afficher sa valeur binaire sur l'octet représenté par les 8 LEDs.
Remarque : on ne cherchera pas ici à éliminer l'effet rebond.
Solution : 06-binary-counter-v1.cpp
Même exercice que le précédent mais, cette fois, cherchez à neutraliser l'effet rebond.
Solution : 07-binary-counter-v2.cpp
Lancer une séquence de mesures de distances à l'aide du transducteur ultrasonique. Les mesures doivent être effectuées périodiquement à une fréquence de 10 Hz (une mesure toutes les 100 ms). Les distances mesurées devront être affichées sur le moniteur série, au fil de l'eau.
Pour cet exercice, vous devrez utiliser le vecteur d'interruption INT0 qui surveille la broche de lecture D2 reliée à la broche ECHO du HC-SR04. Chaque mesure est initiée en maintenant la broche D4 (qui est reliée à la broche TRIG du HC-SR04) au niveau HIGH pendant 10 µs.
N'oubliez pas d'établir la formule de conversion durée => distance à l'aide du calculateur que j'ai mis à votre disposition.
Solution : 08-hc-sr04.cpp
Même exercice que le précédent mais, cette fois, en déclenchant une mesure à chaque pression sur le bouton poussoir.
Remarque : on ne cherchera pas ici à éliminer l'effet rebond.
Solution : 09-hc-sr04-button.cpp
Solution : 10-proximity-sensor.cpp