Accueil > Arduino > Pico puter : de la théorie à la pratique

Pico puter : de la théorie à la pratique


Mon mini cluster est cassé. Noeud principal HS. Diagnostic à venir. Du coup, je n’ai toujours pas de « vrai » serveur Mercurial…

En attendant, j’ai relu et (re-)*dé-coquillé mon premier NaNoWriMo (merci encore Titi !) , et j’ai un peu avancé sur mon projet de « Pico ordinateur« .

Yeps ! Les premiers écueils apparaissent à l’horizon.

Pour rappel, un ATtiny85 vu du programmeur, c’est :

  • 8 kilo-octets de mémoire flash pour les programmes et données statiques
  • 512 octets de mémoire RAM

Côté pratique, l’électronique est à l’avenant :

  • une masse et une alimentation
  • 1 reset qui peut éventuellement être utilisé comme entrée/sortie
  • 5 entrées/sorties, dont deux que je réserve pour le « bus » I2C
  • 512 octets de mémoire de stockage de type EEprom.
  • un capteur de température (si-si)
  • des timers
  • des interruptions

Bref, de quoi s’amuser, surtout vu ce que je compte y « caser » :

  • un petit écran OLED
  • un clavier 4 x 4 touches
  • une horloge/calendrier, sa ram intégrée sauvegardée par pile, ainsi que la mémoire EEProm qui l’accompagne
  • une entrée et une sortie « analogiques » dont l’usage reste à déterminer
  • d’autres petites choses connectées en I2C.

Ça parait léger mais en pratique…

De la théorie …

En principe, tout ça devrait se programmer sans trop de problèmes. I2C ici, I2C là, un clavier « lu » comme une entrée analogique, etc.

Eh bien, non !

… à la pratique

L’I2C n’est pas implémenté en matériel sur l’ATTiny85, et j’utilise une librairie ad-hoc. Et hop, quelques centaines d’octets consommés dans la mémoire flash du contrôleur, plus une quarantaine en RAM.

L’écran OLED a son petit protocole bien à lui, et il faut lui fournir le bitmap (5 octets) de chaque caractère à afficher. Un écran LCD 4×20 aurait été plus simple à programmer mais, je l’ai déjà dit, c’est beaucoup moins fun. Ce sera une solution de repli au cas où…

L’horloge RTC stocke l’heure et la date au format BCD dans sa RAM « non volatile » – comprendre, « sauvegardée par pile ». Elle propose au total dans cette RAM 64 octets de RAM dont l’usage d’une bonne partie est, à priori, laissé libre pour le programmeur. Hop, on ajoute un mini-protocole supplémentaire, et deux routines de conversion BCD <-> binaire.

L’EEPROM qui squatte la carte de l’horloge a, devinez quoi, son petit dialecte propre, mais c’est peut-être le composant le plus simple à utiliser dans ce projet.

J’oubliais l’EEPROM de l’ATtiny, utilisable librement, lui aussi. Heureusement, la librairie standard de l’Arduino suffit. Ouf !

Un peu d’unification

L’EEPROM de l’Attiny – 512 octets – , celle de la carte horloge – 4 kilo octets – , la RAM de l’horloge – 64 octets – ont des besoins assez simples. On peut les considérer comme des périphériques de stockage, mais à la base il faudra y lire et y écrire des valeurs, généralement un octet à la fois. Lent mais simple, et inversement.

Vu la mémoire RAM totale de l’ATtiny85 – 512 octets – ne pourrai pas je n’aurai pas à y manipuler de grosses structures. Partant de là, stocker ou récupérer des informations pourra se faire par paquets de huit, seize, trente-deux octets ou plus à la fois. Je ne suis pas encore fixé là dessus, mais un stockage « de masse » – tout est relatif – par blocs de 32 octets devrait suffire.

On sort son cahier, ses stylos, on dessine l’organisation générale du bousin, les classes, leurs héritages, bref, on fait ses plans, et on se retrouve avec plusieurs « périphériques » de stockage présentant les mêmes routines d’accès. Merci la POO ! Classe de base : I2C, classe abstraite stockage, une classe par périphérique, une pour le clavier, une pour l’écran. Ça a … de la classe !

** /me court se planquer comme un bourrin des Flandres **

Mise en oeuvre

L’écriture du code se passe bien. On joue un peu avec le C++. Et oui, Arduino, à la base, ça se programme en C++ !

Les tests se déroulent bien, l’écran affiche, l’horloge donne la date et l’heure, sa RAM est lue et écrite sans soucis, idem pour sa colocataire l’EEPROM I2C, et le clavier attend sagement qu’on passe à l’étape du fer à souder, même si son code est presque terminé.

Bilan d’étape

La compilation donne :

