L’arduino Uno permet la lecture une valeur analogique à partir des broches A0..A3.
Ce type d’entrée permet de lire la position, par exemple, du potentiomètre (contrôle de volume ou d’intensité) d’un gradateur pour une lumière dans une pièce de la maison.
Pour l’exemple suivant, nous aurons besoin de connecter le module Grove ‘Potentiomètre’ au connecteur A0 du Hat Grove.
Note: Les entrées analogues de l’ATMEGA 328P ont une résolution de 10 bits. C-a-d qu’une valeur entre 0 et 1023 sera retournée lors de la lecture d’un senseur analogique.
/* -------------------------------------------------------------------------- Projet: Introduction à Arduino, la broche analogique. Nom du fichier: digitalRead.uno Auteur: Alain Boudreault Date: 2022.09.10 --------------------------------------------------------------------------- Description: Petit programme qui lit la valeur d'un module analogique (potentiomètre) et affiche la valeur dans la console série --------------------------------------------------------------------------- M-A-J: 2022.09.14 - Nom des contantes en caractères majuscules. --------------------------------------------------------------------------- */ //********************************** // Les constantes //********************************** const int BROCHE_DU_SENSEUR = A0; // La broche du potentiomètre const int BROCHE_DE_LA_DEL = 3; // La broche de la DEL. const int VITESSE_UART = 9600; // Vitesse de la console série //********************************** void setup() { pinMode(BROCHE_DE_LA_DEL, OUTPUT); Serial.begin(VITESSE_UART ); } // setup() //********************************** void loop() { int valeurDuPotentiometre = 0; // Lire et afficher la valeur du potentiomètre // NOTE: Les broches analogiques n'ont pas à être initialisées. valeurDuPotentiometre = analogRead(BROCHE_DU_SENSEUR); Serial.print("Valeur du pot: "); Serial.println(valeurDuPotentiometre); // Ajout d'un délai pour ne pas saturer le moniteur série delay(50); } // loop() //****** FIN DU FICHIER
1.2 – Tester l’exemple
Il faut faire clignoter la DEL connectée sur D3 en utilisant la valeur du potentiomètre.
Par exemple,
ATTENTION: La solution est affichée à la section suivante. Si possible, résistez à la tentation de la consulter avant d’avoir tenter un essai ?.
1.3S – Solution du laboratoire 1.3.
// Les constantes const int BROCHE_DU_SENSEUR = A0; // La broche du potentiomètre const int BROCHE_DE_LA_DEL = 3; // La broche de la DEL. const int VITESSE_UART = 9600; //********************************** void setup() { pinMode(BROCHE_DE_LA_DEL, OUTPUT); Serial.begin(VITESSE_UART ); } // setup() //********************************** void loop() { int valeurDuPotentiometre = analogRead(BROCHE_DU_SENSEUR); Serial.print("Valeur du pot: "); Serial.println(valeurDuPotentiometre); // Allumer/éteindre la DEL en utilisant la valeur du potentiomètre digitalWrite(BROCHE_DE_LA_DEL, HIGH); delay(valeurDuPotentiometre); digitalWrite(BROCHE_DE_LA_DEL, LOW); delay(valeurDuPotentiometre); } // loop() //****** FIN DU FICHIER
Modifier le code source de l’exemple précédent pour que la DEL clignote seulement si la valeur du potentiomètre est comprise entre 200 et 800. Sinon, la DEL doit demeurer éteinte.
Il faut définir les valeurs limites avec des constantes (const int), C-a-d, il ne faut pas coder 200 et 800 à la dure dans votre code.
Écrire un programme qui démarre le clignotement d’une DEL si le bouton poussoir est appuyé une fois et qui arrête le clignotement de la DEL à la prochaine utilisation du bouton poussoir.
La vitesse de clignotement est renseignée par la valeur du potentiomètre.
INDICE: Voir permutation bouton
Voir la section 4.2 – La fonction map(value, fromLow, fromHigh, toLow, toHigh)
Il est possible de simuler un signal de sortie de type analogique pour par exemple varier l’intensité d’une DEL ou bien la vitesse d’un moteur.
Cette simulation est obtenue en variant la durée de l’état allumé et de l’état éteint.
Voici un graphe de démonstration
Référence: Arduino.cc
La fonctionnalité PWM est obtenue grâce à la fonction analogWrite(0..255).
NOTE: Sur Arduino Uno, PWM est disponible seulement sur les broches 3, 5, 6, 9, 10 et 11.
4.1 – Varier l’intensité d’une DEL grâce à PWM. – version 01
#define BROCHE_DEL 3 // LED sur pin 3 #define DELAI 20 #define UNE_SECONDE 1000 void setup() { pinMode(BROCHE_DEL, OUTPUT); // Broche de la DEL en mode OUTPUT } // setup() void loop() { static byte intensiteDEL = 255; analogWrite(BROCHE_DEL, intensiteDEL ); // Allumer la DEL avec le mode PWM intensiteDEL--; // Diminuer la valeur d'intensité de la DEL if ( intensiteDEL == 0) { // Si intensité de la DEL est = 0 alors remettre à 255 intensiteDEL = 255; delay(UNE_SECONDE / 2); // Laisser la DEL éteinte pendant 1/2 sec. } // if ( intensiteDEL == 0) delay(DELAI); // Ralentir un peu la variation d'intensité de la DEL. } // loop()
4.1 – Varier l’intensité d’une DEL grâce à PWM. – version 02 (optimisée)
int ledPin = 3; // LED sur pin 3 int intensiteDEL = 255; int delai = 20; void setup() { pinMode(ledPin, OUTPUT); // Broche de la DEL en mode OUTPUT } void loop() { analogWrite(ledPin, --intensiteDEL ); if (!intensiteDEL) { intensiteDEL = 255; delay(500); // Laisser la DEL éteinte pendant 1/2 sec. } delay(delai); // Ralentir un peu la variation d'intensité de la DEL. }
Il peut être parfois utile de ramener une plage de valeurs, par exemple [0..1023] vers une autre plage de valeurs, par exemple [0.255].
Si nous voulions contrôler l’intensité d’une DEL, en utilisant PWM, par un potentiomètre connecté à une source analogique, il faudrait concilier alors les deux plages de valeurs.
La librairie de développement Arduino propose la fonction map() pour adresser cette situation.
map(value, fromLow, fromHigh, toLow, toHigh)
value
: le nombre à convertirfromLow
: la valeur minimum de l’étendu à convertirfromHigh
: la valeur maximum de l’étendu à convertirtoLow
: la valeur minimum de l’étendu désirétoHigh
: la valeur maximum de l’étendu désiré
/* Fichier: fn-map-println.ino Auteur: Alain Boudreault Date: 2021.09.17 -------------------------------------------------------------------------- Description: Exemple d'une conversion des valeurs d'une entrée digitale comprises entre 0..1023 vers une plage de valeurs comprises entre 0.255. Les valeurs converties sont affichées dans le terminal série en utilisant Serial.print() -------------------------------------------------------------------------- M-A-J: -------------------------------------------------------------------------- */ // Définition des constantes const int brocheDuSenseur = A0; // Sélection de la broche du potentiomètre const int vitesseUART = 19200; // Vitesse du port de communication série // Les variables globales int valeurDuPotentiometre = 0; // --------------------------------------- // Initialisation des paramètres de départ // --------------------------------------- void setup() { Serial.begin(vitesseUART); Serial.print("Programme: fn-map-print.ino\n"); Serial.print("Auteur: Alain Boudreault\n"); Serial.print("----------------------------\n"); Serial.print("---- Début du programme ----\n"); Serial.print("----------------------------\n\n"); } // setup() // ------------------------------------- // Fonction principale de l'application // ------------------------------------- void loop() { // Boucler sur la prochaine ligne tant que la valeur du Pot n'aura pas changée de plus de 1/1023. while ( abs ( valeurDuPotentiometre - analogRead(brocheDuSenseur) ) < 2 ); // abs(valeurDuPotentiometre); // Lire et stocker la valeur du potentiomètre // NOTE: Les broches analogiques n'ont pas à être initialisées. valeurDuPotentiometre = analogRead(brocheDuSenseur); // Convertir la plage des valeurs int valeurConvertieDuPotentiometre = map(valeurDuPotentiometre, 0, 1023, 0, 255); // Afficher les résultats en utilisant Serial.print() Serial.print("Valeur du pot avant conversion: "); Serial.print(valeurDuPotentiometre); Serial.print(" après conversion: "); Serial.println(valeurConvertieDuPotentiometre); // Ajout d'un délai pour ne pas saturer le moniteur série delay(500); } // loop()
/* Fichier: fn-map-stream.ino Auteur: Alain Boudreault Date: 2021.09.17 -------------------------------------------------------------------------- Description: Exemple d'une conversion des valeurs d'une entrée digitale comprises entre 0..1023 vers une plage de valeurs comprises entre 0.255. Les valeurs converties sont affichées dans le terminal série en utilisant les Streams C++ (librairie de Mikal Hart) -------------------------------------------------------------------------- M-A-J: -------------------------------------------------------------------------- */ // https://github.com/janelia-arduino/Streaming #include <Streaming.h> // Définition des constantes const int brocheDuSenseur = A0; // Sélection de la broche du potentiomètre const int vitesseUART = 19200; // Vitesse du port de communication série // Les variables globales int valeurDuPotentiometre = 0; // --------------------------------------- // Initialisation des paramètres de départ // --------------------------------------- void setup() { Serial.begin(vitesseUART); Serial << "Programme: fn-map-stream.ino" << endl; Serial << "Auteur: Alain Boudreault" << endl; Serial << "----------------------------" << endl; Serial << "---- Début du programme ----" << endl; Serial << "----------------------------" << endl << endl; } // setup() // ------------------------------------- // Fonction principale de l'application // ------------------------------------- void loop() { // Boucler sur la prochaine ligne tant que la valeur du Pot n'aura pas changée de plus de 1/1023. while ( abs ( valeurDuPotentiometre - analogRead(brocheDuSenseur) ) < 2 ); // abs(valeurDuPotentiometre); // Lire et stocker la valeur du potentiomètre // NOTE: Les broches analogiques n'ont pas à être initialisées. valeurDuPotentiometre = analogRead(brocheDuSenseur); // Convertir la plage des valeurs int valeurConvertieDuPotentiometre = map(valeurDuPotentiometre, 0, 1023, 0, 255); // Afficher les résultats en utilisant les Streams C++ Serial << "Valeur du pot avant conversion: " << valeurDuPotentiometre << " après conversion: " << valeurConvertieDuPotentiometre << endl; // Ajout d'un délai pour ne pas saturer le moniteur série delay(500); } // loop()
/* Fichier: fn-map-sprintf.ino Auteur: Alain Boudreault Date: 2021.09.17 -------------------------------------------------------------------------- Description: Exemple d'une conversion des valeurs d'une entrée digitale comprises entre 0..1023 vers une plage de valeurs comprises entre 0.255. Les valeurs converties sont affichées dans le terminal série en utilisant la fonction sprintf() -------------------------------------------------------------------------- M-A-J: -------------------------------------------------------------------------- */ // Définition des constantes const int brocheDuSenseur = A0; // Sélection de la broche du potentiomètre const int vitesseUART = 19200; // Vitesse du port de communication série // Les variables globales int valeurDuPotentiometre = 0; char chaine[80]; // --------------------------------------- // Initialisation des paramètres de départ // --------------------------------------- void setup() { Serial.begin(vitesseUART); Serial.print("Programme: fn-map-print.ino\n"); Serial.print("Auteur: Alain Boudreault\n"); Serial.print("----------------------------\n"); Serial.print("---- Début du programme ----\n"); Serial.print("----------------------------\n\n"); } // setup() // ------------------------------------- // Fonction principale de l'application // ------------------------------------- void loop() { // Boucler sur la prochaine ligne tant que la valeur du Pot n'aura pas changée de plus de 1/1023. while ( abs ( valeurDuPotentiometre - analogRead(brocheDuSenseur) ) < 2 ); // abs(valeurDuPotentiometre); // Lire et stocker la valeur du potentiomètre // NOTE: Les broches analogiques n'ont pas à être initialisées. valeurDuPotentiometre = analogRead(brocheDuSenseur); // Convertir la plage des valeurs int valeurConvertieDuPotentiometre = map(valeurDuPotentiometre, 0, 1023, 0, 255); // Afficher les résultats en utilisant sprintf() sprintf(chaine, "Valeur du pot avant conversion: %d, après conversion: %d", valeurDuPotentiometre, valeurConvertieDuPotentiometre); Serial.println(chaine); // Ajout d'un délai pour ne pas saturer le moniteur série delay(500); } // loop()
NOTE: Pour des raisons de performance et d’optimisation de la mémoire, la fonction sprintf() dans Arduino ne supporte pas les nombres réels (float). Une solution est disponible ici.
Écrire un programme qui permet de varier l’intensité d’une DEL connectée sur D6 à partir d’un potentiomètre connecté sur A2.
Note: Il faut ramener les valeurs de Pot entre 0 et 255.
Rappel – Instruction ‘for’
for (int variable; condition tant que vrai; modification de la variable) inst; ou {bloc}
Par exemple:
// Voici une boucle de 10 itérations ( 0 à 9 )
for (int i=0; i < 10; i++) {}
5.1 – Voici un exemple complet d’une boucle ‘for’
void setup() { Serial.begin(9600); Serial.println("Debut du programme\n"); // Boucle 1 Serial.println("BOUCLE DE 0 A 9"); for (int i = 0; i < 10; i++) { Serial.print(i); Serial.println(" - Yo!"); } // Boucle 2 Serial.println("\n\nBOUCLE DE 10 A 1"); for (int i = 10; i > 0; i--) { Serial.print(i); Serial.println(" - Yo!"); } } void loop() { // put your main code here, to run repeatedly: }
5.2 – Varier l’intensité d’une DEL en utilisant une boucle ‘for’
// Varier l'intensité d'une DEL, connectée sur D3, en utilisant une boucle 'for' int ledPin = 3; void setup() { // Rien à faire ici } void loop() { // Allumer graduellement la DEL en pas de 5 for (int intensite = 0 ; intensite <= 255; intensite += 5) { analogWrite(ledPin, intensite); delay(30); } // Éteindre graduellement la DEL en pas de 5 for (int intensite = 255 ; intensite >= 0; intensite -= 5) { analogWrite(ledPin, intensite); delay(30); } delay(500); // Maintenir la DEL éteinte 0,5 sec. }
5.3 – Tester l’application