Illustration : modules électroniques (capteur, écran, pilote moteur) reliés proprement à un microcontrôleur central

Illustration générée par IA

Mis à jour le Par Emmanuel SAUVAGE
Enregistrer

Fonction Arduino : créer et appeler des fonctions en C

Fonctions Arduino : portée, DRY, code lisible, éviter les globales. 20 exercices corrigés.

Quand ton programme robotique grandit, il devient difficile à lire : beaucoup de if, beaucoup de répétitions, et des constantes un peu partout. Les fonctions servent à :

  • regrouper une action : etatVeille(), alerteIntrusion()
  • éviter de recopier du code (principe DRY)
  • tester plus facilement

1) DRY (Don’t Repeat Yourself)

DRY = ne pas répéter la même information à plusieurs endroits.

Exemple : si tu écris 2 fois "Mon message", tu risques d’en modifier une et pas l’autre. En robotique, ça crée des bugs difficiles à comprendre.

Bonne pratique : une seule source :

const char* message = "Mon message";

2) Portée (scope)

  • variable globale : visible partout
  • variable locale : visible dans le bloc où elle est déclarée
  • paramètre : une valeur “donnée” à une fonction

En robotique, trop de globales = programme difficile à raisonner. On garde des globales pour les états nécessaires, et on passe le reste en paramètres.

3) Exemple robotique (structure)

loop():
  lire capteur
  si intrusion -> alerteIntrusion()
  sinon -> etatVeille()

Exercices (20)

Niveau simple

Exercice 1 — Écris une fonction void etatVeille() qui affiche VEILLE sur Serial. Simple

Afficher la solution
void etatVeille() {
  Serial.println("VEILLE");
}

Exercice 2 — Écris void alerteIntrusion() qui affiche ALERTE et joue un “bip” simulé (Serial.println("bip")). Simple

Afficher la solution
void alerteIntrusion() {
  Serial.println("ALERTE");
  Serial.println("bip");
}

Exercice 3 — Appelle etatVeille() dans setup() (après Serial.begin). Simple

Afficher la solution
void etatVeille() { Serial.println("VEILLE"); }
void setup() {
  Serial.begin(9600);
  etatVeille();
}
void loop() {}

Exercice 4 — DRY : déclare const int DIST_STOP = 15; et utilise-la dans une fonction bool isStop(int d). Simple

Afficher la solution
const int DIST_STOP = 15;
bool isStop(int d) { return d <= DIST_STOP; }

Exercice 5 — Écris int absInt(int v) (valeur absolue) et utilise-la pour un seuil d’intrusion. Simple

Afficher la solution
int absInt(int v) { return v < 0 ? -v : v; }

Niveau intermédiaire

Exercice 6 — Écris bool intrusion(int ref, int mesure, int seuil) qui renvoie true si abs(mesure-ref) > seuil. Intermédiaire

Afficher la solution
int absInt(int v) { return v < 0 ? -v : v; }
bool intrusion(int ref, int mesure, int seuil) {
  return absInt(mesure - ref) > seuil;
}

Exercice 7 — Évite une globale : crée void showCounter(int n) au lieu d’accéder directement à intrusions. Intermédiaire

Afficher la solution
void showCounter(int n) {
  Serial.print("intrusions=");
  Serial.println(n);
}

Exercice 8 — Écris void etatVeille(int nbr_intrusion) qui affiche un visage/texte simulé différent selon le compteur (si 0 : OK, sinon : attention). Intermédiaire

Afficher la solution
void etatVeille(int nbr_intrusion) {
  if (nbr_intrusion == 0) Serial.println("OK");
  else Serial.println("ATTENTION");
}

Exercice 9 — Explique en commentaire : pourquoi passer nbr_intrusion en paramètre peut aider la pédagogie même si la variable est globale. Intermédiaire

Afficher la solution
// Pédagogie : on voit quelles infos la fonction utilise (comme f(x)) ;
// bonne pratique : moins dépendre de variables globales rend le code plus testable et lisible.

Exercice 10 — Écris une fonction unsigned long periodFromDistance(int d) qui renvoie 1000ms si 35..69, 250ms si <35, sinon 100ms. Intermédiaire

Afficher la solution
unsigned long periodFromDistance(int d) {
  if (d >= 70) return 100;
  if (d >= 35) return 1000;
  return 250;
}

