Ecran lcd : afficher sans câble USB

Comment faire si l’on veut afficher des valeurs et ne pas utiliser le moniteur série et le câble USB ?

Une solution est d’utiliser un écran LCD directement connecté sur l’Arduino.

Il existe de nombreux écrans lcd pour Arduino, sous forme de shield (la carte lcd s’empile au-dessus de l’Arduino) ou de module indépendant. J’ai trouvé que le module DFR0063 (LCD1602) était très intéressant car pour afficher deux lignes de 16 caractères, 4 fils seulement sont nécessaires : le + le – et deux fils de signal.

L’Arduino, ici en fait un DFRduino, est alimenté en 7,5v grâce à un adaptateur secteur. Le câble USB est nécessaire pour charger le programme mais on peut ensuite s’en passer. S’il l’on veut se passer d’un adaptateur secteur, on peut utiliser des boîtiers de piles. On peut donc sans peine imaginer un modèle Meccano autonome embarquant un Arduino et possédant des capacités d’affichage

Pour les branchements de l’écran, le schéma présenté sur le site de DFRobot ne correspond pas exactement à l’exemplaire d’écran LCD que j’ai sous la main (position de SCL et SDA inversée sur le schéma). Pour que cela marche, SDA doit être relié à l’entrée analogique 4 et SCL à l’entrée analogique 5.

Fichier hébergé par Archive-Host.com

Pour que cela fonctionne il faut télécharger la librairie nécessaire depuis le site de DFRobot. Cette librairie est en fait un dossier nommé LiquidCrystal_I2C qu’il faut décompresser (c’est un .rar) et copier au bon endroit sur votre ordinateur. (Ce bon endroit dépend de votre système d’exploitation Mac, Windows, Linux …)

Un petit programme de démonstration où l’on affiche sur l’écran la valeur de 0 à 1023 que l’Arduino calcule en fonction de la position d’un potentiomètre.


#include <Wire.h> // librairie standard
#include <LiquidCrystal_I2C.h> // librairie à télécharger

// Parametrer l'adresse du LCD à 0x27 
// pour deux lignes de 16 caractères

LiquidCrystal_I2C lcd(0x27,16,2);  


// sur la broche A0  on connecte le signal (0 à 5v)
// une autre broche du potentiomètre est reliée au 5v
// la dernière broche est reliée à la masse (GND)

const int Pin_input=0; 

// Variable qui va contenir une valeur entre 0 et 1023
// suivant la position du potentiomètre

int mesure=0;


void setup()   { 
  
   lcd.init();     // initialiser le lcd 
   lcd.backlight(); // allumer écran
   lcd.print("Valeur lue :    "); // affichage fixe
} 


void loop(){ 

// Sur l'entree analogique la mesure de la tension
// est convertie en un nombre compris entre 0 et 1024 

mesure=analogRead(Pin_input); 

lcd.setCursor(0,1); // curseur début deuxième ligne
lcd.print("    "); // effacer la mesure précédente
lcd.setCursor(0,1); // curseur début deuxième ligne
lcd.print(mesure);




// On attend un peu avant la prochaine mesure

delay(1000); 

} 

Potentiomètre, slider et processing (partie 3)

Et si on a quatre moteurs à commander, on fait comment ? Voici une solution, de luxe, car elle utilise deux cartes DFRduino. Ce n’est pas du tout nécessaire d’utiliser deux cartes, on peut aussi compléter une carte DFRduino par un module de contrôle moteur ou si on a les connaissances nécessaires, se procurer les composants transistors, diodes… et les brancher à la carte.

L’intérêt de cet article c’est que l’on commande les deux cartes avec une seule interface Processing.

Fichier hébergé par Archive-Host.com

Sur chaque carte DFRduino on a un chargé le même petit programme publié au post précédent. Côté PC le code processing a bien sûr évolué, le voici :


// Slider 4

// Quatre sliders pour commander la vitesse de quatre moteurs 

// situés sur deux cartes différentes

// moteur 1 est sur la carte DFRduino 1, port M1

// moteur 2 est sur la carte DFRduino 1, port M2

