Programmer un microcontrôleur avec le langage Python :

Les projets de programme pour la réforme 2019 du lycée font apparaître  clairement et à plusieurs reprises la nécessité d'introduire des éléments de programmation avec le langage Python ainsi que l'utilisation d'un microcontrôleur

Cette nouveauté dans les programmes de seconde et de première se retrouvera très certainement aussi dans le programme de Terminale.

Nous vous proposons dans les onglets ci-dessous de découvrir ce qu'est un microcontrôleur, une carte microcontrôlée et comment l'utiliser avec le langage Python pour réaliser de petites applications accessibles au lycée, tant du point de vue matériel que logiciel :

Le microcontrôleur :

Le microcontrôleur

Si le terme de microcontrôleur est bien moins connu que celui de microprocesseur, ce composant est pourtant omniprésent dans notre environnement. Ci-dessous un lien vers le diaporama réalisé pour faire découvrir ce composant.

diapo_micro.png

A retenir : dans un seul et même circuit intégré, appelé "microcontrôleur" sont embarqués :

  • un microprocesseur (initialement sur 8 bits ... bien souvent sur 32 bits maintenant)
  • de la mémoire de type RAM
  • de la mémoire non volatile pour stocker le programme (c'est l'équivalent du disque dur pour un ordinateur). Cette mémoire est maintenant reprogrammable ce qui permet de mettre à jour le programme ("firmware")
  • des ports de communication de type parallèle ou série : UART (pour la communicationRS232), USB, I2C, CAN (controller area network), Ethernet...voire même un module radio (bluetooth, wifi, zigbee...)
  • des convertisseurs analogique-numériques (CAN) ...

Le même composant peut ainsi être affecté à des tâches très différentes, et selon la complexité de l'application à réaliser, on peut choisir dans une même famille de microcontrôleurs le plus adapté.

Initialement programmés en assembleur (langage spécifique à la famille à laquelle appartient le microcontrôleur), ces composants sont le plus souvent maintenant programmés dans un langage universel de plus haut niveau tel que le C.

Rappelons qu'un programme rédigé en C sera compilé avant d'être implanté dans la cible (le microcontrôleur):

- le programme, rédigé avec un éditeur de texte est ensuite compilé avec un "cross-compilateur" pour être transformé en langage machine adapté au microcontrôleur choisi. La taille du programme obtenu à l'issue de la compilation est souvent supérieure à celle obtenue à ce que l'on aurait obtenu avec une programmation en langage d'assemblage, mais le gain en temps de développement (et en portabilité / réutilisation du code ) est tel que le C s'est imposé depuis une vingtaine d'années comme le langage de programmation de prédilection sur microcontrôleur. La fin de diaporama montre l'intérêt de la programmation en C.

L'augmentation importante de la taille mémoire disponible sur les microcontrôleurs récents permet même aujourd'hui de programmer ces composants en Python. Rappelons que Python est un langage interprété qui nécessite donc un "interpréteur" qui doit être implanté dans le système (ici le microcontrôleur) qui exécutera le code Python. La mémoire "ROM" du microcontrôleur doit donc être suffisante pour contenir :

  • l'interpréteur Python
  • le programme Python que l'on créee pour réaliser une applicattion donnée

C'est une telle solution que l'on vous propose dans les onglets suivants : utiliser une carte microcontrôlée, programmable en Python, ce qui permettra de répondre à la demande des nouveaux programmes de cette réforme 2019 :

  • utiliser un microcontrôleur
  • programmer en Python

 

 

 

Choix d'une carte microcontrôlée :

 

Pour expérimenter avec un microcontrôleur, on utilise bien souvent maintenant des cartes de développement prête à l'emploi qui permettent la (re)programmation du microcontrôleur.

On peut citer le très connu système Arduino dont la carte de développement peut accueillir une multitude de cartes additionnelles différentes (écrans tactiles ou non, modules radio etc...) :

 

arduino.png   shield_bt.png

Platine Arduino .... et ici équipée d'une carte additionnelle (un "shield") Bluetooth

On trouvera sur le net et en librairie une documentation très large de ce système Arduino, mais nous n'en dirons pas plus car :

 ... ARDUINO SE PROGRAMME EN LANGAGE C :

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
 
  This example code is in the public domain.
 */
 
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Une alternative intéressante, et utilisée depuis plusieurs années Outre-Manche, est fournie par la BBC sous la forme d'une carte embarquant un microcontrôleur bien plus puissant que celui présent sur la carte Arduino, ce qui lui donne la possibilité d'être programmé en Python. Il s'agit de la carte BBC Micro:Bit

 

microbit_ar.png  microbit_av.png

Face Arrière Face avant
avec "toute" l'électronique 

avec deux boutons poussoirs et

un panneau de 5x5 Leds rouges

 

Comparaison de ces deux cartes de développement :

  ARDUINO UNO BBC:MICROBIT
Microcontrôleur ATmega328P ARM Cortex M0
Architecture 8 bits 32 bits
Fréquence 16 MHz 16 MHz
Mémoire Flash 32 KB 256 KB
RAM 2 KB 16 KB
EEPROM 1 KB  
Alimentation 5 V 3,3 V
Entrées/Sorties 14 19
CAN 10 bits 10 bits
Bus série I2C, SPI,UART,USB I2C, SPI,UART,USB
Capteurs/Actuateurs    
Boutons poussoirs - 2
LEDs 1 25 (matrice 5x5)
Accéléromètre - 1
Boussole - 1
Capteur de lumière - (avec les Leds)
Capteur de T° - T° du chip
Antenne radio - 1
Programmation C Python
Documentation

Très importante

Réduite
Cartes additionnelles Très variées Beaucoup moins
Prix ~ 20 € ~ 20 €

Dans ce tableau, on a surligné en vert les avantages qu'a une carte par rapport à l'autre.

On voit au premier coup d'oeil que la carte Micro:Bit est, de base, et pour un prix équivalent, plus puissante et bien mieux équipée que la carte Arduino Uno. C'est sur ces caractéristiques et sur la possibilité de la programmer en Python que nous avons décidé de nous y intéresser.

Remarque concernant la tension d'alimentation : la diminution de la tension d'alimentation nécessaire au fonctionnement de l'électronique numérique a été un souci constant chez les fabricants de puces.  Une tension d'alimentation de 3,3 V présente l'intérêt de pouvoir alimenter le montage avec deux piles de type AA ou AAA ce qui est un gros avantage par rapport à une alimentation sous 5 V. Cela diminue effectivement le coût énergétique à l'utilisation, ainsi que l'encombrement et le poids des appareils. Il faut cependant que toute la chaîne électronique soit capable de fonctionner avec cette tension d'alimentation. Dans la liste des cartes ou composants additionnels connectables sur ces cartes de développement, il faudra veiller à la compatibilité au niveau tension. Or actuellement, du fait du fort développement du système Arduino, on trouve, dans le domaine amateur, beaucoup de composants additionnels en 5 volts.

Développer avec la carte Micro:Bit :

 

Les schémas ci-dessous résument de façon visuelle l'ensemble des ressources matérielles disponibles sur la carte BBC Micro:Bit :

MB_avantt.png.jpg

MB_Arriere.png.jpg

Le microcontrôleur, c'est la puce carrée référencée Nordic nRF51822

Plan d'étude proposé pour apprendre à maîtriser cet outil (attention ce n'est pas un cours clé en main à distribuer aux élèves, mais plutôt des éléments d'information pour découvrir BBC Micro:Bit et gagner en confiance pour se sentir à l'aise et créer ensuite ses propres activités) :

  • Démarrer : rassembler le matériel et installer le logiciel nécessaire
  • Découvrir : commencer à programmer en MicroPython quelques unes des ressources matérielles de la carte BBC Micro:Bit (afficheur, boutons poussoirs...)
  • Etendre : utiliser le connecteur d'extension pour augmenter les possibilités de la carte
  • Programmation avancée

 

Démarrer :

Côté Matériel :

Du matériel Micro:Bit est en vente notamment chez les distributeurs suivants (cités par ordre alphabétique) :

Pour démarrer, il faut au minimum : une carte Micro:Bit et un câble USB type B (qui permet d'alimenter la carte et de communiquer avec elle)

Si l'on souhaite pouvoir utiliser la carte de façon autonome (lorsqu'elle a été programmée) alors il y a nécessité de l'alimenter avec deux piles de 1,5V via le connecteur d'alimentation : il faut alors se procurer le coupleur de piles dédié :

coupleur-de-pile-pour-carte-microbit.jpg

Il pourrait être judicieux de protéger la carte Micro:Bit. Pour cela il existe des dispositifs en dur (acrylique) ou souples (caoutchouc).

