Forums LR PRESSE

Où il est question de trains, petits et grands

  • Advertisement

Arduino - Servomoteurs

Toutes les discussions sur l'Arduino !

Modérateur: MOD

Arduino - Servomoteurs

Publié: Ven 08 Nov 2013, 16:12 
Arduino - Servomoteurs

Bonjour à vous, Arduineurs.

Ce fil de discussion est initié par jlb et moi, pour parler de la commande de servomoteurs par Arduino (ceux qu'on utilise en radio-modélisme). En effet, dans la série d'articles que j'ai proposée à Loco-Revue, je n'en ai pas parlé, par manque de place. On verra par la suite ... mais en attendant, on peut déjà aborder le sujet.

Si vous êtes expert dans ce domaine, n'hésitez pas à nous faire part de votre expérience, mais sachez vous mettre aussi à la portée des débutants.

Si vous êtes débutants, c'est ici que vous trouverez des réponses.

Alors, surtout, n'ayez pas le servo lent :mdr2:

Arduinotement vôtre.

Christian
Avatar de l’utilisateur
Arduino
Démonstratif
 
Messages: 1515
Inscrit le: Mer 25 Sep 2013, 17:14

Re: Arduino - Servomoteurs

Publié: Ven 08 Nov 2013, 16:29 
Il y a une excellente implantation de servos autour d'un µCU Atmega (donc le montage est totalement compatible avec l'Arduino) sur le site de l'OpenDCC, dont voici le schéma :
Image
Les servos (2) sont pilotés par les pattes PWM (c'est naturel), et leur fonctionnement général l'est par deux pattes logiques, à travers des MOSFET (on coupe l'alimentation V+ des servos grâce à ces pattes).
.
Avatar de l’utilisateur
Roc
Promesse tenue
 
Messages: 20584
Inscrit le: Jeu 22 Fév 2007, 13:51
Localisation: Aude
Âge: 49
Prénom: Olivier
Club: Intermittent des Rigollots©

Re: Arduino - Servomoteurs

Publié: Ven 08 Nov 2013, 17:18 
Bonjour

C'est un décodeur d'accessoires DCC pilotant 2 servos.

Pour faire "joujou" avec un servo il ne faut qu'un Arduino et un petit sketch

Pierre
Avatar de l’utilisateur
Pierre59
Papotier
 
Messages: 144
Inscrit le: Dim 07 Mars 2010, 10:17
Localisation: Villeneuve d'Ascq (59650)
Âge: 74
Echelle pratiquée: HO
Club: Lille Modélisme

Re: Arduino - Servomoteurs

Publié: Ven 08 Nov 2013, 17:24 
Pierre59 a raison, le but de ce fil est plutôt d'apprendre aux gens à utiliser un servo avec Arduino, pas de les envoyer faire leurs courses pour ensuite utiliser un circuit tout fait. Sinon, autant acheter une radiocommande pour positionner ... les barrières du passage à niveau :lol:

Mais je ne doute pas que tout le monde est déjà capable d'interpréter le schéma du dessus :lol: Euh, n'avez pas plus simple ? :oops:
Avatar de l’utilisateur
Arduino
Démonstratif
 
Messages: 1515
Inscrit le: Mer 25 Sep 2013, 17:14

Re: Arduino - Servomoteurs

Publié: Ven 08 Nov 2013, 18:25 
Bonjour,

le but de ce fil est de réaliser une application complète : le pilotage de 8 servos avec réglage des butées en utilisant seulement un Arduino Uno et des bricoles autour mais pas de shield. C'est une application qui pourra être utilisée telle quelle ou modifiée pour s'adapter à des besoins particuliers.

Je vais faire ça en mode sans filet : Je vois à peu près comment faire mais l'application n'étant pas réalisée, il y aura les aléas du direct :siffle:

Je vais essayer de poster les premiers éléments ce week-end
Avatar de l’utilisateur
jlb
Fécond
 
Messages: 667
Inscrit le: Jeu 04 Oct 2012, 16:38
Echelle pratiquée: N
Prénom: Jean-Luc

Re: Arduino - Servomoteurs

Publié: Ven 08 Nov 2013, 21:36 
Je vais aussi m'attaquer à ce problème ce weekend. C'est juste histoire de voir si la bibliothèque servo.h est aussi simple à utiliser que la bibliothèque Stepper. Je ne ferai donc que reprendre l'exemple publié sur le site Arduino.

Bon WE à tous.

Christian
Avatar de l’utilisateur
Arduino
Démonstratif
 
Messages: 1515
Inscrit le: Mer 25 Sep 2013, 17:14

Re: Arduino - Servomoteurs

Publié: Sam 09 Nov 2013, 12:03 
J'ai dû mal me faire comprendre...

J'ai simplement indiqué que le montage proposé autour des servos était, à mes yeux, très propre, et qu'elle pouvait servir d'exemple, du point de vue de l'électronique.
Que ce soit un décodeur DCC.... tant qu'on n'a pas regardé le code, on n'en sait fichtrement rien, et à mon idée dans le cas précis qui nous intéresse, c'est tout à fait accessoire.

Maintenant, c'est pas mon fil. On a demandé si on avait des billes à apporter. Mes billes vous plaisent pas, pas de problème, je les remets dans ma culotte.
.
Avatar de l’utilisateur
Roc
Promesse tenue
 
Messages: 20584
Inscrit le: Jeu 22 Fév 2007, 13:51
Localisation: Aude
Âge: 49
Prénom: Olivier
Club: Intermittent des Rigollots©

Re: Arduino - Servomoteurs

Publié: Sam 09 Nov 2013, 12:19 
Salut Roc,

C'est pas que tes billes ne nous plaisent pas, c'est qu'on ne voudrait pas embrouiller l'esprit de ceux qui débutent.

Ce fil doit permettre de faire fonctionner un (ou plusieurs) servo avec Arduino et quasiment rien d'autre. Lorsque tout le monde aura acquis cette technique, il sera temps de leur indiquer les cartes ou les shields qu'ils peuvent utiliser (et là, tes billes seront intéressantes, comme ta carte EasyDriver que tu nous conseillais dans un autre forum ...)

Ne mettons pas la charrue avant les bœufs ; le schéma que tu as publié est certainement indigeste pour un débutant, de quoi le rebuter ...

Néanmoins, ton aide est appréciée.

Christian
Avatar de l’utilisateur
Arduino
Démonstratif
 
Messages: 1515
Inscrit le: Mer 25 Sep 2013, 17:14

Re: Arduino - Servomoteurs

Publié: Dim 10 Nov 2013, 13:44 
Bonjour,

En parallèle du fil de discussion sur les servo-moteurs, les articles sont mis en ligne sur mon blog : http://modelleisenbahn.triskell.org/spip.php?rubrique21
Sur le blog, les articles sont accompagnés de vidéos où vous pourrez entendre ma voix mélodieuse, mmm kof kof :mort:

Allons-y

Que veut-on comme fonction ?

Fonctionnellement, l’utilisateur veut le système classique. Il dispose d’une batterie de boutons, un par aiguille. Une pression sur un bouton change la position de l’aiguille. Nous allons prévoir ici 8 aiguilles et donc 8 servo-moteurs et 8 boutons. Son objectif est bien sûr d’avoir un mouvement lent et réaliste.

Il veut aussi un retour sur la position, par exemple une LED verte signifie que l’aiguille est droite et une jaune que l’aiguille est déviée.

Enfin, chaque moteur d’aiguille pouvant être différent, il veut régler les deux positions extrêmes servo par servo. Il faut donc qu’il puisse indiquer qu’il veut régler les servos puis préciser le servo qu’il souhaite régler puis disposer d’un dispositif de réglage.

De quel matériel a-t-on besoin ?

Du point de vue physique, le système que nous allons concevoir est constitué de :

  • Un Arduino Uno. Il s’agit d’une petite carte embarquant un micro-contrôleur ATMega328, un régulateur de tension 5V pour l’Arduino et ce qu’on peut y brancher et une électronique de programmation qui permet d’envoyer un programme sur l’Arduino via la liaison USB de l’ordinateur ;
  • 8 servos-moteur ;
  • 8 boutons poussoir, 1 pour chaque servo-moteur, permettant de changer la position du servo-moteur correspondant ;
  • Un bouton rotatif à 8 positions pour sélectionner un servo-moteur afin de régler ses butées (mode réglage). Un commutateur ou un poussoir permettant de passer du mode réglage au mode exploitation. Le mode exploitation est le fonctionnement normal du dispositif;
  • Une paire de poussoirs pour le réglage des butées des servo-moteurs ;
    Des résistances de tirage ;
  • 16 LED, 8 vertes et 8 jaunes, pour les temoins ;

Certains points peuvent sembler obscurs pour l’instant mais nous allons revenir dessus et les choses s’éclairciront.

L’électronique est réduite à sa plus simple expression et elle sera expliquée au fur et à mesure.

Enfin la plus grosse partie du travail est évidemment le logiciel. Plutôt que d’aborder cette partie de manière académique nous allons la voir au travers de la mise en œuvre de notre application, en amenant les explications sur la programmation au fur et à mesure que le besoin s’en fait sentir. Nous n’allons donc pas faire de conception globale de notre application comme cela se fait dans l’industrie mais présenter des sous-ensembles restreints permettant de saisir les concepts pour ensuite, une brique après l’autre, construire l’application.
Dernière édition par jlb le Dim 10 Nov 2013, 20:18, édité 1 fois au total.
Avatar de l’utilisateur
jlb
Fécond
 
Messages: 667
Inscrit le: Jeu 04 Oct 2012, 16:38
Echelle pratiquée: N
Prénom: Jean-Luc

Re: Arduino - Servomoteurs

Publié: Dim 10 Nov 2013, 17:06 
Superbe ta vidéo ! :coeur1:

Entre ce forum et ton blog, les débutants auront tout pour réussir. :wink:
Avatar de l’utilisateur
Arduino
Démonstratif
 
Messages: 1515
Inscrit le: Mer 25 Sep 2013, 17:14

Re: Arduino - Servomoteurs

Publié: Dim 10 Nov 2013, 19:03 
Merci Christian :)

Je continue:

Mise en œuvre d'un servo-moteur

La mise en œuvre d'un servo-moteur avec l'Arduino est aisée. Il y a une bibliothèque pour ça !

Une bibliothèque est un jeu de fonctions optionnelles que l'on peut ou non employer dans le programme. Pour utiliser la bibliothèque permettant de piloter des servo-moteurs, il suffit d'inclure, au début du programme la directive suivante

Code: Tout sélectionner
#include <Servo.h>


Il faut ensuite pouvoir manipuler le servo-moteur. Il faut pour cela créer une variable de type Servo. On dit aussi instancier une variable. Le type Servo est un peu spécial, on entre là sur le terrain du C++. Servo est une classe et créer une variable de ce type donne un objet. En plus de contenir une valeur comme une variable de type nombre entier, un objet possède des fonctions qui agissent sur lui. Dans le monde de l'objet on appelle communément ces fonctions des méthodes. Nous n'avons pas besoin d'en connaître plus pour utiliser un objet de type Servo. Voici comment on crée une variable, que nous appelons monServo de type Servo.

Code: Tout sélectionner
Servo monServo;


Notez le «; » qui termine la ligne, il est nécessaire et termine la directive. Notez aussi que le respect des majuscules et des minuscules est important car le langage C fait la différence entre s et S par exemple. Par conséquent appeler la variable monServo n'est pas la même chose que de l'appeler monservo.

La variable monServo est instanciée, il faut maintenant l'accrocher à une des sorties numériques de l'Arduino. Nous allons choisir la sortie 2 car les sorties 0 et 1 ont un rôle particulier : elles permettent d'envoyer des messages qui seront affichés sur votre ordinateur hôte. Il s'agit d'une aide irremplaçable qui se révèle nécessaire pour comprendre ce qui se passe quand le programme ne fait pas ce que l'on attend.
Accrocher la variable à une sortie se fait avec la méthode attach et, évidemment, dans la fonction setup() car il est inutile de le faire plus d'une fois.

Code: Tout sélectionner
void setup()
{
    monServo.attach(2); /* accroche monServo à la pin 2 de l'Arduino */
}


Aller-retours

La première application est très simple, il s'agit de faire faire au servo des aller-retours de part et d'autre de la position médiane. La méthode write(...) permet de donner l'angle auquel le servo doit se positionner. L'argument est une valeur comprise entre 0 et 180°. L'angle minimum choisi est donc de 70° et l'angle maximum de 110°. On fixe la pause entre 2 changements de position à 1s. La fonction loop() est donc la suivante.

Code: Tout sélectionner
void loop()
{
    /* positionne le servo à 70° */
    monServo.write(70);
    /* attend 1000 ms */
    delay(1000);
    /* positionne le servo à 110° */
    monServo.write(110);
    /* attend 1000 ms */
    delay(1000);
}


Cette première application ne remplit pas le cahier des charges. À savoir un mouvement lent. Le mouvement a bien lieu toutes les secondes mais il est très rapide, quasi instantané.

Aller-retours lents

Pour obtenir un mouvement lent, il faut faire varier l'angle du servo progressivement. Pour cela, il faut changer l'angle très très peu et le faire plus souvent. Fixons par exemple un changement d'angle de 1°. Si l'on veut que le mouvement, passer de 70° à 110° soit accompli en 1s, il faut augmenter l'angle de 1° toutes les 1000ms / (110 - 70). soit une pause de 25ms. Quand l'angle atteint 110°, il faut inverser le mouvement. Quand l'angle atteint 70°, il faut de nouveau inverser le mouvement. Nous avons donc besoin de deux variables, angle qui contient l'angle courant du servo et vitesse qui contient 1 si on augmente l'angle et -1 si on le diminue. Pour faciliter la programmation, on va placer 70 et 110 dans deux constantes. Le programme est le suivant.

Programme 2
Code: Tout sélectionner
#include <Servo.h>

Servo monServo;
int vitesse;
int angle;

const int angleMin  = 70;
const int angleMax = 110;

/*
* La fonction setup() est exécutée 1 fois
* au démarrage du programme
*/
void setup()
{
    monServo.attach(2);
    angle = angleMin;
    vitesse = 1;
}

/*
* La fonction loop() est exécutée
* répétitivement
*/
void loop()
{
    monServo.write(angle);
    /* calcule le nouvel angle */
    angle = angle + vitesse;

    if (angle > angleMax) {
        /*
         * le nouvel angle dépasse le maximum
         * on le recale au maximum et on inverse la vitesse
         */
        angle = angleMax;
        vitesse = -1;
    }
    else if (angle < angleMin) {
        /*
         * le nouvel angle dépasse le minimum
         * on le recale au minimum et on inverse la vitesse
         */
        angle = angleMin;
        vitesse = 1;
    }
    delay(25);
}


Le mouvement est bien lent comme on le désire mais avec une variation de l'angle par degré, le mouvement est un peu saccadé. Une autre méthode permet un positionnement plus précis. Il s'agit de la méthode writeMicroseconds(...). L'argument de cette méthode n'est plus un angle mais la durée de l'impulsion de commande du servo-moteur en micro-secondes. En effet, le signal de commande du servo-moteur est une impulsion dont la largeur détermine la position du servo (plus d'informations sont données dans La carte de commande 6 servo-moteurs, le matériel, une autre mise en œuvre utilisant une conception matérielle personnelle). Cette impulsion a donc la forme suivante.

