Alors, si vous avez répondu "not accepted", je serais assez satisfait,
puisque on a défini ici, un ss égal 200, qui est en fait sur le cercle des
nombres arithmétiques du 8 bits, le processeur ne voit que des bits et
des nombres, donc le 200 va se trouver à peu près par là; et puis,
dans cette partie-là, et bien, on a des
nombres négatifs, ça correspond en fait à moins 57.
Donc, un bon compilateur devrait vous poser la question : Est-ce
que vous avez bien compris ce que c'était un nombre signé?
Puisque ici, vous avez écrit une valeur,
qui n'est pas une valeur positive, elles sont
limitées, à 127, comme on l'a vu. Alors, en fait le
compilateur s'en fiche, et on a le choix de savoir si c'est vrai ou faux.
Alors, on doit comparer cette valeur moins
57, avec, la valeur 200. Si on représente
ça sur un axe, et bien vous avez 0, 200, et puis,
ça semblerait assez logique de dire, il y a ici jusqu'à
moins 128, et on va trouver ici le 57.
Alors là, c'est évident que 200 est
supérieur à moins 57, et qu'ils sont
différents. Alors est-ce que vraiment
le compilateur, raisonne comme moi? Je suis prudent.
Je n'ai pas lu les 600 pages des spécifications du C,
donc je vais préférer écrire un petit programme, et puis mettre
derrière cette instruction if, allumer la lettre si c'est vrai, éteindre
une lettre si c'est faux; et, je pourrais être sûr que
mon interprétation est correcte.
Donc ça c'est une technique qu'il faut toujours utiliser,
écrire des petits programmes, pour vérifier qu'on a bien compris.
Vous avez naturellement les types 16 bits et 32 bits, qui s'appellent word, int,
alors, le int est abondamment utilisé dans Arduino, parce que on ne veut
pas expliquer trop de choses, et puis, c'est le type passe partout.
En général, on travaille avec des mots qui sont relativement
courts, donc on ne voit pas la différence, entre entier positif et entier signé,
tant que le 16 bits n'est pas retouché, vous avez, les longs
qui sont signés et qu'il faut appeler unsigned
long, quand vous voulez récupérer ces derniers bits.
Et, comme petit exemple de l'utilisation assez rare du long,
vous avez, une primitive d'Arduino, ce n'est pas du
C, c'est les compilateurs Arduino et compatibles, qui ont rajouté
un petit programme, qui utilise une ressource interne du processeur,
pour calculer le temps à partir du reset. Donc au moment où vous lâchez le
processeur, vous avez la valeur 0, et ensuite, ça incrémente de 1 toutes
les millisecondes, et vous pouvez mesurer le temps écoulé.
Donc là, et bien, on utilise ça assez souvent, comme vous le faites
quand vous partez en voiture, vous
regardez l'heure du départ, vous regardez l'heure
d'arrivée, et puis, le temps de parcours qui
vous intéresse, et bien, c'est une bête différence.
Donc, il nous faudra définir dans le type long, le temps, le temps précédent,
le temps de départ, et puis on va calculer le temps écoulé, avec une soustraction.
Donc on va mémoriser le temps actuel, on a
déjà mémorisé le temps précédent, on fait la différence.
Et si maintenant, on continue le voyage, et qu'on veut de
nouveau connaître le temps, on remémorise le temps actuel dans la variable.
Alors, vous me direz, tiens, on pourrait économiser une variable,
parce que, je peux faire ma soustraction, en regardant ma montre,
plutôt que d'avoir déjà copié l'heure sur un bout de papier ou dans ma mémoire.
Donc on pourrait écrire
directement millis moins previous time, et
puis réinitialiser le nouveau temps, avec millis.
Alors, ce que j'aimerais vous faire remarquer, c'est que,
entre ces deux instructions, le temps n'est pas le même,
puisque il a fallu exécuter un certain nombre d'instructions,
pour analyser cette ligne, et commencer en analysant un certain
nombre, avant de transférer le temps. Donc, ça, ça peut être 10, 20
instructions du processeur, donc, 5, 10
microsecondes, qu'on peut considérer comme tout à fait négligeables.
Mais, attention, si vous avez autorisé les interruptions, et c'est
ça qui arrivera dans des applications intéressantes, vous pouvez avoir une
interruption qui surgit entre ces deux instructions, et, c'est
comme avec votre PC, et bien tout à coup votre
clavier est mort, parce qu'il y a les interruptions qui
font que, on ne s'occupe plus de votre programme principal.
Donc, dans ce cas-là, évidemment, si vous avez plusieurs
millisecondes, voir des secondes d'attente, ça va complètement fausser les
mesures de temps, alors qu'ici on a fait une photographie
précise à un instant, et puis, on a copié la variable.
Bien, parlons un petit peu des tableaux de variables.
Alors, une variable, on vient de le voir, on
peut la déclarer avec son point virgule à la fin,
et puis on peut lui assigner une valeur qui
sera valable au début du programme, qui peut être transformée
par la suite, puisque, si j'écris dans le programme var 2 égal 33,
et bien, j'ai réinitialisé cette variable à une nouvelle valeur.
Alors maintenant, c'est assez pratique d'avoir des tableaux de variables, de ne
pas devoir numéroter variable 1, 2, 3, alors que ça va ensemble,
donc, si on écrit tableau crochet 4, et bien, vous réservez
4 fois 16 bits signés et c'est déclaré, vous pouvez
donner des valeurs, à ces 4 modes 16 bits, et le compilateur
est assez intelligent pour compter et puis mémoriser,
que, il y a la valeur 4 ici, dans cet index, on parle
de d'indexage dans un tableau, et maintenant je peux,
en écrivant xx égal tableau crochets 2, je peux aller chercher
le deuxième élément mais souvenez-vous qu'on compte toujours en binaire
à partir de zéro, donc je vais récupérer la valeur 33.
Et puis maintenant je peux aussi assigner une valeur dans
mon tableau, écrire tableau 4 égal 15, et ce qui va
se passer là, ben, mon 4, vous remarquez qu'il est en-dehors du tableau,
le compilateur C, ne va en général rien dire du tout, il va aller mettre
dans la position mémoire suivante, la valeur
15 et va peut-être écraser une variable
que vous utilisez dans le programme et
ce sera une merveilleuse plantée, donc il n'est
pas conseillé de le faire, mais, c'est facile à surveiller.
Application pour un tableau : on veut jouer quelques notes.
Et puis on va mettre ces notes dans un tableau pour dire,
ben, si je veux un ré, ben la fréquence est de 247 hertz.
Alors en fait, ce qu'on devra programmer,
c'est une période, puisqu'il faudra attirer le haut-parleur,
la membrane du haut-parleur, la relâcher, et faire ça avec
une période que l'on peut déterminer à partir de la fréquence.
Alors devoir chaque fois calculer cette période, est absurde,
même si le temps était raisonnable, il nous faut faire un tableau, autant mettre
dans ce tableau directement les périodes, et c'est,
on a donné un nom explicite, les périodes des
notes do, ré, mi, fa, qui vont se trouver dans les
positions 0, 1, 2, 3. Donc maintenant je peux définir mon
tableau en disant, iii nombres entiers, période note, j'ai quatre notes
que j'ai calculées et puis je peux maintenant faire une boucle for puisqu'il
faudra que je répète beaucoup de fois cette
période qui dure 4 microsecondes, 4 millisecondes, pardon là
mon tableau est en microsecondes, pour avoir une note
que l'on peut entendre pendant une seconde au moins.
Donc on va faire un compteur qui va
travailler avec la demi-période, et puis pour changer l'état
du haut-parleur.
Alors de nouveau il y a deux choses qui devraient vous choquer,
le petit point-virgule, ça c'est traditionnel, et puis il y a surtout
ce 1, qui est là, alors que ce que je voudrais, c'est avoir
quelque chose, un nom explicite qui me dit de quoi il s'agit.
Donc ça c'est facile de faire un define,
et puis de dire ben, define, ré, 1, et il y a une facilité
de, d'Arduino, et du C, qui est une énumération,
le nom n'est pas essentiel, mais j'ai mon énumération
ici, j'ai donné l'équivalence entre des noms
que je comprends et des numéros d'ordre que mon
processeur va comprendre. Pourquoi est-ce que j'ai écrit doo?
Ben c'est à cause du do, do while, hein, c'est un mot
réservé par le C, et vous le voyez à l'éditeur il est
coloré alors que les noms que vous définissez vous-mêmes ne sont pas
colorés, donc si vous définissez, si vous mettez do là-dedans vous aurez
un message d'erreur naturel.
Bien, autre application qui est souvent documentée sur internet, vous voulez
allumer un affichage, set seg1, c'est le nom habituel de ces
segments, et là vous trouvez comme exemple de programmation, il faut
commencer par dire que les pins sur lesquels le processeur est câblé
sont sortis, alors les pins 2, 3, 4, jusqu'à
9 dans l'ordre sont utilisés et sont programmés en sortie.
Et puis là, je ne me souviens plus du commentaire qu'il y avait avant mais je
devine que le a est câblé sur la pin 2, le b sur la pin 3,
ça semblerait assez logique, et évidemment, je préfèrerais que ça
soit documenté un petit peu mieux, qu'on dise
define segment a sur la pin 2, segment
b sur la pin 3, comme ça on
sait exactement ce qui a été câblé, et maintenant
puisqu'on vient de parler des tableaux de données,
ben, là ça me fait vraiment penser à
un tableau, et puis je vais le définir,
en disant, c'est mes numéros de pins, segment a,
segment b, segment 3, donc j'ai défini ici 2, 3, 4, mais je
reconnais de quoi il s'agit, heu, ça me fait un tableau de
7, et puis maintenent, je peux écrire une boucle
for, en disant je pars avec i égal zéro, et j'écris
pinMode, pin de zéro, OUTPUT,pin de zëro ça veut dire
que je vais chercher dans ce tableau le segment
a, qui a été défini comme étant pin numéro 2,
donc j'exécute exactement cette instruction
avec pinMode, pin crochets zéro,
OUTPUT, et puis évidemment avec la boucle for je prends 1, je prends
2, je prends 3, l'ordre, les numéros de pins n'ont pas du tout besoin
d'être dans un ordre croissant, j'ai défini
ici les pins qui peuvent être absolument quelconques.
Donc voilà une écriture qui est beaucoup plus élégante, et, on peut aller plus
loin, parce que j'ai défini mes pins, je peux définir
le digit 7 comme étant un tableau.
Dans ce tableau, j'ai a, b, c, qui sont actifs,
allumés, ça ne veut pas dire que je vais mettre un 5
volts ou un 0 volt, c'est à un autre niveau qu'on
réfléchira à ça, et puis ensuite là des segments qui sont éteints.
Et puis maintenent,
ben, pour allumer ce digit, je peux faire une petite boucle
for, où au lieu de faire du pinMode comme tout à l'heure, et bien je vais faire un
digitalWrite, pour dire ben, dans la pin numéro zéro, par
exemple, je vais mettre l'état du segment zéro.
Donc on retrouve le i ici, mais une fois dans un tableau
une fois dans l'autre.
Alors maintenant, ben, accrochez vos ceintures!
Parce que je vais définir un tableau bidimentionnel.
J'ai 10 digits à représenter, et dans chaque
digit j'ai 8 bits. Donc voilà mon tableau, vous reconnaissez
le 7, il est là, là je le définis comme un seul élément, mais maintenant
je peux l'indexer, et puis je pourrai venir avec
un programme adéquat, sélectionner le 7, qui sera une
variable qui vaut 7, et puis balayer pour afficher.
Donc là, ben, j'ai fait un petit programme pour afficher les chiffres dans l'ordre,
for, ça ça sera, le compteur de chiffres,
on termine par un delay d'une seconde comme ça
ben on verra 0, 1, 2, 3, affichés pendant une seconde, et puis
on a une deuxième for boucle à l'intérieur qui va
balayer les segments ici pour les mettre
à 1 ou à 0, ça c'est le digitalWrite qui agit sur des bits, il y
a d'autres façons d'agir sur des bits, on
les verra, qui sont compatibles avec le C, ça
c'est compatible avec Arduino, mais ça nous donne une
écriture assez élégante dans le fond où on va
balayer la bonne ligne du tableau, et étant donné
qu'on a une deuxième boucle for et bien on
va afficher tous les chiffres successifs, heu, il y
a apparamment une petite erreur, qui est, vous reconnaissez,
c'est qu'ici j'ai oublié qu'il y avait 10 chiffres, de 0 jusqu'à
9, donc il faut que je mettes un 10 ici, je reviens sur cette table, qui permet
d'afficher les, les digits, les chiffres de 0 à 9.
Vous n'avez peut-être pas réalisé que, cette séquence de
1 et de 0, ce ne sont pas des bits,
mais ce sont des bytes, des mots de 8 bits.
Donc cette table prend 8 fois 10 positions
en mémoire, 80 bytes, et si sans réfléchir, vous évcrivez
int ici, et bien vous aurez 160 bytes utilisés en
mémoire. Donc c'est clair que, on va éviter de
programmer comme cela, on verra comment, supprimer en fait les virgules,
supprimer un seul mot de 8 bits pour chaque digit, appliquer ces bits
directement sur les segments, et être beaucoup plus efficaces.
Alors encore une chose : en écrivant byte digit, ou int
digit, vous réservez de la place en mémoire.
En mémoire variable. Si vous précisez const,
et bien vous allez définir des constantes
et c'est clair qu'on ne va pas s'amuser à modifier des segments
pendant l'exécution, donc en écrivant const, cette
information va passer dans l'espace programme, qui a dix
fois plus de place que l'espace des variables, et c'est la façon la
plus efficace de procéder, déclarer const toutes
les fois que vous avez des constantes.
Donc vous voyez que, le C permet des écritures qui sont, heu tout à fait
compactes et intéressantes, et puis c'est ce que l'on va continuer
à découvrir en interagissant avec différents types de matériel.