// moteur 3 est sur la carte DFRduino 2, port M1

// moteur 4 est sur la carte DFRduino 2, port M2
  
 
 // importer les librairies nécessaires
 
import processing.serial.*; // présente par défaut
import controlP5.*; // il faut l'installer


ControlP5 controlP5_carte1, controlP5_carte2;

Serial serial_port1, serial_port2;

int prefixe_moteur1 = 111 ; // ce prefixe indique que la commande 
                            // qui va suivre  concerne le moteur 1

int prefixe_moteur2 = 121 ; // ce prefixe indique que la commande
                           // qui va suivre concerne le moteur2

void setup() {
  // On dessine la fenetre de l'interface graphique
  size(400,350);
  
  // Le programme affiche dans la fenetre de debuggage
  // de processing, en bas d'écran la lise des ports
  
   
  println("Voici la liste des ports :");
  println(Serial.list());

 // on utilise deux ports "serie" et deux cables USB
 // mais une seule interface processing
   
  int numero_port_serie1 = 0;
  
  int numero_port_serie2 = 1;
  
  print("Le numero de port 1 est : ");
  println(numero_port_serie1 );
  
  String port1 = Serial.list()[numero_port_serie1];
  
  print("Le port 1 est : " );
  println(port1);
  
  print("Le numero de port 2 est : ");
  println(numero_port_serie2 );
  
  String port2 = Serial.list()[numero_port_serie2];
  
  print("Le port 2 est : " );
  println(port2);
 
  // Crer les ports serie et les controles associes
  
  serial_port1 = new Serial(this, port1, 19200); // attention a mettre la même vitesse
                                                 // coté DFRduino
                                               
  controlP5_carte1 = new ControlP5(this); 
                                            
                                               
  serial_port2 = new Serial(this, port2, 19200); // attention a mettre la même vitesse
                                                 // coté DFRduino
   
  controlP5_carte2 = new ControlP5(this); 
  
  // Crer un premier slider horizontal
  
  //("Nom du Slider", min,max, pos de depart, xpos,ypos, largeur,hauteur);
  controlP5_carte1.addSlider("MOTEUR1", -50,50, 0, 100,50, 200,20);
  
  // Configure les propriétés du Slider
  Slider s1 = (Slider)controlP5_carte1.controller("MOTEUR1");
  s1.setSliderMode(Slider.FLEXIBLE);
  s1.setNumberOfTickMarks(11);
  s1.showTickMarks(true);
  s1.snapToTickMarks(false);

  // Crer un second slider horizontal

  //("Nom du Slider", min,max, pos de depart, xpos,ypos, largeur,hauteur);
  controlP5_carte1.addSlider("MOTEUR2", -50,50, 0, 100,100, 200,20);
  
  // Configure les propriétés du Slider
  Slider s2 = (Slider)controlP5_carte1.controller("MOTEUR2");
  s2.setSliderMode(Slider.FLEXIBLE);
  s2.setNumberOfTickMarks(11);
  s2.showTickMarks(true);
  s2.snapToTickMarks(false);
  
  // Crer un troisieme slider horizontal

  //("Nom du Slider", min,max, pos de depart, xpos,ypos, largeur,hauteur);
  controlP5_carte2.addSlider("MOTEUR3", -50,50, 0, 100,150, 200,20);
  
  // Configure les propriétés du Slider
  Slider s3 = (Slider)controlP5_carte2.controller("MOTEUR3");
  s3.setSliderMode(Slider.FLEXIBLE);
  s3.setNumberOfTickMarks(11);
  s3.showTickMarks(true);
  s3.snapToTickMarks(false);
  
  // Crer un quatrieme slider horizontal

  //("Nom du Slider", min,max, pos de depart, xpos,ypos, largeur,hauteur);
  controlP5_carte2.addSlider("MOTEUR4", -50,50, 0, 100,200, 200,20);
  
  // Configure les propriétés du Slider
  Slider s4 = (Slider)controlP5_carte2.controller("MOTEUR4");
  s4.setSliderMode(Slider.FLEXIBLE);
  s4.setNumberOfTickMarks(11);
  s4.showTickMarks(true);
  s4.snapToTickMarks(false);   
   
}