Image

La valeur médiane est donc de 1500µs et les valeurs minimum et maximum pour les angles que nous avions fixés deviennent respectivement et approximativement 1250 et 1750. On va conserver une vitesse de 1 ou -1 et pour avoir un mouvement d'1s alors que l'on franchi 500 pas d'angle on va désormais faire une pause de 2ms. Le programme est donc le suivant.

Programme 3
Code: Tout sélectionner
#include <Servo.h>

Servo monServo;
int vitesse;
int angle;

const int angleMin  = 1250;
const int angleMax = 1750;

/*
* La fonction setup() est exécutée 1 fois
* au démarrage du programme
*/
void setup()
{
    monServo.attach(2);
    angle = angleMin;
    vitesse = 1;
}

/*
* La fonction loop() est exécutée
* répétitivement
*/
void loop()
{
    monServo.writeMicroseconds(angle);
    /* calcule le nouvel angle */
    angle = angle + vitesse;

    if (angle > angleMax) {
        /*
         * le nouvel angle dépasse le maximum
         * on le recale au maximum et on inverse la vitesse
         */
        angle = angleMax;
        vitesse = -1;
    }
    else if (angle < angleMin) {
        /*
         * le nouvel angle dépasse le minimum
         * on le recale au minimum et on inverse la vitesse
         */
        angle = angleMin;
        vitesse = 1;
    }
    delay(2);
}