Le croquis utilise 6862 octets (83%) de l’espace de stockage de programmes. Le maximum est de 8192 octets.
Les variables globales utilisent 439 octets (85%) de mémoire dynamique, ce qui laisse 73 octets pour les variables locales. Le maximum est de 512 octets.

6862 octets de flash utilisée, avec uniquement quelques tests, sans aucun logiciel de mon système cible (qu’il reste d’ailleurs à définir). Je suis encore confiant là-dessus : les tests prennent de la place qui sera à terme libérée pour autre-chose.

73 octets de RAM disponible. SOIXANTE TREIZE ! Même si j’ai réservé 256 octets de RAM pour le futur système, clairement, ça va coincer. Un stack overflow sur PC, ça éclabousse un peu, mais là, ça va frotter sévère !

J’ai choisi la bonne méthode…

… pour un Arduino Mega (256 ko de flash, 8 Ko de RAM) , ou un Arduino Due (512 ko de flash, 96 ko de RAM). Pour un micro contrôleur beaucoup plus petit comme l’ATTiny85, il faut revoir sa copie car la programmation objet, pour sexy élégante qu’elle soit, n’est pas vraiment indiquée vu le peu d’espace disponible.

  • L’héritage, et en particulier la surcharge de méthodes couplée au polymorphisme consomment énormément de RAM.
  • Il vaut mieux utiliser la composition et la délégation. Les classes de bases fournissent les fonctions simples et se fichent éperdument de ce qu’on en fera. La classe auparavant héritée devient une classe chargée de les coordonner et leur déléguer les fonctions de base. On utilise plus de mémoire programme en flash, mais beaucoup moins de RAM. Si j’étais « jusqu’au bout-iste », je n’utiliserais que des fonctions (au sens C), mais la programmation orientée objet en mode light a quelques petits avantages.
  • Les attributs (variables internes) des classes consomment de la RAM. Il faut donc en limiter le nombre et la taille.
  • Les paramètres passés aux méthodes (fonctions) consomment de la pile, donc de la RAM. Même punition.
  • Les appels de méthodes consomment également de la pile pour les variables locales, mais uniquement lors de l’exécution de la méthode. A la sortie, de la pile est libérée, mais les appels de méthodes en cascade (et encore plus la récursion) multiplient d’autant l’utilisation de la pile. Il faut donc limiter les profondeurs d’appels. Un maximum de trois ou quatre fonctions/méthodes en cascade est une bonne règle. Pour les fonctions très simples (une ligne ou deux), préférer utiliser des macros (#define)
  • Même si ça reste à confirmer, les « switch » occupent apparemment moins de mémoire programme si les valeurs recherchées dans les clauses « switch » sont triés par ordre croissant.
  • Les variables, attributs, fonctions et méthodes inutilisés n’occupent pas de mémoire de programme, mais complexifient le projet. Il faut rester simple.

Résumé simple de ce qui précède :

  • éviter l’héritage
  • utiliser la composition et la délégation
  • limiter au strict nécessaire l’utilisation de variables globales et de variables internes aux classes
  • limiter le nombre de paramètres passés aux fonctions/méthodes
  • limiter la profondeur d’appel des fonctions/méthodes
  • ordonner les valeurs testées dans les clauses « switch »
  • diminuer la complexité tant matérielle que logicielle – le fameux « KISS principle »

Après mise en pratique, la compilation de mon programme enrichi d’une foultitude de tests donne :

Le croquis utilise 7434 octets (90%) de l’espace de stockage de programmes. Le maximum est de 8192 octets.
Les variables globales utilisent 383 octets (74%) de mémoire dynamique, ce qui laisse 129 octets pour les variables locales. Le maximum est de 512 octets.

La RAM disponible pour la pile est maintenant de 129 octets sur les 512 que contient l’ATTiny85, toujours avec la réservation d’un bloc de 256 octets. Cela devrait suffire, même s’il faudra veiller au grain…

Les prochaines étapes

  • Décider du système qui animera le bousin. J’hésite toujours entre un Forth et un Chip-8 fortement dégraissé. Si j’étais cintré du chapeau, BrainF*, pourrait coller. Le Forth a ma préférence, mais avec un clavier 4×4, ça risque de ne pas être pratique.
  • Assembler et tester le clavier 4×4
  • Donner une fonction aux deux entrées/sorties encore libres

Mais d’abord

Un grand merci à Alex Wulff dont la « Business Card/Game Console » m’a donné plusieurs pistes pour mon projet, notamment le code de gestion de l’I2C et de l’écran OLED.

Creative Commons License

Publicités
Catégories :Arduino Étiquettes :
  1. Aucun commentaire pour l’instant.
  1. No trackbacks yet.

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :