Interagir avec Micropython depuis CPython

Note

On utilisera ici les termes CPython et Micropython pour désigner le code Python selon qu'il est côté ordinateur (CPython) ou côté carte Micropython (Micropython donc). Dans les 2 cas, c'est du code Python, mais qui utilisent 2 "moteurs" différents : l'un sur l'ordinateur, l'autre sur la carte Micropython. Nous discutons ici la possibilité d'interaction entre les 2, base du contrôle de dispositifs.

Ce que nous allons faire ici

Nous allons explorer la possibilité d'interagir avec un code Micropython depuis un code Python sur le poste principal. L'idée ici est multiple :

  • soit de pouvoir créer des interactions depuis un interpréteur CPython, notamment Jupyter-notebook pour afficher des graphiques à partir de données obtenues depuis la carte MicroPython
  • ou bien surtout poser les bases de la création d'interfaces graphiques écrites en Python, de la création d'un IDE pour Micropython à des interfaces de contrôle
  • et on peut même imaginer "pousser le bouchon" jusqu'à créer des interfaces dans le navigateur interagissant avec Micropython via un "bridge serveur" écrit en CPython.

Pour le moment, posons les bases de l'interaction.

Discussion technique

Communication série "usuelle"

Lorsque l'on met en place une interaction Arduino / script CPython sur l'ordinateur, ou une interface quelle qu'elle soit (Terminal série Arduino, Pronterface, etc), le principe est celui d'une communication série :

  • l'interface envoi des chaînes vers Arduino et reçoit les chaînes en provenance d'Arduino
  • Arduino envoi vers l'interface et reçoit des chaînes en provenance de l'interface.

Communication asynchrone

On est finalement dans le cas d'une communication asynchrone série, d'où d'ailleurs le nom de UART pour "Universal Asynchronous Receiver Transmitter". Autrement dit que ce soit l'interface ou le script Arduino, on est dans la situation où chacun peut avoir l'initiative de l'envoi indépendemment de l'autre. C'est comme l'envoi de SMS : chacun envoie quand il veut et reçoit quand il peut, etc. C'est comme le websocket en web.

Traitement de la chaîne reçue implémenté dans le code de réception

L'autre point clé ici est que le décodage et le traitement de la chaîne est implémentée dans le code de réception, et c'est d'ailleurs l'objet de plusieurs tutos en ce qui me concerne. En clair, si on envoie LED(ON), le code de réception devra reconnaître la racine LED, le paramètre ON entre les ( ) : on est face à du traitement de chaîne texte, ce qui peut parfois être assez laborieux.

Communication série en mode "interpréteur REPL"

La nouveauté essentielle apportée ici par Micropython, et qui fait sa force, c'est la possibilité de communiquer avec Micropython en mode interpréteur REPL. La première question est de savoir si il est possible et relativement facile d'accèder à ce mode de communication à partir d'un code CPython, ce qui est finalement la "clé" ici pour envisager des interactions poussées entre du code Python et le code Micropython dans la carte. La réponse est oui : le projet Micropython fourni un script utilitaire appelé Pyboard.py, que nous avons présenté en rubrique Outils, et qui permet une telle interaction. Le module s'importe dans le script CPython comme n'importe quel module et permet ensuite d'accéder à l'interaction avec la carte depuis le code : exécuter des commandes, charger des scripts, etc.

Communication synchrone

Dans le cas de figure d'une communication "interpréteur REPL", on est dans le cas d'une communication synchrone sur le mode une instruction => une réponse. C'est comme un appel téléphonique : appel entraîne une réponse au moment de l'appel. C'est le principe d'AJAX ou même d'http : une requete entraîne une réponse.

Non plus des chaînes mais des instructions et fonctions, du code (Micro)python quoi !

La très grande force potentielle ici est le fait que toutes les fonctions préalablement implémentées dans le code chargé, modules, etc. sont appelables "as is" comme du code Micropython. En clair, si on veut implémenter le contrôle d'un moteur ou autre, il n'est plus nécessaire de gérer une communication série avec décodage de chaîne, mais de simplement créer une fonction Python qui contrôle le moteur en question, éventuellement avec paramètres, etc, et de l'appeler ensuite simplement depuis le code CPython. C'est potentiellement extrêmement souple et polyvalent !

Au final, 2 options possibles avec Micropython

Soit communication synchrone "interpréteur REPL"

Dans le cas de Micropython, le fait qu'il est possible de simplement implémenter des fonctions pour obtenir une action et qui seront automatiquement reconnue par Micropython, donne "furieusement" envie d'utiliser ce procédé ! On implémente la fonction voulue dans le code Micropython et on l'appelle par connexion type interpréteur REPL depuis le code Python côté PC.

Note

Dans cette façon de faire, on "perd" la possibilité pour la carte Micropython d'envoyer de façon "asynchrone" des messages vers l'interface. A priori, dans un grand nombre de cas, cela n'est pas forcément problématique. Mais dans certaines situations, cela peut poser problème. Une façon de contourner cela est probablement de passer par une mémorisation des évènements survenus côté Micropython, via un fichier en Flash ou en RAM, et qui sera lu sur un mode synchrone.

Soit communication asynchrone série habituelle

Selon les cartes, il est possible :

  • d'implémenter un VCP, un "Virtual Comm Port", notamment sur la Pyboard, pas sur la Pi Pico (Février 2021)
  • d'utiliser une communication UART "vraie" via les modules UART de la carte. A noter qu'on peut aussi faire passer la comm' REPL sur l'UART, mais dans le cas de la pico pi, ce n'est pas disponible par défaut, il faut recompiler le Micropython en activant cette option. (Février 2021)

Preuve de concept de la communication REPL entre un code CPython et la carte Micropython

Note

On a 2 possibilités pour charger le code Micropython actif dans la carte : soit on le fait sous forme d'un module

Reprendre ici - cf Pyboard.py...

Bon à savoir

Une autre façon également d'interagir avec la carte Micropython depuis le code CPython est d'appeler le code Pyboard.py en ligne de commande pour réaliser des opérations de type shell, etc. Il ne s'agit plus ici à proprement parler d'une communication REPL mais de la réalisation d'opération entre le système et la carte Micropython via l'appel de la ligne de commande depuis le code Python, comme on le ferait manuellement par ailleurs, le script Pyboard.py étant prévu pour çà.