Le résultat est meilleur avec un mouvement plus fluide.

Voici qui conclut cette prise en main des servo-moteurs. Le prochain article portera sur l'ajout d'un bouton permettant de commander le mouvement du servo-moteur.

L'article est sur le blog avec une vidéo en prime : http://modelleisenbahn.triskell.org/spip.php?article57

Il va y avoir une pause plus longue pour la suite car ma breadboard est pleine d'une autre manip et j'attends quelques breadboard supplémentaires :)
Avatar de l’utilisateur
jlb
Fécond
 
Messages: 667
Inscrit le: Jeu 04 Oct 2012, 16:38
Echelle pratiquée: N
Prénom: Jean-Luc

Re: Arduino - Servomoteurs

Publié: Lun 11 Nov 2013, 20:23 
Finalement, un domino plus loin, j'ai fait un montage volant avec un poussoir

Voici la suite :

Commande du servo-moteur par bouton poussoir

L'article est aussi sur mon blog : http://modelleisenbahn.triskell.org/spip.php?article58 avec en prime la coloration syntaxique des programmes et une vidéo :wink:


Nous allons maintenant ajouter un bouton poussoir pour commander le mouvement du servo-moteur. Cet article fait suite à «Mise en œuvre d’un servo-moteur».

Le système fonctionnera de la manière suivante: Lorsque le servo-moteur est dans une des positions extrêmes, une pression sur le poussoir donnera au servo-moteur une vitesse lui permettant de gagner l'autre position extrême. Lorsque le servo-moteur est en mouvement, une pression sur le bouton inversera la vitesse.