// Dessine les objets choisis
void draw() {
background(100); // 100 : fond gris
}

// Dans cette methode
// on recupère la valeur 
// renvoyée par le slider moteur1 (carte 1)
// et on l'envoie à l'Arduino

void MOTEUR1(float valeur_slider) {
  
  int sens = 1; // marche avant moteur
  
  // Récupérer la valeur envoyée par le slider entre -50 et 50
  
  if (valeur_slider < 0) {
      sens= 0 ; // marche arriere
      valeur_slider = - valeur_slider;
  }    
  
  int vitesse = round(valeur_slider);
  
  // envoyer cette valeur à l'Arduino 
 
  serial_port1.write (prefixe_moteur1);
  
  serial_port1.write (sens);
  
  serial_port1.write(vitesse);  
   
}

// Dans cette methode
// on recupère la valeur 
// renvoyée par le slider moteur2 (carte 1)
// et on l'envoie à l'Arduino

void MOTEUR2(float valeur_slider) {
  
  int sens = 1; // marche avant moteur
  
  // Récupérer la valeur envoyée par le slider entre -50 et 50
  
  if (valeur_slider < 0) {
      sens= 0 ; // marche arriere
      valeur_slider = - valeur_slider;
  }    
  
  int vitesse = round(valeur_slider);
  
  // envoyer cette valeur à l'Arduino 
 
  serial_port1.write (prefixe_moteur2);
  
  serial_port1.write (sens);
  
  serial_port1.write(vitesse);
    
}

// Dans cette methode
// on recupère la valeur 
// renvoyée par le slider moteur3 (carte 2)
// et on l'envoie à l'Arduino

void MOTEUR3(float valeur_slider) {
  
  int sens = 1; // marche avant moteur
  
  // Récupérer la valeur envoyée par le slider entre -50 et 50
  
  if (valeur_slider < 0) {
      sens= 0 ; // marche arriere
      valeur_slider = - valeur_slider;
  }    
  
  int vitesse = round(valeur_slider);
  
  // envoyer cette valeur à l'Arduino 
 
  serial_port2.write (prefixe_moteur1);
  
  serial_port2.write (sens);
  
  serial_port2.write(vitesse);  
   
}

// Dans cette methode
// on recupère la valeur 
// renvoyée par le slider moteur4 (carte 2)
// et on l'envoie à l'Arduino

void MOTEUR4(float valeur_slider) {
  
  int sens = 1; // marche avant moteur
  
  // Récupérer la valeur envoyée par le slider entre -50 et 50
  
  if (valeur_slider < 0) {
      sens= 0 ; // marche arriere
      valeur_slider = - valeur_slider;
  }    
  
  int vitesse = round(valeur_slider);
  
  // envoyer cette valeur à l'Arduino 
 
  serial_port2.write (prefixe_moteur2);
  
  serial_port2.write (sens);
  
  serial_port2.write(vitesse);  
  
}

Fichier hébergé par Archive-Host.com

Potentiomètre slider et processing (partie 2)

Une fois que le programme fonctionne pour faire varier la brillance de deux LED en mode pwm, il n’y a pas beaucoup de choses à faire pour commander deux moteurs.

Ici on utilise un DFRduino qui possède déjà deux sorties moteur intégrées. Les branchements sont limpides :

Fichier hébergé par Archive-Host.com

La fenêtre crée par processing a cette allure là :

Fichier hébergé par Archive-Host.com

Le curseur démarre en position milieu, la vitesse est nulle. En déplaçant le curseur à la souris sur la droite la vitesse du moteur concerné augmente, en marche avant. Si on démarre de la position milieu mais que l’on déplace le curseur vers la gauche, la vitesse augmente mais en marche arrière.

Il faut d’abord charger le programme suivant sur le DFRduino :


/*
 * Slider2
 * deux moteurs 
 * DFRduino
*/
 
 
int tab_Pin_sens[2] = {4,7} ; // le sens du moteur 1 est commandé par la Pin 4 
                              // le sens du moteur 2 est commandé par la Pin 7

