Club robotique de Sophia-Antipolis

Accueil > POBOTpedia > Programmation > Apprendre à coder > Programmation Arduino > Interface en ligne de commande

Interface en ligne de commande

Mise en oeuvre sous Arduino

jeudi 19 mars 2009, par Julien H.

Tout d’abord, rappelons ce qu’est une interface en ligne de commande. Il s’agit d’un moyen de communiquer entre un humain et une machine, en tapant du texte lisible dans une console. En anglais, CLI pour Command Line Interface.

On a tous utilisé au moins une fois la ligne de commande, c’est le DOS (pour les Microsoftiens) ou le Shell (pour les Linuxiens). Donc l’objectif ici est de communiquer avec une carte Arduino en tapant dans un terminal des consignes du type "gauche45" ou "avance50" ou "recule9s" pour faire tourner d’un angle de 45°, avancer de 50 cm ou reculer pendant 9 secondes.

Pour ceux qui utilisent des Atmel AVR sans Arduino, sachez qu’il existe une belle implémentation (mieux que celle ci-dessous) dans AVRlib, avec un réel shell (sauvegarde des n dernières commandes, invite de commande en terminal VT100-like, bref du nanan). Ici l’objectif est théorique et pour répondre à quelques demandes de nos amis roboticiens. Je déconseille l’utilisation de la ligne de commande, car ça prend beaucoup de temps de calcul pour rien : il est préférable d’utiliser une simple petite applet Processing pour servir d’intermédiaire entre une interface utilisateur (graphique ou textuelle) et la communication avec l’Arduino utilisant des octets plutôt que des caractères (0x94 plutôt que ’1’ ’4’ ’8’ —> ratio de 1 à 3).

Le principe

Dans la boucle de traitement de notre carte Arduino, on va procéder par étape :
 la récupération de la trame (la suite de caractères) envoyée sur la liaison série et son stockage dans un tableau
 le traitement du tableau en reconnaissant chacune des consignes
 la reconstruction des valeurs numériques selon le format choisi à l’avance pour chacune des consignes

Voici un exemple de trame qu’on va pouvoir traiter dans notre première version : "SG45D123" qui signifie :
 S : comme Start, indique qu’on commence une nouvelle trame (obligatoire, car en fait l’Arduino reçoit deux trames, la première de 1 caractère...)
 G : comme Gauche, indique une vitesse pour le moteur gauche
 D : comme Droite, indique une vitesse pour le moteur... droit, bravo :)

Comme vous l’avez certainement deviné, la difficulté est de pouvoir gérer à la fois une consigne courte G2 et une consigne longue G4531. Bon ok, une fois que vous aurez vu comment j’ai fait vous trouverez que c’était simple, mais bon... j’espère que ça rendra service à quelques-uns.

Le code

/**
 * Command Line Interface for Arduino
 *
 * Julien Holtzer for www.pobot.org
 * 
 * 18 mars 2009, late in the night
 */

// numerical value to be decoded after specific commands
int value = 0;

// where we currently are in the sequence construction or decoding
int indice = 0;

// the sequence of characters where is stored what the user wants
char commande[40]; // reduce the length to save memory (if necessary)

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

/**
 *
 */
void loop()
{
  // Start a new reception, reinit the browser index of the array
  indice = 0;
  // Fill-in the sequence of chars with all received characters
  while (Serial.available())
  {
    commande[indice++] = Serial.read();    
  }
  // End the array with a specific character (E=End)
  // (means that you can't choose 'E' as a user meaning command
  commande[indice] = 'E';

  // Don't continue the loop if no command (adapt to your own code)
  if (indice == 0) return;

  // DEBUG Display that a new sequence has been found
  //Serial.print("> Received command, length=");
  //Serial.println(indice);

  // Start parsing the sequence array
  indice = 0;
  while (commande[indice] != 'E') 
  {
    // Reinit the numerical value
    value = 0;
    //
    switch (commande[indice])
    {
    case 'S':
      Serial.println("> Start command.");
      break;
    case 'G':
      // Continue to the next char (could contain the numerical value
      indice++;
      while (commande[indice] >= 48 && commande[indice] <= 57)
      {
        value = value * 10 + (commande[indice]-48);  
        // next digit
        indice++;
      }
      // Back if no more digit to be added to numerical value
      indice--;
      Serial.print("> servo gauche : ");
      Serial.println(value,DEC);
      break;
    case 'D':
      // Continue to the next char (could contain the numerical value
      indice++;
      while (commande[indice] >= 48 && commande[indice] <= 57)
      {
        value = value * 10 + (commande[indice]-48);  
        // next digit
        indice++;
      }
      // Back if no more digit to be added to numerical value
      indice--;
      Serial.print("> servo droit : ");
      Serial.println(value,DEC);
      break;
    default:
      //Serial.print("> unrecognized command : ");
      //Serial.println(commande[indice]);
      break;      
    }      
    indice++;
  } 

}

Ce code a été discuté quelques mois plus tard sur le forum Arduino : discussion sur le forum officiel Arduino.cc. Il y est fait mention d’une amélioration que vous pouvez essayer.

Résultat

Voici ce que ça donne dans le terminal intégré au logiciel Arduino :

Il y a maintenant une amélioration à faire : gérer le signe - pour pouvoir utiliser des valeurs négatives, comme par exemple une trame "SG-15D15" pour tourner sur place.

Vos commentaires

Un message, un commentaire ?

modération a priori

Attention, votre message n’apparaîtra qu’après avoir été relu et approuvé.

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.