Mise en œuvre du bouton poussoir

Comme déjà expliqué, nous allons réserver les entrées/sorties numériques, les broches 0 à 13 de l'Arduino, au pilotage des servo-moteurs et à l'allumage des LED témoin.

Pour l'instant, l'unique bouton poussoir est connecté sur une entrée analogique, A0 par exemple. Une entrée analogique permet à l'Arduino de lire une grandeur analogique, entre 0V et 5V, et de la convertir en un nombre que l'on pourra manipuler dans le programme. Le nombre obtenu peut prendre des valeurs comprises entre 0 (pour 0V) et 1023 (pour 5V) avec donc 1024 valeurs possibles.

Pour notre bouton, il n'y aura que deux valeurs, celle qui correspond au bouton relâché et celle qui correspond au bouton enfoncé. Le bouton est connecté à l'Arduino comme ceci.

Image

Lorsque le bouton est relâché, l'entrée analogique A0 est tirée à 0V via la résistance de 10kΩ. Lorsque le bouton est pressé, l'entrée est mise à 5V.

Du côté du programme, nous allons séparer l'espace de valeurs (0 à 1023) en deux parties égales : les valeurs inférieures ou égales à 511 et celles supérieures à 511 et nous allons définir une fonction qui lit la valeur analogique, la compare à la valeur milieu et retourne soit RELACHE, soit PRESSE. Ces deux constantes sont des booléens, c'est à dire des valeurs logiques. Elle sont définies pour faciliter la lecture du programme. Jusqu'alors nous n'avons vu que des fonctions qui ne retournaient rien, c'est à dire void. Ici la fonction lireBouton retourne un booléen, qui sera l'état du bouton. Nous avons donc le morceau de programme suivant avec la définition des constantes nécessaires et la fonction de lecture de l'état du bouton poussoir.

