dimanche 20 octobre 2019

Texte et Arduino (1): la classe String



Deux façon possibles de procéder

Lorsque vous désirez traiter des informations sous forme de texte avec votre Arduino (demander le nom de l'utilisateur, afficher une information textuelle sur un écran ou le moniteur série, etc.), deux options s'offrent à vous: les tableaux de caractère classiques du langage C, et les objets de type String.

Les tableaux de caractères du langage C

Les tableaux de caractères terminés par "NULL" font partie intégrante du langage C depuis sa création, au début des années 1970. Ils sont souvent un peu nébuleux pour les néophytes qui abordent la programmation de l'Arduino sans avoir de connaissance préalable en langage C. Les fonctions conçues pour gérer les tableaux de caractères portent souvent des noms peu intuitifs.  Pour les connaître,  il faut consulter des sources documentaires sur le langage C car le site officiel Arduino insiste plutôt sur la classe String. Le programmeur doit également prendre soin de ne pas écrire au-delà des limites du tableau (comme, par exemple, tenter d'écrire un treizième caractère dans un tableau conçu pour en contenir douze).

Ces tableaux de caractères pourront toutefois être utilisés dans n'importe quel programme en langage C (pas seulement Arduino).

Les objets de type String

Les concepteurs du langage Arduino ont créé la classe String pour faciliter la tâche des programmeurs débutants. La syntaxe est souvent plus intuitive, les fonctions portent un nom qui permet de deviner plus facilement à quoi elles servent,  elles sont énumérées sur le site de référence officiel du langage Arduino et un tas d'exemples sont fournis avec l'IDE Arduino.



Malheureusement, cette facilité d'utilisation est accompagnée d'un inconvénient: pendant que votre programme s'exécute, les fonctions de la classe String ont tendance à causer un fractionnement de la mémoire disponible. Conséquence: avec le temps, votre programme risque de devenir instable et de planter. C'est pour cette raison que, dans les forums de discussion, vous verrez souvent des intervenants qui menacent de vous excommunier à la moindre allusion à la classe String.

Alors on fait quoi?

Si c'est très important que votre programme fonctionne sans faille pendant une longue période de temps (exemple: il gère l'alimentation en oxygène de votre scaphandre), évitez à tout prix l'utilisation de la classe String!

Par contre, si vous fabriquez par pur plaisir un gadget dont la fiabilité n'est pas essentielle (une machine qui affiche des obscénités lorsqu'on appuie sur un bouton, par exemple) et que vous détestez vous compliquer la vie, pourquoi vous priver de la classe String?

Bref, les programmeurs sérieux utilisent les tableaux de caractère à terminaison nulle, et les autres font ce qu'ils veulent.

Dans le présent article, je vais explorer l'utilisation de la classe String. Dans un prochain article, à paraître très bientôt, j'aborderai l'utilisation des tableaux de caractères à terminaison nulle.

Sketch de démonstration

Le sketch ci-dessous utilise la plupart des fonctions décrites dans le reste de cet article. Il vous demande d'écrire un message dans le moniteur série, et il fait ensuite l'analyse de ce message.

-
-

Voici un exemple de ce qu'affiche le moniteur série après que j'aie écrit le message "Arduino, le meilleur ami des makers":



N.B.: Dans la suite de cet article, les hyperliens mènent vers la documentation complète de chaque fonction.

Création d'une variable de type String (consructeur)