int tab_Pin_pwm[2] = {5,6} ; // la vitesse du moteur 1 est commandée par la Pin 5 
                             // la vitesse du moteur 2 est commandée par la Pin 6


int pwm = 255;  // la largeur d'impulsion pwm (0-255)

byte donnee_serie = 0;

void setup() {
   // Ouvrir la liaison serie
   Serial.begin(19200);
}

void loop() {
  
  int sens=0;
  int vitesse= 0;
  int moteur=0;
  
   // Est-ce qu'il y a qq chose à lire sur l'interface série ?
   
   if (Serial.available()) {
     
     donnee_serie = Serial.read();
     
     if ((donnee_serie == 111) || (donnee_serie == 121)) {       
    
         donnee_serie = donnee_serie -101 ;
         moteur=donnee_serie / 10 ; // deduire du prefixe le numero moteur
               
         sens=lire_suivant(); // sens
         vitesse=lire_suivant(); // vitesse
         controle(moteur,sens,vitesse);
                 
     }   // 111 ou 121         
               
     } // 1er serial available
          
        
} // loop           

int lire_suivant() {
  
 
while (1) { 

 if (Serial.available() ) {
      return (Serial.read());
 }
 
} // while

}
 

// la procedure de controle des moteurs

void controle (int m, int sens, int v)          // m : 1 ou 2 pour moteur 1 ou moteur 2,                                                                                              
                                                // sens : 1 ou 0 (avant ou arrière)
                                                // v : vitesse de 0 à 50, 
{
        int pwm;
        pwm = map(v, 0,50, 0,255); // ramener vitesse à l'intervalle 0 255
        digitalWrite(tab_Pin_sens[m-1],sens);  // fixer sens
        analogWrite (tab_Pin_pwm[m-1],pwm);    // fixer vitesse
                             

}

Il faut ensuite sortir de l’interface « Arduino », lancer l’interface Processing et exécuter le programme suivant :


// Slider 2

// Deux sliders pour commander la vitesse de deux moteurs 
  
 
 // importer les librairies nécessaires
 
import processing.serial.*; // présente par défaut
import controlP5.*; // il faut l'installer


ControlP5 controlP5;
Serial serial;

int prefixe_moteur1 = 111 ; // ce prefixe indique que la commande 
                            // qui va suivre  concerne le moteur 1

int prefixe_moteur2 = 121 ; // ce prefixe indique que la commande
                           // qui va suivre concerne le moteur2

void setup() {
  // On dessine la fenetre de l'interface graphique
  size(400,350);
  
  // Le programme affiche dans la fenetre de debuggage
  // de processing, en bas d'écran la liste des ports
  
   
  println("Voici la liste des ports :");
  println(Serial.list());
  
  // ici on a choisi le port 0
  // il faut peut-être essayer une autre
  // valeur de la liste en cas de pb
  
  int numero_port_serie = 0;
  
  print("Le numero de port est : ");
  println(numero_port_serie);
  
  String port = Serial.list()[numero_port_serie];
  
  print("Le port est : " );
  println(port);
 
  
  serial = new Serial(this, port, 19200); // attention a mettre la même vitesse
                                          // coté DFRduino
  
 
  controlP5 = new ControlP5(this); 
  
  // Crer un premier slider horizontal
  
  //("Nom du Slider", min,max, pos de depart, xpos,ypos, largeur,hauteur);
  controlP5.addSlider("MOTEUR1", -50,50, 0, 100,50, 200,20);
  
  // Configure les propriétés du Slider
  Slider s1 = (Slider)controlP5.controller("MOTEUR1");
  s1.setSliderMode(Slider.FLEXIBLE);
  s1.setNumberOfTickMarks(11);
  s1.showTickMarks(true);
  s1.snapToTickMarks(false);

  // Crer un second slider horizontal

  //("Nom du Slider", min,max, pos de depart, xpos,ypos, largeur,hauteur);
  controlP5.addSlider("MOTEUR2", -50,50, 0, 100,150, 200,20);
  
  // Configure les propriétés du Slider
  Slider s2 = (Slider)controlP5.controller("MOTEUR2");
  s2.setSliderMode(Slider.FLEXIBLE);
  s2.setNumberOfTickMarks(11);
  s2.showTickMarks(true);
  s2.snapToTickMarks(false);
}

