Arduino : passage et modifications de struct dans des fonctions avec des pointeurs

Les structures permettent de regrouper des informations sous forme d'une structure (une sorte de d'enregistrement).
Dans Arduino, cela permet aussi de passer une structure d'information à une fonction... voire de permettre la modification de ces informations.
C'est génial, du coup, une fonction Arduino peut modifier plusieurs valeurs :-).

Définition d'une structure
Nous allons commencer par définir la structure que nous allons utiliser.

struct Temps { 
 int heure;
 int minute;
};

La structure Temps regroupe deux informations: heure et minute.
Pour pouvoir utiliser cette définition dans des appels de fonction, il est impératif de placer la définition la structure Temps dans un fichier header (defs.h).
Il n'est pas possible de créer le fichier structure directement depuis Arduino IDE. Il faudra créer ce fichier directement à l'aide de notepad dans le répertoire du projet.
Créer un fichier header (defs.h) dans le répertoire du projet Arduino
Utiliser un éditeur texte pour initialiser le contenu de fichier header
Par la suite, le contenu sera éditable dans l'IDE Arduino.
Edition du contenu du fichier d'entête (header)
Utiliser le fichier header
Pour utiliser le contenu du fichier header, il suffit d'ajouter la ligne suivante en début du projet Arduino.

#include "defs.h"

L'utilisation des guillemets (") informe le compilateur qu'il doit chercher le fichier header dans le répertoire du projet. L'utilisation de < et > indique au compilateur de chercher dans les bibliothèques Arduino.

#include "defs.h"

void setup() {
  // put your setup code here, to run once:
  Serial.begin( 9600 );
  Serial.println( "Go go go" );
}

void loop() {
  // put your main code here, to run repeatedly:
  Temps t = {5,6};
  
  while( true ){
    delay( 1000 );
    Serial.println("ping");
  }
}

Le corps de la fonction loop définit la variable t de type Temps et initialise les deux valeurs. Voir l'instruction Temps t = {5,6};

Passer une structure à une fonction
Il est possible de passer la structure en paramètre à une fonction afficherTemps() qui se contente d'afficher le contenu de la structure.
 
void afficherTemps( Temps* x) {
   Serial.println( x->heure, DEC );
   Serial.println( x->minute, DEC );
   Serial.println( "-----------------" );
}

Le paramètre Temps* dans void afficherTemps( Temps* x) indique que x est un pointer vers une variable de type Temps.

Par la suite, il est possible d'accéder aux différentes valeurs de la structure avec x->heure et x->minute

La nouvelle fonction loop ci-dessous montre comment appeler la fonction afficherTemps .

void loop() {
  // put your main code here, to run repeatedly:
  Temps t = {5,6};

  Serial.println( "Valeur par defaut" );
  afficherTemps( &t );
}

Le paramètre &t indique l'adresse mémoire où t est stocké. On dit que &t pointe vers t (point vers où t est stocké).
Cette adresse est passé à la fonction afficherTemps(), ce qui est parfait étant donné qu'elle attend un pointeur (donc l'adresse où se trouve l'information).

Modifier les données de la structure
void changerTemps( Temps* y, int h, int m ) {
   y->heure = h;
   y->minute = m;
}

La fonction changerTemps() montre qu'il est possible de modifier le contenu d'une structure.
En effet, nous travaillons avec des pointeurs, y->heure = h modifie donc la valeur directement à l'emplacement mémoire où la structure à été créée.

Par conséquent, la nouvelle valeur reste disponible après l'appel de la fonction... puisque l'on travaille sur un même emplacement mémoire  :-) Pratique pour modifier les paramètres d'une fonction.

Le script au complet
#include "defs.h"

void setup() {
  // put your setup code here, to run once:
  Serial.begin( 9600 );
  Serial.println( "Go go go" );
}

void afficherTemps( Temps* x) {
   Serial.println( x->heure, DEC );
   Serial.println( x->minute, DEC );
   Serial.println( "-----------------" );
}

void changerTemps( Temps* y, int h, int m ) {
   y->heure = h;
   y->minute = m;
}

void loop() {
  // put your main code here, to run repeatedly:
  Temps t = {5,6};

  Serial.println( "Valeur par defaut" );
  afficherTemps( &t );
  Serial.println( "Valeur Modifiee" );
  changerTemps( &t, 12, 13 );
  afficherTemps( &t );
  
  // boucle infinie pour arrêter le traitement
  while( true ){
    delay( 1000 );
    Serial.println("ping");
  }
}

Et le résultat visible dans le moniteur série d'Arduino.


Le moniteur série montre à l'évidence que les valeurs modifiées dans changerTemps() sont disponible dans loop() puisqu'elles peuvent être, ensuite, passée à la fonction afficherTemps()... qui affiche le contenu modifié.

Bonne lecture,
Dominique