MicroPython OLED Menu: réaliser une interface matériel générique pour application MicroPython

Amis de MicroPython et amis Maker, 

16 mai 2023: nouvelle version de la bibliothèque avec ajout de fonctionnalités!

Les projets Maker les plus sophistiqués ont besoin d'une interface autonome:

  • d'activation de processus
  • de sélection de fonctionnalités
  • de paramétrage

Le problème, c'est que réinventer une interface et la redévelopper son support à chaque nouveau projet c'est assez pesant! 

C'est également contraignant en maintenance puisque l'ajout d'une fonctionnalité réclame une modification de interface matériel (bouton, cadran, LED, afficheur) et du code complémentaire pour supporter cette modification matériel.
Il va de soi que l'ajout d'une fonctionnalité provoque inévitablement une modification du code.

Oled + Encodeur = interface flexible et homogène

En solution à ce problème répétitif, un afficheur OLED et un encodeur rotatif cliquable pourraient couvrir de très nombreux cas de figure en proposant un code homogène (une bibliothèque).

L'association encodeur + écran OLED est assez fréquent dans les projets publiés sur Internet... prouvant ainsi l'intérêt de la solution.


J'ai juste décidé d'une contrainte supplémentaire: usage du bus I2C uniquement! pour économiser des GPIOs (et faciliter l'insertion du code d'interface).

Projet Microython-Oled-Menu

C'est ainsi que le projet MicroPython-Oled-Menu a commencé.

En voici les caractéristiques:

1) Non bloquant

Pour commencer, le code est non-bloquant et le menu constamment mis-à-jour par l'appel de la méthode update().

La méthode update() s'occupera de la gestion visuel du menu, activation de l'entrée sélectionnée, gestion des fonctionnalités, rafraîchissement des écrans utilisateurs/personnalisé.

Comme le code est non bloquant, il peut être exécuté en même temps que le code utilisateur (dans la boucle principale)

2) Un niveau de menu

Un seul niveau de menu... mais illimité en quantité d'entrées avec scroll automatique.
Les entrées Menu peuvent être:

  1. Basé sur le principe d'association code_d_activation=libellé_a_afficher
  2. Activée/désactivée, 
  3. Afficher un texte personnalisé (formatage), 
  4. Possibilité d'afficher une petite icône (prochainement)
  5. Effet d'inversion lorsque activé (750ms, non bloquant).

3) Modifiable au RunTime

Il est possible de modifier les propriétés des entrées du menu pendant qu'il est en cours d'exécution.

4) Utilisation de l'encodeur

Déplace le Focus (cadre de sélection) dans le menu.
Clic = Sélection du point de menu -ou- activation de la fonctionnalité intégrée.

Le bouton utilise une machine à états pour éviter de multiple activations.

5) Fonctionnalités avancées

5.1) Libellé uniquement

Pas vraiment une fonctionnalité en soit mais permet à la boucle de traitement du programme d'être informé d'une action sur le menu (comme une mise en marche/arrêt).

menu.add_label( "start", "Start Oven" )

5.2) Gamme de valeur

Associé à un libellé formaté, l'entrée gamme de valeur permet de modifier une valeur entière en la maintenant dans une gamme de valeur (Range en anglais).

L'exemple suivant permet de sélectionner la température de préchauffage dans la gamme 25°C - 180°C (par incrément de 5°C). La valeur par défaut est fixée à 50°C.

menu.add_range( "preheat" , "PreHeat %s C", 25, 180, 5, 50 )

Lorsque l'utilisateur clique sur une telle entrée, l'affichage bascule sur un écran (toujours non bloquant) permettant de modifier la valeur de la température. 

Cette valeur est confirmée en cliquant sur le bouton de l'encodeur.

Lorsque la valeur est confirmée, le menu est simplement ré-affiché.

Modification de la valeur entière

5.3) Sélection de type combo


Ce type de point de menu permet de sélectionner une entrée parmi une liste de valeurs prédéfinie (avec sélection d'une valeur par défaut).

menu.add_combo( "combo4", "Mode: %s", [("m", "Manuel"),("a", "Autom."),("v8", "value 8")], "v8" )

Associé à au libellé formaté qui permet d'identifier la valeur sélectionnée, cliquer sur ce point de menu affiche la liste des valeur possible.

Voici a quoi ressemble un exemple typique d'écran de sélection (attention, ce n'est pas celui correspondant à l'exemple ci-dessus).

Ecran de sélection d'une valeur Combo

Le signe ">" indique la valeur actuelle présentée dans le point de menu.

5.3) Affichage écran

Associé à un libellé, ce point de menu affiche "un écran" personnalisé, un peu comme un tableau reprenant des informations résumées en plein écran sur l'état de fonctionnement du projet.

Un click sur le bouton de l'encodeur permet de quitter l'écran et revenir au menu!

menu.add_screen( "scr1", "Dashboard", on_dash_draw, on_dash_start )

La mise à jour de l'affichage se fait par rappel d'une fonction (on_dash_draw dans le cas présent) appelé à chaque appel de menu.update()

A noter qu'à l'appel du point de menu, la fonction de rappel on_dash_start est appelée si elle est renseignée lors de la déclaration du point de menu.

Le code complet de l'exemple test_screen.py est disponible dans le dépôt.

Ressources

Le projet est encore jeune et ne manquera pas d'évoluer prochainement.




Aucun commentaire