Code: Tout sélectionner
/* le bouton est connecté à la broche A0 */
const int pinBouton = 0;
/* valeur logique pour indiquer que le bouton est pressé */
const boolean PRESSE = true;
/* valeur logique pour indiquer que le bouton est relâché */
const boolean RELACHE = false;

/*
* lecture du bouton poussoir. Le bouton poussoir est connecté
* sur une entrée analogique. Quand il est pressé, l'entrée est
* connectée au +5V. Quand il est relaché, l'entrée est connectée
* à la masse. On va discriminer les deux états en comparant la
* valeur analogique lue à 511 qui est la valeur milieu.
*/
boolean lirePoussoir()
{
    boolean resultat = RELACHE;
    if (analogRead(pinBouton) > 511) {
        resultat = PRESSE;
    }
    /* retourne l'état */
    return resultat;
}


Mais l'état du bouton ne nous intéresse pas directement. En effet, ne mettre le servo-moteur en mouvement que lorsque le bouton est pressé forcerait l'utilisateur à maintenir le bouton pressé pendant le mouvement. Ce sont donc les changements d'état du bouton qui nous intéressent: le fait de passer de l'état RELACHE à l'état PRESSE ou le fait de passer de l'état PRESSE à l'état RELACHE. Pour détecter ces changements d'état, il faut mémoriser l'état précédent du bouton et, quand on lit son état actuel, le comparé à l'état précédent pour déterminer si l'un des changements a eu lieu. On a donc besoin d'une variable pour y mémoriser l'état précédent. Pour clarifier les choses et rendre le programme lisible, nous allons aussi définir 3 constantes : AUCUN_EVENEMENT, l'état précédent du bouton est identique à l'état courant, EVENEMENT_PRESSE, l'état précédent du bouton était RELACHE, l'état courant est PRESSE et EVENEMENT_RELACHE, l'état précédent du bouton était PRESSE, l'état courant est RELACHE. Ces constantes sont des byte, c'est à dire un type de donnée pouvant prendre 256 valeurs différentes, ce qui suffit amplement.

