ex0ns

about
A Computer Science Student's blog, about programming, algorithms, hack and a lot more.

Débuts avec Arduino : Partie 1

01 Dec 2012

C'est bon, c'est fait, j'ai craqué... Et oui, il y a un mois de ça, j'ai recu mon Arduino, mon premier pas dans le domaine : l'électronique !!

Ce vaste domaine qui me fascine depuis ma plus tendre enfance, époque à laquelle je démontais tout objet électronique dès lors qu'il m'intriguai de trop (et beaucoup y ont perdu la vie : ventilateur, vieux débris informatique, voitures télécommandés, et autres jouets en tout genre). Cependant n'ayant jamais étudié le domaine jusqu'à aujourd'hui, je dois avouer être complètement perdu, sans aucune notion viable en électricité.

Me plaindre ne fait pas parti de mon caractère et je me retrouve donc parcourant la toile à la recherce de documents (et google sait combien de documents il y a sur le sujet...), intéressants qui traitent des principales lois et propriétées à connaitre lorsque l'on commencer à jouer avec de l'électricité.

Une fois cette étape "achevée" (ou plutôt survolée par impatience) nous voici dans le le vif du sujet : Arduino ! Quelques tutoriaux basiques disponibles sur le site officiel ainsi que sur youtube permettent de prendre en main le sujet très rapidement, tutoriaux qui reposent pour le moment sur l'utilisation et la communication avec des LEDs, en intégrant des résistances, un potentiomètre afin de faire connaissance avec tout ce monde là et de se familiariser avec l'électronique.

Une chose me frappe cependant, dans les nombreux tutoriaux que j'ai suivi, une chose me frappe, il semblerait que les programmeurs de LEDs (débutants, ou instructeurs pour débutants sur Arduino) soient allergiques au boucles dans leur programmes et il m'est arrivé de trouver des codes faisant intervenir presque 10 LEDs, UNE à UNE ! Allumer, éteindre, allumer, éteindre, ce qui m'a quelque peu énervé lorsque l'on sait que nous pouvons effectuer les mêmes actions grâce à une instruction on ne peut plus basique telle que le "for" ou le "while" que n'importe quel débutant PEUT comprendre, mais il semblerait que le but soit de faire intégrer aux novices des mauvaises habitudes, dès le début, les rendant dépendants, preuve d'intelligence pour les auteurs qui forcent ainsi les utilisateurs à consulter la ressource plus fréquemment !

Il est vrai que je suis mauvaise langue et pousse probablement l'analyse trop loin sur ce dernier point, mais l'utilisation des boucles est tout de même quelque chose dinévitable lorsque l'on souhaite éxecuter une suite d'instructions répétitives.

Dans la suite de cet article le materiel que nous utiliserons est le suivant :

  • Un potentiomètre (résistance variable)
  • Quelques LED (au minimum 3-4)
  • Des résistances, environ 500ohm (plus ou moins)
  • Une Platine Labdec (plus communément appelé BreadBoard ou table de prototypage)
  • Des fils

La transmission d'informations

Premièrement, il faut savoir que vous pouvez faire transiter des informations entre Arduino et l'IDE grâce au "Serial Monitor" pour cela :

void setup(){
    Serial.begin(9600);
    Serial.println("Hello World"); 
    /*
     println pour un retour à la ligne automatique
     print   simplement pour afficher une information
    */
}

void loop(){ // On n'a pas besoin de la boucle pour le moment
}

Ici, on initialise la communication à 9600 baud ( bits par seconde ), arbitrairement, puis on écrit envoi la chaine "Hello World". Sur l'IDE dans l'onglet "Tools" activez le "Serial Monitor", vous devriez, devant vos yeux ébahis, voir apparaitre "Hello World".

Attaquons nous maintenant au potentiomètre

Fonctionnement d'un potentiomètre et lecture analogique