On crée une variable de type String en précédant le nom de la variable par le mot "String", comme aux lignes 8, 9 et 10 du sketch de démonstration (n'oubliez pas le "S" majuscule au début du mot).

Ce qui est chouette avec un objet de type String, c'est qu'il n'est pas nécessaire de définir sa taille au moment de sa création: pourvu que la mémoire nécessaire soit disponible, votre variable pourra tout aussi bien contenir un texte constitué d'un seul caractère qu'un long paragraphe de plusieurs lignes­.

Réception d'un String par le moniteur série

À la ligne 20 du sketch de démonstration, Serial.readString() permet de placer dans une variable de type String le texte reçu par liaison série. L'utilisation de cette fonction est toujours suivie d'un délai d'attente perceptible, car elle prend fin lorsqu'aucun nouveau caractère n'a été reçu depuis un certain temps.

Remarquez que si vous avez réglé le moniteur série pour qu'il ajoute automatiquement une fin de ligne ou un retour de chariot à la fin de chaque message, ces caractères supplémentaires feront partie du String, à moins que vous n'utilisiez la fonction trim(), qui enlève tous les espaces inutiles situés au début et à la fin d'un String (ligne 22 du sketch).

Affectation d'un String

Pour placer du texte dans une variable de type String, vous utilisez l'opérateur "=", comme pour tout autre type de variable (voir la ligne 25, par exemple).

Concaténation de deux Strings

La concaténation consiste à mettre deux Strings bout à bout. Vous pouvez utiliser la fonction concat() (ligne 26) ou l'opérateur "+" (ligne 30).

Comparaison de deux Strings

Pour vérifier si deux Strings sont identiques, vous pouvez utiliser l'opérateur "=="  (ligne 48) ou la fonction equals() (ligne 56).

Il existe également des fonctions plus spécialisées: equalsIgnoreCase() (ligne 63) compare les deux Strings sans tenir compte de la case ("Arduino" et "ARDUINO" seront donc considérés comme équivalents).

compareTo() (ligne 86) est encore un petit peu plus sophistiquée, et peut être utilisée pour trier des Strings en fonction du numéro ASCII des caractères qu'ils contiennent. On peut également trier deux Strings de façon similaire au moyen des opérateurs ">" ou "<".

Connaître le nombre de caractères d'un String

La fonction length() (ligne 30) permet de déterminer le nombre de caractères à l'intérieur du String.

Analyse caractère par caractère

On peut accéder à un caractère en particulier au moyen de la fonction charAt() (ligne 34) ou de l'opérateur [] (ligne 36). Le premier caractère porte le numéro 0.

Pour modifier un caractère en particulier, on peut utiliser setCharAt() (ligne 98).

On peut également éliminer un caractère ou plusieurs caractères grâce la fonction remove().

On peut utiliser replace() (ligne 94) pour remplacer toutes les occurrences d'un caractère par un autre caractère.

Isoler une partie d'un String

substring() (ligne 76) retourne un String constitué d'une partie d'un autre String.

Recherche à l'intérieur d'un String

indexOf() (ligne 40) et lastIndexOf() (ligne 42) permettent de trouver la position d'un caractère ou d'un String à l'intérieur d'un autre String. La valeur retournée est -1 si la recherche s'est révélée infructueuse.  Par défaut, la recherche débute au tout début ou à la toute fin du String. On peut ajouter un deuxième paramètre facultatif pour commencer la recherche à un autre caractère.

startsWith()  et endsWith() (ligne 70) permettent de vérifier si un String commence ou se termine par les caractères d'un autre String.

On peut utiliser replace() (ligne 94) pour remplacer toutes les occurrences d'un String par un autre String.

Tout réécrire en minuscules ou en majuscules

Deux fonctions permettent de réécrire le contenu du String afin qu'il ne contienne que des majuscules, ou que des minuscules: toLowerCase() et  toUpperCase() (lignes 78 et 82). Dans les deux cas, le contenu du String est immédiatement remplacé par le nouveau texte.

Conversion d'un nombre en String

Lorsque vous désirez afficher une valeur numérique mesurée par un capteur, il peut être utile de convertir un nombre en String. La conversion de type s'effectue avec la même syntaxe que pour les autres types de variable en langage C:  String(nombre). Si le nombre à convertir est de type "float" ou "double", un deuxième paramètre (facultatif) permet de déterminer le nombre de décimales à conserver (lignes 103 et 106 du sketch de démonstration).

Conversion d'un String en nombre

Un String qui débute par un nombre peut être converti en variable de type double, float ou int grâce aux fonctions toDouble()toFloat() et toInt() (ligne 111). Le String doit débuter par un nombre, mais ce nombre peut être suivi de caractères non-numériques, qui seront simplement ignorés lors de la conversion. La valeur retournée est zéro lorsque la conversion échoue.

Prochain article: les chaînes de caractères classiques du langage C (terminées par NULL).

Yves Pelletier   (TwitterFacebook)

mardi 1 octobre 2019

Bluetooth (série) avec l'ESP32


Une des nombreuses caractéristiques épatantes de l'ESP32, c'est qu'il peut communiquer en Bluetooth. Dans cet article, voyons un peu comment il est possible d'utiliser la bibliothèque BluetoothSerial pour établir une communication entre l'ESP32 et un smart phone.

Si vous savez comment utiliser la classe Serial pour établir une communication série de type UART, il n'est pas exagéré d'affirmer que vous savez déjà comment utiliser la bibliothèque BluetoothSerial: les méthodes begin, read, write, print, println et available sont disponibles et accomplissent la même fonction que dans leur équivalent série.

Réglages du smart phone ou de la tablette

Il existe de nombreuses applications Android permettant la communication bluetooth. Pour cette expérience, j'ai utilisé Serial Bluetooth Terminal par Kai Morich. Une autre option consiste à utiliser l'application réalisée dans cet article au moyen de MIT App Inventor.

Si vous n'avez pas l'habitude d'effectuer l'appairage d'un périphérique bluetooth, vous pouvez vous référer à la partie intitulée "Couplage avec un appareil hôte" de cet article.

Envoi d'informations de l'ESP32 vers le smart phone

Le sketch ci-dessous envoie un nombre croissant par bluetooth. C'est une façon simple et rapide de vérifier que la communication fonctionne correctement.


-
-

Contrôle de l'ESP32 par le smart phone

Dans ce deuxième exemple, deux LEDs reliées à l'ESP32 sont contrôlées à partir du smart phone.
  • La commande 'a' allume la première LED
  • La commande 'b' allume la deuxième LED
  • La commande 'c' allume les deux LEDs
  • La commande 'd' éteint les deux LEDs
  • La commande 'e' modifie l'état des deux LEDs


Une des LEDs est branchée à la broche GPIO 4, alors que l'autre est branchée à GPIO 5.


-
-

Articles similaires

Grâce au module HC-06, nous avons eu l'occasion d'utiliser Bluetooth avec Arduino, Raspberry Pi, STM32 Nucleo, MPLAB Xpress (PIC) et MSP430 Launchpad. Nous avons aussi utilisé MIT App Inventor 2 pour programmer une appli Android qui communique en Bluetooth.

En ce qui concerne l'ESP32, de nombreux autres articles sont disponibles ici.

Yves Pelletier   (TwitterFacebook)