Nous avons choisi de prendre un kit de démarrage contenant ces différents éléments (Référence VMM001). Voici le contenu de la boite :

r_P1060870.JPG

On y trouve :

  • une carte BBC Micro:Bit
  • un câble USB de type B de bonne facture (contacts dorés) et de longueur 70 cm environ
  • un coupleur de piles et 4 piles AAA (ce qui donne deux piles d'avance)
  • un boitier de protection en polycarbonate à monter (plaques protégées par un papier à retirer
  • une "notice" (qui en gros renvoie sur le site Micro:Bit !)

Rque : il existe plusieurs "Starter kits" différemment fournis. Attention à la longueur du cordon USB fourni. Selon que le PC sera sur la paillasse ou en dessous la longueur utile ne sera pas la même et pourrait nécessiter l'achat de rallonges USB

La carte Micro:Bit avec sa protection :

r_P1060874.JPG     r_P1060875.JPG

La carte Micro:Bit est livrée avec un programme de démonstration qui met en évidence les possibilités de l'afficheur de 25 Leds embarqué. Ce programme ne demande qu'à démarrer !

Il suffit pour cela d'alimenter la carte :

  • soit à l'aide du coupleur de piles
  • soit en connectant la carte sur un port USB à l'aide du câble micro USB fourni.

Ci-dessous une partie de cette démo :

(le câble USB n'était pas branché, la carte est alimentée par piles)

Côté logiciel

Le site MicroBit propose deux logiciels en ligne pour programmer le microcontrôleur :

 

javascript-editor.png   python-editor.png

A gauche : l'éditeur "MakeCode" pour programmer de façon graphique (à la manière de Scratch pour ceux qui connaissent). Cet éditeur est plutôt destiné à de jeunes programmeurs.

A droite : un éditeur Python. (Inconvénient : il faut être sûr de disposer d'une connexion internet pour le faire fonctionner

Pour cette raison, on préferera travailler avec un autre éditeur Python à installer sur l'ordinateur (fonctionnant sous Windows, Linux ou Mac) prenant en charge une version de Python dédiée aux microcontrôleurs (appelée MicroPython ). Ce logiciel s'appelle Mu-Editor et se trouve sur le site https://codewith.mu.

On choisira sur la page de téléchargement la version adaptée à son systme d'exploitation. Nous allons décrire l'installation sous Windows ainsi que celle sous Linux :

1- Installation sous Windows :

  • Pour vérifier la version de Windows (32 ou 64 bits), Ouvrir le Panneau de configuration et aller dans Système et Sécurité puis Système. L'information se trouve à la rubrique "Type du système"

version_windows.png

  • Choisir sur la page de téléchargement la version adaptée : 32 ou 64 bits puis exécuter le fichier pour installer mu-editor. Si plusieurs personnes peuvent utiliser l'ordinateur, penser à cocher l'option qui autorise l'accès du logiciel à tous les utilisateurs. Le détail de l'installation est donné ici (également pour les administrateurs réseaux)
  • Il faudra également installer le driver :
    • Télécharger le driver
    • Connecter la carte BBC Micro:Bit au PC à l'aide du câble USB
    • La carte est vue comme un lecteur, contenant deux fichiers :

bbc_windows.png

  • Refermer cette fenêtre
  • Installer le driver téléchargé

2- Installation sous Linux :

  • Sous Linux, on installera mu-editor à l'aide de l'outil de gestion de paquets Python pip :
    • Vérifier dans le gestionnaire de paquets la présence du paquet python3-pip ; en faire éventuellement l'installation. (Ci-dessous un exemple dans Synaptic)

python3-pip.png

  • On peut alors utiliser l'outil pip. Dans un Terminal, entrer la commande : pip3 install mu-editor
  • pip va alors télécharger tous les fichiers nécessaires au bon fonctionnement de mu-editor et les installer. Ci-dessous une copie d'écran de l'installation de mu-editor dans une distribution Ubuntu :

linux_install_mu-editor.png

  • Pas de driver à installer, par contre il faut que l'utilisateur appartienne au groupe dialout pour pouvoir utiliser la connexion USB entre l'ordinateur et la carte :

exemple ici pour ajouter l'utilisateur "vincent" au groupe dialout

dialout.png

on obtient ceci :

dialout_fin.png

  • Attention, l'intégration dans un groupe n'est prise en compte qu'au lancement du compte utilisateur : il faudra donc fermer la session puis la réouvrir
  • On pourra vérifier l'intégration au groupe avec la commande : groups

groups.png

On voit que l'utilisateur "vincent" appartient à différents groupes dont "dialout"

On est prêt maintenant à tester l'association du logiciel mu-editor avec la carte Micro:Bit !

Remarque : sous Debian "Stable" l'installation a échoué pour une raison d'incompatibilité de fichiers. Par contre elle se déroule sans problème dans une version Debian "Unstable" (Debian 10) ou dans une version récente d'Ubuntu (18.04) ou dérivée. Debian 10 sera la version stable de Debian en Mars 2019.

Addendum : l'installation a été effectuée sans problème sur une Debian 9.8 (Mars 2019)

Premiers pas avec Mu-Editor :

1- Démarrer mu-editor :

  • Sous Windows, on trouvera mu-editor dans la liste des programmes :

mu_win.png

  • Sous Linux, on entrera dans un Terminal : mu-editor
    • (on pourra réaliser un lanceur avec cette commande ; le site https://codewith.mu propose l'installation d'un racourci par l'installation de l'utilitaire shortcut : pip3 install shortcut suivi de la commande shortcut mu-editor

2- Découvrir mu-editor :

Au premier démarrage, une boite de dialogue va s'ouvrir pour demander dans quel mode utiliser mu-editor :

mode_mu-editor.png

On choisira ici le mode BBC micro:bit

L'ensemble du menu de mu-editor est réalisé au travers d'icônes séparées en cinq groupes :

mu-editore_icones.png

mu-editor_icones_mode.png Permet de revenir dans la boite de dialogue pour changer le mode d'utilisation de mu-editor... Indispensable si on n'a pas fait le bon réglage à la première mise en route du logiciel !

mu-editor_icones_fichiers.png Ce bloc d'icônes concerne les opérations de fichier sur le disque dur du PC

  • NOUVEAU : pour créer un nouveau programme python
  • CHARGER : pour récupérer un fichier programme enregistré préalablement sur le PC
  • ENREGISTRER : pour sauvegarder un fichier programme sur le PC. Attention : le logiciel ne propose pas l'option enregistrer sous. Donc si on modifie le contenu d'un fichier déjà nommé, le bouton "Enregistrer" viendra écraser le fichier enregistré sur le disque dur avec le contenu présent à l'écran. La solution consiste alors à cliquer sur le bouton "Nouveau", ce qui ouvre un nouvel onglet nommé "sans titre", et à copier-coller dedans la/les parties de programme que l'on souhaite reprendre pour une nouvelle utilisation

Remarque : lors de l'installation de mu-editor, un dossier "mu-code" a été créé sur le disque dur, directement dans le dossier de l'utilisateur ("Vincent" étant ici le nom de l'utilisateur connecté) :

  • Sous Windows, il se trouve en : 

fichiers_windows.png

 

  • Sous Linux (ici Ubuntu) :

fichiers_ubuntu.png

Remarque : si l'on veut utiliser l'option Fichiers dans le bloc d'icônes ci-dessous, les programmes devront être stockés à la racine du dossier mu_code et pas dans un sous-répertoire.

mu-editor_icones_memoire.pngCe troisième bloc d'icônes concerne les opérations de communication entre le logiciel mu-editor et la carte Micro:Bit :

  • FLASHER : pour programmer dans le microcontrôleur le programme python présent dans la fenêtre d'édition. La LED orange située côté composant de la carte se met à clignoter pendant le chargement du programme dans la mémoire Flash du microcontrôleur. Puis le programme démarre sur la carte.
  • FICHIERS : MicroPython dispose sur la carte MicroBit d'un petit système de fichiers (environ 30 kilo octets), permettant de stocker dessus quelques fichiers. On peut réaliser le transfert du PC vers la carte ou inversement. En cliquant sur cette icône "Fichiers" on accède alors à ce système de fichiers. Pour quitter ce mode il faut recliquer sur l'icône Fichiers

Utilisations possibles :

  • stocker un programme Python dans la carte, pour pouvoir le réutiliser sur un autre PC
  • Plus intéressant : dans un programme destiné par exemple à de la mesure, il est possible de créer sur la carte un fichier pour enregistrer des couples date/valeur. On peut alors avec ce système de fichiers transférer ce fichier vers le PC pour l'ouvrir dans un tableur par exemple. Cette possibilité sera étudiée dans la partie "Programmation avancée"

sys_fichiers_r.png

On voit ici que le système de fichiers de mu-editor a bien détecté sur le PC la présence de deux fichiers Python (programmes.py et set_pix.py). Le fichier Mesures.txt, présent sur la carte Micro:Bit pourra être rapatrié vers le PC par simple cliquer-glisser

  • REPL : (Read-Evaluate- Print Loop) : c'est un interpréteur interactif, qui permet d'envoyer vers la carte Micro:Bit des instructions ligne par ligne.
  • GRAPHIQUE : cette option permet de visualiser graphiquement en temps réel des valeurs mesurées par la carte Micro:Bit

mu-editor_icones_aspect.png Ce quatrième groupe permet de travailler sur l'aspect du logiciel. L'option ZOOMER sera utile en vidéoprojection en classe pour obtenir à distance une bonne visibilité du code

mu-editor_icones_aide.png Dans ce dernier groupe d'icônes, le bouton VERIFIER permet de faire une analyse "grammaticale" du code écrit : les fautes seront signalées. Ce vérificateur est plutôt strict, et des "erreurs" pointées ne sont pas toujours rédhibitoires...

Après tous ces préparatifs, nous voilà enfin prêts à écrire nos premières lignes de code :

la suite dans l'onglet "Découvrir" sur cette page

Découvrir :

Dans cette partie "Découvrir" nous allons mettre en oeuvre des petits programmes pour :

  • utiliser quelques unes des ressources disponibles sur la carte Micrro:Bit
  • (re)voir quelques éléments du langage Python
Import :

1- Importation du module "microbit"

Un programme écrit en Python s'appuie généralement sur des fonctions standards du langage mais aussi sur d'autres fonctions utiles dans des cas spécifiques et regroupées dans des modules. Il existe par exemple le module math qui permet d'utiliser dans un programme de nombreuses fonctions mathématiques (trigonométriques, logarithmiques, exponentielles ...) ou des constantes (pi, e...).

Ces modules doivent être importés en début de programme pour que les fonctions qu'ils contiennent soient utilisables dans le reste du corps du programme. Cela se réalise par une simple ligne du genre :

from math import *

(* signifie que l'on importe toutes les fonctions du module math)

Un module spécifique au fonctionnement de la carte Micro:Bit a été installé sur l'ordinateur lors de l'installation de mu-editor : il s'agit du module "microbit".

Ainsi, pour pouvoir utiliser la carte, tous nos programmes commenceront par l'importation de ce module :

import.png

Toutes les fonctions fournies par ce module sont décrites à l'adresse suivante :

https://microbit-micropython.readthedocs.io/en/latest/index.html

Nous en utiliserons quelques unes dans les exemples proposés. Pour exploiter davantage la carte Micro:Bit, il pourra être nécessaire de s'y référer.

Afficheur :

2- Gestion de l'afficheur 5x5 Leds

 

L'afficheur 5x5 Leds est perçu comme étant un objet réel.

Le module microbit fourni un objet au sens Python, nommé "display" sur lequel on peut appliquer des méthodes en suivant la syntaxe :

objet.méthode

dans le but d'agir sur l'objet réel qu'est l'afficheur

Mu-editor fourni une aide bien pratique avec l'auto-complétion du code : quand on tape display suivi d'un point, mu-editor nous montre toutes les méthodes que l'on peut appliquer à l'objet display :

 

display1.png

Il suffit de sélectionner la méthode désirée par un double clic. Puis, l'ouverture d'une parenthèse fait apparaître une aide contextuelle qui vient rappeler les différents paramètres que l'on doit entrer :

display1b.png

set_pixel(x,y,b) permet de régler la luminosité b d'une Led de coordonnées x et y sur une échelle de valeurs allant de 0  à 9.

A titre d'exemple, entrer le code suivant :

display1c.png

... puis cliquer sur le bouton FLASHER : la mémoire Flash du microcontrôleur reçoit ce code puis le programme démarre : on doit voir la Led centrale briller fortement.

Histoire de jouer avec les coordonnées des Leds, compléter ce code pour obtenir :

  • dans un premier programme le signe + occupant l'intégralité de l'afficheur.
  • dans un second, le signe X occupant également l'intégralité de l'afficheur :

display_plus.png   display_mult.png

Remarque : on pourra s'entrainer plus rapidement en utilisant l'interpréteur interactif : cliquer sur le bouton REPL, puis dans l'interpréteur situé en bas de fenêtre, entrer des lignes d'instruction comme celle ci-dessous (validées par la touche Entrée du clavier) :

display1d.png

(on voit ici la deuxième Led de la première ligne s'éclairer moyennement )

Rappel : on sort du mode REPL en recliquant sur ce même bouton

Une façon simple d'avoir répondu au premier problème posé est d'utiliser une suite d'instructions display.set_pixel() comme celle ci-dessous :

from microbit import *

display.set_pixel(0,2,9)
display.set_pixel(1,2,9)
display.set_pixel(2,2,9)
display.set_pixel(3,2,9)
display.set_pixel(4,2,9)
display.set_pixel(2,0,9)
display.set_pixel(2,1,9)
display.set_pixel(2,3,9)
display.set_pixel(2,4,9)

C'est une façon un peu "laborieuse" et pas très "élégante" du point de vue du code. A y regarder de plus près on constate de ligne en ligne que :

  • x croit de 0 à 4 pendant que y reste constant à 2 (on trace la barre horizontale du signe +)
  • x reste constant à 2 et y croit de 0 à 4 dans un deuxième temps (on trace la barre verticale du signe +)

La boucle For :

C'est l'occasion pour nous ici de (re)voir la boucle for en Python. Le code précédent peut se réduire à 3 lignes :

from microbit import *

for i in range(5):
    display.set_pixel(i, 2, 9)    # x va varier de 0 à 4 ; y fixé à 2
    display.set_pixel(2, i, 9)    # x fixé à 2 ; y va varier de 0 à 4 
   

La ligne de code :

for i in range (5) :

signifie que l'on va reproduire 5 fois le contenu du code suivant indenté, (attention : l'index i variant de 0 à 4)

  • En suivant le même principe, réécrire le code permettant l'affichage du signe X à l'ide d'une boucle for.
  • Ecrire le code nécessaire à la réalisation de la séquence visible dans la vidéo ci-dessous (affichage des signes +, - , x et / pendant une seconde chacun, avec extinction de l'écran pendant 0,2 s entre l'affichage de deux symboles. Pour cela on devra utiliser
    • des boucles for
    • une nouvelle fonction qui permet de réaliser un délai :

sleep(n)

dans laquelle n représente le nombre de millisecondes choisi pour le délai

 

 

 

La boucle WHILE :

Notre séquence d'affichage des signes +,-,x,/ ne se déroule qu'une seule fois.

On souhaite qu'elle tourne en continu. Pour cela on va utiliser l'instruction WHILE :

while condition:

... qui signifie "tout le temps que la condition est vraie, exécute le code dans le bloc indenté ci-dessous"

Il nous faut une condition qui soit toujours vraie pour que la boucle tourne indéfiniment.

Rque : un microcontrôleur n'est en principe pas programmé pour réaliser une suite d'actions puis s'arrêter. On inscrit donc le programme dans une boucle infinie :

Le plus simple est alors d'écrire :

while True:

Ci-dessous le code tel qu'il devrait être si on a respecté le "cahier des charges" demandé :

Séquence exécutée une seule fois:                              Séquence tournant indéfiniment:

display1e0.png  display1e.png

Ecriture d'une fonction :

Dans le code précédent on s'aperçoit qu'à la fin de l'affichage de chaque signe, on est amené à réécrire les trois mêmes lignes de code pour réaliser la temporisation telle que demandée.

Il est alors judicieux de créer une fonction, appelons la delai() constituée de ces trois lignes de code et que l'on appellera à la suite de l'affichage de chaque signe. Cela donne :

display1f.png

Autres méthodes applicables à l'objet display :

Pour plus de détails aller sur la page : https://microbit-micropython.readthedocs.io/en/latest/display.html

display.get_pixel(x,y) permet de savoir quelle est la luminosité (entre 0 et 9) de la Led en (x,y)

exemple : Cliquer sur REPL et taper dans l'interpréteur interactif :  display.get_pixel(2,2) renvoie la valeur 9 si la Led centrale est allumée au maximum.

 

display.clear() permet comme son nom l'indique d'effacer l'écran

 

display.scroll permet de faire défiler un message

display.show permet d'afficher un message,  une image ou une séquence d'images. Des images sont déjà prêtes à être utilisées : https://microbit-micropython.readthedocs.io/en/latest/tutorials/images.html

 

Tester simplement ces deux fonctions dans l'interpréteur interactif (REPL) pour voir la différence de comportement :

display.scroll('ABCDE')

puis

display.show('ABCDE')

Des paramètres complémentaires peuvent être fournis lors de l'utilisation de ces fonctions :

  • delay= une valeur en milliseconde : pour modifier la vitesse de l'animation
  • wait= True ou False : pour obliger ou pas le programme à attendre la fin de l'animation avant de poursuivre l'exécution des lignes de code qui suivent
  • loop= True ou False : pour faire recommencer l'animation ou pas une fois arrivée à son terme
  • clear= True ou False pour effacer l'écran à la fin de l'animation (uniquement pour display.show)

Trois autres fonctions disponibles :

 display.is_on()

 display.on()

display.off()

....ne sont pas décrites dans cette première approche de l'utilisation de l'afficheur. Elles seront utilisées plus tard dans des programmes plus avancés

En attendant, on peut passer dans l'onglet suivant pour s'intéresser aux deux boutons poussoirs présents sur la carte, ce qui nous amènera à (re)voir les structures de test autour de IF.

Boutons :

3- Gestion des boutons poussoirs

Deux boutons poussoirs sont disponibles pour l'utilisateur :

  • le bouton A à gauche de l'afficheur est géré par l'objet button_a
  • le bouton B  à droite de l'afficheur est géré par l'objet .... button_b

les méthodes disponibles :

button_methodes.png

  • button_a.is_pressed() : à utiliser dans un test, cette méthode renvoie la valeur booléenne True si le bouton est pressé et False dans le cas contraire
  • button_a.was_pressed() : à utiliser dans un test, cette méthode permet de savoir si le bouton a été pressé depuis le démarrage ou depuis le dernier appel de cette méthode. L'appel à cette méthode remet à zéro l'état logiciel du bouton : il faudra donc que le bouton soit de nouveau pressé pour que cette méthode retourne à nouveau la valeur True
  • button_a.get_presses() : à utiliser dans une ligne de code telle que :

N = button_a.get_presses()

N représente alors le nombre de fois que le bouton a été pressé. L'utilisation de cette méthode remet à zéro le compteur.

Mettons en oeuvre la méthode qui sera certainement la plus utilisée, celle qui consiste à savoir si un bouton est pressé.

Pour savoir si un bouton a été pressé, on va utiliser une instruction conditionnelle : IF (= "Si")

Regardons ce que donnerait une version francisée des possibilités offertes :

  • Pour un test unique (aucune autre alternative n'est traitée) :

si1.png

  • Pour un test unique (toutes les autres alternatives sont traitées) :

si2.png

  • Pour un test multiple (ici 3 avec en plus traitement de toutes les autres alternatives) :

si3.png

Pour rédiger le code en Python il suffira de remplacer :

  • Si par if
  • Sinon par else
  • SinonSi par elif (contraction de else if)

Rques :

  • comme toujours en Python, attention à l'indentation des blocs de code à réaliser avec une tabulation
  • On peut imbriquer plusieurs tests de deux façons pour vérifier que deux conditions sont satisfaites pour déclencher une action :
    • en imbricant deux tests
    • si4.png
    • en liant les deux conditions dans le même if à l'aide de l'opérateur logique "and" (= "et")

si5.png

  • On peut réaliser une même action lorsque l'une ou l'autre de deux conditions est réalisée à l'aide l'opérateur logique "or" (= "ou") :

si6.png

Exercice 1 :

écrire et tester le code suivant  :

boutons_display_scroll.png

ou celui-ci, histoire d'utiliser la méthode show avec des images :

boutons_display_show.png

Exercice 2 :

Ecrire le code nécessaire au fonctionnement suivant :

  • le programme démarre avec la Led centrale allumée avec une luminosité moyenne de 5
  • un appui sur le bouton A décroit la luminosité de la Led de 1
  • un appui sur le bouton B augmente la luminosité de la Led de 1
  • La luminosité reste toujours comprise entre 0 et 9
  • Pour ne pas que la variation de la luminosité de la Led soit trop rapide, on introduira un délai de 100 ms à chaque passage dans la boucle infinie
  • 10 lignes de code peuvent suffire pour écrire le programme de cette application...

 

Contrôle du déroulement du programme avec REPL :

... le code fonctionne, mais on veut s'assurer que la luminosité reste bien comprise entre 0 et 9. Pour cela, on va utiliser l'interpréteur interactif REPL.

Au préalable, on va ajouter une ligne de code dans la boucle infinie :

print(N)

N étant le nom de la variable utilisée pour la luminosité de la Led dans le reste du programme (à modifier bien sûr en fonction du nom de varible que l'on aura choisi)

  • Flasher ce nouveau programme et "jouer" avec les boutons A et B
  • Cliquer sur le bouton REPL. On va voir la valeur de "N" à chaque passage dans la boucle : on cherchera en particulier les passages où "N" change, lorsque l'on a appuyé sur les boutons A ou B :

Bouton A appuyé :                                         Bouton B appuyé :

REPL1.png                     REPL2.png

Le bouton A fait bien descendre la luminosité à 0 et le bouton B peut la faire remonter jusqu'à 9 !

Luminosité :

4- "Mesure" de luminosité

Pas de "vrai" capteur de lumière sur la carte Micro:Bit (type LDR ou photodiode par exemple), mais une astuce de la part des concepteurs : utilser en inverse les Leds de l'afficheur pour "mesurer" la luminosité qu'elles perçoivent. Bien sûr les Leds sont alors éteintes !

On a mis mesure entre guillemets car la foncttion méthode utilisée :

display.read_light_level()

ne fait que retourner un entier entre 0 et 255 (donc une "mesure" convertie sur un octet), la valeur augmentant avec la luminosité. Aucune indication n'est fournie sur la linéarité du "capteur" formé par cet ensemble de Leds.

C'est cependant un dispositif pratique (et à coût nul !) pour repérer des variations de luminosité.

Nous allons en profiter pour réinvestir quelques acquis  :

  • affichage d'un pixel sur l'écran
  • utilisation des boutons A et B pour démarrer ou arrêter les mesures
  • utilisation avancée de boucles While

et pour explorer quelques notions nouvelles :

  • notions de liste et de tuple en Python
  • les fonctions print() et reset() pour interagir dans l'interpréteur REPL
  • la visualisation des données du REPL sous forme graphique

Entrer le code suivant dans mu-editor (pour aller plus vite un copier-coller est possible, mais pour l'apprentissage, il est préférable de tout retaper manuellement :

from microbit import *

mesures = []
display.set_pixel(2,2,9)
boucle_mesure = False

while True:
    while boucle_mesure:
        N = display.read_light_level()
        mesures.append(N)
        print(mesures)
        sleep(1000)
        if button_b.was_pressed():
            boucle_mesure = False
            display.set_pixel(2,2,9)
            print('Arret des mesures')
            
    if button_a.was_pressed():
        boucle_mesure = True
        display.clear()
        print('Mesures :')

 

Analysons ce programme :

  • ligne 3 :  mesures = [ ] , on déclare ici une liste vide appelées "mesures". Cette liste initialement vide va voir sa taille augmenter d'un élément à chaque mesure réalisée. Exemple d'une séquence récupérée dans l'interpréteur interactif :

[255]

[255, 29]

[255, 29, 30]

[255, 29, 30, 30]

  •   ligne 4 : display.set_pixel(2,2,9) : on allume la Led centrale (bien pratique pour voir à quel moment le programme a démarré ; cela évite par exemple de rentrer dans l'interpréteur interactif alors que le flashage du programme est encore en cours, ce qui provoque alors un dysfonctionnement de la carte.
  • ligne 5 : boucle_mesure = False    on déclare ici une variable booléenne, qui va permettre de parcourir ou pas la boucle de mesures. A False la boucle de mesures ne sera pas parcourue, et donc les mesures seront arrêtées ; à True ce sera l'inverse. Donc au lancement du programme aucune mesure ne sera réalisée. Il faudra faire basculer cette variable à True, ce qui sera fait lorsque l'on appuiera sur le bouton A (voir les lignes 18 et 19 du programme)
  • ligne 7 : while True : on rentre dans la boucle principale qui tournera tout le temps puisque la condition d'entrée est toujours vraie (True). C'est à l'intérieur de cette boucle principale que va tourner la boucle secondaire dédiée à la mesure et qui démarre à la ligne suivante :
  • ligne 8 : while boucle_mesure , boucle_mesure qui prendra la valeur True ou False selon les cas (voir explication ligne 5)
  • ligne 9 : N = display.read_light_level() : on réalise la "mesure" de la luminosité ; le résultat est stocké dans la variable N
  • ligne 10 : mesures.append(N) : le mot "append" signifie "ajouter" : l'expression mesures.append(N) signifie : ajouter le contenu de la variable N à la liste mesures[ ]. (La nouvelle valeur est ajoutée à la fin de la liste)
  • ligne 11 : print(mesures) : instruction qui va servir dans l'interpréteur interactif. A chaque fois que cette instruction sera lue, l'interpréteur affichera le contenu de la liste mesures[ ]
  • ligne 12 : sleep(1000) : on fait faire une pause d'une seconde pour ne faire qu'une mesure à chaque seconde environ (il faudrait ajouter les timings dus au traitement des différentes instructions de la boucle)
  • lignes 13 à 16 : on vient tester si le bouton B a été et non pas est pressé à l'aide de la méthode "was_pressed()" (Essayer le programme en remplaçant les méthodes was_pressed() par is_pressed() pour voir la différence de comportement)
    • boucle_mesure = False : à la prochaine entrée dans la boucle de mesures ligne 8, la variable boucle_mesure étant False, le programme ira directement au bloc suivant donc en ligne 18, mais avant cela les lignes 15 et 16 seront traitées :
    • ligne 15 : display.set_pixel(2,2,9) : on allume la Led centrale ce qui donne à l'utilisateur l'information que l'appui sur le bouton B a bien été pris en compte et que donc les mesures sont arrêtées
    • ligne 16 : print('Arret des mesures') : de nouveau une instruction dont le résultat sera visible dans l'interpréteur.
  • lignes 18 à 21 : un bloc contenu dans la boucle principal, qui ne sera donc traité que lorsque le programme ne tourne pas à l'intérieur de la boucle de mesures et si le bouton A a été appuyé :
    • ligne 19 : boucle_mesure = True : à la prochaine entrée dans la boucle de mesures ligne 8, la variable boucle_mesure étant True, le programme entrera effectivement dans cette boucle pour (re)faire des mesures.
    • ligne 20 : display.clear() : on efface l'afficheur pour indiquer à l'utilisateur que les mesures reprennent.
    • ligne 21 : print('Mesures) : de nouveau une instruction dont le résultat sera visible dans l'interpréteur.

Utilisation de l'interpréteur interactif :

Lorsque le programme a été chargé (bouton "Flasher") :

  • lancer l'interpréteur interactif (bouton REPL)
  • le programme est arrêté
  • taper dans l'interpréteur la commande reset() qui va réinitialiser le programme et valider par la touche Entrée du clavier. Si on n'avait pas appuyé sur le bouton A alors la Led centrale était restée allumée. Après validation de de la commande reset() la Led s'éteint car toutes les fonctions de la carte sont remises à zéro et se rallume dès l'entrée dans le programme (ligne 4) : on sait alors que le programme a démarré. Rien ne se passe dans l'interpréteur jusquà ce que l'on appuie sur le bouton A : là les mesures démarrent (L'interpréteur affiche "Mesures :" conformément à l'instruction ligne 21) et à chaque seconde l'interpréteur affiche le contenu de la liste mesures[ ] qui s'allonge donc de seconde en seconde. On peut alors jouer avec la lumière qui arrive sur le panneau de Leds et voir les valeurs mesurées changer. On pourra arrêter le programme avec le bouton B et le relancer avec le bouton A et ce indéfiniment.

La vidéo ci-dessous montre un tel exemple :

Visualiser les données dans un graphique

1- Importation manuelle dans un tableur :

La vidéo ci-dessous montre cette possibilité, un peu laborieuse, mais qui permet d'arriver au but recherché néanmoins :

  • On sélectionne les données (éviter de prendre les crochets) et on les copie dans le presse-papier
  • On les colle dans un éditeur de texte ; on enregistre le fichier (par exemple : mesures.txt)
  • On lance le tableur (ici Calc de LibreOffice) et on ouvre le fichier mesures.txt
  • Il reste à sélectionner les données pour en faire un graphe (ici on a choisi le mode Line puisque les abscisses sont espacées du même écart d'une seconde).

2- En utilisant l'outil Graphique associé au REPL

Il est nécessite pour cela de modifier le programme car le graphique ne peut-être obtenu dans ce cas qu'avec des données fournies dans un tuple et non pas dans une liste.

Le tuple est une liste non modifiable (par exemple la méthode append n'existe pas pour le tuple).

On doit alors écrire l'expression : print((display.read_light_level(), )) à l'intérieur de la boucle pour générer à chaque passage un tuple avec un seul élément (la valeur de la mesure). Si le tuple est constitué de par exemple 3 éléments, alors le grapheur tracera 3 courbes.

On a réduit ici le delai de boucle à 100 ms.

  • Charger le programme
  • Démarrer le REPL et cliquer sur le bouton "Graphique" : la fenêtre de l'interpréteur se divise en deux parties pour faire apparaître le graphique
  • taper la commande reset()
  • Appuyer sur le bouton A de la carte Micro:Bit pour lancer les mesures
  • Observer le graphique lorsque l'on change la quantité de lumière qui arrive sur "l'afficheur".
  • Observer ce qui se passe lorsque l'on appuie sur le bouton B de la carte
  • Un logiciel de capture d'écran permettrait de conserver le graphique sous forme d'une image

Ci-dessous le code du programme et une vidéo de la séquence décrite ci-dessus.

from microbit import *

display.set_pixel(2, 2, 9)
boucle_mesure = False

while True:
    while boucle_mesure:
        print((display.read_light_level(), ))
        sleep(100)
        if button_b.was_pressed():
            boucle_mesure = False
            display.set_pixel(2,2,9)
            print('Arret des mesures')
            
    if button_a.was_pressed():
        boucle_mesure = True
        display.clear()
        print('Mesures :')
    
Température :

5- Température :

La carte Micro:Bit ne dispose pas d'un véritable capteur de température. Là aussi les concepteurs ont utilisé une astuce à moindre coût : se servir du module de température intégré dans la puce du microcontrôleur. Ces modules de température sont courants sur les processeurs modernes, leur rôle étant de vérifier si la température de la puce ne devient pas trop élevée et donc d'agir en conséquence (mise en action d'un ventilateur par exemple).

Le module température a une résolution de 0,25°C, mais l'instruction micropython fournie :

temperature()

retourne un entier donnant en °C la température du microcontrôleur.

On comprendra par là qu'il ne peut s'agir que d'une mesure approximative de la température de l'air ambiant (autour du microcontrôleur) à la condition que le microprocesseur ne soit pas occupé de façon importante (ce qui ferait augmenter sa température)...

Ceci dit on est bien là sur un problème de mesure en physique : un thermomètre mesure sa propre température ! A l'utilisateur de faire en sorte qu'il y ait un équilibre (et donc égalité) entre la température du thermomètre et la température du milieu que l'on veut mesurer ... d'où la bêtise de ceux qui mettent leur thermomètre au soleil pour "mesurer la température qu'il fait au soleil" !!!

Qu'ils peignent leur thermomètre en noir ... ils auront plus chaud !

 

Exercices :

Réinvestir les deux programmes fournis dans l'onglet "Luminosité" pour faire des mesures de température. (Remarque : la température ne pouvant varier que lentement, on on aura intérêt à choisir un délai entre deux mesures relativement conséquent)

 

Exemple de résultat de mesures :

La carte Micro:Bit a été placée dans un réfrigérateur pendant une heure environ, dès sa sortie on a lancé le programme avec visualisation du graphe dans le REPL :

temperature1.png

Partie de 5°C en sortie de réfrigérateur, la température mesurée a augmenté ici d'une dizaine de degrés en 20 minutes. (La carte Micro:Bit était protégée par une coque acrylique ce qui a certainement contribué à la lenteur de la remontée de la température)

Accéléromètre :

6- Accéléromètre :

... ou on devrait peut-être dire "accéléromètre-magnétomètre" ?

Sur la vue schématisée de la carte Micro:Bit :            Sur les cartes Micro:Bit que nous avons :

accel_magnet_ST_schema.png                zoom_composants.png

On a :

  • d'une part (schéma de gauche) un seul composant pour jouer le rôle d'accéléromètre ou de magnétomètre (un ST LSM303GR ou un NXP FXOS8700CQ)
  • d'autre part (photo de droite) deux composants séparés : l'un pour jouer le rôle d'accéléromètre (NXP MMA8653FC) l'autre pour jouer le rôle de magnétomètre (NXP MAG3110) conformément au schéma théorique que l'on peut trouver sur le site Microbit

Il s'agit en fait d'une différence de versions : il semblerait que jusqu'à la version 1.4 de la carte ce soient deux composants séparés et qu'à partir de la version 1.5 ce soit un seul composant (et pas toujours le même modèle...)

Pour ces raisons nous traiterons de façon séparées la fonction accéléromètre et la fonction magnétomètre.

Un accéléromètre, de même que le magnétomètre, possède 3 axes préférentiels nommés X,Y,Z.

Il faut aller consulter la notice du composant (la "datasheet") pour connaître ces orientations et avoir une information de la réponse (valeur et signe) du capteur selon sa position dans le champ de gravité :

Pour l'accéléromètre NXP MMA8653FC :

accelerometre_schema.png

Rque : vu le sens des axes, le physicien se serait attendu à avoir des signes contraires à ceux annoncés ici...

 

Pour l'accéléro-magnétomètre NXP FXOS8700CQ :

accel_magnetNXP_schema.png

Rque : ces composants mixtes sont qualifiés de "6 axes"

 

zoom_capteurs_microbit.png   accelerometre_axes.png

En comparant le schéma des axes de l'accéléromètre et l'implantation du composant sur la carte (repérer la barre blanche sur le composant ; les concepteurs ont aussi ajouté un point blanc sur le circuit imprimé pour le repérage de la broche N° 1 du circuit intégré), on peut en déduire l'orientation des axes X,Y,Z pour la carte Micro:Bit :

accelerometre_axes_noms.png

error.png  Attention : en regardant la carte côté afficheur, des axes vont changer de sens...

Sensibilité : l'accéléromètre MMA8653FC peut travailler sur 3 plages de valeurs d'accélération (exprimées en g, l'accélération de la pesanteur) :

  • -2g à +2g
  • -4g à +4g
  • -8g à +8g

avec une résolution de 10 bits (1024 valeurs différentes)

Sur la carte Micro:Bit, la seule plage disponible, c'est la -2g à + 2g.

Accéder à l'accéléromètre :

En MicroPython, on accède à l'accéléromètre :

  • de façon individuelle sur un axe (par exemple l'axe Z) avec la méthode :

accelerometer.get_z()

qui retourne un entier compris entre +/- 2000 (en 10-3g)

Exemple utilisant l'instruction print pour récupérer le graphique dans l'interpréteur interactif :

accelerometre_prog_1D.png

 

  • de façon globale sur les trois axes avec la méthode :

accelerometer.get_values()

qui va retourner un tuple de 3 nombres entiers compris chacun là aussi entre +/- 2000 :

Exemple utilisant l'instruction print pour récupérer le graphique dans l'interpréteur interactif :

accelerometre_prog_3D.png

error.png  Attention à la différence d'écriture du code : dans le premier cas, l'instruction accelerometer.get_z() ne retournant qu'un entier, il faut créer le tuple pour pouvoir visualiser le graphique alors que dans le second cas le tuple est déjà créé par l'instruction accelerometer.get_values()

Premier essai :

Ce premier essai a pour but de confronter ce que nous dit la notice de l'accéléromètre avec le retour donné par les instructions MicroPython.

Nous avons placé la carte Micro:Bit dans les orientations successives suivantes. La flèche bleue représente le vecteur intensité de pesanteur ; à droite les résultats attendus (selon la notice de l'accéléromètre)

  • Carte placée à plat sur la table, face composants vers le haut :

microbit_front.png

  • Carte redressée :

microbit_portrait_up.png

  • Puis rotation en sens inverse des aiguilles d'une montre :

microbit_landscape_left.png

On a enregistré une copie d'écran :

  • la courbe orange résulte de l'instruction accelerometer.get_z()
  • la courbe verte de l'instruction accelerometer.get_y()
  • et la courbe bleue de l'instruction accelerometer.get_x()

 

Analyse des courbes obtenues :

Au départ :

  • la courbe bleue (X) est à 0
  • la courbe verte (Y) est à 0
  • la courbe orange (Z) est à +1000 (x10-3g)

ce qui est conforme à l'indication du fabricant

Puis on redresse la carte :

  • la courbe bleue (X) est à 0
  • la courbe verte (Y) est à +1000 (x10-3g) alors que l'on attendait une valeur négative
  • la courbe orange (Z) est à 0

Puis on tourne la carte :

  • la courbe bleue (X) est à +1000 (x10-3g) alors que l'on attendait là aussi une valeur négative
  • la courbe verte (Y) est à 0
  • la courbe orange (Z) est à 0

Pas d'explication à donner sur cette "anomalie" sans savoir le code qui se cache derrière une instruction telle que accelerometer.get_x() par exemple... Il est vrai que le souci des concepteurs de rendre très abordable et ludique l'ensemble {matériel - logiciel de programmation} élude un grand nombre de questions sur le fonctionnement réel du dispositif. Les documentations techniques ne sont pas mises en évidence sur le site microbit et la personne qui veut en savoir plus devra aller à la pêche aux informations pour en savoir plus...

 

Par ailleurs, on peut se demander ce que l'on peut faire de cet accéléromètre si la carte Micro:Bit reste attachée au câble USB... ce qui est plutôt limitant en terme de mouvements possibles. Il faudra donc pouvoir récupérer les données autrement, ce qui sera travaillé dans la partie "Programmation avancée".

On trouvera aussi sur le site microbit des applications ludiques de la carte en mode autonome, utilisant l'afficheur 5x5 Leds, pour lesquels l'accéléromètre ne sert qu'à voir si la carte a été déplacée

En attendant, voici néanmoins une petite application "physique" facilement réalisable (attention la courbe obtenue est bien une courbe d'accélération et non pas de position... confusion facilement faite ici, provenant des fonctions sinusoïdales dont les dérivées ou primitives restes sinusoïdales... On a le même genre d'effet lorsque l'on accroche par exemple un aimant à un ressort et qu'on le fait osciller dans une bobine : on recueille alors aux bornes de la bobine, une tension liée non pas à la position de l'aimant mais à sa vitesse)

Exemple d'application :

Oscillations amorties de la carte Micro:Bit suspendue à son câble USB !!!

Le code à entrer et la visualisation dans le graphique de l'interpréteur interactif (REPL) :

from microbit import *

while True:
    print((accelerometer.get_y(),))
    sleep(50)

Etendre :

Connecteur d'extension

Extension de la carte BBC Micro:Bit

Bien que déjà convenablement équipée, on peut vouloir étendre les possibilités de la carte Micro:Bit pour des applications spécifiques ou plus complexes.

Ceci peut se réaliser grâce au conecteur d'extension situé sur un des côtés de la carte Micro:Bit :

microbit-pins.jpg

Constitué de 25 broches (= pins en anglais) :

  • 18 broches P0 à P20 (P12 réservée et il manque P17 et P18) sont :
    • des entrées/sorties digitales (qui n'acceptent ou ne délivrent que des niveaux 0 ou 1, donc des tensions de 0 V ou 3,3 V... Attention lors de l'achat de modules à vérifier la compatibilité avec une alimentation 3,3V !!!
    • des entrées analogiques (pour mesurer des tensions quelconques entre 0 et 3,3V. Ces "pins" peuvent aussi servir en entrées/sorties digitales.

Attention : certaines de ces broches sont partagées avec les deux boutons poussoirs et l'afficheur de la carte Micro:Bit

  • 6 broches notées 3V3 (comprendre 3,3 volts) et GND (l"Ground" à traduire par Masse (= 0 volt) et non pas par "Terre"... confusion fâcheuse que nous font souvent les anglais dans les montages électroniques. (de plus avec le nombre d'appareils fonctionnant sur piles ou batterie ou sur chargeur sans prise de terre, il n'y a qu'une fraction de montages dans lesquels la masse et la terre se retrouvent liées !!! ). Ces broches servent à propager les lignes d'alimentation de la carte Micro:Bit pour alimenter l'électronique que l'on vient connecter sur la carte. (Rappelons que la carte Micro:Bit est alimentée soit par la prise USB soit par un coupleur de piles, et que donc la consommation de l'électronique externe doit rester modeste sinon on risque un affaissement du 3,3V engendrant des erreurs de fonctionnement ou un arrêt du processeur)

On remarquera que 5 de ces broches sont utilisables directement avec des fiches bananes de 4 mm de diamètre : P0, P1, P2 et deux bornes d'alimentation 3,3V et Gnd. (Si on souhaite utiliser cette opportunité relativement simple et peu coûteuse, il faudra veiller au moment du câblage à ce que les fils utilisés ne viennent pas faire de court-circuits malencontreux... pas évident avec des élèves débutants en électricité !)

 

Pour utiliser ce connecteur d'extension on trouversur le marché deux types de systèmes :

  • ceux pour lesquels les composants électroniques additionnels sont déjà montés dans des modules prêts à l'emploi (exemple le système Grove que l'on va décrire), et qui permettent une mise en place simple, rapide, relativement sécurisée pour le système, mais limitée aux modules existants
  • ceux pour lesquels la carte Micro:Bit est reliée à un montage réalisé sur une plaque d'expérimentation. Il s'agit alors d'implanter les différents composants sur la plaque, sans faire d'erreur de câblage... Cela ouvre alors un champ de possibilités très grand, essentiellement limité par les connaissances en électronique de l'utilisateur. Ce genre de dispositif est plutôt destiné au prototypage , en vue d'une réalisation finalisée sur circuit imprimé. On voit clairement que ce système est davantage destiné aux utilisateurs avancés ou à ceux qui veulent franchir un cap de progression en conception.

Ci-dessous : à gauche le système Grove relié à trois modules

et à droite le kit de prototypage pour Micro:Bit (pas encore en acttion...)

r_P1060929.JPG

 

Le système Grove

Le système Grove propose une multitude de modules utilisables sur différentes plateformes (Arduino notamment ). Ces modules sont reliés par des câbles à une base elle même connectée à la carte de développement :

r_P1060926.JPG   r_P1060924.JPG

Détail intéressant : les petits modules Grove peuvent être insérés sur des socles nommés "Wrappers" (ici en rouge et jaune) compatibles avec le système ©LEGO bien connu (sur cette photo les wrappers fixés sur une plaque Lego des années soixante...

Ces wrappers peuvent éventuellement se raccorder les uns aux autres ; ils sont fournis avec vis et écrous pour les fixer sur une plaque de bois par exemple :

r_P1060928.JPG

Les différentes tailles de modules (source : SeedStudio)

tailles_modules.png

Tous les modules sont reliés avec le même type de câble constitué de 4 fils :

  • pin 1 - Jaune (ligne de signal Nº1 ; celle utilisée si le module nécessite une seule ligne de signal)
  • pin 2 - Blanc (ligne de signal Nº2 , si une deuxième est nécessaire au fonctionnement du module)
  • pin 3 - Rouge - VCC donc 3,3V pour la carte Micro:Bit ...mais 5V sur Arduino
  • pin 4 - Noir - GND ... la masse

Les connecteurs pour circuit imprimé étant disponibles à la vente, il est donc possible de créer ses propres modules.

Pour la carte Micro:Bit, la platine de liaison (Shield Grove pour micro:bit  Réf : 103100063) permet la connexion de 4 modules :

  • un module supportant le protocole de communication série I2C
  • 3 modules généraux travaillant en digital ou en analogique

shield_grove.png

D'après le principe de câblage évoqué ci-dessus, on constate qu'un module Grove occupe systématiquement 2 lignes de données. Pour le shield Grove utilisé ici, ce sont les broches :

  • P0 et P14 sur le connecteur 2
  • P1 et P15 sur le connecteur 3
  • P2 et P16 sur le connecteur 4

Nous allons étudier quelques uns de ces modules, ce qui sera l'occasion d'approfondir nos connaissances sur le langage Python

Module Led

Le module LED : (Référence Seedstudio : 104030007 )

1- Présentation :

schema_led.png   module_led.png

Rque : la référence fournie (104030007) correspond au module fourni avec une Led verte. D'autres couleurs sont disponibles. La Led n'est pas soudée: juste enfoncée dans un connecteur. Cela facilite le changement de la Led (maintenance, choix d'une autre couleur), mais il faut veiller à la placer dans le bon sens !

A la lecture du schéma, on constate que la Led est pilotée par une seule ligne de signal (on pouvait s'y attendre !) notée SIG. Cette ligne pilote un transistor NPN qui sera

  • passant lorsque le niveau appliqué sur sa base sera élevé (donc un état haut = "1") ; la Led sera donc allumée
  • bloqué lorsque le niveau appliqué sur sa base sera faible (donc un état bas = "0") ; la Led sera alors éteinte.

On remarque la présence d'un "potentiomètre" monté en fait en résistance ajustable qui permet d'ajuster la luminosité de la Led (c'est aussi une petite astuce du concepteur pour pouvoir utiliser ce module en 3,3V (avec la carte Micro:Bit) ou en 5 V (avec la carte Arduino). Si le montage ne semble pas fonctionner, vérifier :

  1. que la Led est montée dans le bon sens
  2. si la Led n'est pas sous alimentée en tournant le potentiomètre

La ligne de signal unique utilisée est comme indiqué dans le principe de câblage sur la broche N°1 du connecteur du module.  Selon le connecteur utilisé du shield Grove, on devra donc travailler sur le niveau de la ligne :

P0 pour le connecteur N°2 (noté P0/P14)

P1 pour le connecteur N°3 (noté P1/P15)

P2 pour le connecteur N°4 (noté P2/P16)

2- Mise en oeuvre :

Pour la carte Micro:Bit la broche utilisée (par exemple P0) est une sortie sur laquelle on doit appliquer un niveau 0 ou un niveau 1. La fonction MicroPython qui le permet se nomme :

write_digital(val)      val étant égal à 0 ou à 1

A titre d'exemple, écrire le code suivant et le flasher dans la carte :

led_clignot_1.png

La compréhension de ce listing ne devrait pas poser de problème particulier. Pour tester le programme, il faut bien sûr connecter le module Led sur le connecteur P0/P14.

Rque : ne pas mettre la même durée permet de bien voir que la Led s'allume effectivement avec un niveau 1 et s'éteint avec un niveau 0.

On pourra s'entraîner à modifier le programme pour un module Led connecté en P1/P15 ou P2/P16.

Une petite astuce : pour n'avoir à modifier qu'une seule fois le nom de la broche utilisée, on peut écrire le programme suivant :

led_clignot_2.png

 

3- Fonctions et module :

La fonction utilisée pour gérer la led, write_digital(), est une fonction généraliste pour gérer le niveau appliqué sur une sortie digitale. On pourrait souhaiter avoir une fonction dont le nom serait plus explicite, et pourquoi pas en français, pour "allumer" ou "éteindre" une Led branchée sur telle ou telle broche.

On va donc ici créer deux nouvelles fonctions. Entrer le code suivant et le flasher pour en vérifier le fonctionnement :

led_clignot_3.png

Analyse du code :

  • ligne 3 on définit une fonction avec le mot réservé "def". Cette fonction prend un seul paramètre qui sera le nom de la broche sur laquelle est branchée la Led. Une seule instruction dans cette fonction : la mise à un de cette broche de sortie, donc l'allumage de la Led.
  • ligne 6, on définit une fonction qui fera exactement l'inverse, donc l'extinction de la Led

On rentre ensuite en ligne 9 dans la boucle infinie du programe, dans laquelle on utilise ces deux fonctions et bien sûr la fonction de temporisation sleep().

Allons encore plus loin dans l'utilisation de ces fonctions pour en créer une nouvelle chargée de gérer le clignotement de la Led. Cette fonction aura trois paramètres :

  • un pour définir le nom de la broche utilisée (pin)
  • un pour définir la durée à l'état haut (th) de la broche (donc la durée d'allumage de la Led
  • un pour définir la durée à l'état bas (tb) de la broche (donc la durée d'extinction de la Led)

Appelons clignote(pin,th,tb) cette nouvelle fonction. Le code devient alors :

led_clignot_4.png

Une remarque s'impose alors : pourquoi s'embêter à créer de telles fonctions, puisque cela a fini par rallonger sérieusement le programme, comparé à celui écrit au début avec la fonction write_digital() ?

  1. On gagne en lisibilité et compréhension du programme
  2. On constate que le corps principal du programme, celui qui tourne dans la boucle infinie est maintenant réduit à une seule ligne. Cela nous amène alors à l'idée suivante : si nos fonctions (que l'on pourrait d'ailleurs vouloir réutiliser dans d'autres programmes) étaient placées dans un autre fichier (qui sera alor un module de fonctions), alors le nombre de lignes de code de notre programme serait extrêmement limité, rendant du coup très aisée sa lecture et sa compréhension.

Commençons par créer le module de fonctions. Nommons le par exemple module_led.py :

module_python_led.png

Une bonne habitude à prendre quand on rédige un module de fonctions qui est censé être réutilisé (beaucoup, beaucoup) plus tard dans un autre programme :

commenter les fonctions utilisées (ce qu'elles font, quels sont les paramètres à rentrer).

Le programme principal devient alors :

led_clignot_5.png

Remarquer :

  • l'importation du module "module_led.py" indispensable car la fonction clignote() est inconnue de MicroPython
  • l'absence de notre classique ligne d'entrée :

from microbit import *

En effet cette ligne a été placée dans le module de fonctions module_led.py et n'est donc plus utile ici.

  • la compacité du code ....

MAIS... Si on flashe ce programme dans la carte ... cela ne fonctionne pas !

katuberling.png Un module de fonctions doit se trouver dans le même dossier que le fichier qui l'utilise... mais ici l'exécution du programme se fait non pas sur le PC mais sur la carte Micro:Bit !!!

Il faut donc au préalable déposer le module de fonctions dans la mémoire de la carte !

Comment faire ?

Cliquer sur l'icône "Fichiers" de Mu-Editor, ce qui va faire apparaître :

  • dans le volet de gauche les fichiers présents sur la carte (ici le fichier main.py uniquement)
  • dans le volet de droite les fichiers présents sur le PC.

Déplacer à la souris le fichier "module_led.py" comme indiqué dans la copie d'écran :

module_python_led_fichiers_1_m.png

Après quelques instants, on obtient :

module_python_led_fichiers_2.png

 

Remarquer que le fichier module_led.py n'a pas été déplacé dans cette action mais simplement copié du PC vers la carte Micro:Bit

Flasher le programme principal : maintenant cela fonctionne ;-)

katuberling.png Lorsque l'on développe un module de fonctions, il arrive que tout ne fonctionne pas du premier coup... On doit donc réaliser les modifications du fichier sur le PC, puis retourner dans l'option Fichiers de Mu-Editor pour refaire la manipulation décrite ci-avant, ce qui donne un message d'avertissement demandant confirmation de l'écrasement du fichier :

module_python_led_fichiers_3.png

Si l'on souhaite supprimer un fichier de la mémoire de la carte, faire un clic droit sur le fichier :

module_python_led_fichiers_suppression.png

et confirmer la suppression par un nouveau clic droit.

Le programme principal utilisé dans cet exemple avait été nommé "grove_Led_clignotante_5.py". Après flashage de ce fichier, on trouve dans la liste de fichiers de la carte uniquement deux fichiers :

  • le fichier de module que l'on a placé manuellement
  • un fichier nommé main.py
  • mais pas grove_Led_clignotante_5.py ...

module_python_led_fichiers_4.png

Quel est donc ce fichier main.py ? Pour le savoir, le sélectionner à la souris pour le copier vers la liste des fichiers du PC. Puis avec le bouton charger de Mu-Editor, observer son contenu :

module_python_led_fichiers_5.png

main.py est la copie exacte du fichier programme que l'on a flashé !

Après un Reset du microcontrôleur (suite à la mise en route, au flashage ou à l'appui du bouton Reset situé sur l'arrière de la carte Micro:Bit), le programme de démarrage ("Boot") inclus dans la mémoire de la carte cherche un fichier nommé main.py. C'est celui là qui sera interprété. Ceci laisse la possibilité d'embarquer sur la carte d'autres fichiers qui seront invisibles pour l'interpréteur Python sauf si ce sont des fichiers liés au programme main.py (par exemple un module de fonctions).

 

Module Bouton

Le Bouton poussoir (Référence Seeedstudio: 101020003)

1- Présentation

schema_bouton.png   photo_bouton.png

Le schéma (pas très pédagogique !) du montage de ce bouton poussoir nous montre qu'il est connecté entre le +3,3V et une résistance elle même reliée à la masse. La ligne de signal utilisée (D1) est reliée au point milieu entre le poussoir et la résistance. Cela donne :

  • bouton poussoir relâché : la ligne D1 se retrouve au niveau 0 à travers la résistance R2
  • bouton poussoir enfoncé : la ligne D1 se retrouve au 3,3V donc au niveau 1

Rque : cette façon de procéder n'est pas très correcte, et on préfère faire le montage inverse, la résistance étant sur la ligne d'alimentation et le bouton poussoir avec une de ses deux broches à la masse. D'ailleurs, les microcontrôleurs possèdent déja ce type de résistance intégrée à la sortie, résistances dites de "pull up" et que l'on peut activer ou non. L'activation permet alors de n'avoir qu'un bouton poussoir à placer sur le circuit imprimé.

Ci-dessous les deux schémas possibles (en version plus lisible) pour réaliser un niveau logique avec un bouton poussoir. On pourra étudier facilement ces deux montages avec du matériel d'électricité du lycée. Si on possède un oscilloscope numérique, on pourra le mettre en mode monocoup (Single), à la place du voltmètre, ce qui permettra de bien "visualiser" les niveaux logiques, et peut-être aussi le problème du "rebond" évoqué un peu plus bas dans l'exercice 3.

BP_logique.png

BP_logique_tableau.png

En savoir plus sur les niveaux logiques

Le câblage choisi par le fabricant (qui correspond au schéma de droite avec la ligne de signal qui serait branchée sur le point A) a certainement pour but d'avoir au niveau programmation une vision simple du type :

  • pas d'action = niveau 0
  • action = niveau 1

2- Mise en oeuvre

On travaille, comme pour la Led, sur des niveaux logiques. Mais alors que la broche choisie pour piloter la Led était traitée comme une sortie sur laquelle on "écrivait" avec la fonction write_digital() un niveau 0 ou 1, celle que l'on utilisera ici sera traitée comme une entrée sur laquelle on va "lire" un niveau 0 ou 1.

La fonction MicroPython pour faire cette lecture se nomme read_digital(). Cette fonction ne prend aucun paramètre (la parenthèse restera vide) mais retourne une valeur 0 ou 1

 

Exercice 1 :

Commençons directement par un petit exercice. Observer les deux listings suivants :

bouton_1.png   bouton_2.png

Ces deux programmes utilisent un module Led et un module bouton Grove. Ils utilisent aussi le module de fonctions "module_led.py" qui devra donc être présent sur la carte comme décrit dans l'onglet sur le module Led.

Avant de les faire fonctionner, décrire leur fonctionnement en répondant aux questions suivantes pour chacun d'eux :

  1. Sur quel connecteur de la carte Micro:Bit est branché : le module bouton ; le module Led
  2. Que va-t-il se produire lorsque l'on va appuyer sur le bouton poussoir ?

Réponse : ...il suffit maintenant de taper ces quelques lignes de code et les faire exécuter par la carte Micro:Bit !

 

Exercice 2 : Réalisation d'un monostable (principe d'une minuterie type allumage temporaire d'un escalier d'immeuble par exemple)

Modifier l'un de ces deux listings pour que la Led reste allumée pendat une durée prévue (par exemple 30 s) après un bref appui sur le bouton poussoir

 

Exercice 3 : Ecrire le code suivant ; réaliiser les câblages nécessaires au bon fonctionnement et exécuter le code :

bouton_3.png

  1. Que se passe-t-il lorsque l'on presse une première fois le bouton poussoir
  2. Que se passe-t-il lorsque l'on presse une deuxième fois le bouton poussoir
  3. En ligne 5 on utilise l'opérateur d'inversion logique not (une valeur True devient False et inversement). Expliquer le fonctionnement du programme.

Rque : la temporisation de 200 ms insérée dans le programme sert à éviter la prise en compte des "rebonds" du bouton poussoir : on réalise un anti-rebond logiciel. Quand on appuie ou relâche un tel bouton, le contact n'est jamais franc, engendrant des microcoupures pendant quelques dizaines de ms, et donc une succession momentanée de 0 et de 1.  (Une alternative matérielle serait de monter un condensateur sur le module bouton poussoir pour lisser les variations de tensions). Pour tester le programme et ainsi voir ce problème, enlever cette temporisation du programme : on peut simplement mettre le signe # devant la ligne 10, qui ne sera plus exécutée car vue comme un commentaire.

3- Ecriture d'une fonction et nouveau module

En suivant l'exemple réalisé avec la Led, on pourrait là aussi créer une fonction plus parlante que l'on va nommer par exemple bouton_presse(pin) 

Rque : les accents sont interdits dans les noms de variables ou de fonctions, donc pas possible d'écrire bouton_pressé(pin) :

bouton_4.png

On peut alors décider d'intégrer cette fonction dans le module créé précédemment pour la Led. Il serait alors plus judicieux de renommer ce module de façon plus générique, par exemple "modules_grove.py", module dans lequel on viendrait placer toutes les fonctions spécifiques à la gestion des module Grove dont on dispose :

modules_grove_py.png

(image partielle du fichier )

 

Exercice 4 :

  1. Ecrire ce nouveau module de fonctions "modules_grove.py" .
  2. Réaliiser les câblages, ainsi que les modifications dans la mémoire de la carte Micro:Bit, nécessaires au bon fonctionnement pour pouvoir exécuter le code :

bouton_5.png

 

 

 

package_settings.png En travaux ...

Programmation avancée :

package_settings.png En travaux ...