Code: Tout sélectionner
const byte AUCUN_EVENEMENT = 0;
const byte EVENEMENT_PRESSE = 1;
const byte EVENEMENT_RELACHE = 2;


Enfin nous allons définir la fonction lireEvenement() qui va lire l'état courant du bouton et calculer l'événement. Le code vient assez naturellement.

Code: Tout sélectionner
/*
* construction d'un événement.
* - Si l'état du bouton n'a pas changé entre l'état précédent du bouton
*   et le nouvelle état, l'événement est AUCUN_EVENEMENT.
* - Si le pouton était précédemment RELACHE et qu'il est maintenant PRESSE,
*   l'événement est EVENEMENT_PRESSE.
* - Si le pouton était précédemment PRESSE et qu'il est maintenant RELACHE,
*   l'événement est EVENEMENT_RELACHE.
*/
byte lireEvenement()
{
    byte evenement;

    /* lit l'état courant du bouton */
    boolean nouvelEtat = lirePoussoir();
    /* calcule l'événement */
    if (nouvelEtat == etatBouton)
        evenement = AUCUN_EVENEMENT;
    if (nouvelEtat == PRESSE && etatBouton == RELACHE)
        evenement = EVENEMENT_PRESSE;
    if (nouvelEtat == RELACHE && etatBouton == PRESSE)
        evenement = EVENEMENT_RELACHE;
    /* L'état courant devient l'état précédent */
    etatBouton = nouvelEtat;
    /* retourne l'événement */
    return evenement;
}


Afin de tester la lecture du poussoir indépendamment, nous allons mettre en œuvre l'envoi de message sur la ligne série qui, via l'USB, s'affiche dans le Moniteur Série de l'environnement de programmation Arduino. Il faut tout d'abord ouvrir la connexion dans la fonction setup() en utilisant la méthode begin(...) de Serial. Nous allons ensuite utiliser la méthode println pour afficher un message sur le moniteur série. Voici le programme complet pour cette première application mettant en œuvre un bouton.

Code: Tout sélectionner
const int pinBouton = 0; /* le bouton est connecté à la broche A0 */

const boolean PRESSE = true;
const boolean RELACHE = false;

boolean etatBouton = RELACHE;

const byte AUCUN_EVENEMENT = 0;
const byte EVENEMENT_PRESSE = 1;
const byte EVENEMENT_RELACHE = 2;

boolean lirePoussoir()
{
  boolean resultat = RELACHE;
  if (analogRead(pinBouton) > 512) {
    resultat = PRESSE;
  }
  return resultat;
}

byte lireEvenement()
{
    byte evenement;
    boolean nouvelEtat = lirePoussoir();
    if (nouvelEtat == etatBouton)
        evenement = AUCUN_EVENEMENT;
    if (nouvelEtat == PRESSE && etatBouton == RELACHE)
        evenement = EVENEMENT_PRESSE;
    if (nouvelEtat == RELACHE && etatBouton == PRESSE)
        evenement = EVENEMENT_RELACHE;
    etatBouton = nouvelEtat;
    return evenement;
}

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

void loop()
{
    byte evenement = lireEvenement();
 
    if (evenement == EVENEMENT_PRESSE) Serial.println("presse !");
    if (evenement == EVENEMENT_RELACHE) Serial.println("relache !");
}


À ma grande surprise ce programme fonctionne sans effort supplémentaire ! À ma grande surprise car lorsque l'on presse ou que l'on relâche un bouton, le contact ou la coupure ne s'effectue pas d'un coup et une succession rapide de contact-coupure a lieu. On appelle cela un rebond. Mon poussoir n'a pas de caractéristique particulière et j'ai par ailleurs eu des rebonds en le connectant à une entrée numérique. La réponse à ce mystère est donc ailleurs.

Deux techniques sont possibles pour filtrer les rebonds des poussoirs:
- par matériel : un condensateur de filtrage;
- par logiciel : laisser passer du temps entre deux lectures.

Or, la conversion analogique numérique n'est pas instantanée. Entre deux conversions successives et donc deux acquisitions successive de la valeur analogique, il s'écoule 100µs. Ce qui équivaut à la solution logicielle de « laisser passer du temps entre 2 lectures ». Cette durée semble être suffisante pour filtrer les rebonds de notre bouton.

Intégration avec le programme de pilotage du servo-moteur

