Découverte des variables Arduino

Qu'est-ce qu'une variable ?

Un type de données, également connu sous le nom de variables, est une unité de mémoire identifiée par un nom et contenant une valeur numérique ou alphabétique. Les variables sont des éléments essentiels pour stocker et manipuler différentes données. Elles permettent de gérer des nombres entiers, des nombres à virgule flottante, des caractères, des chaînes de caractères, etc... Les types de données numériques vous permettent d'effectuer diverses opérations mathématiques telles que la multiplication, la division, l'addition, la soustraction, ainsi que la conversion vers d'autres types de données. Dans cet article, nous allons explorer en détail les types de variables Arduino les plus couramment utilisés, ainsi que leurs caractéristiques et exemples d'utilisation.

Dans un programme, les variables sont déclarées en utilisant la syntaxe suivante : <type> <nom> = <valeur>;

Comme vous le savez certainement, nos ordinateur, nos calculettes, et tous nos appareils électronique utilise le langage binaire pour transmettre des données. Le langage binaire est composé de seulement deux chiffre, 0 ou 1 (Il est en base 2). Un 0 ou 1 est appelé un "bit" (contraction de l’expression anglaise binary digit). 8 "bits" équivaux a un "octet". Nos petits micro-contrôleur de type Arduino manipulent des mots de 8 bits (même si certaines cartes - ESP32, DUE - manipulent des mots de 32 bits - 4 octets). Nos ordinateurs, quand à eux, manipulent des mots de 64 bits.

Mais comment transmettre des données avec seulement deux chiffre, me direz vous. Et bien c'est simple, nous avons deux possibilité 8 fois. Cela fait 2 puissance 8, soit 256 possibilités. Par exemple, pour transmettre le chiffre 1 en langage binaire sur 8 bits, nous n'utilisons pas le chiffre 1 mais 00000001. Le nombre 2, c'est 00000010, etc... Une variable utilise un certaine espace mémoire (la mémoire utilisée par les variable est la mémoire RAM (Read Access Memory)). Elle peut être stocker sur 8 bits, 16 bits, 32 bits, etc... Par exemple. Une variable de type uint8_t stocke sa valeur sur 8 bits.

Comme nos carte sont généralements des µContrôleur 8bits, la manipulation de mots plus grands, de 32 bits par exemple, ralenti les calculs de l'Arduino.

1. Les variables les plus courantes :

Variables numériques :

  • int : utilisé pour stocker des nombres entiers signé (positifs ou négatifs) allant de -32,768 à 32,767.
  • uint8_t : utilisé pour stocker des nombres entiers non signés (seulement positif) de 8 bits (sur 1 octet), allant de 0 à 255.
  • uint16_t : utilisé pour stocker des nombres entiers non signés de 16 bits (sur 2 octets), allant de 0 à 65536.
  • uint32_t : utilisé pour stocker des nombres entiers non signés de 32 bits (sur 4 octets), allant de 0 à 4294967296.
  • byte : utilisé pour stocker des nombres entiers positifs allant de 0 à 255.
  • long : utilisé pour stocker des nombres entiers signé sur 4 octets, soit 32 bits : de -2 147 483 648 à 2 147 483 647.
  • short : utilisé pour stocker des nombres entiers signé de 16 bits (2 octets), allant de -32 768 à 32 767
Variables à virgule flottante :
  • float : utilisé pour stocker des nombres à virgule flottante sur 32 bits (4 octets) avec une précision suffisante pour la plupart des applications Arduino.
  • double : utilisé pour stocker des nombres à virgule flottante avec une précision égale a celle de float sur les carte ATmega, mais double sur les cartes Arduino Due, MKR1000 ou Zero (les données occupant 64 bits)

Variables de caractères et de chaînes de caractères :

  • char : utilisé pour stocker un seul caractère ASCII.
  • String : utilisé pour stocker une chaîne de caractère.

Variables booléennes :

  • bool : utilisé pour stocker des valeurs booléennes (vrai ou faux). On peut également utiliser 1 pour vrai et 0 pour faux.

