Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Maîtriser le multitâche Arduino avec les Protothreads : Tutoriel pas à pas

Composants nécessaires

Composant Quantité
Arduino UNO 1
Écran LCD 16x2 Sunfounder Blue (ou équivalent compatible HD44780) 1
Plaque d'essai (breadboard) et fils de connexion 1
Potentiomètre rotatif (environ 1 kΩ) 1

À propos de ce projet

Ce tutoriel montre comment faire exécuter trois tâches simultanément sur un Arduino mono-cœur :

Qu'est-ce que le protothreading ?

Le protothreading est une technique qui simule le multitâche sur un microcontrôleur mono-cœur comme l'ATmega328P de l'Arduino Uno. Contrairement au vrai multitâche (qui nécessite plusieurs cœurs), le protothreading utilise une approche coopérative : la boucle principale (loop()) agit comme un « gestionnaire » qui vérifie périodiquement si d'autres tâches doivent s'exécuter, en fonction du temps écoulé.

Multitâche réel vs Protothreading

Un processeur multi-cœurs exécute véritablement des threads en parallèle. L'Arduino Uno, avec son unique cœur à 16 MHz, ne peut exécuter qu'une instruction à la fois. Le protothreading contourne cette limitation en découpant le travail en petites unités non-bloquantes et en utilisant millis() pour la gestion du temps, au lieu de delay() qui bloque tout le processeur.

Comment ça marche ?

Le principe repose sur la bibliothèque TimedAction (ou une implémentation maison) :

  1. On définit des « threads » avec leur intervalle d'exécution et leur fonction associée.
  2. Dans la boucle principale (la tâche la plus fréquente, ici le fading du rétroéclairage), on appelle check() sur chaque thread à chaque itération, y compris à l'intérieur des boucles for qui pourraient bloquer.
  3. Si le temps écoulé depuis la dernière exécution dépasse l'intervalle, la fonction du thread s'exécute immédiatement.

Attention : les opérations bloquantes (lecture carte SD, communications lentes) perturberont la précision des autres threads. Pour des tâches légères (modification de variables, écriture LCD, PWM), c'est très efficace.

Implémentation pas à pas

  1. Identifier les tâches et les classer du moins bloquant (fréquent, rapide) au plus bloquant (rare, lent).
  2. Choisir la tâche principale (celle qui s'exécute le plus souvent) comme boucle loop().
  3. Initialiser les threads avec leurs intervalles (ex: 700 ms pour le compteur, 3000 ms pour le texte).
  4. Appeler check() partout : dans loop() et dans toute boucle interne.

Code complet (multithread.ino v1.1)

/* Arduino Protothreading Example v1.1
 * Auteur : Drew Alden (@ReanimationXP)
 * Basé sur la bibliothèque TimedAction.h
 * Note : Remplacer WProgram.h par Arduino.h dans TimedAction.h pour Arduino IDE 1.6.6+
 */

#include <TimedAction.h>
#include <LiquidCrystal.h>

// --- Brochage LCD (standard Hitachi HD44780) ---
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// --- Variables globales ---
const int backlightPin = 9;      // PWM pour le rétroéclairage
int timerCounter = 0;            // Compteur incrémenté
int stringNo = 0;                // Index du message affiché
char* stringArray[] = {
  "Check it out... ",
  "I have 3 threads",
  "going at once...",
  "Cool, huh?! :D "
};

// --- Déclaration des threads (après les fonctions !) ---
TimedAction numberThread = TimedAction(700, incrementNumber);
TimedAction textThread = TimedAction(3000, changeText);

// --- Fonctions des threads secondaires ---
void incrementNumber() {
  lcd.setCursor(0, 1);
  timerCounter++;
  lcd.print(timerCounter);
}

void changeText() {
  lcd.setCursor(0, 0);
  lcd.print(stringArray[stringNo]);
  stringNo = (stringNo + 1) % (sizeof(stringArray) / sizeof(char*));
}

void setup() {
  lcd.begin(16, 2);
  changeText(); // Affichage initial
}

void loop() {
  // Vérifier les threads secondaires
  numberThread.check();
  textThread.check();

  // Tâche principale : fading du rétroéclairage (montée)
  digitalWrite(13, HIGH);
  for (int fadeValue = 0; fadeValue <= 255; fadeValue += 10) {
    numberThread.check(); textThread.check(); // Indispensable !
    analogWrite(backlightPin, fadeValue);
    delay(20); // Court délai, non bloquant pour les threads
  }

  // Fading (descente)
  digitalWrite(13, LOW);
  for (int fadeValue = 255; fadeValue >= 0; fadeValue -= 10) {
    numberThread.check(); textThread.check();
    analogWrite(backlightPin, fadeValue);
    delay(20);
  }
}

Points clés à retenir

Aller plus loin

Pour des applications plus complexes nécessitant une vraie préemption ou une gestion de tâches bloquantes, envisagez :

Processus de fabrication

  1. Mesurer la qualité de l'air avec OpenSensors : Guide Arduino et Python
  2. Créer un verrou RFID sécurisé avec Arduino – Guide étape par étape
  3. Construire une télécommande IR universelle avec Arduino : Guide étape par étape
  4. Construisez un Stadiomètre Numérique : Suivez la Croissance avec Arduino et Capteur Laser
  5. Utiliser une thermistance facilement : Guide étape par étape Arduino
  6. Générer des Sons Musicaux avec Arduino : Guide Pas à Pas
  7. Connecter Arduino à NMEA‑0183 : Guide étape par étape
  8. Enregistreur de Données Environnementales Arduino avec Carte SD et RTC
  9. Tutoriel Arduino Débutant 01 : Démarrez votre Premier Projet