Archives de septembre, 2014

[Tutorial] Arduino, Serial et ASCII

Publié: 18 septembre 2014 dans Tutoriaux
Tags:,

Bonjour à tous,

Aujourd’hui un petit article sur un sujet assez redondant sur le forum Arduino, à savoir l’ASCII et la différence en Serial.write() et Serial.print().

Rappels

Si vous lisez cet article c’est surement que vous débutez et il me semble indispensable pour bien comprendre la suite d’avoir de bonnes bases.

La liaison série, comme toute transmission de données, et toutes les données informatique en général, sont toujours en binaire. Quelque soit la façon dont vous remplissiez une variable, au fond du fond, dans la mémoire du microcontrôleur, ça sera toujours des 0 et des 1. Toutes les autres représentations (décimal, hexa, chaines de caractères …) ne sont que des représentation « de confort » uniquement la pour nous humains.

Pour en revenir à nos moutons, quand on transmet des informations par liaison série, on ne transmet que des 0 et des 1, soit un nombre. Dans le cas de ce type de liaison, on transmet les informations par paquet de byte ou d’octet (c’est la même chose), soit 8 bits, donc un nombre compris entre 0 et 255. Mais maintenant vous allez me dire « pourtant je peux bien faire des Serial.print(« Hello world ») ! Il sont où tes nombres ??! » J’y viens 😉

L’ASCII

Un terme que l’on maudit presque au début alors que c’est enfantin : l’ASCII c’est tout simplement une table qui pour un nombre donné, renvoi un caractère donné. Il s’agit simplement en fait de mettre d’accord des systèmes pour dire : tel nombre c’est un « A », tel nombre c’est un « z » etc … Voici la table ASCII :

Colonne CHR on retrouve les caractères disponibles, les autres colonne représente leur code ASCII sous différentes formes mathématique. Supposons que deux systèmes veuille communiquer, et que le système A veuille envoyer « Arduino » au système B. A va donc devoir envoyer 7 octets, chaque octet correspondant à une lettre, soit :

65,114,100,117,105,110,111

Quelques remarques :

– « Mais y’a que 128 nombre dans ta table ! » en effet, la table ASCII de base ne contient que 128 caractères. Il existe une table dite étendue qui en contient 255 mais qui n’est pas prise en charge par Arduino. C’est pour celà que si vous faites Serial.print(« Mesuré ») vous allez recevoir dans le moniteur série « Mesu » + un caractère bizarre car l’Arduino n’a pas la correspondance pour le « é »

– Vous noterez des choses bizarres au début de la table (jusqu’à 31). Ce sont des caractères spéciaux : il ne représente pas un caractère littéraire mais des sortes de signaux. Beaucoup ne sont quasiment plus utilisés, les 3 qui présentent une vraie utilité en Arduino sont le 0 (NULL), le 10 (Line Feed) et le 13 (Carriage Return). Les deux derniers sont automatiquement ajoutés en fin de chaîne lorsque vous faites un Serial.println(). Concrètement, lorsque que je vais faire Serial.println(« Arduino »), il sera envoyé :

65,114,100,117,105,110,111,10,13

Le LF+CR est utilisé un peu partout en programmation, il est un petit peu l’analogie du « Roger » en communication radio, signifiant la fin d’un message.

– Vous remarquerez que le chiffre 1 n’a pas le code 1 et ainsi de suite … Il y a donc une distinction entre les chiffres et les caractères de ces chiffres. C’est pour celà que dans certains codes que vous trouverez, il y aura des instructions du genre :

byte chiffre = Serial.read() – 48

Par exemple si j’ai envoyé le chiffre 8 en ASCII, soit 56, ça donne 56 – 48 = 8 => je récupère bien mon chiffre.

Vous devez donc maintenant comprendre que quelque soit la solution adoptée, il ne s’agit que d’une question d’interprétation et de représentation. Voyons maintenant comment on peut jouer avec tout ça sur Arduino.

Serial.write() Serial.print() Serial.read()

Serial.write() va envoyer ce qui est passé en argument brut de fonderie. Donc si j’écris Serial.write(48), il va effectivement envoyé 48 et de l’autre côté je recevrais donc 48. Libre à mon autre système d’interpréter cette donnée comme il l’entend, soit en regardant la correspondance dans la table ASCII et donc de comprendre que ce qu’il a reçu est le caractère « 0 », soit en prenant ce nombre comme il est, soit 48.

A l’opposé, si je fait Serial.print(48), le système va envoyé le code ASCII pour le « 4 » puis celui pour le « 8 ». Donc ici, contrairement au write() je vais d’une part envoyer deux octets au lieu d’un seul, et d’autre part je vais encoder ces caractères. Il sera donc transmis 52,56.

Je n’ai pas encore parler de la réception, car il n’y qu’une seule commande sur Arduino, c’est Serial.read(). Bizarre non ? Il devrait pourtant y avoir deux types de réception possibles puisque je peux recevoir les informations sous deux formats différents ? Alala décidément vous ne suivez rien 😀

