• 15 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

J'ai tout compris !

Donnez du mouvement à vos montages avec un servo-moteur (... et la fonction Switch)

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Je dois avouer que nous abordons maintenant une partie des possibilités qu'offre l'Arduino qui me fait toujours l'effet de mon premier cadeau de Noël motorisé (livré avec les piles bien sûr...), car en effet, nous allons donner du mouvement à nos montages !

Dans ce chapitre vous allez découvrir comment utiliser un servo-moteur et le programmer avec l’Arduino.

J'en profiterai pour vous apporter un nouveau mot de vocabulaire pour effectuer des conditions : le switch.

En route pour de nouveaux montages !

Le servo-moteur

Le nom lui-même est intrigant. Notez bien qu'il ne s'agit pas de cerveau (oui Lukas, ce qui se trouve entre vos deux oreilles, enfin, j'espère...) mais bien de servo. Ce mot vient du latin "servus", qui signifiait esclave. Un servo moteur est donc un moteur esclave... mais de quoi ?

Tout d'abord, une petite image de présentation :

Quelques servo-moteurs (source : francerobotique.com)
Quelques servo-moteurs (source : francerobotique.com)

Vous remarquez un bloc, un axe et une roue trouée (ou une sorte de barre trouée aussi) sur l'axe.

Des servo-moteurs, il en existe de plusieurs tailles : des plus petits de quelques grammes, tout en plastique, au plus gros de plusieurs kilogrammes, en métal. L'énergie qui les pilote et les fait n'est pas toujours électrique, il existe des servo-moteurs hydrauliques.

Dans notre cas, je parlerai de servo-moteurs électriques de petite taille comme ceux que l'on utilise souvent en modélisme.

C'est bien beau tout ça, mais c'est quoi alors un servo-moteur ?

Alors avant d'aborder le côté servo, voyons d'abord le côté moteur...

Un servo-moteur contient (dans le cas de ceux que vous utiliserez avec votre Arduino) un moteur à courant continu. Nous aborderons plus précisément ce que c'est dans le chapitre suivant, mais pour résumer, c'est un mécanisme qui tourne lorsqu'il est parcouru par l'électricité. 

Le moteur du servo-moteur en revanche, n'est pas un simple moteur, il est associé à une série d'engrenages qui va lui permettre de gagner un puissance. Mais comme rien n'est gratuit, ce gain en puissance réduit sa vitesse de rotation.

Aparté sur les engrenages

Un engrenage est une roue denté qui en tournant entraîne (engrène) une autre roue, dentée aussi. Ça a l'air évident mais deux principes fondamentaux s'ajoutent pour bien maîtriser la notion :

  1. Si la première roue dentée tourne dans un sens, la seconde tournera dans l'autre sens. On peut donc dire que le sens de rotation s'inverse d'une roue à l'autre dans un engrenage.

  2. Si les deux roues dentées ne font pas la même taille, la vitesse de rotation de chaque roue sera différente. En effet si la première roue a 6 dents, et la seconde 24 dents, la première effectuera 4 tours alors que la seconde n'en fera qu'un (6 dents* 4 tours= 24 dents). N'oublions pas qu'une roue entraîne l'autre dent à dent.

Un engrenage de deux roues :10 et 20 dents. (source : futura-sciences.com)
Un engrenage de deux roues : 10 et 20 dents. (source : futura-sciences.com)

Dans l'image ci-dessus, la grande roue effectue 1 tour pendant que la petite en effectue 2.

Les dentures de l'image sont droites, mais il existe d'autres formes dont celles en V de monsieur Citroën, qui en a fait le logo de sa marque. ;)

La conséquence de la différence de taille entre deux roues (la petite est appelée pignon) est que la transmission du mouvement gagne en puissance (couple) de la petite vers la grande roue. Je ne vais pas entrer ici dans des explications physiques mais retenez que :

  • Si vous voulez accélérer le mouvement, le moteur doit entraîner la grande roue qui entraînera la petite. Dans ce cas la puissance de rotation (le couple) de l'axe de la petite roue sera plus faible.

  • Si vous souhaitez gagner en couple, vous devrez entraîner la petite roue par le moteur, qui entraînera la plus grande. Dans ce cas, vous perdrez de la vitesse.

