leJOS et Eclipse (Java avec le LEGO Mindstorms EV3)

L'installation de la plateforme Java leJOS, basée sur Eclipse, est une expérience incontournable et facile pour les programmeurs qui ont une expérience avec Eclipse.
Pour des programmeurs C++, ce serait aussi une manière d'acquérir plus de compétences avec le langage Java.

Dans le livre Maximum LEGO Mindstorms EV3 nous retrouverons aussi différents aspects de développement de cette plateforme robot en Java. 

Lorsque j'ai commencé de jouer avec la balise infrarouge (IR) de l'EV3, avec les exemples qui viennent avec la plateforme Java leJOS et avec sa classe EV3IRSensor ... je n'ai pas vraiment compris grand chose.

L'idée m'est donc venue d'écrire une première application, toute petite, pour comprendre cette classe et les événements générés en pressant les différents boutons. Ensuite, je l'ai faite évoluée, en fonction des résultats, pour obtenir quelque chose de plus concret, comme de faire rouler mon robot en le commandant depuis la balise IR.

Le véhicule nécessaire doit être équipé au minimum des deux grands servomoteurs et du capteur infrarouge à gauche:

 

 

 

Les boutons de la balise infrarouge sont expliqués ci-dessous. 


Le capteur infrarouge doit être connecté au port 4.

 

Pour comprendre ce code, j'assume que le lecteur possède déjà de bonnes connaissances en Java.

La documentation API de la classe EV3IRSensor est décrite ici:
http://www.lejos.org/ev3/docs/index.html?lejos/hardware/sensor/EV3IRSensor.html. 

J'utilise un dongle USB Wifi de TP-Link connecté à la brique EV3 pour pouvoir télécharger, exécuter, voir déboguer, les exercices directement depuis Eclipse. Mes autres articles de cette catégorie sont à consulter pour la partie installation et l’environnement Eclipse.

L'indentation de 3 définie dans l'éditeur de code Java dans Eclipse est un peu faible, mais nécessaire pour montrer correctement le code source sur un site Web comme celui-ci.

import lejos.hardware.lcd.LCD;
import lejos.hardware.port.SensorPort;
import lejos.hardware.sensor.EV3IRSensor;
import lejos.utility.Delay;

public class Ev3Exercice1a {
   public static void main(String[] args) {
      EV3IRSensor ir = new EV3IRSensor(SensorPort.S4);

      boolean continuing = true;  //Stop for particular key pressed
      int channel        = 0;     //The red switch
      int loopCount      = 0;     

      while (continuing) {
         Delay.msDelay(25);
         loopCount++;

         // Get the IR commands
         byte [] cmds = new byte[4];
         ir.getRemoteCommands(cmds, 0, cmds.length);

         // Find out the active channel and button pressed
         int theCmd = 0;
         for (int i=0; i < 4; i++) {
            if (cmds[i] > 0) {
              channel = i + 1;
               theCmd  = cmds[i];
            }
         }

         LCD.drawString("Command:" + theCmd + " ", 0, 2);
         LCD.drawString("Channel:" + channel,      0, 3);
         LCD.drawString("Counter:" + loopCount,    0, 4);

         LCD.drawString("Both red to stop",        0, 6);

         if (theCmd == 10) {
            continuing = false; 
         }
      }

      ir.close();
   }
}

 