// Dessine les objets choisis
void draw() {
  background(100); // 100 : fond gris
}


// Dans cette methode
// on recupère la valeur 
// renvoyée par le slider moteur1
// et on l'envoie à l'Arduino

void MOTEUR1(float valeur_slider) {
  
  int sens = 1; // marche avant moteur
  
  // Récupérer la valeur envoyée par le slider entre -50 et 50
  
  if (valeur_slider < 0) {
      sens= 0 ; // marche arriere
      valeur_slider = - valeur_slider;
  }    
  
  int vitesse = round(valeur_slider);
  
  // envoyer cette valeur à l'Arduino 
 
  serial.write (prefixe_moteur1);
  
  serial.write (sens);
  
  serial.write(vitesse);  
 
}



// Dans cette methode
// on recupère la valeur 
// renvoyée par le slider moteur2
// et on l'envoie à l'Arduino

void MOTEUR2(float valeur_slider) {
  
  int sens = 1; // marche avant moteur
  
  // Récupérer la valeur envoyée par le slider entre -50 et 50
  
  if (valeur_slider < 0) {
      sens= 0 ; // marche arriere
      valeur_slider = - valeur_slider;
  }    
  
  int vitesse = round(valeur_slider);
  
  // envoyer cette valeur à l'Arduino 
 
  serial.write (prefixe_moteur2);
  
  serial.write (sens);
  
  serial.write(vitesse); 
  
 }

Ce programme Processing s’éxecute donc sur le PC, lit les déplacements de curseur et les transmet au DFRduino par le câble USB ; le programme installé sur le DFRduino lit les données envoyées et commande en conséquence les deux moteurs.

Potentiomètre Slider et processing (partie 1)

Un ami passionné de Meccano, Yves, m’a dit : « est-ce qu’on pourrait commander des moteurs à la souris à l’aide de l’Arduino ? » J’ai pensé à utiliser le langage Processing et je suis tombé sur un article qui permet de contrôler la luminosité d’une LED au moyen d’un curseur déplacé à la souris grâce à un petit programme à charger sur l’Arduino et à un autre programme écrit en langage Processing.

Pour aller plus loin, j’ai voulu faire la même chose mais avec deux led (avec l’arrière-pensée de remplacer les led et de piloter bientôt deux moteurs).

Arduino processing slider

Voici le petit programme à implanter sur l’Arduino :


/*
 * Slider1
 * deux LED
 *
*/
 
 
int tab_Pin[2] = {9,10} ; // la led1 est sur la Pin 9 , la led 2 sur la pin 10

int pwm = 255;  // la largeur d'impulsion pwm (0-255)

byte donnee_serie = 0;

void setup() {
   // Ouvrir la liaison serie
   Serial.begin(19200);
}

void loop() {
  
   // Est-ce qu'il y a qq chose à lire sur l'interface série ?
   
   if (Serial.available()) {
     
     donnee_serie = Serial.read();
     
     if (donnee_serie == 111) { // prefixe pour commander la LED1
                   
          donnee_serie=lire_suivant();
          controle(1,donnee_serie);
                 
        } else {
              if (donnee_serie == 121) { // prefixe pour commander la LED2                 
                    donnee_serie=lire_suivant();
                    controle(2,donnee_serie);
                }
          } // else si donnee_serie 211
          
               
     } // 1er serial available
          
        
} // loop           

int lire_suivant() {
  
 
while (1) { 

 if (Serial.available() ) {
      return (Serial.read());
 }
 
} // while

}

void controle (int pin , int pwm) {
  
 Serial.print ("PWM1 : "); Serial.println(pwm);

 pwm = map(pwm, 0,100, 0,255);
 
 pin = tab_Pin[pin -1] ;
 
 Serial.print ("PIN : "); Serial.println(pin);
 
 Serial.print ("PWM : "); Serial.println(pwm);
 
 analogWrite (pin,pwm);

} 