Avant de pouvoir faire quoi que ce soit, il faut comprendre le fonctionnement du potentiomètre et ce qu'il nous retourne, vous l'aurez deviné, on va utiliser la fonction Serial pour analyser tout ça. Un potentiomètre a 3 branches, une pour l'alimentation, une autre pour la valeur de sortie (celle du milieu) et enfin, la troisième que l'on branche à la sortie (ground), ce qui nous donne le schéma suivant : schema potentiomètre Remarque importante : Pour lire une valeur sur un PIN, il faut utiliser la fonction analogRead(int pint) c'est pour cela que la branche du milieu est connectée à un PIN de type "Analog In" (qui commence avec avec la lettre A).

Le code :

void setup(){
    Serial.begin(9600);
}

void loop(){
    Serial.println(analogRead(0)); // On lit la valeur sur le pin analogique 0 (A0) puis on l'affiche
    delay(1000); // On attend une seconde
}

En jouant un peu avec le potentiomètre, on se rend compte que la valeur lue sur A0 varie entre 1023 et 0.

Make the LEDs rock

En utilisant ce que nous avons vu au dessus, nous allons nous amuser à allumer 4 LEDs dans un ordre... incertain... En effet, le but est de lire sur une entrée analogique la valeur envoyée par le potentiomètre puis d'affiche les LEDs branchées sur les PINs 6 à 10 de l'Arduino, un bout de code valant mieux que 10 phrases (surtout les mienne), voici le code :

int ancien = 0;
void setup(){
    for(int i = 6; i < 10; i++) // Pour les LEDs branchées sur les PIN 6 à 10 de l'arduino (6 inclu 10 exclu)
    pinMode(i, OUTPUT);
}

void loop(){
    int value = analogRead(1);
    value %= 4;
    digitalWrite(ancien+6, LOW);
    digitalWrite(value+6, HIGH);
    ancien  = value;
    delay(500);
}

Voici quelques explications: value %= 4 : permet d'obtenir le reste de la division par 4, cette astuce est fort utile pour ramener de très grandes valeurs à l'intérieur d'un interval plus petit,en effet, le reste de la division par un nombre est toujours inférieur à ce nombre, dans notre cas, value prend donc une valeurs située entre 0 et 4 (la borne inférieure est toujours inclue, l'extérieur exclue). value+6 : Nos LEDs sont branchées sur les PIN 6 à 10, il suffit donc d'ajouter 6 à la valeur pour allumer une de ces quatre leds. ancien = value : cette ligne permet de se souvenir quelle LED a été allumé à la boucle précédente, pour ainsi la laisser allumé jusqu'à ce que l'on modifie le potentiomètre afin d'allumer une autre LED. digitalWrite(ancien+6, LOW): Sans cette ligne, les LEDS s'allumerai une part une sans jamais s'éteindre.

En somme, rien de très complexe, l'ordre dépend du reste de la division et est donc "complètement" aléatoire. Mais nous allons maintenant nous intéresser à la manipulation de LED les unes à la suite des autres dans un ordre choisi, afin de manipuler un peu tout ce monde à l'aide des fameuses BOUCLES dont je vous parle depuis le début. Vidéo :

Chenillards à gogo !

Premier projet : allumer 4-5 LEDs les une la suite des autres, en faisant varier la vitesse. Le materiel necessaire est le même que la liste énoncée ci dessus, voici le schema du montage : AP1_2 4 résistances, 4 leds, un potentiomètre, nous voilà pret pour la grande aventure, enfin il manque tout de même un élément relativement important : le code que voici :

void setup(){
 for(int i = 6; i < 10 ; i++)
  pinMode(i, OUTPUT); 
}

void loop(){
 int wait = analogRead(0);
 for(int i = 6; i < 10 ; i++){
  digitalWrite(i, HIGH);
  delay(wait);
  digitalWrite(i, LOW);
 } 
}