En jouant avec ce programme, nous allons comprendre précisément comment fonctionne cette balise (assignée à l'entrée 4 de la brique) et chacun des boutons.

Nous pourrons alors nous imaginer des combinaisons de commandes pour, par exemple, actionner des moteurs ou stopper le programme. 

  • L'interrupteur rouge à quatre positions, 1 en haut et 4 en bas, (valeur marquée d'ailleurs dans le petit indicateur rouge).

    Dans la classe Exercice1a, c'est la variable channel.
    En lisant la documentation API de la classe EV3IRSensor, mon interprétation est que nous pourrions aussi "jouer" avec 4 balises.
    Ici nous allons simplement accepter les commandes venant de n'importe quelles balises, donc de n'importe quelle position du curseur rouge.    


  • Les quatre petits boutons gris nous retournent une valeur différente, mais seulement s'ils sont tenus pressés.
    Les valeurs seront de 1 (côté rouge en haut) à 4 (côté bleu en bas).

  • En pressant plusieurs de ces 4 petits boutons, nous obtiendrons une valeur composée.
    En tenant par exemple les deux à gauche en même temps (côté marqueur rouge), le getRemoteCommands() au travers de theCmd retournera la valeur de 10. Ce cas est traité ici pour stopper le programme. Dans l'exercice suivant on considérera aussi les deux boutons à droite pour la même fonction.  

  • Le gros bouton gris est différent. Il retourne la valeur de 9, mais restera actif. C'est aussi indiqué par la petite lampe verte en haut de la balise.
    Pour le désactiver, nous presserons ce bouton à nouveau, une seconde fois, ou alors un des 4 petits boutons.   

Nous comprendrons facilement que le gros bouton gris pourrait être utilisé afin d'activer différents modes de commandes.  

Il n'y a que peu de remarques pour ce premier exemple:

  • Le constructeur EV3IRSensor ir = new EV3IRSensor(SensorPort.S4); nous indique sur quel port de la brique est connecté le capteur infrarouge.

  • L'instruction ir.getRemoteCommands(cmds, 0, cmds.length); nous retourne 0 (pas de boutons pressés au moment de la demande) ou alors une des 11 valeurs comme décrit dans l'API.
    cmds a une dimension de 4 pour les 4 canaux.

  • Les valeurs 0 et 2 de LCD.drawString("Command:" + theCmd + " ", 0, 2); correspondent à la position sur le petit écran où sera affiché le texte.

Nous allons passer à la classe Exercice1b en réutilisant le code de la précédente afin d'activer les deux grands servomoteurs.

import lejos.hardware.lcd.LCD;
import lejos.hardware.motor.Motor;
import lejos.hardware.port.SensorPort;
import lejos.hardware.sensor.EV3IRSensor;
import lejos.robotics.RegulatedMotor;
import lejos.utility.Delay;

public class Ev3Exercice1b {

   static RegulatedMotor leftMotor  = Motor.B;
   static RegulatedMotor rightMotor = Motor.C;

   public static void main(String[] args) {
      int speedMotor = 400;

      EV3IRSensor ir = new EV3IRSensor(SensorPort.S4);

      leftMotor.setSpeed(speedMotor);
      rightMotor.setSpeed(speedMotor);

      LCD.drawString("EV3 Ready", 0, 2);

      boolean continuing = true; // Stop for particular key pressed
         while (continuing) {
         Delay.msDelay(25);

         int theCmd = ir.getRemoteCommand(0); // Get the command from channel 1

         if ((theCmd > 0) && (theCmd < 10)) {   
            LCD.drawString("Command:" + theCmd + " ", 0, 2);
            LCD.drawString("Both red to stop", 0, 6);
         }

         switch (theCmd) {
            case 0:
               leftMotor.stop();
               rightMotor.stop();
               break;

            case 1:
               leftMotor.forward();
               rightMotor.stop();
               break;
            case 2:
               leftMotor.backward();
               rightMotor.stop();
               break;
            case 3:
               rightMotor.forward();
               leftMotor.stop();
               break;
            case 4:
               rightMotor.backward();
               leftMotor.stop();
               break;
            case 5:
               leftMotor.forward();
               rightMotor.forward();
               break;
            case 8:
               leftMotor.backward();
               rightMotor.backward();
               break;

            default:
               break;
         }

         if ((theCmd == 10) || (theCmd == 11)) {
            continuing = false; //Stop the program
            leftMotor.stop();
            rightMotor.stop();
         }
      }
      
      ir.close(); //The IR sensor  
   }
}


Ces quelques remarques vont nous aider à comprendre cet second exercice:

  • J'ai tout de suite ajouté LCD.drawString("EV3 Ready", 0, 2); afin de savoir à quel moment le programme était prêt pour accepter les premières commandes depuis la balise IR.
    Depuis Eclipse, cela prend un peu plus de temps pour le téléchargement.

  • Le getRemoteCommand(0) permet de récupérer la commande de la balise IR qui doit avoir ici, impérativement, l'interrupteur rouge sur la position 1 (index 0).

  • Le case 0 du switch va stopper les deux moteurs même s'ils ne sont pas actifs, c'est plus facile pour le code. Nous sommes dans le cas où aucun bouton est pressé.

  • Les cases 1, 2, 3 et 4 vont activer un des deux moteurs dans une des deux directions. L'autre moteur est stoppé, même s'il n'était pas actif.
    Nous pourrons donc faire tourner le robot pour lui faire changer de direction.

  • Les case5 et 8 vont activer les deux moteurs en même temps. Le robot avancera ou reculera ... tout droit.


En jouant avec la balise IR, nous nous rendrons compte rapidement du problème. Pour les 
case5 et 8, le robot aura tendance à faire une petite rotation en fin de parcours. C'est tout à fait explicable: lorsqu'on lâche les deux boutons, il est difficile de le faire précisément, en même temps, aussi à cause du délais de 25ms (lecture de la balise 40 fois par seconde). Un des boutons restera donc pressé un court instant. Il faudrait rajouter du code pour analyser ce cas, où alors faire avancer ou reculer le robot avec un seul bouton.

Un des Exercice1a ou Exercice1b peut, à tout moment, être définis comme programme par défaut de la brique EV3. C'est bien expliqué ici

Finalement j'ai eu beaucoup de plaisir à écrire ce code, le comprendre et l'expliquer ici.

Maximum LEGO Mindstorms EV3 est un excellent livre.
Nous trouverons ici le code source des exemples décrits dans le livre.

Brian Bagnall nous parle aussi bien de types de batteries, de connexion Wifi, d'exemple de montage de différents modèles de robots (avec la description illustrées des pièces LEGO), que de classes et d'interface Java. C'est aussi un excellent livre d'apprentissage du langage Java lorsque les bases sont déjà bien assimilées.

