Au printemps 2018, j'ai à nouveau repris le langage Python pour tester mes composants sur les breadbords de mes Raspberry Pi et autres ESP32 et ESP8266!

Depuis le printemps 2021, j'ai une autre nouvelle passion et j'y trouve beaucoup de plaisir: Imprimante 3D - Creality Ender 3 V2. C'est génial et d'un prix équivalent à un Mindstroms EV3.

Mon livre Java avec le Raspberry Pi 3B est dédié à Java, mais le langage Python y est aussi présenté et indispensable. 

En décembre 2017, j'ai eu des difficultés avec ma micro carte SD et je n'ai pas réussi à la récupérer et la réinstaller.
Typiquement j'utilise une carte SD comme la SanDisk Ultra 16gb micro SD (moins de 10 euros).
Il faudrait vraiment que je trouve le temps de déterminer si ce type de carte cause des problèmes (arrive à certains) et quel marque ou type peut faire l'affaire!
Merci au nombreux lecteurs.
L'objectif de cet article est de donner un aperçu rapide de la bête EV3 dans son environnement de développement sous Linux et avec le langage de programmation Python.
Le petit exemple de code en fin d'article, qui utilise la télécommande pour contrôler les moteurs, devrait suffire pour titiller le lecteur. Mais j'ai quand même eu beaucoup de difficultés, comme quelques-uns de mes lecteurs, à mettre en place les drivers et l'environnement (jamais pareil d'un PC à l'autre). 

Pour les personnes prêts à utiliser un langage de programmation comme Java, voir de s'y mettre, je recommanderais ce dernier (j'y ai trouvé vraiment beaucoup de plaisir: leJOS et Eclipse (Java avec le LEGO Mindstorms EV3)).    

Mise en route

La construction de ce véhicule est décrite dans l'article LEGO Mindstorms EV3: Dépaquetage du 31313.

Les point de départ sont (1)Getting Started with ev3dev et (2)EV3 Python.

Pour les débutants en programmation Python, on trouvera de nombreuses références sur le Web, comme par exemple http://python.developpez.com/cours/ (j'aime bien http://python.developpez.com/tutoriels/cours-python-uni-paris7/)