Une fois ce programme implanté sur l’Arduino, il faut fermer l’interface de développement Arduino et lancer sur le PC l’interface de développement Processing.

Fichier hébergé par Archive-Host.com

Celle-ci ressemble furieusement à l’interface de développement pour Arduino mais le langage n’est pas le même. Le script processing à éxécuter sur le PC est le suivant :


// Slider 1

// Deux sliders pour commander la luminosité de deux led 
  
 
 // importer les librairies nécessaires
 
import processing.serial.*; // présente par défaut
import controlP5.*; // il faut l'installer


ControlP5 controlP5;
Serial serial;

int prefixe_led1 = 111 ; // ce prefixe indique que la commande 
                         // qui va suivre  concerne la led1

int prefixe_led2 = 121 ; // ce prefixe indique que la commande
                         // qui va suivre concerne la led2

void setup() {
  // On dessine la fenetre de l'interface graphique
  size(400,350);
  
  // Le programme affiche dans la fenetre de debuggage
  // de processing, en bas d'écran la lise des ports
  
   
  println("Voici la liste des ports :");
  println(Serial.list());
  
  // ici on a choisi le port 0
  // il faut peut-être essayer une autre
  // valeur de la liste en cas de pb
  
  int numero_port_serie = 0;
  
  print("Le numero de port est : ");
  println(numero_port_serie);
  
  String port = Serial.list()[numero_port_serie];
  
  print("Le port est : " );
  println(port);
 
  
  serial = new Serial(this, port, 19200); // attention a mettre la même vitesse
                                          // coté Arduino
  
 
  controlP5 = new ControlP5(this); 
  
  // Crer un premier slider horizontal
  
  //("Nom du Slider", min,max, pos de depart, xpos,ypos, largeur,hauteur);
  controlP5.addSlider("LED1", 0,100, 0, 100,50, 200,20);
  
  // Configure les propriétés du Slider
  Slider s1 = (Slider)controlP5.controller("LED1");
  s1.setSliderMode(Slider.FLEXIBLE);
  s1.setNumberOfTickMarks(11);
  s1.showTickMarks(true);
  s1.snapToTickMarks(false);

  // Crer un second slider horizontal

  //("Nom du Slider", min,max, pos de depart, xpos,ypos, largeur,hauteur);
  controlP5.addSlider("LED2", 0,100, 0, 100,150, 200,20);
  
  // Configure les propriétés du Slider
  Slider s2 = (Slider)controlP5.controller("LED2");
  s2.setSliderMode(Slider.FLEXIBLE);
  s2.setNumberOfTickMarks(11);
  s2.showTickMarks(true);
  s2.snapToTickMarks(false);
}

// Dessine les objets choisis
void draw() {
  background(100); // 100 : fond gris
}

// Dans cette methode
// on recupère la valeur 
// renvoyée par le slider LED1
// et on l'envoie à l'Arduino

void LED1(float valeur_slider) {
  
  // Récupérer la valeur envoyée par le slider entre 0 et 100
  
  int brillance_LED = round(valeur_slider);
  
  // envoyer cette valeur à l'Arduino
  // en commençant par le prefixe
  // qui permet de savoir quelle LED
  // est concernée
  
  serial.write (prefixe_led1);
    
  serial.write(brillance_LED);
  
  // pour controle dans la fenetre du bas de processing
  //print ("LED1 ");
  //println(brillance_LED);
  
 
}

// Dans cette methode
// on recupère la valeur 
// renvoyée par le slider LED2
// et on l'envoie à l'Arduino
void LED2(float valeur_slider) {
  
  // Récupérer la valeur envoyée par le slider entre 0 et 100
  
  int brillance_LED = round(valeur_slider);
  
  // envoyer cette valeur à l'Arduino 
 
  serial.write (prefixe_led2);
  
  serial.write(brillance_LED);
  
  // pour controle dans la fenetre du bas de processing
  
  //print ("LED2 ");
  
  //println(brillance_LED); 
 
}

A suivre une petite évolution pour commander deux moteurs à la souris …

loco sur une voie

