• 20 hours
  • Medium

Free online content available in this course.

Certificate of achievement available at the end this course

Got it!

Last updated on 7/13/17

Codez et décodez des informations

Log in or subscribe for free to enjoy all this course has to offer!

Le chapitre précédent vous a montré comment fonctionne l'échange d'information par code de caractères.

Les chaînes de caractères ont la possibilité de transporter non seulement des mots qui ont du sens pour les humains, mais aussi des instructions et des données. Car si l'on peut envoyer des lettres (codées grâce à des chiffres) on peut donc tout à fait envoyer des nombres et des instructions.

Vous allez donc dans ce chapitre apprendre à créer un code pour échanger avec votre Arduino.

Vous allez aussi programmer votre Arduino pour qu'il décode vos instructions.

Vous découvrirez l'objet  String qui vous facilitera la vie pour manipuler des chaînes de caractères.

Enfin vous concevrez un programme qui pilote des LED grâce aux instructions que vous enverrez par le moniteur.

Alors, commençons par cette notion de code...

Créez un code

Imaginons que vous souhaitiez donner un ordre à votre Arduino. Vous avez réalisé un montage avec 5 LED et vous voulez qu'il allume sur commande celle que vous désirez.

Si vous écrivez dans le moniteur "Allume la LED numéro 3", il risque de ne rien se passer. Ben oui, puisque vous n'avez pas dit à votre Arduino de lire ce qui vient du moniteur.

Imaginons que vous réparez ce problème et que vous envoyiez le même message. Il ne se passera rien de plus !

(Non Lukas, même si on rajoute "s'il te plaît")

En effet, les mots ne veulent rien dire pour votre Arduino. Je vous rappelle que ce ne sont que des successions de codes numériques.

Il va donc falloir apprendre à votre Arduino à décoder cette phrase !

C'est là qu'il faut réfléchir. Car si vous souhaitez un programme assez complet vous risquez d'avoir des instructions du genre : "Allume la LED 5", "Éteins la LED 3 et la LED 5", "Fais clignoter la LED 2 et la LED 4"...

Ce sont des phrases adaptées au langage humain, mais pas adaptées à votre Arduino. Il faut simplifier tout ça !

Choisir des mots-clés

Nous allons donc d'abord réfléchir aux instructions que nous voulons créer.

  • Allumer,

  • Éteindre,

  • Clignoter.

C'est déjà pas mal. On peut tout à fait simplifier ces ordres avec trois lettres : a (allumer), e (éteindre) et c (clignoter).

Il nous faut maintenant des paramètres, c'est-à-dire des informations précises sur ce que l'on veut faire. Dans notre cas, il serait intéressant de pouvoir choisir quelle LED s'allume, quelle LED clignote et quelle LED s'éteint.

On peut imaginer un code du genre "c2" qui voudrait dire "fait clignoter la LED 2"

Éventuellement, on peut ajouter un truc du genre " c23" qui voudrait dire "fait clignoter la diode 2 et 3". C'est tout à fait possible, et on est dans un échange d'information assez simple.

Enfin on peut imaginer plus compliqué : un code comme "c23e4a15" qui voudrait dire " fait clignoter la LED 2 et la LED 3, éteins la LED 4 et allume la LED 1 et la LED 5".

En réfléchissant ainsi, nous venons de créer un code qui pourra être envoyé à l'Arduino. On imagine déjà un peu une sorte de boucle qui va lire chaque caractère du code et qui va ensuite agir en fonction de la demande. Mais en même temps qu'on imagine, on se pose quand même quelques questions :

  • Comment stocker l'information de l'ordre (allumer, éteindre, clignoter) pendant qu'on lit les numéros de diodes ?

  • Comment passer d'un ordre à un autre ?

  • Comment gérer les clignotements des diodes ?

Et là encore, il faut réfléchir. Et la ruse est là ! Il ne faut pas tout de suite réfléchir pour résoudre ces questions. Il faut avant réfléchir pour savoir si notre code ne peut pas être amélioré. Une idée ?

(Oui Cunégonde ! Ça me paraît bien plus simple !)

Plutôt que de coder des instructions, on va coder directement l'état des diodes ! Ce qui donne un code du genre :

"accea" qui correspondrait à notre "c23e4a15". La première lettre correspond à l'état de la première diode. La seconde lettre à l'état de la seconde... c'est un code par position. On garde l'idée des lettres, mais on simplifie le message.