Niveau avancé

Exercice 11 — Écris bool every(unsigned long period, unsigned long* last) (timer générique). Avancé

Afficher la solution
bool every(unsigned long period, unsigned long* last) {
  unsigned long now = millis();
  if (now - *last >= period) { *last = now; return true; }
  return false;
}

Exercice 12 — Crée une fonction int readDistanceFake() qui renvoie une distance qui descend de 70 à 0 puis remonte (simulation). Avancé

Afficher la solution
int readDistanceFake() {
  static int d = 70;
  static int step = -1;
  d += step;
  if (d <= 0) { d = 0; step = 1; }
  if (d >= 70) { d = 70; step = -1; }
  return d;
}

Exercice 13 — Écris void radarTick(int distance_cm) qui affiche bip si distance < 70 (sinon rien). Avancé

Afficher la solution
void radarTick(int distance_cm) {
  if (distance_cm < 70) Serial.println("bip");
}

Exercice 14 — Mini-architecture : dans loop, lis la distance, calcule period, puis si every(period) alors radarTick. Avancé

Afficher la solution
unsigned long last = 0;

bool every(unsigned long period, unsigned long* last) { unsigned long now = millis(); if (now - *last >= period) { *last = now; return true; } return false; }

unsigned long periodFromDistance(int d) { if (d >= 70) return 100; if (d >= 35) return 1000; return 250; }

int readDistanceFake() { static int d = 70; d—; if (d < 0) d = 70; return d; }

void setup() { Serial.begin(9600); } void loop() { int d = readDistanceFake(); unsigned long p = periodFromDistance(d); if (every(p, &last) && d < 70) Serial.println(“bip”); }

Exercice 15 — Écris une fonction void logKV(const char* k, int v) et utilise-la pour logger distance. Avancé

Afficher la solution
void logKV(const char* k, int v) {
  Serial.print(k);
  Serial.print('=');
  Serial.println(v);
}

Exercice 16 — DRY : crée const int SEUIL = 3; et utilise-le dans 2 endroits (intrusion + alerte) sans recopier le 3. Avancé

Afficher la solution
const int SEUIL = 3;
int absInt(int v) { return v < 0 ? -v : v; }
bool intrusion(int ref, int mesure) { return absInt(mesure - ref) > SEUIL; }

Exercice 17 — Explique en commentaire ce que veut dire “modularité”. Avancé

Afficher la solution
// Modularité : découper un programme en blocs/fonctions indépendants et réutilisables,
// chacun avec une responsabilité claire.

Exercice 18 — Crée une fonction int vitesseFromDistance(int d) qui renvoie 0 si d<=15, 80 si d>=50, sinon 30. Avancé

Afficher la solution
int vitesseFromDistance(int d) {
  if (d <= 15) return 0;
  if (d >= 50) return 80;
  return 30;
}

Exercice 19 — Ajoute une fonction void drive(int v) qui simule l’envoi vitesse moteur (Serial.println(v)). Avancé

Afficher la solution
void drive(int v) {
  Serial.print("drive=");
  Serial.println(v);
}

Exercice 20 — Mini-projet : dans loop, lis une distance simulée, calcule la vitesse via vitesseFromDistance, puis appelle drive(v) toutes les 200 ms (non-bloquant). Avancé

Afficher la solution
unsigned long last = 0;
bool every(unsigned long p, unsigned long* last) {
  unsigned long now = millis();
  if (now - *last >= p) { *last = now; return true; }
  return false;
}
int vitesseFromDistance(int d) {
  if (d <= 15) return 0;
  if (d >= 50) return 80;
  return 30;
}
int readDistanceFake() { static int d = 70; d--; if (d < 0) d = 70; return d; }
void drive(int v) { Serial.print("drive="); Serial.println(v); }

void setup() { Serial.begin(9600); } void loop() { if (every(200, &last)) { int d = readDistanceFake(); int v = vitesseFromDistance(d); drive(v); } }

Cette page vous a-t-elle été utile ?

Une question sur cet article ou besoin d'un conseil ? Posez-la ici

Vous hésitez entre deux modèles ou vous avez besoin d'aide sur un montage ? Écrivez-nous, nous vous répondons rapidement par e-mail.