Pour intégrer les exemples dans Eclipse, nous définirons un nouveau projet en copiant tous les fichiers sous (default package) et vérifiant que la version de Java est correcte (c'est à dire 1.7). 

Après un bel été 2016 très peu sur mon PC, je suis de retour avec ma brique EV3  et mon robot TRACK3R (image ci-dessous dont la construction a été décrite dans LEGO Mindstorms EV3: Dépaquetage du 31313) . J'ai beaucoup "joué" avec l'interface LabView pour bien comprendre la bête, mais c'est le moment de passer à quelque chose de plus sérieux au niveau programmation.

Étant un fun de systèmes embarqués comme le Raspberry Pi voir de Nodes.js sur BBB, et plus récemment de l'ESP8266,  je suis en train d'étudier des solutions comme indiquées sur  Nine alternative programming languages for LEGO MINDSTORMS et EV3 Python.

Un article général pour la programmation en langage Python est maintenant disponible: LEGO Mindstorms EV3: ev3dev et Python


Mise en route

Il est tout à fait possible de programmer la brique EV3 de Mindstorms EV3 en Java et ceci en utilisant la plateforme leJOS décrite sur http://www.lejos.org/.

Pour les impatients, ils pourront se renseigner un peu plus sur la page Wiki de leJOS (en anglais).

Il faudra tout d'abord télécharger le logiciel depuis https://sourceforge.net/projects/ev3.lejos.p/files/. Nous prendrons la dernière version ainsi que les fichiers d'exemples.

Sur mon PC Windows, j'ai choisi le sous-répertoire D:\LEGO Software\leJOS EV3 et en choisissant les options pour télécharger aussi les exemples et le code source.  
J'ai aussi créé les répertoires D:\LEGO Software\LeJOS EV3 Samples et D:\LEGO Software\LeJOS EV3 Development Kit Sources en y déposant le matériel nécessaire pour la partie liée au développement de programmes en Java.

Au démarrage, on utilisera l'utilitaire EV3SDCard à partir de ev3sdcard.bat dans le répertoire D:\LEGO Software\leJOS EV3\bin. Cela nous permettra de visualiser le déroulement de l'opération comme des problèmes éventuels de microSD card.

J'ai moi-même utilisé une carte microSD bon marché de 16 Gbytes à moins de 10 Euros.

Après avoir cliquer sur link on choisira chez Oracle la version Aejre-7u60-b19-ejre-7u60-fcs-b19-linux-arm-sflt-headless-07_may_2014.tar.gz.
Il faudra être enregistrer chez Oracle avant de pouvoir télécharger le fichier.

Ensuite on insérera la carte SD dans la brique EV3 éteinte. Au démarrage il faudra patienter plusieurs minutes (brique allumée en rouge) avant que la carte soit prête (extension, décompression) avec son Linux, le JRE et les différents menus et actions disponibles à l'écran.

Sur le site https://sourceforge.net/p/lejos/wiki/Using%20the%20Menu%20System/ on trouvera une description complète, en anglais, de ce qui est présenté sur l'écran de la brique EV3 en "mode" leJOS.
C'est assez similaire à l'EV3 standard ou la version Python.

La procédure du Shutdown est la même que pour la version EV3 standard: il s'agira de presser le bouton retour (1), de sélectionner l'action qui apparaît sur l'écran (2) et de l’exécuter (3).  

Si l'on désire revenir à la version normale de la brique EV3, sans Java, il suffira de retirer la carte SD (la brique doit absolument être éteinte préalablement et correctement).


Accès avec Bluetooth ou WiFi sur PC

Dans mon article LEGO Mindstorms EV3: ev3dev et Python j'avais utilisé le câble USB afin d'obtenir une connexion Internet. Ici je n'ai pas réussi, certainement pour des questions de drivers, mais l'installation d'une connexion Bluetooth s'est si bien bien passée que je ne la décrirai pas ici.

L'activation du pairing sous Bluetooth est expliqué ici. La plupart des PC, au contraire des Laptop, n'ont pas d'interface Bluetooth.

J'ai donc moi-même utilisé un dongle WiFi (TP-Link) qui a été automatiquement reconnu par le leJOS! Cool! La configuration est expliquée ici.

Il faudra entrer le mot de passe du routeur WiFi avant qu'il termine sa configuration et son initialisation.
Chez moi il m'a donné l'adresse IP 192.168.1.65. Cette dernière est indiquée sur le cadran de la brique EV3 après son démarrage (qui prend un certain temps).


Accès avec Putty

Pour ouvrir une console Linux sir la brique EV3 leJOS, l'émulateur de terminal Putty sur le réseau avec Wifi fera l'affaire.
Installation: Émulateur de terminal Putty et WinSCP .

Utilisateur: root  Mot de passe: (vide)

 

Nous nous déplaçons dans le répertoires des exemples installés (samples) et exécutons le programme PilotTester.


Dans l'article LEGO Mindstorms EV3: Java, leJOS et Eclipse , pour les spécialistes en Java, nous montrons comment compiler, télécharger et exécuter dans notre brique EV3 un autre exemple, et celui-ci à partir d'un fichier de code Java dans un environnement Eclipse.


Sauvegarde et récupération

Pour sauvegarder une image d'une carte SD, nous pouvons utiliser le logiciel opensource Win32DiskImager
Il faudra insérer notre micro SD carte dans un lecteur USB (voir avec un adaptateur SD).
Il est très facile à installer avant de sauvegarder son image (exemple ici) ou de réécrire une ancienne ou une version clonée:

Win32DiskImager.jpg

 

Dans cette article, j'assume que le programmeur Java possède suffisamment de connaissances avec l’environnement de développement pour le langage Java sous Eclipse.

Voir aussi: LEGO Mindstorms EV3: Exercices pratiques en Java (1)

Moi-même, je travaille en ce moment avec la version Photon d'Eclipse. Nous trouverons son installation sur le site https://eclipse.org/downloads/. D'autres versions devraient fonctionner avec le Plug-in décrit ci-dessous. Nous exécuterons le fichier eclipse-inst-win64.exe après l'avoir téléchargé. Nous installerons la version "Eclipse IDE for Java Developers". Moi-même j'ai choisi le répertoire D:\Eclipse\java-neon et nous laisserons l'option du raccourci de démarrage sur le bureau. Au lancement de l'application Eclipse on nous demandera de spécifier un répertoire pour l'espace de travail, et j'ai l'habitude d'en définir plusieurs, suivant les différentes versions ou activités. Il n'y a aucun problème pour travailler avec plusieurs versions d'Eclipse ou de Workspace. J'ai donc choisi ici pour nos travaux Lego: D:\EclipseWorkspaceEV3.   

Pour installer le Plug-in à partir d'Eclipse, nous fermerons la fenêtre Welcome pour laisser libre l'espace de travail, nous choisirons le menu Help, Install new software, en utilisant le lien https://marketplace.eclipse.org/content/lejos-ev3-plug:

 

En sélectionnant le bouton "Install", nous le glisserons dans le Workspace d'Eclipse. Ensuite nous confirmerons l'installation, l'acceptation des termes de licence, le logiciel non signé, et attendrons la fin de l'installation avant une relance d'Eclipse comme demandée.

Dans l'article LEGO Mindstorms EV3: Java avec leJOS nous avons expliqué comment installé le logiciel qui sera utilisé par Eclipse, c'est à dire les exemples et les librairies déposés dans le répertoire D:\LegoSoftware\leJOS EV3. Les exemples sont archivés dans  et nous les unziperons dans le répertoire D:\LegoSoftware\leJOS EV3

Sous Eclipse, le menu Window, et ensuite Preferences, nous devons mettre correctement les paramètres du leJOS EV3 avec toutes les options cochées comme indiquées ici.
Ci-dessous nous avons importé dans le workspace tous les exemples en utilisant le menu File et Open Projects from File System avec la source de D:\LegoSoftware\leJOS EV3 Samples.

Ici nous avons utilisé la connexion WiFi. L'adresse IP est visible sur le display de la brique EV3 après son démarrage. Elle peut très bien changer à la prochaine session, suivant l'utilisant d'objets connectés contrôler par votre routeur. Nous pouvons aussi vérifier l'adresse IP avec Putty.

L'exemple RcControlChassis fait partie des exemples à disposition.
Aucun problème pour le compiler, le télécharger et l’exécuter.
Il a juste fallu vérifier que le senseur infrarouge était bien connecté sur le port 1 de la brique EV3, les moteurs sur les connecteurs A et D, avant d'utiliser la télécommande pour faire avancer notre véhicule avec les boutons rouges et bleus.

Pour exécuter le programme RcControlChassis nous avons sélectionné le bouton Run dans Eclipse (pour cette classe) et les messages suivants sont apparus dans la console d'Eclipse:

Jar file has been created successfully
Using the EV3 menu for upload and to execute program
IP address is /192.168.1.65
Uploading to 192.168.1.65 ...
Program has been uploaded
Running program ...
leJOS EV3 plugin launch complete

L'écran de la brique EV3 nous donne des informations de position du robot. Le code source nous montre comment ces informations sont obtenues depuis l'instance de la classe Java Pose.


Pour bien démarrer, évidemment, nous irons sur http://www.lejos.org/ et pourquoi pas sur le Wiki.
Dans la partie EV3 Wiki: Sensor Framework on pourra, par exemple, trouvé des infos sur le senseur à ultrason et découvrir comme identifier des distances à des objets.

Sous Google search, un "leJOS ev3 samples" devrait aussi bien nous aider.

Le livre Maximum LEGO Mindstorms EV3 (Java) est aussi une alternative où l'on retrouvera avec plus de détails les aspects de développement de cette plateforme robot en Java. 


J'accepte volontiers toutes questions ou commentaires: Cette adresse e-mail est protégée contre les robots spammeurs. Vous devez activer le JavaScript pour la visualiser.