Bien entendu, il existe d'autres types. Voici un lien vers une liste des variables existant sur le site officiel d'Arduino® : https://www.arduino.cc/reference/en/#variables, (voici le même lien en français)

Attention,

Piège courant : une variable flottante (float) utilise le point comme séparateur entre partie entière et décimales, et non pas la virgule :

float valeur = 23.47;        // correct
float valeur = 23,47;        // incorrect

2. Les constantes :

Les variables, comme indiqué plus haut, servent a stocker des valeurs. Ces valeurs peuvent bouger (elles varient, d'où le nom). Mais imaginons que nous ayons besoin d'un chiffre ou d'un nombre qui ne bouge pas, et qui ne puisse pas être modifié après sont initialisation. Nous appelons des variables a valeur fixe des constantes. Pour "verrouiller" une variable, nous mettons devant celle-ci le mot "const". Par exemple, pour définir la pin d'une LED, nous mettons : const byte pinLED = 13;. Nous pouvons aussi définir la pin avec #define, qui est une constante symbolique

NOTE : Si aucune valeur n'est assignée à une variable globale ou locale, elle sera automatiquement initialisée avec une valeur de 0.

3. Variable signée et non signée :

Quand une variable est dite "signée", cela signifie que la variable peut avoir une valeur aussi bien positive que négative. Par exemple, un int est une variable signée, c'est a dire qu'elle peut prendre comme valeur un nombre ou un chiffre négatif (ex : -12). Parallèlement, une variable de type "non signée" ne peut prendre que des valeur positive (ex : 3).

Nous pouvons forcer une variable de type signée a devenir une variable non signée, grâce au mot "unsigned". Par exemple, on peut transformer une variable de type long (signée) en variable non signée, comme ceci : unsigned long maVariable;

Quand une variable est signée, elle peut stocker qu'une certaine quantité de valeur. Si on la transforme en variable non signée, elle peut ne stocker peut que des valeurs positive, mais elle peut stocker le double (toute la place consacrée au nombres négatifs auparavant est maintenant également consacrée au valeurs positives). Par exemple, prenons une variable de type int. Si elle n'est pas non signée, elle peut aller de -32,768 à 32,767. En revanche, si nous la transformons en variable non signée, elle pourra aller de 0 à 65 535 (soit le double).

4. Les variables globales et locales :

Les variables doivent obligatoirement être déclarées dans le programme, sinon, le compilateur revoit une erreur (<variable> is not declared in this scope). Nous pouvons les déclaré a deux endrois : dans une fonction, ou hors des fonctions.

Une variable créée dans une fonction (par exemple dans void setup) ne sera utilisable que dans cette fonction. Si vous essayez de l'utiliser hors de celle-ci, le compilateur vous renvéra l'erreur vue plus haut, car il ne reconaitra pas la variable. On appelle ces variables des variables dites locale. Par exemple :

void setup() {
  // Calcul de 2 + 2 en utilisant une variable locale
  int resultatLocal = 2 + 2;

  // Affichage du résultat sur le moniteur série
  Serial.begin(9600);
  Serial.print("Résultat local : ");
  Serial.println(resultatLocal);
}

void loop() {
  // Rien à faire dans la boucle loop
  // attention, si on appelle la fonction "resultatLocal"
  // ici,le compilateur nous renverai une erreur !

En renvanche, une variable créer hors des fonctions pourra être utilisée partout dans le programme. C'est ce que l'on appelle une variable globale. Par exemple :

// Déclaration d'une variable globale
int resultatGlobal;

void setup() {
  // Initialisation de la variable globale
  resultatGlobal = 0;

  // Calcul de 2 + 2
  resultatGlobal = 2 + 2;

  // Affichage du résultat sur le moniteur série
  Serial.begin(9600);
  Serial.print("Résultat global : ");
  Serial.println(resultatGlobal);
}

void loop() {
  // Rien à faire dans la boucle loop
  // Si on utilisai "resultatGlobal" ici, le compilateur
  // ne nous renverai pas d'erreur, mais nous utiliserons
  // plus de mémoire programme...
}

5. Variable static ou volatile ?

Une variable volatile est utilisée pour indiquer au compilateur qu'elle peut être modifiée à tout moment par des éléments extérieurs au programme principal. Cela permet de garantir que la valeur de la variable sera toujours lue à partir de sa source actuelle, plutôt que d'être optimisée en utilisant une copie mise en cache. La situation courante où l'on utilise des variables volatiles sont les interruption, ou les variables utilisé peuvent être modifiés par des processus externes à la routine principale du programme.

Voici un exemple de déclaration d'une variable volatile Arduino :

volatile int compteur;

Une variable statique est utilisée pour déclarer une variable dont la portée est limitée à un certain bloc de code (fonction), mais dont la valeur est conservée entre les appels successifs de ce bloc. Cela signifie que la variable conserve sa valeur même lorsque le bloc de code dans lequel elle est déclarée est quitté, et elle est initialisée une seule fois au moment de la déclaration. Les variables statiques sont souvent utilisées pour maintenir des compteurs ou des indicateurs d'état dans les fonctions.

Voici un exemple de déclaration d'une variable statique en Arduino :

void maFonction() { static int compteur = 0; compteur++; Serial.println(compteur); }

Dans cet exemple, la variable "compteur" est déclarée comme statique à l'intérieur de la fonction "maFonction()". Chaque fois que la fonction est appelée, la valeur de "compteur" est incrémentée et affichée sur le moniteur série. La particularité est que la variable "compteur" conserve sa valeur entre les appels successifs de la fonction, ce qui permet de maintenir son état même lorsque la fonction est quittée.

Si on l'appelle dans la loop, après un delais (delay) de 500 ms, chaque tour de boucle incrémentera la valeur de +1. Si on ne l'avait pas déclaré en static, elle reviendrai a 0 a chaque tour :

// ----------------------------setup---------------
void setup() {} // rien dans le setup
// -----------------------------loop---------------
void loop() {
  maFonction(); // on appelle la fonction
  delay(500); // on attend une demi-seconde
}
// --------------------fonction conteur------------
void maFonction() {
  static int compteur = 0;
  compteur++; // on incrément le conteur
  Serial.println(compteur); // on affiche la variable "comteur"
}

6. Conversion de type :

En C++, une conversion de variable est la conversion d’une valeur de variable à un type différent. Par exemple, vous souhaitez convertir un type de données byte en type de données int dans un programme. Pour ce faire, indiquez le type de variable souhaité entre parenthèses avant la variable à convertir – le résultat renverra une variable avec le nouveau type de données. Voici un exemple de conversion explicite de variables Arduino :

byte x = 150;
int y = (int)x;
float x = 15,4;
int y = (int)x; 
extrait de [source Arduino France site]

7. Conclusion / résumé :

Il est important de bien typer ses variables, pour optimiser notre code et l'espace mémoire de notre carte. Les variables sont des éléments très importants dans la programmation, car elle permettent de manipuler des chiffres, des nombres, des caractères et des chaînes de caractère.

Certains types de variables peuvent prendre des valeurs négatives et positives (type signée), d'autres uniquement des valeurs positives (non signée) - faire passer une variable signée en non signée est possible, et double sa capacité a stocker des valeurs positives.

Une variable peut être déclarée dans et hors d'une/des fonction(s). Une variable déclarée dans une fonction est appelée variable locale, et n'est utilisable que dans celle-ci. Une variable déclarée hors des fonctions du code est appelée variable globale, et elle peut être utilisée partout dans le code.

Une variable volatile permet d'indiquer au compilateur que celle-ci peut être modifiée hors du programme principal. On s'en sert principalement lor de l'utilisation d'interruptions.

Une variable static est utilisée dans les fonctions, pour éviter que les variables locales a cette fonction ne se réinitialisent lors de chaque appels de cette fonction. Cela sert par exemple pour réaliser des conteurs.

On peut facilement convertir une valeur de variable en un type différent, en indiquant le nouveau type entre parenthèses, ce qui renvera une nouvelle variable sur ce type avec cette valeur.