Serial.read() lit chaque octet reçu. Mais vous voyez bien que, que ce soit avec le write() ou le print() j’ai transmis des octets. Donc pourquoi devrais-je avoir deux modes de réception ? Il s’agit tout simplement à moi programmeur de mettre en forme les données reçus comme elles me conviennent. Reprenons mes exemples :

A => Serial.write(48) => un octet valant 48 est envoyé

B option 1 => byte nombre=Serial.read() => nombre vaudra 48

B option 2 => char caractère = Serial.read() => caractère vaudra … 48 ! Oui mais étant de type char il sera reconnu en tant que caractère dans le système. Si maintenant je veux afficher ce que j’ai reçu sur un écran dont la librairie hérite de print() :

monEcran.print(nombre) => affichera « 48 »

monEcran.print(caractère) => affichera « 0 »

Autre cas, je fais Serial.write(‘8’). Les apostrophes signifient au compilateur que je veux le caractère correspondant en ASCII. Il sera donc transmis un octet valant 56.

La vérité c’est qu’on pourrait très bien se passer de print() mais qu’il rend bien service 😉 d’ailleurs je vais vous avouer un secret : print() utilise write() 😉

Et mes variables dans tout ça ?

Et bien du coup, maintenant que vous avez un peu assimilé tout ça vous devez avoir compris que du côté des variables on peut également un peu faire ce qu’on veut et qu’au final c’est toujours des 0 et des 1 et que tout n’est question que de représentation/interprétation. Concrètement, je peux déclarer la chaîne « Arduino » comme ceci :

char chaine[]= »Arduino »;

ou bien

char chaine[]={‘A’,’r’,’d’,’u’,’i’,’n’,’o’};

ou bien

char chaine[]={65,114,100,117,105,110,111};

puis faire

Serial.print(chaine);

Maintenant si je suis un peux maso :

byte chaine[]={65,114,100,117,105,110,111};

puis

for(int i=0;i<7;i++) Serial.write(chaine[i]);

Dans tous les cas, l’information transmise sera 65,114,100,117,105,110,111

Autre fonctions utiles

Quelques fonction que je ne vais pas détailler ici (une recherche google et vous saurez tout;) ) mais dont il est bon de connaitre l’existence :

atoi() => transforme une chaine en entier, donc à faire une conversion genre « 48 » en nombre 48

itoa() => transforme un entier en chaine de caractère, donc 48 en « 48 »

sprintf() => permet de construire des chaines de caractère et d’y insérer des variables (attention sur Arduino pas de prise en charge des float)

Conclusion

J’imagine qu’arriver ici vous avez peut-être un peu la tête qui tourne … Si vous ne savez pas quoi faire, posez vous deux minute et reprenez votre programme point par point : que vaut ma variable/chaine ? Comment va-t-elle être interprété ? Va elle être encodé en ASCII ? A la réception : comment je veux utiliser mes données ? Sous quelle forme ont-elles étaient envoyés ?

Vous verrez qu’en étant méthodique au début ça devient vite plus limpide 😉

[News] Débarquement sur Twitter

Publié: 12 septembre 2014 dans Non classé

Bonjour à tous,

Petite brève pour vous signaler mon débarquement sur Twitter, explications …

J’ai toujours trouvé Twitter d’une inutilité inimaginable pour le grand public, au sens Facebook du terme, genre « je viens de péter dans ma baignoire » ou « bébé a fait son premier rototo » et j’en passe … Mais il est vrai qu’il y a un domaine où Twitter a su se rendre utile pour moi, c’est pour l’information sous forme de microbloging. Hop j’ai juste une petite info à balancer, pas la peine d’en faire un article sur Rue89, et tous les téléphones ont aujourd’hui leur appli Twitter (sauf ceux qui sont restés sur 3310, mais je les envies parfois je dois avouer xD).

Pour en revenir à mon cas, je me suis aperçu que je pourrais plus faire vivre mon blog par ce biais, car faisant beaucoup de choses en même temps j’en termine pas toujours et donc les articles ne débitent pas au rythme qu’ils devraient … Au moins la je pourrais montrer des choses et avoir un meilleur échange avec mes lecteurs.

Alors j’avais un compte Twitter depuis plusieurs années qui n’avait été créer que dans le seul but d’avoir les résultats des élections avant l’heure (bon tout le monde savait le résultat à l’avance mais curiosité oblige …). Je le réveille donc aujourd’hui dans le but de mieux vous faire partager mes avancés 😉 cependant ça ne remet en cause en rien les articles « normaux » et j’espère avoir le temps d’en rédiger quelques uns bientôt !

Sur la colonne de gauche de la page d’accueil vous pouvez donc voir ma timeline Twitter et me suivre !

A bientôt 🙂