Nous allons maintenant intégrer notre fonction de lecture d'événement au programme de pilotage du servo-moteur tel que nous l'avons présenté dans l'article précédent.

Il faut procéder à quelques modification. Tout d'abord, il faut supprimer l'aller-retour qu'effectue le servo-moteur. Ensuite, il faut ajouter une variable qui va permettre de savoir dans quel état se trouve le servo-moteur afin de prendre la décision adéquate quand le bouton est pressé. On va distinguer 4 états:

SERVO_A_ANGLE_MIN : le servo-moteur est arrêté dans la position correspondant à l'angle minimum. Sa vitesse est égale à 0.
SERVO_A_ANGLE_MAX : le servo-moteur est arrêté dans la position correspondant à l'angle maximum. Sa vitesse est égale à 0.
SERVO_EN_MOUVEMENT_VERS_ANGLE_MAX : le servo est en mouvement vers la position d'angle maximum. Sa vitesse est égale à 1.
SERVO_EN_MOUVEMENT_VERS_ANGLE_MIN : le servo est en mouvement vers la position d'angle minimum. Sa vitesse est égale à -1.

Comme tout est nombre, nous allons définir chacune de ces constantes comme étant un byte et définir une variable etatServo de type byte comme ceci.

Code: Tout sélectionner
const byte SERVO_A_ANGLE_MIN = 0;
const byte SERVO_A_ANGLE_MAX = 1;
const byte SERVO_EN_MOUVEMENT_VERS_ANGLE_MAX = 2;
const byte SERVO_EN_MOUVEMENT_VERS_ANGLE_MIN = 3;

const int angleMin = 1250;
const int angleMax = 1750;

Servo monServo;
int vitesse = 0;
int angle = angleMin;
byte etatServo = SERVO_A_ANGLE_MIN;


Dans setup(), nous retrouvons l'accrochage de monServo à la broche 2. La gestion du mouvement du servo est modifiée. Quand l'angle dépasse l'angle maximum, il est recalé comme auparavant. Mais dorénavant la vitesse est mise à 0 et l'état du servo est changé en SERVO_A_ANGLE_MAX. Quand l'angle dépasse l'angle minimum, il est recalé à l'angle minimum, la vitesse est mise à 0 et l'état du servo est changé en SERVO_A_ANGLE_MIN. De cette manière, le servo arrête son mouvement quand il atteint l'une des positions extrêmes.

On va ensuite lire l'événement. Si l'événement est EVENEMENT_PRESSE, on va effectuer les actions suivantes :
  • Si le servo est dans l'état SERVO_A_ANGLE_MIN ou SERVO_EN_MOUVEMENT_VERS_ANGLE_MIN, la vitesse est mise à 1 et l'état du servo est changé en SERVO_EN_MOUVEMENT_VERS_ANGLE_MAX.
  • Si le servo est dans l'état SERVO_A_ANGLE_MAX ou SERVO_EN_MOUVEMENT_VERS_ANGLE_MAX, la vitesse est mise à -1 et et l'état du servo est changé en SERVO_EN_MOUVEMENT_VERS_ANGLE_MIN
Le programme complet est le suivant.

Code: Tout sélectionner
#include <Servo.h>

const byte SERVO_A_ANGLE_MIN = 0;
const byte SERVO_A_ANGLE_MAX = 1;
const byte SERVO_EN_MOUVEMENT_VERS_ANGLE_MAX = 2;
const byte SERVO_EN_MOUVEMENT_VERS_ANGLE_MIN = 3;

const int angleMin = 1250;
const int angleMax = 1750;

Servo monServo;
int vitesse = 0;
int angle = angleMin;
byte etatServo = SERVO_A_ANGLE_MIN;

const int pinBouton = 0; /* le bouton est connecté à la broche A0 */

const boolean PRESSE = true;
const boolean RELACHE = false;

boolean etatBouton = RELACHE;

const byte AUCUN_EVENEMENT = 0;
const byte EVENEMENT_PRESSE = 1;
const byte EVENEMENT_RELACHE = 2;

/*
* fonctions de gestion du poussoir
*/
boolean lirePoussoir()
{
    boolean resultat = RELACHE;
    if (analogRead(pinBouton) > 512) {
        resultat = PRESSE;
    }
    return resultat;
}

byte lireEvenement()
{
    byte evenement;
    boolean nouvelEtat = lirePoussoir();
    if (nouvelEtat == etatBouton)
        evenement = AUCUN_EVENEMENT;
    if (nouvelEtat == PRESSE && etatBouton == RELACHE)
        evenement = EVENEMENT_PRESSE;
    if (nouvelEtat == RELACHE && etatBouton == PRESSE)
        evenement = EVENEMENT_RELACHE;
    etatBouton = nouvelEtat;
    return evenement;
}

