Bonjour, nous allons parler de la mise au point de vos programmes, et je suppose que vous êtes un utilisateur plutôt débutant, et que vous utilisez Arduino ou Energia. Les professionnels utilisent des outils beaucoup plus complexes, qui incluent, des dévermineurs, ils se popularisent et on en verra un dans la prochaine séquence. Ce qu'il faut de toute façon, c'est savoir structurer les programmes, comprendre les messages d'erreurs, imaginer des solutions pour, observer le programme, et ne pas trop perturber son exécution en temps réel dans certaines applications. Votre programme a une structure schématisée ici, il faut naturellement commencer par mettre un nom, une date, pour que s'il est imprimé, vous retrouviez sur quel dossier il va se trouver. Ensuite, vous avez la description du matériel avec des includes, c'est très important de choisir des noms explicites, on l'a vu, et d'initialiser complètement le matériel. Ceci se fera dans le set up. Et maintenant, les fonctions utilisées dans le programme, certaines sont appelées dans le set-up, pour initialiser, et on les retrouve évidemment, dans la boucle de programmation. Et ces fonctions, naturellement, très souvent, appellent des fonctions de plus bas niveau, qui se réfèrent au matériel. Ce qui est important, c'est de progresser par petits pas, de bien tester le matériel et les définitions et les fonctions indépendamment. C'est aussi important de garder les anciennes versions, avec des nombres, ou une chronologie; très souvent, on perd tout à coup les pédales, en disant mais pourquoi est-ce que ça marche plus, j'ai fait un tout petit pas de rien du tout, est-ce que c'est le matériel qui s'est dégradé? Donc là , c'est très utile de pouvoir remonter, prendre une version précédente, re-tester des routines de base du matériel, et reprendre confiance progressivement, pour trouver l'erreur dans la dernière version. Les erreurs de compilation, c'est souvent assez surprenant, vous oubliez un point virgule, vous pouvez avoir un message relativement clair, l'instruction suivante est "delay"; mais, si vous trouvez un "63 cannot be used as a function" il y a pas de 63 dans votre programme, et ce qu'il faut remarquer c'est qu'il y a par contre, un mot binaire, dont la valeur est 63, où le point-virgule a été oublié à la fin, et voilà comment a réagi le compilateur. Une virgule oubliée, peut effectivement, on peut comprendre que il manquait des arguments, mais on se pose vraiment la question quand, tout à coup, il y a des destructeurs, qui ne sont pas apparus dans votre programme. Les typos, le plus fréquemment, c'est les erreurs de minuscules, majuscules, qui font que le symbole n'est pas déclaré, toutes les fois que vous avez un symbole qui n'est pas reconnu par le compilateur, hé bien il va vous sortir ce message. Bien, le plus grave, c'est quand vous avez des erreurs qui n'ont pas été reconnues par le compilateur. Hé bien la plus fréquente, c'est quand vous écrivez une condition, c'est d'oublier le double signe égal, pour le compilateur, ceci est une expression qui a une valeur, ça a la valeur 0, donc le if sera toujours faux ici, quelle que soit la valeur de aa, évidemment que ça risque de faire dévier votre programme. Ensuite, quand vous écrivez une valeur comme 78, vous avez fortement tendance à vous dire que c'est un nombre décimal et puis oublier de marquer le 0x devant, qui va évidemment pas du tout donner la même valeur numérique. Les parenthèses manquantes, c'est clair que si vous écrivez a plus 1, décalé de 2, est-ce que que c'est a plus 1, prenons l'exemple où a vaut 3, hé bien ça, ça ferait 4, décalé de 2, ça ferait 16, 4, 8, 16. Alors que si vous mettez la parenthèse différemment, a plus 1 décalé de 2, 1 décalé de 2, hé bien, ça fait 4, on avait décidé que c'était 3, ici, vous aurez la valeur 7. Alors, ce que fait le compilateur, par défaut, il a des règles de priorité, le plus simple, hé bien, c'est de respecter la bonne solution, et puis vous pouvez vérifier, avec un petit programme de test, ce qui est fait. Un peu plus délicat des fois, c'est les types incorrects. Il y a des conversions de types que l'on vous a pas expliquées, il y a le volatile, qu'on a mentionné, il y a le statique, qu'on a mal expliqué, donc là , il y a en fait, tout un niveau, du langage C, que un professionnel a besoin, et puis que l'on a partiellement pas eu le temps de bien expliquer. Maintenant, votre compilation est correcte, électriquement, vous pouvez avoir des problèmes sur les pattes d'entrées-sorties, vous devez avoir des 0, qui sont inférieurs à un volt, des 1 qui sont supérieurs à trois volts. Il peut arriver que vous ayez un mauvais niveau parce que vous avez trop demandé de courant sur une sortie et si vous demandez du courant, la tension va naturellement monter, si c'est un court-circuit, là , c'est clair que c'est catastrophique. Un état flottant peut prendre toutes les valeurs entre 0 et 5 volts, vous vous souvenez, si vous touchez avec le doigt, hé bien, ça va prendre la tension du doigt, heureusement avec des diodes de protection, qui fait que si vous êtes légèrement électrostatique, ça restera dans le domaine de 0 à 5 volts. Les signaux peuvent être pulsés, là c'est plus difficile de les observer avec un voltmètre, mais avec un crayon logique, une "logic probe" qui vous offre la possibilité d'avoir une diode rouge, une diode verte pour montrer les signaux logiques, et une logique, qui va convertir les impulsions brèves, en impulsions plus longues visibles sur ces diodes, vous avez un bon moyen d'observation des signaux. L'idéal évidemment, c'est l'oscilloscope, qui vous montrera, à la fois les niveaux analogiques et les impulsions. Vous avez l'impression que vous avez un comportement critique dans votre système? La règle que j'applique, c'est de modifier la tension. Si effectivement, dû à des mauvais niveaux, dû à différentes conditions, à des retards par exemple, le comportement ne semble pas être parfaitement répétitif, ou pas identique d'une copie du programme, dans un autre système, vous modifiez la tension, et tous les circuits doivent être très tolérants à la tension actuellement, ça doit fonctionner, si c'est garanti 5 volts, ça doit en tout cas fonctionner de 4 à 5 volts et demi. Bien, vous avez quand même un problème maintenant avec votre programme, et une solution, c'est d'enlever des parties de programme, en se disant, hé bien, peut-être que l'erreur est dans cette partie, alors vous avez une facilité d'Arduino, que vous trouvez dans le menu édition, qui est de commenter, décommenter. Donc ici, dans cette période, hé bien on avait, supprimé, commenté une partie du programme, et puis maintenant, en re-cliquant sur le même index, hé bien, on va décommenter et faire repartir cette partie. C'est évidemment un petit peu dangereux parfois, puisque si une variable est utilisée ou déclarée dans cette partie, ça peut perturber le reste du programme. Mais dans beaucoup de cas, enfin il faut connaitre le truc. Les professionnels, utilisent dans leurs programmes très complexes, une possibilité d'insertion conditionnelle, qui est très pratique, si vous voulez avoir, un seul programme qui en fait, agit sur deux environnements différents, et puis qui sont légèrement différents, vous avez deux types de capteurs, hé bien, votre programme avec un if, dièse if, en fait, va dire ce qu'on garde comme instruction, dans un cas, ou dans l'autre. Alors, il y a l'instruction dièse define Debug, et puis, ici, hé bien pour un petit programme de test, j'ai un ifdef Debug. Donc, si Debug a été défini, les instructions entre le ifdef, et le endif, vont être exécutées. Alors, voilà le genre de petit programme de test qu'il vous faut toujours faire, pour vérifier que vous avez bien compris quel est le rôle du Debug, et puis maintenant, si je supprime cette ligne, c'est ce que demande cette syntaxe, hé bien, je vais supprimer l'exécution de ces instructions, qui se font seulement quand Debug est défini. Alors il y a pas de point virgule, c'est un pré-processeur qui va gérer le programme avant de l'envoyer au compilateur, et il va simplement envoyer les instructions qui ont été définies avec des dièse if. Une solution de dépannage, c'est de dire, j'ai ma fonction qui semble pas donner les bons résultats, est-ce que c'est la faute de la fonction, ou bien est-ce que c'est la faute de l'utilisation de ces résultats plus loin? Alors si vous simplifiez cette fonction pour simplement qu'elle rende la valeur connue, vous pouvez vérifier que la suite du programme travaille correctement avec cette valeur, et puis, vérifier des conditions limites, est-ce que c'est un 0, est-ce que c'est maximum? Donc, c'est un bon moyen de certifier, en quelque sorte, les programmes. Et maintenant, une fois que vous avez focalisé, sur l'erreur, sur le fait qu'il y a une erreur dans cette fonction, vous pouvez la tester séparément, ou l'analyser un petit peu mieux. Quand vous avez les affichages balayés comme on avait vu, l'affichage à quatre digits, augmenter les délais, c'est clair, permet de bien voir ce qui se passe, successivement, sur chaque digit. On peut aussi, à un endroit critique du programme, allumer une LED, et puis on sait que si cette LED est allumée et éteinte, hé bien, le programme a passé par là . Plus riche, mais qui va alors, bloquer l'exécution, c'est d'observer les variables, grâce au Serial print, et vous pouvez faire une fonction StopHex, qui va prendre le paramètre que vous avez déclaré, et puis imprimer valeur Hexa, print l, et valeur hexadécimale. C'est très important, quand vous voyez une valeur, de bien savoir si elle est décimale ou hexadécimale. Et ensuite vous bloquez le programme, et puis il faudra le recompiler, en ayant repéré l'erreur. Alors, le Serial print est relativement lent, vous pouvez utiliser du SPI, plus rapide, mais c'est moins confortable. Si vous voulez maintenant observer et continuer, alors, vous pouvez, par exemple, prévoir deux paramètres, et faire en sorte que quand vous appelez cet affichage de la variable, d'avoir un numéro de référence, une variable qui n'est pas toujours la même, et vous allez voir maintenant, en ayant pressé chaque fois, ou en ayant fait un delay, mais ça peut être assez pratique d'aller pas à pas, d'un point d'observation au suivant, et, dans le fond, c'est ce que font les dévermineurs, simplement, ils vous offrent une possibilité d'interaction avec toutes vos variables, beaucoup plus complète, et aussi, une plus grande facilité d'enlever ces, ces points d'arrêt dans le programme. Maintenant, si vous avez des problèmes de temps réel, et que vous ne pouvez pas arrêter l'exécution, une solution c'est d'afficher, sur une LED, et si vous utilisez un digitalWrite, ça va ralentir votre programme de 2 microsecondes. Donc c'est nettement mieux d'utiliser un bitSet, bitClear, qui va prendre deux cycles d'instructions, moins de 0,1 microseconde. Vous pouvez aussi, comme on l'a vu, faire un ou exclusif avec un masque qui est un Bit 1, position 5, et pas 4. Evidemment que si maintenant, vous avez un oscilloscope, ça vous permet de visualiser des bits qui ont été activés, désactivés, ça vous permet de mesurer des durées de routines, et, vous pouvez perturber, dans le fond, le moins possible, les activités du programme. Si vous avez, par exemple, un programme qui reçoit un signal infrarouge, c'est clair que vous pouvez pas l'arrêter, mais vous pouvez par exemple, allumer une LED au début d'un bloc d'informations reçues, l'éteindre à la fin, vous pouvez l'allumer, seulement si ce bloc d'informations correspond à une adresse qui a été décodée correctement, et cetera. Donc, ce qu'on a vu, pour aider à la mise au point, c'est qu'il faut bien documenter les programmes évidemment, c'est qu'il faut connaitre quelques trucs, pour mieux interpréter les messages d'erreur et intervenir dans le programme pour le faire avancer pas à pas, et vérifier que son évolution est correcte, jusqu'à ce qu'il marche entièrement. Et puis maintenant, la grande question, c'est de savoir est-ce que ça vaut la peine d'utiliser un dévermineur, ça implique d'avoir un outil plus compliqué à mettre en oeuvre, déclarer des projets. Surtout, ce que j'aimerais que vous réalisiez, c'est que ces programmes sont compatibles avec du C, et ne reconnaissent pas les instructions Arduino. Donc, un compilateur Arduino, qui permettrait d'appeler des fonctions de débuggage, n'existe pas encore à ma connaissance, et si maintenant, vous évoluez une fois, vers un outil plus performant, ce qui certainement arrivera, hé bien, vous avez tout avantage dès maintenant, à éviter, dans le programme principal, d'utiliser des facilités Arduino, que par contre, rendent service au niveau des définitions, déclarations, où là , la transformation du programme sera beaucoup plus localisée et facile à faire.