Maintenant qu’on a tout ce qu’il faut pour mesurer des distances, on va construire une petite loco de manoeuvre, l’équiper d’un capteur infra-rouge à l’avant, d’un autre à l’arrière et la laisser se débrouiller entre les deux butées aux extrémités de la voie.

Quand la loco se rapproche de la fin de voie, elle ralentit progressivement et, arrivée à 3 cm, elle stoppe ; après 5 secondes d’arrêt, elle repart dans l’autre sens. Le même comportement a lieu aux deux extrémités de la voie.

Le DFRduino est embarqué à l’intérieur de la loco (il est protégé par un emballage spécial matériel électronique). Il a encore des fils à la patte (alim moteur 12v + câble USB) mais on pourrait imaginer l’équiper d’un boîtier de piles.

Il faut au moins 60 cm de voie pour que la loco se déplace de façon intéressante mais si la voie fait 5m, il n’y a rien à modifier dans le programme.

Loco meccano Dfrduino Arduino


// Arduino loco IR2

// On va connecter deux capteurs IR en entrée sur le DFRduino
// qui vont servir a controler le mouvement d'une loco
// sur un rail

// la vitesse diminue quand on se rapproche de l'obstacle 
// placé en fin de voie
// puis la loco stoppe 5 secondes
// et repart en sens inverse



// Entrées analogiques utilisées pour les capteurs

const int Pin_capteur_avant=0; 

const int Pin_capteur_arriere=1; 

// On a établi expérimentalement un tableau de correspondance
// entre mesure (entre 0 et 1023) et distance (entre 20 et 3 cm)
// on vise une précision au centimètre

// nombre maxi d'éléments du tableau 

#define NBEL 18

/*
mesure  distance indice tableau
81	20       0
90	19       1
105	18       2
118	17       3
130	16       4
144	15       5
156	14       6
172	13       7
188	12       8
205	11       9
232	10      10
257	9       11
294	8       12
339	7       13
394	6       14
459	5       15
544	4       16
635	3       17

*/

// Attention, pour ce capteur, en dessous de 3 cm
// les valeurs mesurées chutent

const int tab [NBEL]= {81,90,105,118,130,144,156,172,188,205,232,257,294,339,394,459,544,635} ;

// on fait un certain nb de mesures dont on fera la moyenne
// car le signal fluctue, meme pour une distance fixe

const int nb_mesures=5;

int mesure=0;

// distances min et max mesurées en cm

const int dmin = 3;

const int dmax = 20;

// valeurs retournées quand la mesure
// est hors bornes

int distance_avant = -1;

int distance_arriere= -1;

// valeurs paramètres pwm ok pour moteur jaune 6 vitesses
// controlant la vitesse du moteur

const int vmin = 100;

const int vmax= 255;


// Les différents états du mouvement

// V : marche avant
// R : marche arriere
// S : stop et attente

char etat='V';

// 2 sens V : marche avant ; R : marche arrière

char sens='V';

int vitesse=0;

// Pin de controle moteur

const int E1= 5;

const int M1=4;


void setup()   { 

// initialise connexion série à 115200 bauds

Serial.begin(115200); 

// initialiser pin controle moteur en sortie

pinMode(E1, OUTPUT); 

pinMode(M1, OUTPUT); 

} // setup


void loop(){ 
  
switch (etat) {
 
 case 'V' : // marche avant
      
    // mesurer distance avant  

    distance_avant=mesurer_distance(Pin_capteur_avant);
     
  if ( distance_avant == dmin)  { //  il faut stopper
      etat = 'S';
      } else {
      if (distance_avant == -1) { // on est encore loin de l'arrivée
          vitesse = vmax ; // max
      } else { // on s'approche, il faut ralentir
        vitesse = map (distance_avant,dmin,dmax,vmin,vmax);
      }
    sens='V';
    controle_moteur(1,vitesse,sens);
   }  
break ;   
      
case 'R' : // marche arriere
    
    // mesurer distance arriere  

      distance_arriere=mesurer_distance(Pin_capteur_arriere);
     
  if ( distance_arriere == dmin) { // il faut stopper
      etat = 'S';
      } else {
      if (distance_arriere == -1) { // on est encore loin de l'arrivée
          vitesse = vmax ; // max
      } else { // on s'approche, il faut ralentir
        vitesse = map (distance_arriere,dmin,dmax,vmin,vmax);
      }
    sens='R';
    controle_moteur(1,vitesse,sens);
   }  
break ;
  
case 'S' :

      // on stoppe la loco
      vitesse=0;
      controle_moteur(1,vitesse,sens);
      
      // on attend 5 secondes
      delay (5000);
      
      // on fixe la vitesse au maximum
      vitesse = vmax;
     
     // on change de sens
      
    if (sens == 'V') {
        etat = 'R' ; sens ='R'; 
        } else {
        etat = 'V' ; sens = 'V'; 
 }
    
break;

} // switch

} // loop