/*
* La fonction setup() est exécutée 1 fois
* au démarrage du programme
*/
void setup()
{
    monServo.attach(2);
}

/*
* La fonction loop() est exécutée
* répétitivement
*/
void loop()
{
    /* actualisation de l'angle du servo */
    monServo.writeMicroseconds(angle);
 
    angle = angle + vitesse;
 
    if (angle > angleMax) {
        angle = angleMax;
        vitesse = 0;
        etatServo = SERVO_A_ANGLE_MAX;
    }
    else if (angle < angleMin) {
        angle = angleMin;
        vitesse = 0;
        etatServo = SERVO_A_ANGLE_MIN;
    }

    /* lecture de la commande de l'utilisateur */
    byte evenement = lireEvenement();
 
    if (evenement == EVENEMENT_PRESSE) {
        switch (etatServo) {
            case SERVO_A_ANGLE_MIN:
            case SERVO_EN_MOUVEMENT_VERS_ANGLE_MIN:
                vitesse =  1;
                etatServo = SERVO_EN_MOUVEMENT_VERS_ANGLE_MAX;
                break;
            case SERVO_A_ANGLE_MAX:
            case SERVO_EN_MOUVEMENT_VERS_ANGLE_MAX:
                vitesse = -1;
                etatServo = SERVO_EN_MOUVEMENT_VERS_ANGLE_MIN;
                break;
        }
    }

    delay(3);
}


Ce programme est l'occasion d'introduire une nouvelle construction du C, le switch ... case. Il s'agit d'un choix multiple. On a vu avec le if ... else ... un choix double. Ici la valeur de la variable etatServo indique à quel case le programme continue son exécution. L'exécution se poursuit jusqu'à rencontrer un break qui fait que le programme continue sont exécution après le switch.

Distinguer les états SERVO_A_ANGLE_MIN et SERVO_EN_MOUVEMENT_VERS_ANGLE_MIN n'est pas nécessaire, idem pour SERVO_A_ANGLE_MAX et SERVO_EN_MOUVEMENT_VERS_ANGLE_MAX. On le conserve tout de même car le programme est plus lisible ainsi et la distinction qui est faite va nous servir plus tard.
Dernière édition par jlb le Mar 12 Nov 2013, 09:20, édité 2 fois au total.
Avatar de l’utilisateur
jlb
Fécond
 
Messages: 667
Inscrit le: Jeu 04 Oct 2012, 16:38
Echelle pratiquée: N
Prénom: Jean-Luc

Re: Arduino - Servomoteurs

Publié: Mar 12 Nov 2013, 01:03 
Ce troisième article est tout aussi pédagogique que les deux premiers : :applause:

Et celui qui suit tes posts a déjà appris, de façon progressive, beaucoup de choses concernant la programmation.

Faudra par contre que tu m'apprennes à faire ces petites fenêtres défilantes pour inclure du code car je ne sais pas faire ... :oops:

Bonne continuation.
Avatar de l’utilisateur
Arduino
Démonstratif
 
Messages: 1515
Inscrit le: Mer 25 Sep 2013, 17:14

Re: Arduino - Servomoteurs

Publié: Mar 12 Nov 2013, 01:12 
Merci Christian !

Il faut utiliser la balise Code, juste à droite de Citer au dessus de la fenêtre de rédaction des messages (éditeur complet)
Avatar de l’utilisateur
jlb
Fécond
 
Messages: 667
Inscrit le: Jeu 04 Oct 2012, 16:38
Echelle pratiquée: N
Prénom: Jean-Luc

Re: Arduino - Servomoteurs

Publié: Mar 12 Nov 2013, 11:47 
Il y a encore plus simple. Dans l'IDE arduino tu sélectionne ton code. Après tu fais edition et copier pour le forum et ensuite coller ici exemple (il y aura de plus la syntaxe en couleur) :
/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
 
  This example code is in the public domain.
 */
 
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
  delay(1000); // wait for a second
  digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
  delay(1000); // wait for a second
}



Mais cela prend plus de place
Guillaume22
Papotier
 
Messages: 138
Inscrit le: Dim 29 Sep 2013, 09:20

Suivant

Retour vers Arduino

Qui est en ligne ?

Utilisateur(s) parcourant actuellement ce forum : Yahoo [Bot] et 1 invité