Phare à LED (moteur pas à pas, commutation....), gyrophare

Phare à LED version 2 : Programme de test

J’ai repris le concept de phare à LED en repartant de zéro et j’ai opté pour mettre une LED sur un moteur et de faire tourner ce dernier. Le but est de pouvoir contrôler la rotation de notre moteur.
Nous utilisons un Arduino MEGA 2560, un écran LCD, des boutons poussoirs, un ULN2803 et un moteur pas à pas 55SI-25DAYA.


Figure 1 : Ecran LCD


Figure 2 : Carte Arduino


Figure 3 : ULN2803


Figure 4 : Moteur 55SI-25DAYA
Le moteur est un moteur pas à pas unipolaire : le courant ne passe que dans un seul sens. Il possède 6 pins : 2 pour l’alimentation (1 de chaque cotés) et 4 autres pins afin d’alimenter ou non ses bobines. Cela va nous permettre aussi de changer son sens de rotation.

Dans cette première partie, je n’ai réalisé que la simulation avec un programme de test.

Programme de test

#include <TimerOne.h>
#include <LiquidCrystal.h>

#define HG 2
#define BG 3
#define HD 4
#define BD 5
#define BP_SENS 32
#define LED13 13
#define BP_incrementation 34
#define BP_decrementation 35

LiquidCrystal lcd(27, 28, 25, 24, 23, 22); // RS=12, Enable=11, D4=5, D5=4, D6= 3, D7=2

signed int etape=0;
unsigned int temps=0;   //temps entre deux pas
unsigned int flag;        // sens de reotation du moteur
unsigned int seconde_pas;  //temps par pas

Dans cette partie du programme, j’ai d’abord inclus les bibliothèques nécessaires. Vu que nous utilisons un écran LCD, nous devons intégrer la bibliothèque LiquidCrystal. De plus, nous utilisons une routine d’interruption, nous devons rajouter la bibliothèque TimerOne. Ensuite, j’ai défini mes entrées et sorties en fonction de mes besoins. Le moteur à 4 pins et chacune d’entre elle est reliée à l’Arduino. Elles sont représentées par HG (Haut Gauche), BG (Bas Gauche), HD (Haut Droite), et BD (Bas Droite) par rapport à la simulation.

void setup() {
  pinMode(HG,OUTPUT);
  pinMode(BG,OUTPUT);
  pinMode(HD,OUTPUT);
  pinMode(BD,OUTPUT);
  seconde_pas = 100;
  // programmation d'une interruption toutes les 1 millisecondes
  Timer1.initialize(1000);
  Timer1.attachInterrupt(timerIsr);
  lcd.begin(16, 2);
}

Nous faisons ici la partie setup du programme où nous déclarons le sens des broches de l’Arduino. Nous initialisons aussi la variable qui indique le nombre de seconde par pas. Le Timer1 est initialisé à 1 milliseconde. L’écran que nous utilisons est un écran 2 lignes 16 colonnes.

void timerIsr() { // fonction appelée lors de l'interruption 1ms
 temps++;

}

Ici nous incrémentons notre variable temps de 1 à chaque interruption. Elle nous servira pour définir la vitesse de rotation des étapes.

void pas(int etape) {
  switch(etape) {
    case 0: // 1000
    digitalWrite(HG,HIGH);
    digitalWrite(BG,LOW);
    digitalWrite(HD,LOW);
    digitalWrite(BD,LOW);
 //   delay(200);
    break;
    case 1: // 0010
    digitalWrite(HG,LOW);
    digitalWrite(BG,LOW);
    digitalWrite(HD,HIGH);
    digitalWrite(BD,LOW);
//    delay(200);
    break;
    case 2: // 0001
    digitalWrite(HG,LOW);
    digitalWrite(BG,LOW);
    digitalWrite(HD,LOW);
    digitalWrite(BD,HIGH);
 
    break;
    case 3: // 0100
    digitalWrite(HG,LOW);
    digitalWrite(BG,HIGH);
    digitalWrite(HD,LOW);
    digitalWrite(BD,LOW);
    break;
  }  
}

Notre fonction pas ici nous donne le séquencement des pins à alimenter. Elles sont alimentées en fonction de leur position et de la position du moteur. Le digitalWrite permet d’écrire une valeur sur la pin voulue (1 ou 0).

void pas_sens_1() {
  etape++;
  if (etape>3) etape = 0;
  pas(etape);
 }

void pas_sens_2() {
  etape--;
  if (etape<0) etape = 3;
  pas(etape);  
}

Nous avons ici 2 fonctions permettant la rotation du moteur. La première permet de tourner dans le sens horaire, la deuxième dans le sens antihoraire. En fonction de la rotation, soit la valeur de etape monte d’un cran, soit elle diminue. Quand la valeur dépasse 3 dans le sens horaire, on la remet à 0. Si elle tombe en dessous de 0 dans le sens antihoraire, elle remonte à 3 afin de perpétuer le cycle. Ensuite, on alimente la bobine en fonction de l’étape actuelle.

