Une débutante dans le décor - Ep8 - Un servo pour l'Arduino

Salut,

Ce tutoriel est un prolongement de l’épisode 6 - Une débutante dans le décor - Ep6 - Quelques automatismes (Arduino Nano), comment réaliser des automatismes en mode “lego” basé sur la plateforme Arduino Nano.

Objectif : pas de fer à souder, pas de câblage compliqué, pas de résistance/condo/… à rajouter et bien sur un prix mini mini. Si tu sais brancher un M84, tu sais utiliser un Arduino à la sauce Julaye :wink: !

Ce tutoriel démarre avec l’idée assez classique de motoriser les portes d’un bâtiment, au hasard, l’atelier moteur ou la remise de mon dépôt diesel de Obourg.

Débutante intégrale au début de mes activités, j’ai acheté des servo moteurs chez Faller ainsi qu’un boitier de servo-commande.

Référence des servos 180726 (12 € pièce) :

https://www.faller.de/fr/fr/Produits/Construction-d-installations/Electronique/Servo-sid12271.html

Référence du servocommande 180725 (50 €) :

https://www.faller.de/fr/fr/Produits/Construction-d-installations/Electronique/pid.14.17.91/agid.1115/atid.6753/ecm.at/Servocommande.html

Cout de l’automatisation de quatre servos chez Faller : 100 € !

Et puis je me suis aperçue que l’Arduino Nano pouvait commander jusqu’à 6 servo-moteurs … avec une interface de programmation intégrée à l’environnement de développement :

Vous remarquerez au passage que j’évite l’alimentation 16V requise par la servo-commande Faller, les servos ont tendance à être en 3.3V, alimentation disponible directement sur l’Arduino.

Bilan de ce tutoriel : je vais revendre mon boitier de servocommande et en achetant les quatre servo-moteurs sur la Bay (4€ pièce) avec un Arduino Nano (6€), c’est plus de 75 euros que j’aurais pu économiser.

Alors un servo-moteur, c’est quoi déjà ? un moteur à courant continue qui prend des positions particulières exprimées sous forme d’angle.

J’ai trouvé un article passionnant à lire et que je vous conseille, n’ayant pas envie de paraphraser ce document :

https://zestedesavoir.com/tutoriels/686/arduino-premiers-pas-en-informatique-embarquee/747_le-mouvement-grace-aux-moteurs/3437_le-moteur-a-courant-continu/

et

https://zestedesavoir.com/tutoriels/686/arduino-premiers-pas-en-informatique-embarquee/747_le-mouvement-grace-aux-moteurs/3438_un-moteur-qui-a-de-la-tete-le-servomoteur/

Pour mon tutoriel, j’ai ajouté une interface de détection de présence Infra Rouge (IR). La porte s’ouvre sur détection et se ferme sinon.

Cette interface IR coute quelques euros (12€ les 5 pièces) :

https://www.amazon.fr/gp/product/B07V6YR2P7/ref=ppx_yo_dt_b_asin_title_o06_s00

Voici le montage sur ma paillasse à Dakar :

Mon Arduino est alimenté par le port USB de mon ordinateur. Je n’avais pas emmené d’alimentation autonome.

Bien évidemment, cette carte de détection IR peut être remplacée par une entrée de contact (présence d’une locomotive sur la voie), un bouton poussoir, une sortie de M83/M84 … ou une combinaison de tout ça.

Du coup le montage est assez classique :

  • le rouge du servo sur le 3.3V de l’Arduino

  • le noir du servo sur le GND de l’Arduino

  • le orange du servo (la commande PWM) sur une sortie de l’Arduino

  • le rouge du détecteur sur le 5V de l’Arduino

  • le noir du détecteur sur le GND de l’Arduino

  • le jaune du détecteur (signal) sur une entrée de l’Arduino

Le programme est plutôt simplissime, il gère deux positions sur le servo : porte ouverte (90°) ou fermée (0°), et il est possible de régler la vitesse de fermeture et d’ouverture de la porte (fixée à environ 1 seconde dans le code ci-après).

// Servo Faller v0.1
// (c) Julie Dumortier, 2021
// licence GPL
//
// Evolutions
// v0.1 première version sur plateforme de démonstration

// Un serveur moteur a un connecteur à trois fils : +, - et signal.
// le + est typiquement de couleur rouge et doit être connecté au 5V de l'Arduino
// le - est typiquement de couleur marron ou noir et doit être connecté au GND de l'Arduino
// le signal est typiquement de couleur jaune ou orange et doit être connecté à une sortie digital

// inclure les définitions pour la commande d'un servo
#include <Servo.h>

// utiliser une PIN pour envoyer un signal PWM sur le servo
#define SERVO_PIN 2

// cette PIN allume la led infrarouge à la fréquence de 38 Khz
#define ENABLE_PIN 3

// cette PIN détecte l'infrarouge
#define SIGNAL_PIN 4

// créer un objet Servo pour la référence 180726
// documentation Arduino : https://www.arduino.cc/reference/en/libraries/servo/
Servo servoFaller;

// variable pour stocker l'angle de variation (0 à 90)
int servoAngle;

// trigger pour décider qu'un objet est présent ou absent
int trigger = 32;

// fonction qui détecte la présence d'un objet
bool objetDetect()
{
  int n = 0;
  int d = 0;

  digitalWrite(ENABLE_PIN, HIGH);

  while (n<64) {
    n = n + 1;
    if(!digitalRead(SIGNAL_PIN)) {
      d = d + 1;
    }  
    delay (1);
  }

  digitalWrite(ENABLE_PIN, LOW);

  if (d>trigger) {
    Serial.print("objet détecté d=");
    Serial.println(d);
    return true;
  }
  Serial.print("aucun objet d=");
  Serial.println(d);
  return false;
}

void OuvrePorte() 
{
  digitalWrite(LED_BUILTIN,HIGH);
  for (int i=0;i<=90;i++) { // pour chaque angle entre 0 et 90
    servoFaller.write(i); // positionne sur l'angle i
    delay(10); // impacte la vitesse d'ouverture (pause de 10 ms entre chaque déplacement)
  }
  Serial.println("Porte ouverte");
}

void FermePorte() 
{
  digitalWrite(LED_BUILTIN,LOW);
  for (int i=90;i>=0;i--) { // pour chaque angle entre 90 et 0
    servoFaller.write(i); // positionne sur l'angle i
    delay(10); // impacte la vitesse de fermeture (pause de 10 ms entre chaque déplacement)
  }
  Serial.println("Porte fermée");
}


// le code de démarrage du Nano
void setup() {
  // debug mode sur la console de l'IDE
  Serial.begin(57600);

  // pour afficher la présence, utilise la led interne à l'Arduino
  pinMode(LED_BUILTIN,OUTPUT);
  digitalWrite(LED_BUILTIN,LOW);

  // enable le détecteur
  pinMode(ENABLE_PIN, OUTPUT);
  digitalWrite(ENABLE_PIN, HIGH);

  // Signal de détection en entrée
  pinMode(SIGNAL_PIN, INPUT);
  
  // attache le PIN utilisé pour le servo pour lui envoyer un signal.
  servoFaller.attach(SERVO_PIN);  

  // assure toi que la porte soit bien fermée
  FermePorte();
}

// le code executé en permanence
bool  objetPresent = false;

void loop() {

  if (objetDetect()) {
    if (!objetPresent) {
      objetPresent = true;
      OuvrePorte();
    }
  } else {
    if (objetPresent) {
      objetPresent = false;
      FermePorte();
    }
  }
  
}

J’ai tourné une petite vidéo de l’exécution de mon programme :

Merci de votre attention,


Retrouvez tous les épisodes de la débutante en clickant ici !

3 « J'aime »

Bonjour Julie,

La vitesse de rotation du servo est-elle réglable ? Pour monter ou descendre des barrières de PN, c’est plutôt chouette.

J’ai essayé avec un montage électronique de faire fonctionner un servo qui, la sale bête, n’a jamais voulu faire ce que je voulais… :face_with_symbols_over_mouth: (mais je vais recommencer !!! et je l’aurais … je l’aurais !!! sinon je me rabattrais sur cette solution.

Merci en tout cas de ton post.
Bonne fin de journée,
Cdlt,

Claude papaciela

Bonjour Claude,

Oui : cf la ligne :

delay(10); // impacte la vitesse d'ouverture

10 ms est le temps d’attente entre deux mouvements, les mouvements étant d’un degré (boucle for i qui va de 1 à 90).

Donc la porte parcourt les 90° en 90x10 millisecondes soit 900 millisecondes, environ une seconde.

En augmentant cette valeur, tu ralentis la vitesse d’ouverture de la porte : 20 ms et la porte mettra environ deux secondes à s’ouvrir.

Je te conseille de passer à l’Arduino directement :slight_smile:

@+

PS: il y a la même chose pour la vitesse de fermeture. Donc oui c’est une bonne solution pour piloter une barrière mobile. L’angle aussi est réglable, on peut avoir un déplacement sur 0-45 degrés par exemple pour un PN.

Je me doutais bien que ça pouvait se régler, mais je dois t’avouer que j’ai “sauter” le programme (un peu fainéant le claudius from time to time !!) qui, s’il avait été lu, aurait apporté la réponse.

Je crois que je vais faire l’emplette du kit dont tu parlais sur un autre de tes posts. Au moins pour voir à quoi ça ressemble et pour ne pas mourir iidiioot.
Tchao !!

Claude

1 « J'aime »

Bonsoir,
Toujours aussi intéressant ce post ! Sur ce principe on doit pouvoir commander un aiguillage sans passer par la centrale. Ca ouvre des perspectives pour la gestion d’une gare cachée par ex.
Cordialement,

Bonsoir

Effectivement je n’y avais pas pensé ! (étant en voie C) mais oui on doit pouvoir utiliser un servo pour un aiguillage, gérer la vitesse de déplacement et se passer d’un décodeur et d’une centrale.

Un Arduino Nano pourrait gérer 4 à 6 aiguillages avec les commandes associées (boutons poussoirs sur des entrées pull-up). 25 € la motorisation et la commande de 4 aiguillages !

Ça se tente effectivement si on a pas besoin d’une centrale. Si je devais faire un jour de la voie K, c’est une option que je regarderais de près.

En cherchant vite fait sur Google on trouve tout un tas de réalisations d’aiguillage avec des servos. L’Arduino Nano est une bonne option pour une commande par un TCO.

@+

Bonjour Julie,

J’ai réussi à “programmer” (plutôt copier un pgrm) pour faire fonctionner un servo moteur.

Le servo va de 0 à 100 ° et revient à 0.

Je souhaite arrèter le servo pendant xx secondes à chaque fin de cycle Donc 0-100° arrêt xx s, retour à 0° arrêt yy sec.

Mais bien sur, je n’y connais rien ds ce truc (ma programmation date du Basic sur Apple des années 1980 c’est dire !!! :upside_down_face:)

Voilà le prgm, si tu peux éclairer ma lanterne !!!

Puis je utiliser un “stop xx sec” et reprendre ou faire une loop ds la loop pour “manger du temps” (avec un "delay (yy)). ?

#include <Servo.h>
Servo myservo;
int pin_servo = 6;
int pos = 0;
int angle_initial = 0;
int angle_final = 100;
int increment = 1;
bool angle_actuel = false;

void setup() {
  Serial.begin(9600);  
  while(!Serial){;}
  myservo.attach(pin_servo);
}

void loop() {

  for(pos = angle_initial; pos <= angle_final; pos += increment) { //Va à 100°
     myservo.write(pos);              
     delay(55);   
     if (angle_actuel) {
        Serial.println(myservo.read());
     }
 }
 for (pos = angle_final; pos >= angle_initial; pos -= increment) { // Fait le chemin inverse
     myservo.write(pos);              
     delay(50);   
     if (angle_actuel) {
        Serial.println(myservo.read());
     }
  }
}

Merci d’avance

Claude papaciela

Ps : Si tu juges que cette conversation doit être à un autre endroit…bouge la.

Je viens de le déplacer dans l’épisode 8 qui traite justement les servos.

L’idée est de faire des petites routines que tu vas appeler depuis loop().

On peut partir du programme que j’ai proposé initialement.

// Papa01
//
// Evolutions
// v0.1 première version (pas testée)

// Un serveur moteur a un connecteur à trois fils : +, - et signal.
// le + est typiquement de couleur rouge et doit être connecté au 5V de l'Arduino
// le - est typiquement de couleur marron ou noir et doit être connecté au GND de l'Arduino
// le signal est typiquement de couleur jaune ou orange et doit être connecté à une sortie digital

// inclure les définitions pour la commande d'un servo
#include <Servo.h>

// utiliser une PIN pour envoyer un signal PWM sur le servo
#define SERVO_PIN 6

// créer un objet Servo
// documentation Arduino : https://www.arduino.cc/reference/en/libraries/servo/
Servo servoPapa;

// variable pour stocker l'angle de variation
int servoAngle;

// quelques paramètres 
int angle_initial = 0;
int angle_final = 100;
int increment = 1; // increment d'angle entre deux mouvements
int vitesse = 10; // délai en ms entre deux mouvements

int pause_xx = 1000; // 1 seconde
int pause_yy = 2000; // 2 secondes

void Ouvre()
{
  digitalWrite(LED_BUILTIN,HIGH);
  for (int i=angle_initial;i<=angle_final;i=i+increment) {
    servoPapa.write(i); // positionne sur l'angle i
    delay(vitesse); // impacte la vitesse d'ouverture
  }
  Serial.println("Ouvert");
}

void Ferme() 
{
  digitalWrite(LED_BUILTIN,LOW);
  for (int i=angle_final;i>=angle_initial;i=i-increment) {
    servoPapa.write(i); // positionne sur l'angle i
    delay(vitesse); // impacte la vitesse de fermeture
  }
  Serial.println("Fermé");
}

// le code de démarrage du Nano
void setup() {
  // debug mode sur la console de l'IDE 
  Serial.begin(57600); // mettre la même valeur que dans ta console, 9600 éventuellement mais c'est lent :) 

  // pour afficher l'état, utilise la led interne à l'Arduino
  pinMode(LED_BUILTIN,OUTPUT);
  digitalWrite(LED_BUILTIN,LOW);

  // attache le PIN utilisé pour le servo pour lui envoyer un signal.
  servoPapa.attach(SERVO_PIN);  
}

// le code executé en permanence

void loop() {
  Ferme();
  delay(pause_xx);
  Ouvre();
  delay(pause_yy);
}

Pas testé :slight_smile: en cas de problème, dis moi je monte la manip

Bonjour Julie, bonjour tout le monde,

Lucky Luke à coté de toi, c’est un amateur !!! Tu penses plus vite que ton cerveau !!!

Sérieusement… désolé d’avoir usé de ton temps, mais j’ai pensé un peu à cette écriture de programme.
Je n’avais pas bien remarqué la fonction et l’utilité des “crochets”, des parenthèses et autre " ; ", puisque j’ai copié “bêtement” le pgrm. Par hasard, la souris a fait apparaître lors des essais de modification pour obtenir ce que je voulais, des crochets à différents endroits du prgm. J’ai pensé aux parenthèses utilisées dans une feuille Excel qui, placées là ou ailleurs font que le résultat du calcul n’est pas le même.
Donc en plaçant le “delay(xx);” entre les bonnes parenthèses, le prgm obéit comme je le veux.
le code

#include <Servo.h>
Servo myservo;
int pin_servo = 6;
int pos = 0;
int angle_initial = 0;
int angle_final = 100;
int increment = 1;
bool angle_actuel = false;

void setup() {
  Serial.begin(9600);  
  while(!Serial){;}
  myservo.attach(pin_servo);
}

void loop() {

  for(pos = angle_initial; pos <= angle_final; pos += increment){ 
    myservo.write(pos);              
    delay(55);   
    if (angle_actuel){
        Serial.println(myservo.read());
    }
  }
  delay(3000);
  
  for(pos = angle_final; pos >= angle_initial; pos -=increment){
    myservo.write (pos);
    delay(55);
    if (angle_actuel){
      Serial.print(myservo.read());
    }
  }
  delay(3000);  
}

Merci encore,

Claude papaciela

Ok :slight_smile: j’ai corrigé et supprimée une paire de { qui ne servait à rien :slight_smile:

@+

1 « J'aime »