On récupère la valeur sur l'entrée Analogique 0 (celle branchée au potentiomètre) cette valeur sera utilisée dans le delay, plus la résistance est grande, plus la valeur est petite, plus le delai sera long et donc plus l'animation semblera lente. On allume, on attend puis on éteint sans attendre de nouveau, et cela car nous voulons que l'enchainement du chenillard soit fluide en rajoutant un delai, il y aurait une période pendant laquelle aucune LED n'est allumée : MOCHE !

Après plusieurs tests vous vous êtes peu-être rendu compte que la variation de la vitesse est loin d'être précise, cela s'explique par le fait que nous lisons la valeur du courant transmis à travers le potentiomètre une seule fois pour les quatres LEDs, si vous modifiez cette valeur entre la 2ième et 3ième LED, elle ne sera prise en compte qu'au tour suivant, pour combler cela transformez votre loop() comme suit :

void loop(){
 for(int i = 6; i < 10 ; i++){
  int wait = analogRead(0);
  digitalWrite(i, HIGH);
  delay(wait);
  digitalWrite(i, LOW);
 } 
}

Vous devriez sentir une nette différence entre les deux codes, comme quoi, parfois cela ne tient qu'a une ligne :)

La fonction map

Avec le code précendent, la valeur du delay peut varier entre 0 et 1023 c'est à dire en 0ms et 1,23s ce que certains peuvent trouver très restrictif, pour contourner cette contrainte, il faut utiliser la fonction Map qui s'utilise comme suit si nous voulons convertir une valeur située entre 0 et 1023 en une valeur dans l'interval [0, 200]

wait = map(wait, 0, 1023, 0, 200);

Mais, grâce à cette fonction nous pouvons également attendre des delais largements supérieur à 1,23 secondes, par exemple :

wait = map(wait, 0, 1023, 1500, 2500);

Dans ce cas, le delai minimal sera de 1,5 seconde et le maximal de 2,5 secondes, ce qui peut s'avérer utile dans certains cas voici le code complet dans lequel le delai minimal est de 0,5 seconde et le maximal de 3 secondes!

void loop(){
    for(int i = 6; i < 10 ; i++){
        int wait = analogRead(0);
        wait = map(wait, 0, 1023, 500, 3000);
        digitalWrite(i, HIGH);
        delay(wait);
        digitalWrite(i, LOW);
   } 
}

A partir de là, nous avons tout les outils nécessaire pour nous amuser simplement avec des LEDs, et faire toute sorte de chenillard, par exemple (je n'écrirai maintenant que le void loop() le void setup() ne change pas !

void loop(){
    for(int i = 6; i < 10 ; i++){
        int wait = analogRead(0);
        digitalWrite(i, HIGH);
        delay(wait);

   } 
   for(int i = 6; i < 10; i++)
             digitalWrite(i, LOW);

   delay(200);
}

Dans ce cas, les LED vont s'allumer les unes après les autres, puis s'éteindront simultanément pour recommencer (une sorte "barre de progression")

Autres "astuces"

Imaginons que les LEDs ne soient pas situées sur des PINs qui se suivent, mais sur les PIN 3, 8 et 10, dans ce cas, la boucle précédente ne fonctionnerai pas, pour pallier à ce problème il faut utiliser un tableau:

int led = [3, 8, 10];

Dans ce code, on déclare un tableau avec trois valeurs : 3;8 et 10 qui correspondent au PIN des LEDs, maintenant, il faut modifier la boucle :

void loop(){
    for(int i = 0; i < 3 ; i++){ // Nous avons trois LED
        int wait = analogRead(0);
        wait = map(wait, 0, 1023, 500, 3000);
        digitalWrite(led[i], HIGH); // Le PIN situé à la case "i" du tableau
        delay(wait);
        digitalWrite(led[i], LOW);
   } 
}

Attention : comme dans beaucoup de langage, les tableaux sont numérotés à partir de 0, donc si votre tableau contient 3 éléments, le troisième élément se trouve à l'indice 2.