Bonjour, nous commençons aujourd'hui la programmation en C. Dans l'industrie, si on doit faire un projet, on choisit un microcontrôleur, on achète les outils de développement, et on s'investit pour terminer l'application. Avec Arduino, il y a eu tout à coup une possibilité qui concernait les amateurs, qui a eu énormément de succès. Ce succès est dû à deux raisons, d'une part, l'environnement est gratuite, et tourne sur différentes plates-formes. Et d'autre part, les trois grands fabriquants de microcontrôleurs, actuellement, supportent cet Arduino avec des appelations différentes, Pinguino pour Microchip, Energia pour Texas Instruments, avec CMSP. Le but de notre cours est de vous faire comprendre les microcontrôleurs, et de vous aider à les mettre en œuvre. Mettre en œuvre, sans avoir une pratique est difficile. Donc, nous vous encourageons à acheter, ou si vous ne les avez pas déjà , une de ces nombreuses cartes microcontrôleurs, euh, qui existent, et nous proposerons parfois, des travaux pratiques qui n'interviennent pas dans le, l'évaluation du cours, et qui vous permettront de tester des programmes que l'on a cités ou de les compléter. Bien, donc, ce que nous allons faire maintenant, c'est de comprendre la structure d'un microcontrôleur, euh, voir comment on peut gérer simplement, des entrées sorties, et surtout, apprendre à voir comment on peut gérer des entrées-sorties, et surtout apprendre à écrire les programmes correctement. Revenons à notre, euh, dessin qui montrait, euh, les plates-formes sur lesquelles les logiciels tournent. On va essentiellement s'occuper d'Arduino qui tourne sur de nombreuses cartes de type AVR, et avec Energia qui tourne sur MSP. Alors, ce que j'ai dit, c'est que l'intérêt, pour le débutant d'Arduino, est que l'on cache la complexité du processeur, on la remettra en évidence, rassurez-vous, et que l'on travaille avec des pins qui sont des sorties, ou des entrées, et on va garder la possibilité de programmer ces pins, soit en entrée, soit en sortie. Pour cela, il nous faut des instructions, et prenons tout de suite une implication pratique. Sur la pin trois, on va brancher une led avec sa résistance. Il faudra donc un zéro pour allumer la led. La flèche, ici, montre que c'est une sortie vis-à -vis du processeur. Mais le courant va devoir rentrer dans le processeur, hein, pour allumer la led. Sur la pin quatre, et bien, on va mettre un poussoir, on l'a expliqué avec sa, sa résistance pour l'amp. Et les instructions Arduino, c'est pour définir cette direction. C'est pinMode, la pin trois est en sortie, les pin quatre est à l'entrée. PinMode, c'est facile de se souvenir, c'est une instruction qui se termine par un point-virgule. Et si on veut maintenant allumer la led, et bien, on a l'instruction digitalWrite. On va écrire sur cette pin en digital. On verra une fois que on peut aussi écrire en analogique. Sur la pin trois, on met soit high, qui est en fait, l'état logique un, soit un low qui est l'état logique zéro, cinq volts, zéro volt, high, low, selon les habitudes, euh, prises par Arduino. Si on veut lire le poussoire, on doit écrire digitalRead de quatre. Alors, commençons par faire le fameux programme, euh, à Arduino, euh, clignotement, pink. En C, c'est Hello World. Ici, ça sera clignoter. On doit définir que la pin trois est en sortie. On doit ensuite répéter, écrire, attendre, écrire, attendre. La fonction qui va s'exécuter en permanence, elle s'appelle loop. L'initialisation s'appelle setup, et il faut bien remarquer cette structure du C, où on a toujours une accolade ouvrante et une accolade fermante, et parfois l'accolade est mise, ouvrante est mise, euh, au début d'une ligne, euh, ici, pour gagner un petit peu de place, euh, elle est mise à côté de l'instruction. Et toujours, on a des points-virgules à la fin des instructions. Si vous les oubliez, vous avez des messages qui peuvent être parfois un petit peu, euh, inappropriés. Alors, comme dans tout microcontrôleur, il y a une phase d'initialisation, et même dans votre PC, vous en souffrez avec tout ce temps de démarrage dans le fond de votre PC, et ensuite, on rentre dans une boucle, où le programme fait successivement ce qu'on lui a dit de faire. Alors, ceci n'est pas un programme C, c'est vraiment un programme Arduino. En C, on rentre dans le programme avec un main, et puis une fois qu'on a fini d'initialiser, et bien, c'est l'instruction while que l'on verra tout à l'heure qui permet de répéter éternellement la boucle. Bon, maintenant, si je vous montre ce programme dans une semaine, vous allez inévitablement dire, mais qu'est-ce que c'est que cette pin trois? Output, bon, et bien, ça doit être une sortie. Ça, je me souviens. Ensuite, ici, tiens, on retrouve un trois, on a l'air de mettre à zéro. À quoi ça sert? Qu'est-ce qu'on cherche à faire? On met un zéro, on met un un, on attend. De quoi s'agit-il? Alors, naturellement, vous me direz, ce programme est mal écrit, il fallait documenter, ici, ce que l'on fait. Et si on commence à mettre des é, des commentaires à chaque instruction, euh, ça va en fait, pas aider la lisibilité. Ce qui est important, c'est de dire, ici, comme première chose, la pin trois, c'est une led. Donc, on peut le déclarer avec les notations Arduino, int led égal trois. On comprendra, une fois, pourquoi je n'aime pas cette notation. Je préfère le define, qui en fait, annonce un dictionnaire. Toutes les fois que vous avez écrit led dans le programme, et bien, le compilateur va mettre trois à la place. Led espace trois, pas de point-virgule à la fin, puisque ce n'est pas une instruction. C'est vraiment une équivalence qui nous permet maintenant d'écrire led, ici, et puis d'écrire led aussi dans le digitalWrite. Et alors maintenant, et bien, pour allumer, il faut mettre un low, mais dans d'autres schémas, on a vu, on peut tourner la diode à l'envers, et pour l'allumer, il faut mettre un high. Donc, ça, si dans chaque partie du programme, il faut répéter, euh, c'est un low pour allumer, ça n'a pas de sens. Donc, on va définir, dire, et bien, ça c'est la fonction allumée, la fonction LedOn. Et je vais définir LedOn comme étant cette instruction. Ce qui me permettra, dans le programme, d'écrire très élégamment LedOn, delay, LedOff, delay. Dans un mois, vous saurez très bien ce que j'ai voulu faire avec ce programme. La prochaine chose à comprendre, c'est comment gérer une entrée. On a branché un poussoir sur la pin quatre. Donc, on va définir, pinMode, quatre, input. On a l'instruction digitalRead de quatre, mais attention, ça n'est pas une expression. Si vous dites un processeur digitalRead de quatre, il va vous répondre, OK, j'ai lu la pin quatre, j'ai lu que c'était un ou zéro, mais qu'est-ce que j'en fais? Hein? Alors, le digitalRead, vous rend une valeur qui est un, si relâché, zéro si c'est pressé, et on utilise, le plus souvent, l'instruction if pour prendre une décision si cette touche est pressée, ou relâchée. Donc, on écrira if, parenthèses, avec justement cette condition qui est vraie ou fausse. Si digitalRead de quatre est égal à zéro, et bien, la touche est pressée, et on va mettre dans une accolade, les instructions à réaliser. Pourquoi égal, égal? Et bien, là aussi, on le verra, l'égal, comme en arithmétique, c'est réservé pour l'assignation, euh, six égal deux fois trois. Ici, on a besoin d'un signe pour dire point d'interrogation, est-ce que c'est égal? Hein, ceci est une question, en fait. C'est vrai, ou c'est faux, si c'est vrai, on exécute. Alors, de nouveau, on est en train de traîner ces quatre en réfléchissant à ce pin, et il nous faut rajouter des définitions, Pous vaut quatre, mode, Pous, input. Et puis, le digitalRead de Pous, dans son égalité, qui veut dire est-ce que c'est pressé? On peut très bien lui donner un nom, en disant PousOn. Si vous voulez inventer un autre nom, vous êtes libres. Et ce qui compte, c'est que dans le programme, on ait quelque chose, ici, qui est tout à fait clair. If PousOn, on doit faire ceci. Et puis, on continue ensuite, la programmation. Alors, maintenant, et bien, comme petits exemple concrets, j'aimerais faire, allumer quand je presse sur la touche. Et bien, if PousOn, LedOn, autrement, LedOff. Alors, les instructions du C, if, else, euh, sont faciles à comprendre; on les reverra. Les accolades sont exigées comme toujours. On a la structure de la boucle. La structure du "if", la structure du "else" et les points-virgules à la fin des instructions. Le compilateur sera content et l'exécution va se faire conformément aux définitions. Alors là j'insiste vraiment parce que ici vous voyez que on a un programme qui ne dépend pas du cablage. On a fait une application, copié un poussoir sur une LED et le programme est parfaitement clair. Maintenant, pour que ce programme s'exécute sur votre petite carte où vous avez branché la LED sur la pin 3, le poussoir sur la pin 4, et bien, il faut simplement définir en langage C, le cablage que vous avez fait. Le poussoir est actif à 0, la LED est active à 0. Si maintenant vous changez, vous avez des raisons de changer ou que c'est une autre application, et bien, vous modifiez les définitions uniquement. Bien, petite question pour euh, voir si vous avez bien compris : Si j'enlève la structure "else" ici, hein, j'ai "if" Pous, Led On, et bien, qu'est-ce qu'il se passe? Ça ne change rien, la LED ne s'allume plus, la LED reste allumée? Réfléchissez pendant quelques secondes. C'est clair que les deux premières réponses sont mauvaises puisque ici on va en tout cas avoir une possibilité d'allumer. Euh, la troisième réponse est la plus proche de la vérité mais la LED va s'allumer quand on pousse, elle ne va jamais s'éteindre. Et maintenant la question c'est de savoir quel est le setup? Si le setup a éteint la LED, et bien elle va rester éteinte jusqu'à ce qu'on presse. Et ensuite, elle va s'allumer et rester éternellement allumée. C'est en fait une fonction alarme. Il faut simplement mettre dans le setup le LED off et puis ensuite, ben euh, dès que quelqu'un aura pressé sur la touche, et bien la LED va s'allumer, vous saurez que quelqu'un est venu intervenir sur cette touche. Une deuxième question similaire c'est que maintenant j'enlève uniquement le "else", je garde le "if" et puis le LedOff. Alors qu'est-ce qu'il va se passer? La LED clignote, on, off, on, off, la LED ne s'allume plus ou la LED ne s'éteint plus? Bien, ben la réponse, c'est presque la réponse A. Euh, qu'est-ce qu'il se passe, en fait? Si vous n'appuyez pas sur la touche, et bien, vous traversez ce, ce bloc d'instructions, vous eteignez la LED et vous restez avec la LED éteinte. Si maintenant, vous appuyez sur la touche, et bien, vous allumez la LED, mais vous continuez, et vous éteignez la LED. Donc, allumer, éteindre, allumer, éteindre. Et puis maintenant, est-ce que c'est du 50%? C'est là que, quand on veut vraiment faire du C et savoir ce que l'on fait, et bien, on va regarder quelles sont les, les temps d'exécution des instructions euh, pour déterminer le pourcentage d'allumé. Donc, la LED clignote si on presse sur le bouton. Autrement, elle ne s'allume pas. Analyser ce que fait le processeur est quelque chose d'extrêmement important et il faut avoir ce réflexe de se mettre dans la peau du processeur pour bien comprendre, dans le fond, l'information que vous lui donnez. Bon, maintenant, petite variante, j'aimerais allumer la LED si je n'agis pas sur le poussoir. Alors, évidemment, une solution simple, ce serait de dire : ben, je définis la fonction PousOff. Si c'est PousOff, ben j'allume. Une variante, ce serait de dire : ben, j'éteins la LED si j'agis sur le poussoir. Donc, ben, ici on changerait. Et puis, ce que j'aimerais vous montrer là , c'est que cette fonction PousOff, qui est l'inverse de PousOn, hein, si PousOff est vrai, ben PousOn est faux et réciproquement, et bien, on peut la définir avec un petit signe très pratique que l'on verra très souvent qui est le point d'exclamation, qui est la négation logique, l'"inversion" logique. On l'avait déjà vue avec le petit, le petit triangle et un petit rond. Donc, euh, je peux écrire "if! PousOn" ce qui veut dire "PousOff" et dans ce cas-là , j'allume. Donc, voilà une petite fonctionnalité supplémentaire qui nous rendra service. Bien un autre instruction fondamentale que l'on verra aussi plus tard avec plus de détails, c'est le "while" qu'il faut bien distinguer du "if". Le "while", avec une condition, touche pressée par exemple, et bien, on va faire tant que la condition est vraie. Alors "while" PousOn, et bien, tant qu'on presse, on va faire cette condition. Donc si j'écris ici "while PousOn" justement, LedOn, et bien, tant que je presse, la LED sera allumée. Et je reste bloqué ici contrairement au "if" qui allait regarder plus loin. Donc, au moment où je relache, et bien, "while" n'est pas satisfait, on sort tout de suite, LedOff, et puis on recommence. Donc on a fait la même fonction, copie dans le fond, du poussoir sur la LED mais d'une façon qui n'est pas vraiment recommandée puisqu'on va se bloquer ici, dans cette attente. Pour un programme aussi simple que ça évidemment, cela n'a pas de conséquence. Alors, si vous avez bien compris le "while", "while (condition)", si on mettait "while (1)", la condition 1, elle est toujours vraie. Hein, vrai c'est 1, on aurait peut-être pu écrire euh, "while (high)", "while euh". Et ça, ben ça veut dire faire éternellement. Donc vous allez rester, c'est justement ce que fait le, quand on écrit du C, et bien on remplace "loop" par ce "while (1)". Et puis si maintenant vous avez "while (1)" avec une accolade qui ne contient rien du tout, et bien le processeur ne fait plus rien. Ça c'est faux de dire comme ça. Le processeur, il fait toujours quelque chose hein, il passe toujours à l'instruction suivant. Simplement, ben, au niveau du code machine, et bien, ce qu'on lui a dit c'est : tu es maintenant à l'instruction 18, par exemple, et bien, va en 18, répète, aller en 18, et puis recommence, répète ne fais rien, retourne en 18, ne fais rien, retourne en 18, ne fais rien, retourne en 18, il se tourne les pouces. Et puis euh, il faudra un reset pour sortir de cette boucle. Alors dernière, avnat-dernière chose intéressante, c'est inverser l'état de la LED. Hein, on a vu comment la mettre à 1, on a vu comment la mettre à 0, Maintenant, ce que j'aimerais c'est inverser son état. Je peux très bien dire, je vais lire l'état de la LED, si c'est 0, ça veut dire qu'elle est éteinte, je vais l'allumer. Et puis autrement, je vais l'éteindre. Alors évidemment ça c'est pas très plaisant, parce que de nouveau euh, si vous lisez ça dans le programme, rien ne vous apprend que la LED allumée est allumée par un état 0. Donc, il aurait fallu définir en tout cas ÉtatLed comme étant digitalRead de Led et mieux définir est-ce que la LED est éteinte? Est-ce que la LED est éteinte? Si oui, on l'allume. Donc, "if (LedEstÉteinte)", LedOn. Et on met cette transcription du matériel dans une définition dans laquelle on a donné un nom explicite et le codage que le compilateur saura traduire dans les instructions de bas niveau du processeur. Alors, on peut encore faire plus astucieusement. C'est de dire : mais inverser ma LED, c'est écrire avec un digitalWrite, écrire dans la LED, quoi? Ce qu'on a lu sur la même pin LED, mais inversé. Donc on va copier dans la LED l'inverse de son état. Et ça va vous rappeler la bascule D qu'on avait cablée en branchant la sortie sur l'entrée. Qu'est-ce qu'on avait fait? On l'avait fait en diviseur par deux. Chaque fois, la valeur est inversée. Maintenant, ben ce qui remplace l'horloge, et bien, c'est la sélection quand cette instruction s'exécute, et bien, on va avoir cet effet. On pourrait écrire tout simplement dans le programme : LedToggle. Alors réfléchissez bien à ça, c'est effectivement une façon très élégante d'écrire du C. On peut faire plusieurs choses dans une seule instruction. C'est un peu plus difficile à décoder, mais puisqu'on va réfléchir une seule fois au niveau de la définition et qu'on pourra ensuite écrire quelque chose qui est tout à fait facile à comprendre. Et bien, c'est une bonne façon de programmer. Et maintenant je fais un petit peu plus compliqué, c'est-à -dire que j'ai noté basculer à chaque fois que je pèse sur une touche. Alors, basculer à chaque fois que je pèse sur une touche en fait, il faut que je pèse, il faut que je relache, et c'est seulement au moment où je relache que ça va s'allumer. Je pourrais imaginer l'inverse, au moment où je presse, ça s'allume, mais ensuite il faut relacher, represser pour que cela change d'état. Alors c'est des, c'est des boutons on/off que l'on voit dans plusieurs appareils qu'on peut réaliser avec un système logique et puis là on va le faire par programmation. Alors, attendre que le bouton soit pressé, ben c'est "while (!PousOn)". Tant qu'on est relâché, on reste ici dans cette ligne "while" et ce petit délai à cause des rebonds de contact, on en reparlera plus tard. On ne voulait pas vous le cacher si on ne le met pas, ça risque de mal fonctionner. Ensuite, ben une fois qu'on a pressé, ben on passe à la ligne suivante. Et on attend que ça soit relaché avec un "while". Et quand on sort ici, on inverse la LED, et puis on revient, attendre, presser, relacher, et cetera. Donc ici, la LED va changer quand on relache, si vous permettez les instructions, la LED va s'allumer quand on pèse. Donc voilà un exemple de programme qui fait bien sentir la richesse du C et la possibilité d'écrire les programmes d'une façon à la fois compacte et lisible. Donc on a vu aujourd'hui des choses très importantes : cette structure générale des programmes C, les facilités d'Arduino pour lire, écrire euh, sur un bit et la nécessité de nommer clairement la fonctionnalité que l'on, dont on a besoin pour, au niveau du programme, parler dans ce langage fontionnel et pas dans un langage qui tient compte du cablage.