Le lien (1) nous permettra de télécharger une image du logiciel LEGO MINGSTROMS EV3 à installer ensuite sur une carte micro SD (comme ev3dev-jessie-ev3-generic-2016-10-17.zip, qu'on copiera par exemple dans D:\LEGO Software\e3vDev\) et en utilisant l'outil Etcher que nous téléchargerons et installerons sur son PC.

Comme je travaille aussi avec des systèmes embarqués ESP8266, mon Windows 10 a été mis à jour avec le driver USB CP210x. Je ne sais pas s'il y a un impact de ce logiciel ici. En cas de difficultés, je conseillerais de l'installer.

Etcher nous donnera le moyen de préparer notre micro carte SD et avant de l'insérer dans notre brique EV3 éteinte :

 

Sous (1) Step 4 on nous explique comment démarrer le système d'exploitation ev3dev sur notre brique.
Ceux qui ont des difficultés en anglais peuvent me contacter (Cette adresse e-mail est protégée contre les robots spammeurs. Vous devez activer le JavaScript pour la visualiser.) ou utiliser le traducteur du navigateur comme dans Chrome.

Pour ouvrir une console ssh sur notre brique, nous utiliserons la connexion au travers d'un câble USB et d'un Émulateur de terminal Putty. Je n'ai pas réussi sous Windows 10 à établir un même style de connexion avec Bluetooth. 

La partie configuration de l'adresse IP est la plus délicate et bien décrite dans http://www.ev3dev.org/docs/tutorials/connecting-to-the-internet-via-usb/.

>>>> Si cette partie ne fonctionne pas ou ne fonctionne plus, passer la description ci-dessous.



>> Attention de bien définir le Sharing sur la connexion Internet normale du PC (à partir du point 9 du document ci-dessus).

L'EV3 doit avoir l'autorisation d'accéder au PC.
Procédure pour Windows 10: sous Paramètres, Réseau et Internet, Ethernet, Centre Réseau et Partage, sélectionner Ethernet dans le réseau public actif du PC (pas de l'EV3) et ensuite Propriété et l'onglet Partage:  

Sans ces deux autorisations cochées, le Linux de la brique ne pourra jamais accéder le PC pour obtenir l'adresse IP.
Si par hasard la brique est déjà connecté, je conseillerais de redémarrer le PC et plus tard la brique.
La partie centrale de la propriété, avec le référence au réseau EV3, ne m'est pas apparue sur un Laptop Windows 10 où la connexion Internet classique se fait sur un réseau Wifi. Mais la brique fonctionnait (i.e. Putty et WinCPP)!

Une erreur classique est de définir le partage aussi pour le réseau EV3. Si c'est le cas, cela ne fonctionnera pas, même si l'adresse IP semble correcte.



Malheureusement ... cela ne marche pas vraiment ... toujours ... comme on veut.
En travaillant sur une seconde machine, un Laptop avec Blutooth, et en essayant en plus de faire fonctionner un dongle WiFi TP-Link, je me suis retrouvé dans une situation où il mettait impossible de me connecter en ssh (robot/maker).
Il ne voulait plus reconnaître le mot de passe et l'adresse IP était totalement farfelue!?!
Et ceci sur mon PC d'origine.

J'ai refait complètement ma micro SD carte, j'ai relancé mon PC sous Windows 10, et cette fois-ci j'ai reçu une autre adresse IP, 192.168.137.117.

Sous Paramètres, Réseau et Internet, Ethernet, Centre Réseau et Partage, en sélectionnant Ethernet dans le réseau public actif du PC (pas de l'EV3): et l'onglet Partage n'était pas présent.

J'ai tout de même pu travailler correctement et installer le dernier exemple de cet article.  



Après avoir branché le câble USB et allumé la brique EV3, l'adresse IP devrait apparaître en haut de l'écran de la brique, en principe 192.168.137.3. mais, suivant la configuration, peut-être quelque chose de différent comme 169.254.100.69.

Pour vraiment nous en assurer: faire un ping avec cette adresse dans une console CMD de Windows.

Les applications Putty et WinCPP (voir ci-dessous) devraient alors fonctionner.

 

avec le nom d'utilisateur robot et le mot de passe maker 

 

Nous avons à présent une console ssh à disposition sur notre Linux ev3dev de la brique.


Pour commencer je vais présenter un petit exemple, afin de vérifier que notre environnement de développement fonctionne bien.

J'ai préparé ce fichier Python (PlusSimpleOnMeurt.py) avec Notepad++ sur mon PC. 

#!/usr/bin/env python3
from ev3dev.ev3 import *
from time       import sleep

m1 = LargeMotor('outB')
assert m1.connected, "Connecter un large motor sur outB"
m2 = LargeMotor('outC')
assert m2.connected, "Connecter un large motor sur outC"

m1.run_forever(speed_sp = 200)
m2.run_forever(speed_sp = 200)
sleep(2)

m1.run_forever(speed_sp = 0)
m2.run_forever(speed_sp = 0)
sleep(1)

Le deux moteurs vont tourner à la même vitesse et le véhicule stoppera après 2 secondes.

Pour télécharger cet exemple, on se référera à la description en fin d'article, après la présentation d'un exemple un peu plus évolué.


A présent un de mes exemples qui fonctionne assez bien, mais pourrait encore être amélioré (le code et mais aussi la description des détails et des problèmes potentiels).

Les senseurs infrarouge et de couleur doivent être posés à l'avant du véhicule (voir l'image ci-dessous en fin d'article).
Code source: Distance2.py.

Pour faire simple: le robot avance avec ces deux moteurs, et, dès qu'il détecte un objet, recule, tourne un peu avec un moteur seulement et repart!?!
La procédure exitrouge() va identifier si quelques choses de suffisamment rouge et de suffisamment proche se trouve devant le senseur de couleur ... pour stopper la bête.

#!/usr/bin/env python3
from ev3dev.ev3 import *
from time       import sleep
import sys

def beeps( nb ):  #plusieurs bips
   for i in range (0,nb):
      Sound.beep()
      sleep(.2)

def exitrouge():
   if cl.value(0) > 100:  # panneau rouge 
      if cl.value(1) + cl.value(2) < 50:
         m1.run_forever(speed_sp = 0)
         m2.run_forever(speed_sp = 0)
         beeps(3)
         sleep(1)
         sys.exit(0)

m1 = LargeMotor('outB')
assert m1.connected, "Connecter un large motor sur outB"
m2 = LargeMotor('outC')
assert m2.connected, "Connecter un large motor sur outC"

beeps(1)

ir = InfraredSensor()
assert ir.connected, "Connecter svp le senseur infrarouge a un des ports"

#Mettre le senseur infrarouge en mode de proximite
ir.mode = 'IR-PROX'

cl = ColorSensor() 
assert cl.connected, "Connecter svp le senseur de couleur a un des ports"

# Mettre le senseur en mode RGB
cl.mode='RGB-RAW'

cur_distance = ir.value()
# print "Distance %d cur_distance de depart" % cur_distance

m1.run_forever(speed_sp = 0)
m2.run_forever(speed_sp = 0)

while ir.value() > 2:
    exitrouge()  #stoppe avec panneau rouge

    cur_distance = ir.value()
    # print "Distance1 %d cur_distance" % cur_distance

    while ir.value() > 7:
       exitrouge()

       cur_distance = ir.value()
       # print "Distance2 %d cur_distance" % cur_distance
       m1.run_forever(speed_sp = 300 - 2000/(cur_distance + 3))
       m2.run_forever(speed_sp = 300 - 2000/(cur_distance + 3))

    m1.run_forever(speed_sp = 0)
    m2.run_forever(speed_sp = 0)
    m1.run_forever(speed_sp = -400)
    m2.run_forever(speed_sp = -400)
    sleep(1.5)

    exitrouge()  #stoppe avec panneau rouge

    for num in range(1,5):
        m2.run_timed(speed_sp=400)
        sleep(0.6)
        exitrouge()  #stoppe avec panneau rouge

        if ir.value() < 7:
            break

m1.run_forever(speed_sp = 0)
m2.run_forever(speed_sp = 0)

beeps(2)
sleep(1)

En analysant le code, on remarquera que la vitesse du véhicule dépendra de la distance. Plus on s'approchera, plus la bête ralentira.


Téléchargement et exécution

Pour télécharger cet exemple dans la brique EV3 connectée avec un câble USB et le PC sous Windows 10, nous pouvons utiliser WinScp, décrite dans la catégorie Raspberry Pi de ce site Joomla (sous Émulateur de terminal Putty et WinSCP).

Dans le gestionnaire, j'ai défini notre EV3 afin de pouvoir le réutilisé (mot de passe maker):  

 

En se connectant nous aurons alors un accès avec nos fichiers locaux sur le PC à gauche, et ceux de l'EV3 à droite:  

Moi-même j'ai édité les fichiers sur le PC avec Notepad++.
Il faut choisir un éditeur qui prend en charge correctement le retour de ligne et les tabulateurs.
Sous Notepad++ il y a quelques outils comme l'affichage des blancs et des tabulateurs. Ces derniers donnent souvent des erreurs d’exécution sous Python.

Le sous-répertoire PythonBin est pratique: j'y ai déposé mes scripts Python dans des fichiers .sh que j'exécuterai, depuis le menu de la brique, lorsque je déposerai le robot sur le sol, sans câble connecté au PC.

Ici depuis la console Putty:

robot@ev3dev:~$ cd Python
robot@ev3dev:~/Python$ ls -lt
total 40
-rw-r--r-- 1 robot robot 1169 Dec  3  2016 Distance2.py
-rw-r--r-- 1 robot robot 1628 Dec  2  2016 Dancing1.py
-rwxr-xr-x 1 robot robot 4258 Dec  1  2016 DemoNavigation3.py
-rw-r--r-- 1 robot robot  559 Dec  1  2016 ColorRgbRaw.py
-rwxr-xr-x 1 robot robot  564 Nov 28  2016 Distance1.py
-rwxr-xr-x 1 robot robot 3565 Nov 27  2016 DemoNavigation2.py
-rwxr-xr-x 1 robot robot 1638 Nov 27  2016 DemoNavigation1.py
drwxr-xr-x 2 robot robot 4096 Nov 26 00:16 PythonBin
-rwxr-xr-x 1 robot robot  304 Nov 24 16:41 LargeMotor1.py
robot@ev3dev:~/Python$ cd PythonBin
robot@ev3dev:~/Python/PythonBin$ ls -lrt
total 12
-rwxr-xr-x 1 robot robot 35 Nov 25 23:16 Dancing1.sh
-rwxr-xr-x 1 robot robot 36 Nov 26 00:16 Distance2.sh
-rwxr-xr-x 1 robot robot 42 Dec  1  2016 DemoNavigation3.sh

robot@ev3dev:~/Python/PythonBin$ cat Distance2.sh cd ../ /usr/bin/python Distance2.py

Et c'est parti en déconnectant le câble sur outB (un des deux gros moteurs): 

robot@ev3dev:~/Python/PythonBin$ ./Distance2.sh
Traceback (most recent call last):
  File "Distance2.py", line 9, in <module>
    assert m2.connected, "Connect a large motor to outB"
AssertionError: Connect a large motor to outB
Exception AttributeError: "'LargeMotor' object has no attribute '_path'" in <bound method LargeMotor.__del__ of <ev3dev.core.LargeMotor object at 0xb693cd50>> ignored

Le problème est bien visible. 
Si on a fait une erreur en programmation Python, on a le choix entre l'éditer avec Textpad++ et refaire le transfert avec WinScp, ou utiliser un éditeur Linux dans Putty avant de réessayer.

Un bon moyen pour tester la bête reliée au PC:

Notre véhicule est hors sol, sur une petite boîte, ici mon chargeur de batterie!?!
Trop facile pour tester: il roule dans le vide et juste mettre la main devant pour simuler un objet et tester la bête.
Pour notre exemple, le capteur de couleur est utilisé pour stopper le robot immédiatement. 

Et c'est reparti:

robot@ev3dev:~/Python/PythonBin$ ./Distance2.sh 
Distance 100 cur_distance de depart

A une certaine distance d'un objet, le message distance vient sur la console (si le print actif) et le robot fait une "pirouette". 
En mode connexion avec le câble USB, on laissera un ou plusieurs "print Distance" pour comprendre la logique. 

Un Ctrl-C dans la console Putty nous permettra d'interrompre le programme.
Ce sera un peu plus difficile lorsqu'il "roulera" en mode autonome: le code et la logique peuvent encore être améliorés, c'est certain.

En mode autonome, on utilisera le menu "File Browser" sur la brique (sélection avec le bouton principal), ensuite "Python" (si un tel répertoire a été créé par vos soins), PythonBin (le répertoire de mes scripts shell avec l’exécution du programme sous Python), et finalement le choix Distance2.sh. En cas de difficultés, on pourrait être obligé de stopper la brique d'une manière abrupte, comme décrite en fin d'articleLEGO Mindstorms EV3: Dépaquetage du 31313. 


Suggestions d'exercices:

- Stopper le véhicule avec un objet bleu
- Pivoter en utilisant les deux moteurs 


Trouvant que mon article était un peu minimaliste, j'ai rajouté cet exemple qui utilise la télécommande qui vient avec le kit de l'EV3 :

#!/usr/bin/env python3

# Nous utilisons la telecommande pour controler les 2 moteurs 
# Boutons rouge: moteur de gauche
# Boutons bleu:  moteur de droite
# Les leds montrent la direction du mouvement

from time import sleep
import ev3dev.ev3 as ev3
from ev3dev.ev3 import *
import sys

# lmotor: moteur de gauche  rmotor: moteur de droite
lmotor = LargeMotor('outB')
rmotor = LargeMotor('outC')
assert lmotor.connected, "Connecter le moteur gauche sur outB"
assert rmotor.connected, "Connecter le moteur droite sur outC"

Sound.speak('Hello guys').wait()

ir = InfraredSensor()  #distance et telecommande
assert ir.connected, "Connecter svp le senseur infrarouge a un des ports"

# Connect remote control
rc = RemoteControl(); 
assert rc.connected, "Remote control does not work"

# Initialize button handler
#button = Button()   # not working so disabled 

# Turn leds off
Leds.all_off()

def tourne(moteur, led_group, direction):
    def on_press(state):
        if state:
            # tourne quand le bouton est presse
            moteur.run_forever(speed_sp=600*direction, speed_regulation="on") 
            Leds.set_color(led_group, direction > 0 and Leds.GREEN or Leds.RED)
        else:
            # sinon stop
            moteur.stop(stop_action='brake')
            Leds.set(led_group, brightness_pct=0)

    return on_press

# Assigne un event handler a chaque bouton
rc.on_red_up    = tourne(lmotor, Leds.LEFT,   1)
rc.on_red_down  = tourne(lmotor, Leds.LEFT,  -1)
rc.on_blue_up   = tourne(rmotor, Leds.RIGHT,  1)
rc.on_blue_down = tourne(rmotor, Leds.RIGHT, -1)


# Boucle de travail
while True:
    ir.mode = 'IR-REMOTE'  # mode telecommande
    rc.process()
    sleep(0.01)
    
    ir.mode = 'IR-PROX'	   # mode distance
    cur_distance = ir.value()
    #print "Distance %d cur_distance" % cur_distance
    #sleep(.5)

    if cur_distance >= 0 and cur_distance <= 8:
      lmotor.stop(stop_action='brake')
      rmotor.stop(stop_action='brake')
	  
      Sound.beep()
      sleep(1.0)
      
      sys.exit(0)
    

Il suffit de mettre un objet devant le senseur de proximité pour que le programme s'arrête.

Nous pourrons à nouveau définir un script shell exécutable (chmod +x) dans le répertoire PythonBin. Il sera aussi accessible à partir du menu de la brique, comme expliqué plus haut, lorsque le robot EV3 ne sera pas connecté via le câble USB.

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