Pyboard.py
Note
Ce module est le même que celui que l'on installe lors de la configuration de Geany par exemple, mais son usage est beaucoup plus polyvalent que simplement l'utilisation avec Geany.
Pour comprendre
Pyboard.py est un utilitaire qui permet d'interagir avec micropython à partir d'un interpréteur ou d'un code Python tournant sur le poste principal. Il s'agit donc d'un outil particulièrement intéressant, notamment dès lors que l'on envisage de réaliser des interfaces, etc.
Avec Pyboard, on va ainsi pouvoir, à partir d'un code Python envoyer vers la carte micropython :
- une simple instruction
- un code complet
- accèder au système de fichier de la carte micropython
Noter que l'on peut aussi utiliser pyboard.py de 2 façons :
- soit en mode interpréteur, ce qui revient à un mode "ligne de commande"
- soit au sein d'un code python, comme un module
Un outil polyvalent !
Au contraire de ce que son nom laisse à penser, Pyboard.py, est un utilitaire qui fonctionne avec n'importe quelle carte Micropython et çà c'est une bonne nouvelle ! Yes !
Télécharger pyboard.py
Pyboard.py est un simple script Python 3 qui se télécharge et se placera dans le répertoire à partir duquel on veut communiquer avec la carte micropython, typiquement le répertoire où se trouvent les codes que l'on veut envoyer.
La dernière version est ici sur Github ou là
Dépendances
La seule dépendance de pyboard.py est le module serial :
sudo apt-get install python3-serial
Dans le terminal sur ordinateur
Ne vous trompez pas et comprenez bien !
On exécute ce qui suit SUR LE POSTE QUI COMMUNIQUE AVEC LA CARTE MICROPYTHON ! (et pas dans l'interpréteur REPL de micropython)
En clair, les commandes sont à saisir dans un terminal système sans lancer l'outil de communication série habituel tel que screen
au préalable.
Commencer par se placer dans le répertoire où on a placé le fichier pyboard.py et ouvrir un terminal à cet emplacement (clic droit > "ouvrir un terminal ici" sous XFCE)
Afficher l'aide
Ensuite saisir la commande :
python3 pyboard.py --help
Ce qui affiche l'aide :
usage: pyboard.py [-h] [-d DEVICE] [-b BAUDRATE] [-u USER] [-p PASSWORD]
[-c COMMAND] [-w WAIT] [--follow | --no-follow] [-f]
[files [files ...]]
Run scripts on the pyboard.
positional arguments:
files input files
optional arguments:
-h, --help show this help message and exit
-d DEVICE, --device DEVICE
the serial device or the IP address of the pyboard
-b BAUDRATE, --baudrate BAUDRATE
the baud rate of the serial device
-u USER, --user USER the telnet login username
-p PASSWORD, --password PASSWORD
the telnet login password
-c COMMAND, --command COMMAND
program passed in as string
-w WAIT, --wait WAIT seconds to wait for USB connected board to become
available
--follow follow the output after running the scripts [default
if no scripts given]
--no-follow Do not follow the output after running the scripts.
-f, --filesystem perform a filesystem action: cp local :device | cp
:device local | cat path | ls [path] | rm path | mkdir
path | rmdir path
On constate d'entrée de jeu que l'on dispose de pas mal de possibilités et c'est donc un outil "couteau suisse" pour la communication entre le Python du poste principal et micropython de la carte. Noter notamment les commandes permettant d'accéder au système de fichier de la carte micropython.
Forme alternative de la commande
On peut également utiliser une commande de la forme :
pyboard.py --help
ou encore :
./pyboard.py --help
Il faut par contre rendre au préalable le script exécutable ce qui se fait soit graphiquement ( clic droit sur le fichier > propriétés > onglet permissions > cocher "Autoriser exécution" ) ou bien avec la ligne de commande suivante :
chmod +x pyboard.py
Voyons à présent quelques exemples concrets :
Envoyer une commande à micropython
Pour envoyer une commande à micropython et recevoir la réponse, on fera :
python3 pyboard.py --device /dev/ttyACM0 -c 'print(1+1)'
où :
- --device /port/serie : indique le port série à utiliser. Adapter le chemin à celui utilisé par la carte. Si on a un doute, vérifier avec
ls /dev/ttyACM*
par exemple. - -c 'instruction' : entre guillemets, la commande Python à passer à micropython
Ce qui donne ici :
2
Remarquer donc que pyboard.py intercepte par défaut la réponse de la carte. Ceci peut être désactivé avec le paramètre --no-follow
(voir la sortie de --help
)
Réaliser des opérations sur le système de fichiers de la carte avec Pyboard.py
On peut réaliser des opérations sur le système de fichier de la carte avec Pyboard.
Pour charger en RAM un fichier local :
python3 pyboard.py --device '/dev/ttyACM0' "fichier.py"
Note
La commande de configuration de Geany est celle-ci légèrement adaptée :
python3 pyboard.py --device '/dev/ttyACM0' "%f"
Note
On peut ajouter --no-follow
à la commande pour éviter les blocages
Pour copier un fichier local vers le fichier main.py de la carte :
python3 pyboard.py --device /dev/ttyACM0 -f cp gpio_out_led_timer.py :main.py
Noter qu'ici, on fait "d'une pierre 2 coups" en copiant sur la carte et en renommant simultanément le fichier
Note
Les chemins correspondant à la carte microPython lorsqu'ils sont appelés depuis Pyboard.py sont précédés d'un :
Le :
représente la racine de la Flash de la carte.
A noter que l'on peut facilement réaliser de la sorte quelques opérations simples :
Afficher le contenu du fichier boot.py
python3 pyboard.py --device /dev/ttyACM0 -f cat :boot.py
Lister le contenu de la Flash :
python3 pyboard.py --device /dev/ttyACM0 -f ls :
Ce qui donne par exemple :
304 main.py
2721 pybcdc.inf
528 README.txt
302 boot.py
13474 upyduino.py
7 test.txt
0 test/
7255 lcd_api.py
3091 pyb_i2c_lcd.py
Si on souhaite copier localement un fichier de la carte, on fera :
python3 pyboard.py --device /dev/ttyUSB0 -f cp :boot.py boot.py
Pour copier le contenu d'un répertoire, on fera :
python3 pyboard.py --device /dev/ttyUSB0 -f cp picoweb/* :/lib/picoweb/
Effacer un fichier sur la carte :
python3 pyboard.py --device /dev/ttyACM0 -f rm :trans.py
Utiliser micropython depuis un interpréteur Python
Ne vous trompez pas et comprenez bien !
Ici on va communiquer avec micropython depuis un interpréteur Python sur le "poste fixe" auquel la carte micropython est connectée. Soyez bien conscient que l'interpréteur ici n'est pas l'interpréteur REPL de micropython mais l'interpréteur Python du système.
A présent, nous allons voir comment interagir avec micropython depuis un interpréteur Python sur le poste fixe. Pour éviter la confusion, je vous conseille de lancer Ipython par exemple, ce qui vous montrera clairement la différence d'avec screen
utilisé dans le terminal.
Placez-vous dans le répertoire où se trouve pyboard.py, ouvrez un terminal dans ce répertoire (clic droit > ouvrir un terminal ici sous XFCE) et lancer la console Jupyter, ce qui se fait avec :
jupyter-qtconsole
ce qui donne :
Une fois fait, on va saisir successivement :
import pyboard # importe le script pyboard.py
pyb=pyboard.Pyboard('/dev/ttyACM0', 115200) # definit un objet Pyboard correspondant à la carte
pyb.enter_raw_repl() # bascule en mode repl_raw permettant l'envoi / réception de bytes depuis micropython
#------- a partir de ce moment on peut envoyer des commandes et interagir avec micropython - tout est placé en RAM --------
pyb.exec('print(1+1)')
# b'2\r\n'
ret=pyb.exec('print(1+1)')
# aucun affichage
print(ret)
# b'2\r\n'
print(ret.decode()) # pour afficher en str
# 2
# chargement d'un code depuis poste fixe
file=open("test.py",'r') # ouverture fichier
code=file.read() # lecture fichier
file.close() # fermeture fichier
ret=pyb.exec(code) # exécution du fichier
pyb.exec('hello()') # appel d'une fonction présente dans le code précédent
#b'Micropython OK !\r\n' # on récupère sa sortie !
# chargement d'un code présent sur la carte micropython
ret=pyb.exec("""from upyduino import *
millis()
digitalWrite(1,0)
""")
# saisie d'un code en multilignes
ret=pyb.exec("""import pyb
pyb.LED(4).on()
""")
#--- sortie du mode d'interaction directe - conseillé / obligatoire ?
pyb.exit_raw_repl() # sortie du mode repl_raw
On peut pousser le bouchon un peu plus loin même avec Jupyter qui permet les affichages graphiques. Soit un petit code micropython intégrant une fonction de mesure analogique :
import pyb
rvar=pyb.ADC(pyb.Pin('X1'))
def getData(nb=1): # fonction d'acquisition des données
for i in range(nb):
mesure=rvar.read()
print(mesure)
Ensuite, on fait une acquisistion de 1000 mesures que l'on affiche sous forme graphique :
pyb.enter_raw_repl()
file=open("test_adc_2.py", 'r')
code=file.read()
file.close()
ret=pyb.exec(code)
ret=pyb.exec("getData(1000)")
data=ret.decode()
import io
buf=io.StringIO(data)
lines=buf.readlines()
%pylab inline
x=arange(len(lines))
y=[ int(value) for value in lines ]
plot(x,y)
# pyb.exit_raw_repl()
Ce qui donne :
Trucs et astuces
Si on souhaite transférer un code dans la RAM de la Pyboard, on utilisera la commande :
python3 pyboard.py --device '/dev/ttyACM0' "file.py"
A noter que si on utilise cette commande dans Geany, on remplaçant file.py par "%f", on obtient l'équivalent du "téléverser" de Arduino :
python3 pyboard.py --device '/dev/ttyACM3' "%f"
Si on souhaite transférer un code sur la carte Micropython (dans la mémoire Flash) et que l'on veut de plus faire un Reset dans la foulée, on fera :
python3 pyboard.py --device /dev/ttyACM3 -f cp file.py :main.py && python3 pyboard.py --device /dev/ttyACM3 -c 'machine.reset()' --no-follow
Ne fonctionne pas avec machine.soft_reset() mais Ok avec machine.reset()
A noter que si on utilise cette commande dans Geany, on remplaçant file.py par "%f", on obtient l'équivalent du "téléverser" de Arduino :
python3 pyboard.py --device /dev/ttyACM3 -f cp "%f" :main.py && python3 pyboard.py --device /dev/ttyACM3 -c 'machine.reset()' --no-follow
C'est cadeau !
Cette dernière commande m'a demandé un peu de recherche, quelques essais et de "jugeote" pour l'obtenir, mais elle fonctionne à merveille et est une excellente façon de simplfier l'utilisation d'une carte Micropython, "façon Arduino".
Alternative pour utilisation de Pyboard depuis un script Python
Dans la mesure où il est facile de réaliser toute une série d'opération facilement avec Pyboard en ligne de commande, on peut vouloir simplement garder le bénéfice çà et appeler Pyboard en ligne de commande depuis le code Python lui-même.
Ce qui donne par exemple :
Copie d'un fichier
import subprocess
pathThisApp=os.getcwd()+"/"
# python3 pyboard.py --device $1 -f cp $2 :main.py # commande pour copier dans main.py
cmd=['python3', pathThisApp+'pyboard.py', '--device', '/dev/ttyUSB0' , '-f', 'cp', 'test.py', ':test.py', '--no-follow']
# cmd=['python3', 'pyboard.py', '--device', '/dev/ttyUSB0' , '-f', 'cp', 'test.py', ':test.py', '--no-follow']
p=subprocess.run(cmd)
Ensuite, on peut vérifier, toujours depuis le même terminal que la copie s'est bien déroulée :
import pyboard
pyb=pyboard.Pyboard('/dev/ttyUSB0', 115200)
pyb.enter_raw_repl()
ret=pyb.exec("""import os
print(os.listdir())
""")
print(ret)
pyb.exit_raw_repl()
Lister les fichiers de la carte :
import subprocess
cmd=['python3', 'pyboard.py', '--device', '/dev/ttyACM0' , '-f', 'ls', ':']
p=subprocess.run(cmd)
out=subprocess.check_output(cmd)
out
Out[8]: b' 195 gpio_blink_onboard_timer.py\r\n 195 main.py\r\n 7097 neoSPI.py\r\nls :\n'
out.decode()
Out[10]: ' 195 gpio_blink_onboard_timer.py\r\n 195 main.py\r\n 7097 neoSPI.py\r\nls :\n'
lines=out.decode().split('\n')
lines
Out[12]:
[' 195 gpio_blink_onboard_timer.py\r',
' 195 main.py\r',
' 7097 neoSPI.py\r',
'ls :',
'']
```
## Un script bash pour automatiser la copie d'un code Micropython sur la carte
Cerise sur le gâteau, voici un petit script d'automatisation du upload d'un fichier *.py vers main.py en passant en paramètre au script la cible au format `/dev/ttyACM0` et le nom du fichier.
```bash
#!/bin/bash
# Transfert d'un fichier *.py vers main.py sur la carte Micropython
#le fichier pyboard.py doit se trouver dans le répertoire du script
echo "Le fichier à uploader vers la carte $1"
echo "est $2"
echo "Copie du fichier vers main.py :"
python3 pyboard.py --device $1 -f cp $2 :main.py
echo "Reboot de la carte."
python3 pyboard.py --device $1 -c 'machine.reset()' --no-follow
echo "Upload OK !"
exit 0;
# commande type : ./upload.sh /dev/ttyACM3 gpio_blink_onboard_timer.py
A enregistrer dans le répertoire de vos fichiers Micropython sous le nom upload.sh par exemple et à rendre exécutable avec :
chmod +x upload.sh
Ensuite, on appelle la commande avec :
./upload.sh /dev/ttyACM3 programme.py
Et aussi
A noter que si on veut extraire l'exception renvoyée par Pyboard, on fera :
try :
ret=self.pyb.exec(code)
ret=ret.decode() # bytes en str
except Exception as e:
#print(dir(e))
ret=e.args[2].decode() # extraction de la réponse
print(ret)
# forme ('exception', b'', b'Traceback (most recent call last):\r\n File "<stdin>", line 1, in <module>\r\nNameError: name \'a\' isn\'t defined\r\n')
ret=str(e)
L'exception renvoie 3 args et le dernier est le message, d'où index 2
Gui pour Pyboard ?
Une petite GUI PyQt5 serait intéressante avec éditeur syntaxique Python et des boutons différents pour charger en RAM ou charger sur la carte.