// Fonction mesurer_distance //////////////

int mesurer_distance (int pin) { 
  
// Variable qui va contenir une valeur entre 0 et 1023
// suivant la distance capteur - objet

int mesure=0;

// accumulateur pour calculer la moyenne des mesures
// on fait la moyenne car les valeurs fluctuent un peu
// meme pour une distance fixe

long acc=0;

// indice de boucle

int i=0;
   
// Sur l'entree analogique, la mesure de la tension
// délivrée par le capteur est convertie en un nombre
// compris entre 0 et 1023 

for (i=0; i < nb_mesures ; i++) {
  
  acc=acc + analogRead(pin); 
  
   // On attend un peu avant la prochaine mesure
   // il faut au moins 38ms entre deux mesures
   // sur ce capteur

   delay(40); 
}

// on fait la moyenne des mesures

mesure=acc/nb_mesures;


// On vérifie que la valeur mesurée est dans 
// un intervalle qui est celui des limites 
// du tableau légèrement assouplies

if ( (mesure > 650) || (mesure < 75)){
  
   // Serial.println ("Valeur mesurée hors bornes");
    
    return(-1);
    
} else {    

} // else hors bornes

return(convertir(mesure));

} // mesurer


// Fonction convertir  //////////////

int convertir(int mesure) { 
  
  // fonction de conversion mesure -> distance
  // Si on ne trouve pas la valeur exacte ce n'est pas
  // grave on prendra la valeur du tableau la plus
  // proche
  
  // on initialise l'indice qui limite à droite 
  // le tableau de recherche  
  // et l'indice qui limite 
  // à gauche le tableau de recherche
  // ce type de recherche est très performant
  
// nb éléments du tableau  

int N=NBEL;

// indices borne de gauche, borne de droite, milieu tableau

int g,d,m; 

int i=0;

g=0;

d=N-1;

while ( g<=d) {
       m = (g+d) / 2;
       if ( tab[m] < mesure)
           g = m + 1;
       else
           d = m - 1;
}

// de quelle borne est-on le plus proche ?

if ( abs(mesure - tab[g]) <   abs(mesure - tab[d]) ) {
  i = g ;
} else {
  i = d;
}

// l'indice 0 du tableau correspond à 20 cm
// l'indice 1 du tableau correspond à 19 cm ...

return(20-i);

} // convertir


//Procedure de controle du moteur ///////

  // m : 1 ou 2 pour moteur 1 ou moteur 2, 
  // v : vitesse de 0 à 255, 
  // sens : V ou R (avant ou arrière)

void controle_moteur (int m, int v, char sens)        
{
// Pin controle moteur

  
  if ( m == 1) { // moteur 1
      
    if (sens == 'V') { 
                  analogWrite (E1,v);      // fixer vitesse
                  digitalWrite(M1,HIGH);   // fixer sens en avant
                  } else {
                          analogWrite (E1,v);      // fixer vitesse
                          digitalWrite(M1,LOW);   // fixer sens en arrière
  
                  }
                  
  }

} // controle_moteur

Une vue de l’intérieur :

Arduino meccano

Les branchements :

Arduino meccano

On utilise des câbles de capteurs analogiques (analog sensor cable for Arduino ref FIT0031 chrez DFrobot), les mêmes câbles que ceux des potentiomètres précédemment utilisés.