Dernier point, lorsque plusieurs roues dentées s'entraînent à la suite les unes des autres, on parle de train d'engrenages.

Revenons à nos servo-moteurs.

Le moteur du servo entraîne un train d'engrenage qui lui permet de gagner en puissance de rotation. L'axe qui sort du servo-moteur (celui qu'on utilise) tourne donc bien moins vite que celui du moteur qui est à l'intérieur, en revanche son couple est plus important.

Servomoteur Dagu RS001A (source : gotronic.fr)
Servomoteur Dagu RS001A (source : gotronic.fr)

Vous pouvez voir sur l'image, grâce au boîtier transparent, les trains d'engrenages à l'intérieur du servo-moteur.

Le couple de ce servo est de 1,5 kg.cm.

Mais c'est quoi au juste cette histoire de couple ?

Le couple est l'effort de rotation que l'on peut appliquer sur un axe. C'est-à-dire, quelle force est nécessaire pour que l'axe tourne. Voici un petit schéma :

Schéma d'illustration du couple de rotation
Schéma d'illustration du couple de rotation

L'axe est celui du servo-moteur. Le bras représente la partie solide sur laquelle on va fixer quelque chose. Le poids représente la force qui va être appliquée sur le bras (soit l'axe tourne et le bras entraîne le poids, soit l'axe est fixe et le poids tire sur le bras et provoque sa rotation). La distance qui sépare l'axe de la position du poids est une donnée importante. En effet, plus le poids est éloigné de l'axe, plus l'effort nécessaire pour le soulever sera important. C'est cette capacité d'effort qui est appelée couple.

La mesure du couple est en kg.cm (kilogramme-centimètre), et pour comprendre, 1,5 kg.cm signifie que le servo pourra soulever un poids de 1,5 kg placé à 1 cm de son axe.

Si cela vous paraît obscur, ne vous découragez pas car c’est un point primordial dans l’utilisation des servo-moteurs. En effet, si vous demandez à un servo-moteur une rotation au-dessus de ses forces (si le couple nécessaire à la rotation est supérieur au couple qu'il fournit) vous risquerez d'endommager votre servo-moteur, et surtout, votre projet ne pourra pas fonctionner.

Donc retenez bien : un servo-moteur a un axe qui fournit une rotation d’une certaine force appelée couple, à ne pas dépasser pour ne pas endommager le moteur.

Bien, nous avons vu le côté moteur, voyons maintenant le côté servo...

On l'a dit au-dessus, servo veut dire esclave. En effet, non seulement un servo-moteur peut tourner, mais surtout, il peut maintenir sa position (tant que son couple le permet) ! C'est d'ailleurs très souvent pour cette utilisation qu'il est apprécié. On lui commande de se mettre à une position précise, il se positionne puis ne bouge plus.

Le moteur ne tourne plus ?

Attention, c'est l'axe du servo-moteur qui ne bouge plus. Le moteur, lui est toujours en action, mais il tourne très peu dans un sens puis dans l'autre pour justement garder cet équilibre. C'est ce qu'on appelle l'asservissement. Ceci est rendu possible grâce à un peu d'électronique et aussi à un potentiomètre (voir le chapitre précédent).

En effet, nous allons demander, grâce à un code que nous verrons plus loin, au servo-moteur de se placer à une certaine position. Le moteur va tourner, entraîner son train d'engrenages qui va faire tourner l'axe du servo-moteur. À cet axe est lié un potentiomètre qui tourne en même temps ! C'est rusé, car il récupère de manière électrique (comme nous l'avons fait précédemment) la position de rotation du servo-moteur. Il la compare à la demande et ajuste la position en envoyant des ordres au moteur (son esclave).

Bon, ce n'est pas le potentiomètre qui envoie des ordres, mais un petit circuit électronique contenu dans le servo-moteur.

Du coup, notre servo-moteur maintient sa position (si le couple est suffisant pour le faire).

Les contraintes de rotation d'un servo-moteur

Il faut savoir qu'un servo-moteur est souvent limité dans sa rotation. En effet, il ne peut tourner que d'un demi-tour, soit 180° (Non Lukas, ce n'est pas si chaud que ça !). Il peut donc prendre 180 positions et les tenir.

Si vous lui demandez de se mettre à 30°, puis 170°, il ira d'une position à l'autre le plus rapidement possible pour ses capacités. On ne peut donc pas gérer facilement la vitesse de rotation d'un servo-moteur !

Certains servo-moteurs sont dits à rotation continue (c'est-à-dire qu'ils ne sont pas bloqués dans un sens ou dans l'autre).

L'utilisation et la programmation des servo-moteurs de ce chapitre concernent des servo-moteurs d'amplitude 180°.

Bien, je pense que nous avons suffisamment survolé le principe du servo-moteur. Voyons maintenant comment on le connecte à notre carte Arduino pour le mettre en mouvement...

Connexion d'un servo-moteur à une carte Arduino

Les servo-moteurs que vous utiliserez fonctionnent à l'électricité. On peut donc s'attendre à voir au moins deux fils, mais en fait, il y en a trois !

  • Le fil rouge qui se connecte à l'alimentation (voir avec le servo utilisé, souvent aux alentours de 5V),

  • Le fil noir (parfois marron) qui se connecte au ground,

  • Le fil jaune (parfois orange ou blanc) qui va servir de commande. Il se connecte à n'importe quelle sortie numérique de l'Arduino (de 0 à 13).

Du fait que le servo-moteur utilise un moteur, il peut être préférable de l'alimenter par une source différence que celle fournie par l'Arduino. Dans ce cas, il est nécessaire que les ground de l’Arduino, de l’alimentation et du servo-moteur soient connectés ensemble.

Voici le schéma du montage électrique :

Connexion d’un servo-moteur à une carte Arduino
Connexion d’un servo-moteur à une carte Arduino

Et voici la représentation Fritzing du montage :

Connexion d'un servo-moteur au pin 8 de l'Arduino
Connexion d'un servo-moteur au pin 8 de l'Arduino

Et là j'aurais tendance à dire : c'est fini ! Votre servo-moteur est connecté et prêt à l'emploi !

Voyons maintenant ce que nous pouvons lui demander...

Envoyez des ordres à un servo-moteur

Pour commander un servo-moteur, il faut lui envoyer ce qu'on appelle un train d'impulsions électriques (oui Lukas, si vous voulez, un train électrique...), on peut traduire par : des envois de courant électrique qui se suivent à intervalle et durée précis. L’intervalle de temps entre chaque impulsion envoyée est aussi appelé période.

Voici à quoi ressemble un train d'impulsions :

Un train d'impulsion de période 20ms
Un train d'impulsions de période 20ms

Il faut observer plusieurs choses :

  • La valeur de la tension est soit +5V (HIGH  de l'Arduino) soit 0V (LOW  de l'Arduino),

  • Les impulsions sont envoyées régulièrement, ici toutes les 20 millisecondes. C'est la durée généralement utilisée pour piloter un servo-moteur.

La durée de l'impulsion peut varier. C'est d'ailleurs grâce à elle que nous allons piloter notre servo-moteur.

Trois trains d'impulsions : 1ms, 1.5ms et 2ms de période 20ms
Trois trains d'impulsions : 1ms, 1.5ms et 2ms de période 20ms

Et voici comment le servo-moteur va interpréter ces impulsions :

  • Lors d'une impulsion à 1ms : le servo-moteur se met à la position 0°,

  • Lors d'une impulsion à 1.5 ms : le servo-moteur se met à la position 90°,

  • Lors d'une impulsion à 2ms : le servo-moteur se met à la position 180°.

On peut donc facilement faire un mappage des valeurs pour obtenir pour obtenir la durée de l'impulsion en fonction de l'angle :

int dureeImpulsion=map(angle,0,179,1000,2000);

La valeur de l'angle est entre 0° et 179°, le résultat sera entre 1 000 et 2 000 microsecondes (donc entre 1 et 2 millisecondes). Grâce à cette formule, on peut obtenir toutes les valeurs d'impulsions pour des positions entre 0° et 179°.

Mais comment envoyer une impulsion aussi précisément ?

Et bien nous allons utiliser l'horloge interne de l'Arduino ! Nous l'avons d'ailleurs déjà fait grâce à la fonction delay()  mais pour calculer en microsecondes, nous avons un autre fonction :

delayMicroseconds(valeur);

Il suffit ensuite d'envoyer du courant (HIGH) ou non (LOW) dans le PIN de commande du servo, en respectant la durée de l'impulsion et le temps entre chaque impulsion.

Je vous livre un code qui va nous permettre d’incliner le servo-moteur à différents angles entre 0° et 179° à partir de l’Arduino :

/*
Commande de servo-moteur par impulsion
Nanomaître 2015
Le servo est connecté au pin 8 de l'arduino
*/
int periode=20000;// période entre chaque début d'impulsion en microsecondes
int pinServo=8; // variable pour le pin connecté à la commande du servo

void setup() {
  pinMode(pinServo,OUTPUT);// on prépare le pin en mode OUTPUT
  digitalWrite(pinServo,LOW); // on l'initialise à l'état bas
}

//boucle principale
void loop() {
  for (int angle=0;angle<=180;angle+=20){//on fait varier l'angle de 0 à 180° par tranche de 20°
    setAngle(angle);// on appelle la fonction setAngle définie plus bas
  }
}

//fonction setAngle pour envoyer les impulsions
void setAngle(int a){
  int duree=map(a,0,179,1000,2000);// on transforme l'angle en microsecondes et on stocke dans la variable duree
  digitalWrite(pinServo,LOW);//on met le pin à l'état bas
  
  // la boucle qui suit est nécessaire 
  // pour laisser le temps au servo d'aller à sa position
  for (int t=0;t<300;t++){ 
    digitalWrite(pinServo,HIGH);// on envoie l'impulsion
    delayMicroseconds(duree); // pendant la bonne durée
    digitalWrite(pinServo,LOW); // on stoppe l'impulsion
    delayMicroseconds(periode-duree); // on attend le temps restant pour atteindre la période
  }
}

Envoyez et testez ! Si tout se passe bien, le servo prend une position extrême (0°) puis se déplace par tranche de 20°, puis lorsqu'il atteint les 180°, il revient à la position de départ et recommence.

Plusieurs cas de figure peuvent se présenter et empêcher le programme de fonctionner correctement :

  • Le servo-moteur ne revient pas à sa position de 0° : il faut alors augmenter le nombre de boucles effectuées par le compteur  t dans la fonction  setAngle(). En effet, si la vitesse de rotation de votre servo ne lui permet pas d'atteindre le zéro en 300 boucles, il lui faut plus de temps.

  • Le servo-moteur ne parcourt pas un demi-tour complet : il faut alors changer les valeurs dans le mappage. En effet, tous les servos ne sont pas réglés de manière identique.Par exemple, pour celui que j’utilise sur ce test, j’ai remplacé les valeurs 1 000 et 2 000 par 500 et 2 500 respectivement.

Que se passe-t-il si l'on envoie pas assez longtemps le train d'impulsions ?

Et bien le servo ne rejoindra pas sa position. De plus, même s'il l'atteint et que le train d'impulsions s'arrête, il ne maintiendra pas sa position angulaire. Ce qui est fâcheux...

Prenez l'exemple d'un servo qui est utilisé pour faire fonctionner un bras robotique, s'il ne maintient pas la position demandée, le bras se pliera si le poids relié au servo est assez lourd (souvent le poids du bras lui-même suffit !).

Je vous laisse chercher par vous-mêmes pour modifier le programme ci-dessus afin de comprendre les limites de votre servo (et de votre cerveau ;)). Attention tout de même, ne proposez pas des impulsions de valeur trop grande : c'est inutile et le servo peut se détériorer à vouloir dépasser des limites qui lui sont interdites.

Bien, vous avez compris et testé comment se pilote un servo-moteur par un train d'impulsions électriques. Et bien je vous annonce que l'équipe d'Arduino a conçu une bibliothèque spéciale qui gère tout ceci bien plus facilement : la bibliothèque Servo !

La bibliothèque Servo

Je vous ai déjà parlé des bibliothèques. Ce sont des programmes et des constantes stockées dans des fichiers que l'on peut inclure dans nos programmes.

Elles sont réalisées par les ingénieurs de chez Aduino, ou par toute personne qui se sent capable d'en créer une qui répond à un besoin particulier. Nous verrons comment créer une bibliothèque bien plus loin dans un autre cours. Pour le moment, il suffit de savoir que votre programme peut s'enrichir du travail des autres, gratuitement, et souvent avec performance.

Vous avez déjà utilisé la bibliothèque Serial (Serial.begin(9600) , Serial.print() ,  Serial.println() ). Ces commandes sont des fonctions incluses dans la bibliothèque Serial. On le repère d'ailleurs par la présence du mot-clé  Serial devant chaque nom de fonction.

La bibliothèque Serial est incluse par défaut dans chaque programme que vous démarrez. Il vous suffit d'en appeler les fonctions. En revanche, la bibliothèque Servo, doit être appelée dans le programme, afin qu'elle soit ajoutée au programme. On inclue une bibliothèque avec un mot-clé spécial. Voici l'exemple pour la bibliothèque Serial :

#include <Servo.h>

Ceci est une directive pré-compilation. C'est-à-dire que l'IDE, avant même de chercher à transformer votre programme en langage machine, va aller chercher la bibliothèque sur votre ordinateur, ajouter ses lignes de codes aux vôtres et créer un programme complet. Ensuite seulement, il va compiler.

Je vous propose une petite expérience : 

  1. Ouvrez un programme vide et nommez-le "test",

  2. Cliquez sur le V de vérifier,

  3. Lisez le message de l'IDE (en bas) qui vous informe de la taille de votre programme et des variables,

  4. Essayez de retenir en gros ce qui est dit,

  5. Ajoutez au tout début de votre programme la ligne de code que l’on vient de voir pour inclure la bibliothèque Servo (il faut la mettre avant le  setup()),

  6. Cliquez sur vérifier et observez les changements.

Votre programme prend 3 fois plus de place en mémoire juste avec cette ligne. Tout simplement parce que cette ligne en a ajouté bien d'autres !

Les bibliothèques utilisent des classes que l'on peut simplifier en les imaginant comme des objets programmables, c’est-à-dire des objets qui ont plusieurs fonctions spécifiques.

Souvent pour utiliser une bibliothèque, il faut créer un objet lié à cette bibliothèque. C'est le cas pour la bibliothèque Servo. Nous allons créer un objet de type Servo et lui donner un nom :

Servo monServo;

Maintenant, à chaque fois que nous ferons référence à "monServo" il s'agira de cet objet que nous venons de créer. Pour qu'il soit accessible partout (pensez au scope des variables) on le créé généralement avant le setup() .

Bien, ensuite il faut relier cet objet au pin de commande que l'on a choisi (par exemple le pin 8). On va utiliser une autre fonction qui est assez transparente :

monServo.attach(8);

On remarque que l'on commence par le nom de l'objet puis on appelle une fonction qu'il peut comprendre.

Enfin pour mettre le servo à l'angle désiré, on appelle une fonction de l'objet monServo qui là encore est claire comme de l'eau de roche, voyez vous-même :

monServo.write(angle);

Où "angle" est la valeur de l'angle que l'on désire. 

Voici un code qui place un servo en position 0° puis 180° d'une seconde à la suivante :

#include <Servo.h> //on importe la bibliothèque Servo
int pinServo=8; // variable pour stocker le pin pour la commande
Servo leServo; // on définit un objet Servo nommé leServo
void setup() {
  leServo.attach(pinServo); // on relie l'objet au pin de commande
}

void loop() {
  leServo.write(0); // on dit à l'objet de mettre le servo à 0°
  delay(1000); // ce délai est nécessaire pour que le servo atteigne sa position
  leServo.write(179); // position à 179, 180 est à éviter car cela forcerait le servo à dépasser ses limites
  delay(1000); // attente à nouveau
}

Les commentaires devraient suffire à comprendre. 

Pour prouver que la bibliothèque permet réellement au servo-moteur d'agir et de se maintenir même lorsque l'Arduino est sur une autre tâche, voici un programme de test  qui va vous rappeler votre premier programme ;) :

#include <Servo.h> //on importe la bibliothèque Servo
int pinServo=8; // variable pour stocker le pin pour la commande
Servo leServo; // on définit un objet Servo nommé leServo
void setup() {
  leServo.attach(pinServo); // on relie l'objet au pin de commande
  pinMode(13,OUTPUT); //pin 13 en mode OUTPUT
}

void loop() {
  leServo.write(0); // on dit à l'objet de mettre le servo à 0°
  diode13(); // appel de la fonction diode13() définie plus bas
  leServo.write(179); // position à 179°, 180° est à éviter
  diode13(); // appel de la fonction
}

void diode13(){
  // on fait clignoter 30 fois la LED 13
  for (int t=0;t<30;t++){
    digitalWrite(13,HIGH);
    delay(100);
    digitalWrite(13,LOW);
    delay(100);
  }
}

Vous remarquerez que la LED attachée au pin 13 clignote alors que le servo-moteur se déplace. De plus, si vous essayez de faire tourner le servo à la main sans trop forcer, vous sentirez une résistance à la rotation qui montre que le servo maintient sa position (Lukas, j'avais dit doucement ! Vous êtes bon pour casser votre tirelire maintenant...).

Je vous laisse essayer plusieurs valeurs pour les angles, les nombres de boucles et les temps d'attente.

Potar et Servo

Lorsque je vous disais au début de chapitre que c'est la partie de l'Arduino qui me fait toujours un petit effet, il s'agit en fait de ce qui suit...

Vous savez maintenant utiliser un servo-moteur. Vous savez aussi lire les valeurs d'un potentiomètre. Que diriez-vous de commander votre servo-moteur grâce au potentiomètre ? L'idée est simple, le servo se positionne en fonction de la position du potentiomètre.

Techniquement, vous avez tout ce qu'il vous faut pour réaliser ce programme sans aide, et je vous conseille d'essayer !

Quelques indices :

  • Branchez correctement le potentiomètre et le servo-moteur (on ne sait jamais...).

  • Prévoyez les variables de lecture du potentiomètre, de position du servo, la bibliothèque, l'objet Servo.

  • Avec un mappage habile des valeurs, transformez la position du potentiomètre en angle.

  • Positionnez le servo.

  • Faites mumuse .

Voici le schéma du montage électrique :

Connexion d'un servo-moteur et d'un potentiomètre
Connexion d'un servo-moteur et d'un potentiomètre

Et voici le code qui va bien...

#include <Servo.h>// on importe la bibliothèque
Servo servo; // on crée l'objet Servo
int pinServo=8; // on définit le pin lié à la commande du servo
int pinPotar=A0; // on définit le pin lié à la lecture du potenitomètre
void setup() {
  servo.attach(pinServo); // on relie l'objet servo au pin de commande
}

void loop() {
  int valeurPotar=analogRead(pinPotar); // lecture de la valeur du potentiomètre
  int angle=map(valeurPotar,0,1023,0,179); // tranformation en angle
  servo.write(angle); //mise en position du servo
}

Un tout petit bout pour le code, un grand mouvement pour le servo !

Bien, pour finir, je vous propose de réaliser un programme qui utilise un servo et un bouton poussoir.

L'accélérateur

Le principe du programme est le suivant :

  • Le servo est à 0° au départ.

  • Lorsqu'on appuie sur le bouton poussoir (en restant appuyé) le servo passe à 45° puis 90° puis 135° et 180° en fonction du temps d'appui.

  • Lorsqu'on relâche, le servo "redescend" par les positions inverses, avec les mêmes paliers de temps, jusqu'à 0°.

  • Si on appuie durant la "descente" le servo "remonte".

La difficulté de ce programme réside dans la méthode que vous allez utiliser pour la durée d'appui et la reprise d'appui sur le bouton.

On connectera le bouton poussoir sur le pin 2 en mode INPUT_PULLUP,  le servo sur le pin 8.

Voici le schéma électrique :

Potentiomètre au pin 8 et bouton poussoir au pin 2
Potentiomètre au pin 8 et bouton poussoir au pin 2

Je vous propose de réaliser ce programme en deux temps. 

  1. Premier programme : le servo bouge en fonction du temps d'appui et redescend, sans les paliers d'angles (0,45,90...) ;

  2. Second programme : on solutionne les paliers d'angles (et on apprend du même coup un mot de programmation : switch() .

Accélérateur sans paliers d’angles

Le servo se se déplace vers sa position maximale tant qu'on appuie, et revient lorsqu'on relâche.

Pour réussir ce premier programme, il vous faut :

  • Un objet Servo attaché au pin 8,

  • Le pin 2 en mode INPUT_PULLUP et relié au bouton poussoir,

  • Une variable qui stocke le temps d'appui, (je l’ai appelée  cumul , mais faites-vous plaisir si vous avez d’autres idées de nom)

  • Un mappage du temps d'appui vers un angle pour le Servo,

  • Des limites pour le temps d'appui.

Je vous laisse réaliser ce programme en essayant de respecter ces points. Vous avez maintenant tout ce qu'il faut pour réussir. Il est très probable que vous ne réussissiez pas du premier coup (bugs, oublis, test erronés...) et c'est nécessaire pour mieux programmer par la suite. Allez ! au boulot !

Comme l'objectif de ce programme reste d'apprendre à programmer, voici le code que je vous propose :

#include <Servo.h> //import de la bibliothèque Servo
Servo accel; //création de l'objet Servo "accel"
int pinServo=8; //pin de commande du servo
int pinBouton=2;//pin de lecture du bouton poussoir
int cumul=0; //variable d'appui

void setup() {
  pinMode(pinBouton,INPUT_PULLUP); //mode INPUT_PULLUP pour le poussoir
  accel.attach(pinServo); //liaison de l'objet Servo au pin de commande
  Serial.begin(9600);//pour lecture sur la console (Optionnel)
}

void loop() {
    boolean etatBouton=digitalRead(pinBouton); //lecture de l'état du bouton
    
    //si le bouton est appuyé
    if (!etatBouton){// en mode INPUT_PULLUP on obtien 0 quand on appuie !
      cumul++; // on fait augmenter la valeur de la variable
      if (cumul>1000) //test limite d'augmentation
        cumul=1000;//mise à limite si dépassement
    }
    
    //si le bouton n'est pas appuyé
    else{
      cumul--; //on fait diminuer la valeur de la variable
      if (cumul<0) //test si limite de diminution
        cumul=0;//mise à la limite si dépassement
    }
    Serial.println(cumul); //on affiche la valeur sur la console (Optionnel)
    int angle=map(cumul,0,1000,0,179); //on transforme en angle
    accel.write(angle); //on positionne le servo
}

La conditionif(!etatBouton)  peut paraître étrange, mais nous l'avons déjà vu, en mode INPUT_PULLUP quand le contact se fait, la valeur renvoyée est 0. On utilise donc un test du genre if(!contact) qui signifie est équivalent à if(contact==0) .

Avant d'aborder le second programme je vais vous apprendre un nouveau mot-clé...

... La condition SWITCH !

Vous connaissez la condition if   qui réalise un test et exécute un code si il est vérifié. Allez, un petit rappel ne vous fera pas de mal :

int nombreDePersonnes=5;
int nombreDeChaises=4;

if (nombreDeChaises<nombreDePersonnes){
    Serial.print("Il y en a qui resteront debout...");
}

Vous connaissez les conditionsif  , else if   et  else   qui permettent de réaliser le test suivant si le premier n'est pas vérifié. Allez, un deuxième petit rappel ne vous fera pas de mal non plus :

int nombreDePersonnes=5;
int nombreDeChaises=3;

if (nombreDeChaises==nombreDePersonnes){
    Serial.print("Tout le monde peut s'asseoir");
}
else if (nombreDePersonne-nombreDeChaises==1){
    Serial.print("Il y en a 1 qui reste debout");
}
else if (nombreDePersonne-nombreDeChaises>1 && nombreDeChaise!=0){
    Serial.print("Il y en a plusieurs qui restent debout");
}
else {
    Serial.print("Tout le monde reste debout");
}

J'ai volontairement mis plusieurs sortes de test, pour vous montrer des possibilités. Ici, on ne passe au test suivant que si le test précédent n'a pas été vérifié. Si un test est vérifié, les autres ne seront pas testés.

Et bien il existe une autre façon de réaliser des conditions. Il s'agit de la commande switch.

On l'utilise en lui indiquant une valeur (variable de type  int, ou bien de type  char) puis les actions à faire en fonction de cette valeur. “To switch” en anglais signifie “changer, intervertir”, c’est-à-dire que l’on va passer d’un cas à l’autre, les tester et agir en conséquence.

Voici les exemples précédents utilisés avec une fonction  switch :

int nombreDePersonnes=5;
int nombreDeChaises=3;
int diff=nombreDePersonnes-nombreDeChaises;

switch (diff){
    case 0:
        Serial.print("Tout le monde peut s'asseoir");
        break;
    case 5:
        Serial.print("Tout le monde reste debout");
        break;
    case 1:
        Serial.print("Il y en a 1 qui reste debout");
        break;
    default:
        Serial.print("Il y en a plusieurs qui restent debout");
}

Donc

  • On commence par indiquer au switch  la valeur à tester (ici la différence entre chaise et personnes) :  switch(diff).

  • Lignes 6, 9 et 12, le switch compare la valeur à tester (ici  diff ) avec celle qui suit le mot  case  (ici 0, 5 ou 1). Il est impératif de mettre les : en fin de ligne.

  • Le  mot-clé  break sert à sortir des tests (le test étant positif). Il est impératif de l'accompagner d'un point-virgule ; . Si vous ne mettez pas une instruction  break;  pour vous échapper des tests, le programme testera toutes les possibilités suivantes avant de rencontrer un break.

  • Le mot-clé  default: n'est pas obligatoire, mais il permet de proposer une solution par défaut. c'est-à-dire si aucun des tests précédents n'a été validé.

Revenons maintenant à notre accélérateur… et ajoutons des paliers d’angles !

Accélérateur avec paliers d’angles

Nous allons utiliser la fonction switch pour définir les paliers d'arrêt pour le servo. Voici le code :

#include <Servo.h> //import de la bibliothèque Servo
Servo accel; //création de l'objet Servo "accel"
int pinServo=8; //pin de commande du servo
int pinBouton=2;//pin de lecture du bouton poussoir
int cumul=0; //variable d'appui

void setup() {
  pinMode(pinBouton,INPUT_PULLUP); //mode INPUT_PULLUP pour le poussoir
  accel.attach(pinServo); //liaison de l'objet Servo au pin de commande
  Serial.begin(9600);//pour lecture sur la console (Optionnel)
}

void loop() {
    boolean etatBouton=digitalRead(pinBouton); //lecture de l'état du bouton
    
    //si le bouton est appuyé
    if (!etatBouton){// en mode INPUT_PULLUP on obtien 0 quand on appuie !
      cumul++; // on fait augmenter la valeur de la variable
      if (cumul>1000) //test limite d'augmentation
        cumul=1000;//mise à limite si dépassement
    }
    
    //si le bouton n'est pas appuyé
    else{
      cumul--; //on fait diminuer la valeur de la variable
      if (cumul<0) //test si limite de diminution
        cumul=0;//mise à la limite si dépassement
    }
    
    Serial.println(cumul); //on affiche la valeur sur la console (Optionnel)
    int pos=map(cumul,0,1000,0,4);//on mappe de 0 à 4 (5 positions) dans un variable pos
    int angle=0; //on initialise une variable angle
    
    switch (pos){// va switcher en fonction de la valeur pos
      case 1:
        angle=45;
        break;
      case 2:
        angle=90;
        break;
      case 3:
        angle=135;
        break;
      case 4:
        angle=179;
        break;
      default:
        angle=0;
    }
    
    accel.write(angle); //on place le servo à la position angle
}

Alors là je vous ai fait plein de commentaires dans le code, donc pas besoin que je vous recommente les commentaires, vous pourriez mal le prendre ! ;)

Là encore il existe des possibilités pour que ce code soit plus simple, mais l'objectif était de découvrir cette nouvelle condition ;).

Rien ne vous empêche ensuite de réaliser sur une feuille un cadran pour repérer les positions du servo et de positionner une aiguille sur l'axe du servo... mais je suis sûr que vos idées ne manquent pas !

Je pense que ce sera suffisant pour les servo-moteurs. Plein de nouveautés vous attendent dans le prochain chapitre, alors détendez-vous un peu avant d’enchaîner !

Exemple de certificat de réussite
Exemple de certificat de réussite