15) Note sur l’élaboration du programme.

Comme j’ai été en mesure de le constater à chaque développement d’un projet, les premières séquences écrites sont boulimiques en ressource du microcontrôleur. Aussi, c’est toujours un peu dans la peur de manquer d’espace mémoire que l’on avance, ajoutant de nouvelles routines. Au début l’encombrement du code augmente fiévreusement, car chaque nouveau thème d’affichage impose de nouvelles routines. Aussi, avec un acharnement qui confine à de l’obsession on optimise, on corrige et modifie pour gagner un petit Octet ici, un autre là. Puis, et c’est ce que j’ai été en mesure de constater à chaque fois, quand le « noyau » est en place, on ajoute des options à profusion sans que le code ne diverge, car on réutilise à outrance les séquences paramétrées pour offrir une combinatoire « explosive ».
Observant le programme source, vous pourrez lire en tête de listage l’historique du développement. Vous allez constater que les thèmes n’ont pas été ajoutés « dans l’ordre ». C’est assez normal, car lorsque les séquences paramétrées étaient au point, pour éviter de lasser le « spectateur » par des thèmes semblables, les programmes d’affichages ont été éparpillés. Vous pouvez vérifier que de PGM_0() à PGM_17() (Alors que PGM_11() à PGM_16() ne sont pas encore installés) on a consommé déjà 30% de la mémoire disponible. Puis, les programmes qui suivent deviennent de moins en moins voraces. Aussi, arrivé à PGM_41() on ne dépasse pas les 51% d’occupation. La richesse des affichages est considérable puisque déjà il faut une durée significative pour enchaîner les séquences écrites. Il reste pratiquement la moitié des ressources encore disponibles alors que toutes les idées « de base » sont effectives et en place.

Comme j’ai à cœur de toujours « saturer » l’ATmega328 quand je développe un projet « sérieux », (En tant que programmeur, j’estime que ne pas employer le matériel à 100% relève un peu de la paresse.) le problème s’inverse : Comment arriver « gloutonner » tous les octets disponibles ? Pour la mémoire EEPROM c’est gagné, la totalité des 1024 octets disponibles en mémoire non volatile est utilisée par l’utilitaire Ecrire_les_Empreintes_en_EEPROM.ino et maintenant toute nouvelle image éventuelle devra résider en mémoire de programme sous forme d’un tableau. En revanche, comme les 49% d’espace disponible constituent une abondance inespérée, on peut se permettre d’abuser, c’est à dire de concevoir de nouvelles séquences sans se préoccuper exagérément de la consommation en code objet. C’est la raison pour laquelle à partir de PGM_42() on peut observer des thèmes qui à eux seuls se gavent facilement de 5% d’un coup, sans vergogne. Par exemple le thème de PGM_42() juste pour « tricoter un cube » la bagatelle de 1810 octets. Autant dire que l’on dilapide l’héritage à tout va, comme si nous ne l’avions pas gagné avec peine !
Le thème le pire, La_pluie() qui a été intégré ultérieurement dans PGM_5() est de loin celui qui se goinfre le plus d’espace mémoire réservé au programme. À lui seul il réduit notre capital de 1934 octets et représente 6% du programme objet !
Pour ce qui relève de la mémoire dynamique, même abus, plus de recherche fébrile pour gagner un ou deux octets. C’est l’avantage de toujours aborder un développement avec de l’optimalisation systématique … du coup à la fin on peut se faire plaisir dans « des délires informatiques » sans retenue.

Durée actuelle d’un cycle de visualisation.

Cycle de visualisation fait référence à un affichage en mode automatique, l’intégralité des thèmes étant parcourue dans « l’ordre croissant ». Pour évaluer la durée d’une boucle complète, la ligne série USB du Moniteur a été mise à contribution en affichant en début de boucle la valeur du compteur Millis. La liste donnée ci-dessous présente en vert la chronologie sur quatre cycles, les thèmes qui suivent n’étant pas encore programmés. Puis, dilapidant sans vergogne les octets qui restaient de disponibles dans la mémoire de programme, les thèmes colorés en bleu ciel dans le texte ont été ajoutés, avec pour chacun la nouvelle valeur de durée du cycle complet qui en résulte.
Mise en service : Millis = 3000
Après une boucle complète : Millis = 2110458 soit 2104 S pour une boucle complète. (35 minutes.)
Après une deuxième boucle : Millis = 4217090 soit 2106 S pour une boucle complète. (35 minutes.)
Après la boucle n°3 : Millis = 6327930 soit 2110 S pour une boucle complète. (35 minutes.)
Après la boucle n°4 : Millis = 8443128 soit 2115 S pour une boucle complète. (35 minutes.)
Rayons_filaires() : 42 secondes; Total = 2157 S pour une boucle complète. (36 minutes.)
Le_serpent() : 40 secondes; Total = 2197 S pour une boucle complète. (37 minutes.)
BUBULE() : 55 secondes; Total = 2252 S pour une boucle complète. (37 minutes.)
La pluie : 64 secondes; Total = 2316 S pour une boucle complète. (38 minutes.)
Sépare un cube en deux : 20 secondes soit 2336 S pour une boucle complète. (39 minutes.)
Sépare un cube en quatre : 36 secondes soit 2372 S pour une boucle complète. (39 minutes.)
Le bougeoir : 36 secondes soit 2408 S pour une boucle complète. (40 minutes.)

Bien que les informations des chapitres précédents soient déjà une aide précieuse pour celles et ceux qui désirent se plonger dans les arcanes du logiciel d’exploitation Cube_3D.ino, sans effectuer une analyse de toutes les particularités de codage éparpillées dans le code source, il me semble pertinent d’aborder quelques spécificités, dont l’agencement ou le déroulement n’est pas particulièrement élémentaire. Le traitement de matrices de points carrées ou cubiques en coordonnées cartésiennes semble assez élémentaire à première vue. Cette apparence « intuitive » est assez trompeuse, et ce d’autant plus que l’on cherche à minimiser le code objet. Tout particulièrement les rotations à 90° des plans font appel à des « chassés-croisés » assez indigestes : Voir la suite …

La suite est ici.