void loop() {

    lcd.setCursor(1,0);      //colonne, ligne
    lcd.print("etape : ");
    lcd.setCursor(9,0);
    lcd.print(etape);
    lcd.setCursor(1,1);
    lcd.print("sec/pas :");
    lcd.print(seconde_pas); 
    lcd.print("     "); 
      

    if(digitalRead(BP_incrementation)==1) { seconde_pas++; delay(50); }
    if(digitalRead(BP_decrementation)==1) { seconde_pas--; delay(50);}

    if(digitalRead(BP_SENS)==1){ flag=1;}
    else {flag = 2;}


     if (temps>seconde_pas) {
      if(flag == 1) { 
        pas_sens_1();
      } 
      else{
        pas_sens_2();
      }
        temps=0; 
      }
}

La fonction principale du programme va nous permettre ici d’écrire sur l’écran LCD les valeurs voulues. Le lcd.setCursor nous permet de déplacer le curseur sur l’écran et le lcd.print d’écrire à l’endroit du curseur. Nous écrirons sur le LCD la valeur de l’étape actuelle ainsi que le nombre de secondes par pas.
Ensuite, nous avons l’utilisation des boutons : le BP_incrementation va permettre d’augmenter le nombre de secondes par pas. Le délai de 50ms va permettre de ne pas incrémenter trop rapidement.
Idem pour le BP_decrementation mais dans l’autre sens cette fois. Le BP_SENS va nous permettre de changer le sens de rotation. Quand le bouton sera sur 1, on ira dans le sens horaire, quand il sera sur 0 on ira dans l’autre sens. Enfin, si notre temps devient supérieur à la valeur de notre variable seconde_pas alors en fonction du flag (qui indique le sens de rotation), le moteur tournera dans le sens voulu.

Le programme complet :

// commande d'un moteur pas à pas unipolaire avec un ULN2803
// programmation des pas par interruption

#include <TimerOne.h>
#include <LiquidCrystal.h>

#define HG 2
#define BG 3
#define HD 4
#define BD 5
#define BP_SENS 32
#define LED13 13
#define BP_incrementation 34
#define BP_decrementation 35

LiquidCrystal lcd(27, 28, 25, 24, 23, 22); // RS=12, Enable=11, D4=5, D5=4, D6= 3, D7=2

signed int etape=0;
unsigned int temps=0;   //temps entre deux pas
unsigned int flag;        // sens de reotation du moteur
unsigned int seconde_pas;  //temps par pas

void setup() {
  pinMode(HG,OUTPUT);
  pinMode(BG,OUTPUT);
  pinMode(HD,OUTPUT);
  pinMode(BD,OUTPUT);
  seconde_pas = 100;
 // pas(etape);
  // programmation d'une interruption toutes les 1 millisecondes
  Timer1.initialize(1000);
  Timer1.attachInterrupt(timerIsr);
  lcd.begin(16, 2);
}


void timerIsr() { // fonction appelée lors de l'interruption 20ms
 temps++;

}


void pas(int etape) {
  switch(etape) {
    case 0: // 1000
    digitalWrite(HG,HIGH);
    digitalWrite(BG,LOW);
    digitalWrite(HD,LOW);
    digitalWrite(BD,LOW);
 //   delay(200);
    break;
    case 1: // 0010
    digitalWrite(HG,LOW);
    digitalWrite(BG,LOW);
    digitalWrite(HD,HIGH);
    digitalWrite(BD,LOW);
//    delay(200);
    break;
    case 2: // 0001
    digitalWrite(HG,LOW);
    digitalWrite(BG,LOW);
    digitalWrite(HD,LOW);
    digitalWrite(BD,HIGH);
 
    break;
    case 3: // 0100
    digitalWrite(HG,LOW);
    digitalWrite(BG,HIGH);
    digitalWrite(HD,LOW);
    digitalWrite(BD,LOW);
    break;
  }  
}

void pas_sens_1() {
  etape++;
//  delay(200);
  if (etape>3) etape = 0;
  pas(etape);
 }

void pas_sens_2() {
  etape--;
//  delay(200);
  if (etape<0) etape = 3;
  pas(etape);  
}



void loop() {

    lcd.setCursor(1,0);      //colonne, ligne
    lcd.print("etape : ");
    lcd.setCursor(9,0);
    lcd.print(etape);
    lcd.setCursor(1,1);
    lcd.print("sec/pas :");
    lcd.print(seconde_pas); 
    lcd.print("     "); 
      

    if(digitalRead(BP_incrementation)==1) { seconde_pas++; delay(50); }
    if(digitalRead(BP_decrementation)==1) { seconde_pas--; delay(50);}

    if(digitalRead(BP_SENS)==1){ flag=1;}
    else {flag = 2;}


     if (temps>seconde_pas) {
      if(flag == 1) { 
        pas_sens_1();
      } 
      else{
        pas_sens_2();
      }
        temps=0; 
      }
}

programme_pas_pas_4pins.ino (2.31 KB)