Pourquoi toute cette démonstration ?

Tout simplement pour vous montrer qu'il n'y a pas qu'une façon de coder des données. Je dirais que le bon code est celui qui va vous servir le mieux. Il existe des standards de codage de données, nous en verrons quelques un plus loin dans ce cours. Mais ils sont fait pour des machines puissantes, et pour un nombre d'instruction important.

Dans notre cas (faire s'allumer, s'éteindre ou clignoter des LED sur commande) ces codages complexes n'ont pas d'intérêt (à part celui de s'entraîner à les manipuler).

Nous avons donc maintenant notre système de codage, voyons ce que l'Arduino peut en faire !

Décodez un train d'informations

L'Arduino va recevoir ce code par le port série (port USB dans notre cas). La fonction  Serial.available()  va lui indiquer que des données sont en attente.

Il va pouvoir lire ces données pour les utiliser. Mais il faut faire attention à ne pas tomber dans certains pièges...

Décodez la bonne quantité d'informations

Imaginons que par mégarde, nous ayons envoyé le code deux fois (pas simple avec le moniteur, mais ça pourra arriver dans d'autres cas), ou que le code envoyé n'aie pas été complètement capté. Il nous faut prévoir un moyen de vérifier que notre carte Arduino a bien reçu le bon code.

La première chose à faire est de demander à la carte Arduino de lire uniquement les informations dont elle a besoin, soit 5 lettres dans notre cas. Le reste éventuel, on ne l'utilisera pas dans notre programme (on le lira pour vider la mémoire d'attente, mais on ne le stockera pas).

On peut ensuite prévoir un moyen de vérifier que les données envoyées ont bien été reçues. Un moyen simple est de définir une valeur pour chaque instruction, d'en faire la somme et de vérifier que cette somme correspond à celle envoyée.

Exemple : si a vaut 1, e vaut 2 et c vaut 4. Le code "accea" vaudrait 1+4+4+2+1=12. Si nous assignons ces chiffres à ces lettres dans notre code, il suffira de vérifier que le code reçu par l’Arduino vaut bien 12.

Dans notre cas, nous allons décider ne ne pas créer de vérification, car les conséquences d'une erreur restent sans importance. Plus l'erreur est grave de conséquence, plus il est important de vérifier l'intégrité des données échangées. Par exemple, dans le cadre d'un échange d'une clé électronique d'accès, il est primordial de vérifier que la réception correspond à l'envoi (avant de vérifier si la clé est correcte).

 

Voyons donc le programme qui reçoit les données du moniteur série et les transforme en code de vérification :

char reception[5]; //tableau pour la réception des données (5 valeurs)

void setup() {
  Serial.begin(9600); //on initialise la communication série
}

void loop() {
  while (Serial.available()) { //tant que des données sont en attente
    for (int p=0;p<5;p++){ //on en lit 5
      char c=Serial.read(); // lecture
      reception[p]=c; //écriture dans le tableau
      delay(10); //petite attente
    }
    while (Serial.available()) //s'il reste des données
      Serial.read(); //on les lit sans les stocker
    decodage(reception); // on appelle la fonction de décodage
  }
}

//fonction pour décoder la réception
void decodage(char c[5]){
  for (int p=0;p<5;p++){ //on parcourt le tableau
    Serial.print("LED "); //on écrit le mot LED
    Serial.print(p+1); //on écrit le numéro de la LED (position dans taleau +1)
    Serial.print(" "); //on fait un espace
    if (c[p]=='a') // on teste si le code est 'a'
      Serial.println("allumee"); //si oui on écrit "allumee"
    else if (c[p]=='e') // sinon on teste si le code est 'e'
      Serial.println("eteinte"); //si oui on écrit "éteinte"
    else if (c[p]=='c') //sinon on teste si le code est 'c'
      Serial.println("clignote"); //si oui on écrit "clignote'"
    else //sinon c'est que ça ne correspond à rien
      Serial.println("erreur de code"); // on inscrit donc "erreur de code"
  }
}

Vous remarquerez que dans la définition de la fonction, j'indique que l'on attend en paramètre un tableau de taille 5 contenant des variables de type  char .

L'objet String

L'objet  String (chaîne de caractères) est un objet existant par défaut dans la boîte à outils de l’IDE d’Arduino. Il permet de manipuler les chaînes de caractères de façon plus naturelle et intuitive, sans forcément entrer dans les détails de la manipulation de chaîne comme nous l'avons vu précédemment.

En gros, avec un tableau de caractères, vous devez vous-même créer toutes les fonctions dont vous avez besoin (mise en majuscule ou en minuscule, tri des lettres, remplacement d'une lettre...)

Mais avec  un objet  String, vous créez une chaîne de caractères (elle est contenue dans l'objet), mais vous lui attachez aussi toutes les fonctions pour la manipuler (car elles font partie de l'objet). C'est tout le principe des langages "objets" (comme par exemple  objectiveC, C++, Java...). Du coup, pas besoin de créer des fonctions, il suffit d'utiliser celles de l'objet.

Donc, chaque objet String, contient sa chaîne de caractères et les fonctions pour la manipuler.

Voici la page du site officiel de l'Arduino qui traite de l'objet String. Nous ne verrons pas ici toutes ses possibilités, donc n'hésitez pas à y jeter un œil !

Alors pour pouvoir utiliser les fonctionnalités de l'objet  String, nous devons tout d'abord en créer un. On utilise la même méthode que pour déclarer un type de variable mais dans le cas d'un objet, on appelle cela un constructeur (on construit un objet de la famille  String en lui donnant une personnalité en quelque sorte) :

String maChaine="Ceci est une chaîne de caractères";

On peut ajouter deux chaînes ensembles pour créer une nouvelle chaîne :

String longueChaine=String(maChaine + " avec une phrase ajoutée !");

On remarque que le fait d'écrire  String(quelqueChose);  transforme le "quelqueChose" en format  String. On peut donc transformer un nombre (ou le résultat d'une lecture sur un pin analogique) en objet  String. Par exemple, dans l'instruction :

String chaineNombre=String(123); la variable  chaineNombre contiendra un tableau de 4 caractères : '1', '2', '3' et '\0'.

Mais l'intérêt de l'objet  String ne s'arrête pas là ! On peut, grâce à lui manipuler les chaînes plus facilement !

Il existe tout plein de petites fonctions utiles pour nos besoins de décodage dont voici quelques exemples avec ce programme commenté :

void setup() {
  Serial.begin(9600);
  //on crée une chaîne avec des espaces, des majuscules et des minuscules
  String maChaine="  Bonjour le monde Actuel !     \n\r";
  String resultat=""; //on crée une chaîne qui va contenir les résultats
  Serial.println(); //saute une ligne
  
  resultat=maChaine;//copie maChaine dans resultat
  resultat.toLowerCase(); //fonction qui passe tout en minuscules
  Serial.println(resultat); //affiche le résultat

  resultat=maChaine;//copie maChaine dans resultat
  resultat.toUpperCase(); //fonction qui passe tout en majuscules
  Serial.println(resultat); //affiche le résultat

  resultat=maChaine; //copie maChaine dans resultat
  resultat.trim(); //fonction qui enlève tous les espaces superflus en début et fin de chaîne(caractères 9, 10,11, 12, 13 et 32)
  Serial.println(resultat);

  int taille=maChaine.length(); //fonction qui renvoie le nombre de caractères de la chaîne dans l'objet String
  Serial.println(taille);
  
}

void loop() {
}

Les 4 fonctions présentées dans ce code,  toLowerCase() ,  toUpperCase() ,  trim()  et  length() , sont très utiles pour "nettoyer" une chaîne reçue par l'Arduino. En effet, si l'utilisateur envoie des espaces inutiles en début ou fin de chaîne, s'il est en majuscules alors qu'on souhaite des minuscules (ou l'inverse) ou tout simplement si l'on souhaite effectuer une boucle sur la longueur de la chaîne, avec ces fonctions, on peut réaliser ce qui nous convient.

Il y a trois autres fonctions à connaître qui sont utiles pour analyser un train d'informations :

  • maChaine.startsWith("exemple");  qui teste si l'objet  String commence par les caractères de la chaîne entre parenthèses (ici "exemple") et renvoie 1 si oui et 0 si non.

  • maChaine.endsWith("exemple");  qui teste si l'objet  String se termine par les caractères de la chaîne entre parenthèses.

  • maChaine.substring(début,fin);  qui renvoie la chaîne de caractères (en objet  String) qui se trouve entre la position "début" et "fin" de la chaîne. "fin" peut être omis, dans ce cas, la fonction renvoie tout le reste de la chaîne depuis la position "début".

Avec toutes ces fonctions, nous avons largement de quoi analyser une chaîne complexe pour créer les actions voulues. Nous le verrons d'ailleurs dans le chapitre sur l'Arduino connecté au réseau. Pour le moment, revenons à notre programme de clignotement !

Voici comment utiliser l'objet String pour analyser notre code sur 5 caractères :

String reception = ""; //création de l'objet String reception

void setup() {
  Serial.begin(9600); //on initialise la communication série
}

void loop() {
  if (Serial.available()) {
    while (Serial.available()) { //tant que des données sont en attente
      char c = Serial.read(); // l’Arduino lit le caractère
      reception += String(c); //et l’ajoute à l’objet reception
      delay(10); //petite attente
    }
    reception.trim(); //on enlève le superflu en début et fin de chaine
    reception = reception.substring(0, 5); // ne prend que les caractère de 0 à 4 (soit 5 caractères)
    decodage(reception); // on appelle la fonction de décodage
    reception = "";
  }
}
//fonction pour décoder la réception
void decodage(String s) {
  Serial.println("* Etat des LED *");//titre
  for (int p = 0; p < 5; p++) { //on parcourt le tableau
    Serial.print("LED "); //on écrit le mot LED
    Serial.print(p + 1); //on écrit le numéro de la LED (position dans taleau +1)
    Serial.print(" "); //on fait un espace
    // on utilise la fonction switch qui fonctionne aussi avec des caractères (puisque ce sont des nombres !)
    switch (s.charAt(p)) { // fonction string.charAt(pos) renvoie le caractère à la position "pos" de l'objet String
      case 'a':// on teste si le code est 'a'
        Serial.println("allumee"); //si oui on écrit "allumee"
        break;
      case 'e': // sinon on teste si le code est 'e'
        Serial.println("eteinte"); //si oui on écrit "éteinte"
        break;
      case 'c': //sinon on teste si le code est 'c'
        Serial.println("clignote"); //si oui on écrit "clignote'"
        break;
      default://sinon c'est que ça ne correspond à rien
        Serial.println("erreur de code"); // on inscrit donc "erreur de code"
    }
  }
  Serial.println();// saut de ligne
}

J'ai utilisé la fonction switch que nous avions vue dans le cours d'initiation (pour vous la remettre un peu en mémoire). Elle fonctionne ici aussi car le caractère 'a' est en fait un nombre entier. 

Vous remarquerez dans le  switch()une nouvelle fonction de l'objet String :  maChaine.charAt(p);  qui renvoie le caractère (type char) situé à la position  p  de la chaîne de l'objet String  maChaine.

Bon, nous avons tout ce qu'il faut maintenant. Voyons comment finir ce programme de pilotage de LED.

Pilotez des LED avec un programme de codage/décodage

Nous savons récupérer les informations du moniteur et les trier pour utilisation. Bien. Mais il nous faut maintenant réfléchir à une structure correcte pour notre programme. Faisons donc un petit point :

  • Le montage des LED ne pose pas de problème particulier. Il nous faudra juste correctement repérer chaque pin.

  • Allumer ou éteindre une LED n'est pas compliqué.

  • Faire clignoter une LED et pas les autres va nous demander de ruser un peu. Il va nous falloir utiliser la gestion du temps (en créant des timers simples). Pour débuter, le temps de clignotement sera identique pour chaque LED.

Le montage

Vous êtes normalement rodés pour monter 5 LED en ligne avec les résistances qui vont bien (on prendra du 220Ω). Je vous propose d'utiliser les pins de 2 à 6. La LED attachée au pin 2 sera la LED numéro 1, celle du pin 3, la LED numéro 2...

Nous utiliserons un tableau pour stocker les numéros des pins.

Mais comme je suis gentil, je vous donne un schéma électrique ;) :

5 LED attachées au pins 2 à 6
5 LED attachées au pins 2 à 6

Nous connecterons les LED en reliant la patte + de la LED au port de sortie de l'Arduino. Chaque port alimentera donc une LED. Là encore, vu notre montage, l'Arduino supportera la charge.

Il ne faut pas oublier de bien définir chaque port en mode OUTPUT, et on les initialisera tous à LOW.

Le programme de base

Pour plus de clarté, nous allons créer une fonction par étape du programme. Il nous faut donc définir les étapes du programme.

  1. Lecture et traduction des données envoyées à l’Arduino, et mise à jour d’un tableau de comportement (c'est-à-dire si les LED sont allumées, éteintes ou clignotantes)

  2. Évaluation du temps écoulé et changement éventuel du tableau d'état des LED en fonction du tableau de comportement (c'est-à-dire leur état réel à l'instant donné : allumée ou éteinte)

  3. Allumage des LED en fonction du tableau d'état.

Ces trois fonctions ne nécessitent pas de paramètre.

Vous remarquez que je décide de créer deux tableaux distincts :

  • Le tableau des comportements des LED : il va stocker si la LED doit s'allumer, s'éteindre ou clignoter. Comme il y a trois valeurs possibles, on créera un tableau de variables de type  char

  • Le tableau des états des LED : il va stocker si la LED, à un instant donné, est allumée ou éteinte. Ce tableau changera en fonction du tableau des comportements et du temps qui s'écoule (une LED clignotante passe de allumée à éteinte à chaque écoulement du temps défini). Comme il n'y a que deux valeurs possibles, on créera un tableau de booléens.

Il nous faut aussi une variable globale de stockage du temps et une variable qui définit le temps de clignotement.

Voici donc le corps du programme :

int pins[5] = {2, 3, 4, 5, 6}; //tableau qui stocke les pins des LED
char comportements[5] = {0, 0, 0, 0, 0}; //tableau des comportements. 0 pour éteint, 1 pour allumé, 2 pour clignotant
boolean etats[5] = {0, 0, 0, 0, 0}; // tableau des états. 0 pour éteint, 1 pour allumé
unsigned long tempsDepart; // variable pour stocker le temps à un instant donné
int duree = 200; // variable pour stocker la durée de clignotement en ms

void setup() {
  Serial.begin (9600);
  // initialisation des LED et mise à LOW
  for (int l = 0; l < 5; l++) {
    pinMode(pins[l], OUTPUT);
    digitalWrite(pins[l], LOW);
  }
  //titre de présentation (c'est toujours plus sympa !)
  Serial.println("******************");
  Serial.println("* Gestion de LED *");
  Serial.println("******************");
  Serial.println("> start");//message de début de programme
  tempsDepart = millis(); //initialisation du temps de départ sur le temps actuel
}

void loop() {
  decodage(); //appel de la fonction de décodage
  timer(); // appel de la fonction de gestion du temps
  allumage(); // appel de la fonction d'allumage des LED
}

//------------------------fonctions
void decodage(){
  if (Serial.available()){ // teste si il reste des données en attente
    //code pour le décodage
    //la mise à jour du tableau des comportements
    //la mise à jour du tableau des états
    //et l'affichage sur le moniteur pour contrôle
  }
}

void timer(){
  unsigned long tempsActuel=millis();
  if (tempsActuel-tempsDepart>=duree){ //teste si le temps est écoulé
    //code pour modifier le tableau d'état des LED
    //pour chaque LED qui a un comportement clignotant
  }
}

void allumage(){
  // code pour allumer chaque LED
  // en fonction du tableau d'état des LED  
}

Vous avez tout ce qu'il vous faut pour finir ce programme. Il est important de réfléchir seul et d'essayer d'aller au bout en obtenant le résultat. 

Rassurez-vous, je vais vous donner la correction !

(Cunégonde ne soyez pas égocentrée ! Même si vous pensez ne pas en avoir besoin, jetez-y tout de même un œil une fois votre programme conçu...)

Correction 

int pins[5] = {2, 3, 4, 5, 6}; //tableau qui stocke les pins des LED
char comportements[5] = {0, 0, 0, 0, 0}; //tableau des comportements. 0 pour éteint, 1 pour allumé, 2 pour clignotant
boolean etats[5] = {0, 0, 0, 0, 0}; // tableau des états. 0 pour éteint, 1 pour allumé
unsigned long tempsDepart; // variable pour stocker le temps à un instant donné
int duree = 200; // variable pour stocker la durée de clignotement en ms

void setup() {
  Serial.begin (9600); // initialisation de la communication série
  // initialisation des LED et mise à LOW
  for (int l = 0; l < 5; l++) {
    pinMode(pins[l], OUTPUT);
    digitalWrite(pins[l], LOW);
  }
  //titre de présentation (c'est toujours plus sympa !)
  Serial.println("******************");
  Serial.println("* Gestion de LED *");
  Serial.println("******************");
  Serial.println("> start");//message de début de programme
  tempsDepart = millis(); //initialisation du temps de départ sur le temps actuel
}

void loop() {
  decodage(); //appel de la fonction de décodage
  timer(); // appel de la fonction de gestion du temps
  allumage(); // appel de la fonction d'allumage des LED
}

//------------------------fonctions
void decodage() {
  if (Serial.available()) {// teste s'il reste des données en attente
    String reception = "";
    while (Serial.available()) { //tant que des données sont en attente
      char c = Serial.read(); // lecture
      reception += String(c); //on ajoute à l'objet reception
      delay(10); //petite attente
    }
    reception.trim(); //on enlève le superflu en début et fin de chaîne
    reception = reception.substring(0, 5); // ne prend que les caractères de 0 à 4 (soit 5 caractères)
    Serial.print ("> Etat : ");
    //boucle de test par caractère
    for (int c = 0; c < 5; c++) {
      switch (reception.charAt(c)) {
        case 'a':
          Serial.print("\tON");
          comportements[c] = 1; //mise à jour du tableau des comportements
          break;
        case 'e':
          Serial.print("\tOFF");
          comportements[c] = 0; //mise à jour du tableau des comportements
          break;
        case 'c':
          Serial.print("\tCLI");
          comportements[c] = 2; //mise à jour du tableau des comportements
          break;
        default :
          comportements[c] = 0; //mise à jour du tableau des comportements par défaut à 0
          Serial.print("\t???");
      }
    }
    Serial.println(); // saut de ligne
    // boucle de mise à jour du tableau des états en fonction du tableau des comportements
    for (int l = 0; l < 5; l++) {
      if (!comportements[l]) {
        etats[l] = 0;
      }
      else {
        etats[l] = 1; // on allume aussi les lED clignotantes
      }
    }
  }
}
void timer() {
  unsigned long tempsActuel = millis(); //récupération du temps Arduino
  if (tempsActuel - tempsDepart >= duree) { //test si temps écoulé
    for (int l = 0; l < 5; l++) {
      if (comportements[l] == 2) { //test si comportement clignotant
        etats[l] = !etats[l]; //passe de 0 à 1 ou de 1 à 0
      }
    }
    tempsDepart = tempsActuel; //initialisation du temps de départ
  }
}

void allumage() {
  for (int l = 0; l < 5; l++) {
    digitalWrite(pins[l], etats[l]); //allumage des LED en fonction du tableau des Etats
  }
}

Un programme de ce type peut permettre de piloter des LED, mais aussi des moteurs, des servos. À vous de l'adapter à vos projets. Nous en verrons d'autres exemples plus loin dans ce cours. 

Évolutions possibles

Si vous souhaitez vous entraîner un peu plus à décoder des informations, rien ne vous empêche de complexifier ce programme. Voici quelques idées intéressantes (de mon point de vue ;)) :

  • Ajouter un code possible pour faire varier la vitesse de clignotement depuis le moniteur.

  • Faire varier la vitesse de clignotement grâce à un potentiomètre.

  • Préparer des séquences d'allumages (de droite à gauche, de gauche à droite, tout clignote, on allume une, puis deux, puis trois...) qui peuvent être appelées depuis le moniteur par un codage (tout en gardant la possibilité de commander chaque diode).

  • Créer une version du jeu MOTUS à 5 lettres (l'Arduino choisit un mot au hasard dans un tableau, vous proposez un mot de 5 lettres et les diodes s'allument si une lettre est au bon endroit, s'éteint si elle n'existe pas dans le mot et clignote si elle n'est pas placée correctement). C'est un gros boulot, mais très enrichissant !

En résumé

Vous venez de voir dans ce chapitre :

  • Comment créer un code de communication entre vous (l'humain) et l'Arduino (la machine).

  • Comment récupérer ce code pour piloter l'Arduino, en allumant de LED.

  • Comment utiliser des fonctions de l'objet  String() qui permettent de traiter des chaînes de caractères.

Je crois que vous avez avec tout ceci de bons bagages pour aller plus loin. Nous allons maintenant voir d'autres sortes d'interfaces homme/machine qui n'utilisent pas l'ordinateur...

Example of certificate of achievement
Example of certificate of achievement