Évaluer la santé des plantes avec TinyML : guide pratique
Composants nécessaires
- 1 × Arduino Nano 33 BLE Sense
- 1 × Moteur pas à pas (Digilent)
- 1 × Driver DRV8825 pour moteur pas à pas (Theremino)
Outils nécessaires
- Imprimante 3D
- Fer à souder
Applications et services en ligne
- Microsoft VS Code
- Arduino IDE
- Edge Impulse Studio
À propos du projet
Le principe
Comme les humains, les plantes peuvent tomber malades. Une infection fongique ou un pathogène jaunit ou tache les feuilles. En exploitant l'apprentissage automatique, on peut scanner les couleurs des feuilles et entraîner un modèle capable de détecter quand la couleur d'une feuille est anormale.
Le matériel
Le cerveau du projet est l'Arduino Nano 33 BLE Sense, choisi pour ses capteurs intégrés puissants : IMU 9DoF, APDS-9960 (couleur, geste, proximité, luminosité), microphone, capteur température/humidité/pression. Pour déplacer le capteur sur la feuille, deux moteurs pas à pas avec drivers DRV8825 sont utilisés.
Configuration de TinyML avec Edge Impulse
Les capteurs intégrés listés pour le Nano 33 BLE Sense sur Edge Impulse ne fonctionnent pas directement (seuls l'accéléromètre et le microphone sont listés). Il faut utiliser le « data forwarder » au lieu du démon série.
- Créer un nouveau projet sur Edge Impulse Studio
- Installer Node.js et NPM, puis
npm install -g edge-impulse-cli - Ajouter le chemin d'installation au PATH si nécessaire
- Lancer
edge-impulse-data-forwarderet vérifier qu'il fonctionne
Lecture de la couleur
L'APDS-9960 lit la couleur en renvoyant de la lumière infrarouge sur la surface et en analysant les longueurs d'onde non absorbées. Utilisez la bibliothèque Arduino APDS9960. Dans le code, le capteur est initialisé, puis dans la boucle on attend la disponibilité des données couleur. Si une lecture est disponible, on lit la couleur avec APDS.readColor() et la proximité. Chaque composante RGB est convertie d'une valeur 0-65535 en ratio sur la somme.
Le scanner 2 axes
Le scan de la feuille se fait en déplaçant un chariot sur deux axes (vis sans fin) pour passer divers points de la feuille sous l'APDS-9960. Le système a été conçu dans Fusion 360.
L'axe X repose sur l'axe Y, permettant au bloc supérieur de se déplacer dans les deux axes. Une roue en V supplémentaire supporte le poids du moteur pas à pas sur l'axe Y. Pièces imprimées en PLA avec ~45% de remplissage.
Collecte des données
Au démarrage, les moteurs ne connaissent pas leur position : ils font un « homing » vers l'origine pas à pas jusqu'à déclencher les fins de course. Ensuite, l'APDS-9960 est initialisé. Une boîte englobante (bounding box) est définie par deux coins opposés. Un point aléatoire est choisi dans cette zone, les moteurs y déplacent le capteur en lisant les couleurs en chemin.
Traitement et envoi des données couleur
Les couleurs sont lues avec APDS.readColor(). Après calcul de la somme, un pourcentage est calculé et envoyé via USB par Serial.printf(). Les valeurs sont séparées par des virgules, chaque lecture par un saut de ligne. Le data forwarder envoie ces données au projet Edge Impulse comme données d'entraînement avec l'étiquette « sain » ou « malade ».
Entraînement du modèle
Après collecte, on crée un « impulse » composé d'une série temporelle 3 axes, un bloc d'analyse spectrale et un bloc Keras. La capture d'écran montre la génération des caractéristiques.
Test
Test avec de nouvelles données d'une feuille malade. Précision du modèle ~63%, classifiant correctement la feuille la plupart du temps. Cette précision peut être améliorée en ajoutant plus de données d'entraînement et en réduisant la vitesse d'apprentissage.
Code
leafReader.ino
#include
#include
#include
#include "pinDefs.h"
int r, g, b, c, p;
float sum;
AccelStepper xStepper(AccelStepper::DRIVER, STEPPER_1_STEP, STEPPER_1_DIR);
AccelStepper yStepper(AccelStepper::DRIVER, STEPPER_2_STEP, STEPPER_2_DIR);
MultiStepper steppers;
const long boundingBox[2][2] = { {0, 0}, {40, 40} };
void setup() {
Serial.begin(115200);
while(!Serial);
if(!APDS.begin()) {
Serial.println("Could not init APDS9960");
while(1);
}
pinMode(X_AXIS_HOMING_SW, INPUT_PULLUP);
pinMode(Y_AXIS_HOMING_SW, INPUT_PULLUP);
xStepper.setPinsInverted(X_AXIS_DIR);
yStepper.setPinsInverted(Y_AXIS_DIR);
xStepper.setMaxSpeed(150);
yStepper.setMaxSpeed(150);
steppers.addStepper(xStepper);
steppers.addStepper(yStepper);
homeMotors();
}
void loop() {
long randomPos[2];
randomPos[0] = random(boundingBox[0][0], boundingBox[1][0]) * STEPS_PER_MM;
randomPos[1] = random(boundingBox[0][1], boundingBox[1][1]) * STEPS_PER_MM;
steppers.moveTo(randomPos);
while(steppers.run()) {
if(!APDS.colorAvailable() || !APDS.proximityAvailable()) {}
else {
APDS.readColor(r, g, b, c);
sum = r + g + b;
p = APDS.readProximity();
if(!p && c > 10 && sum >= 0) {
float rr = r / sum, gr = g / sum, br = b / sum;
Serial.printf("%1.3f,%1.3f,%1.3f\n", rr, gr, br);
}
}
}
}
void homeMotors() {
while(digitalRead(X_AXIS_HOMING_SW)) xStepper.move(-1);
while(digitalRead(Y_AXIS_HOMING_SW)) yStepper.move(-1);
xStepper.setCurrentPosition(0);
yStepper.setCurrentPosition(0);
}
pinDefs.h
#define STEPPER_1_STEP 2
#define STEPPER_1_DIR 3
#define STEPPER_2_STEP 4
#define STEPPER_2_DIR 5
#define X_AXIS_HOMING_SW 6
#define Y_AXIS_HOMING_SW 7
#define X_AXIS_DIR false
#define Y_AXIS_DIR false
#define MICROSTEPS 1
#define STEPS_PER_MM 160 * MICROSTEPS
Pièces à imprimer en 3D
Fichiers CAO disponibles sur Thingiverse.
Schéma de câblage
Processus de fabrication
- Capteur CO2 K30 : Surveillance en temps réel de la qualité de l'air intérieur
- Faciliter la communication sourd-aveugle avec 1Sheeld et Arduino
- Construire une Tirelire Intelligente : Contrôler un Accepteur de Pièces avec Arduino Nano
- Contrôler une LED par Bluetooth avec Arduino et MIT App Inventor
- Intégrer un capteur d'empreintes capacitif DFRobot (ID809) avec Arduino ou ESP8266
- Station météo interactive Nextion HMI avec Arduino Mega et capteurs
- Bras robotique 6 DoF piloté par Nunchuk Wii – Kit Arduino Mega
- Contrôler 2 moteurs pas-à-pas avec Arduino Nano et joystick – Tutoriel Visuino
- Mesure précise du rayonnement solaire avec Arduino UNO et shield Ethernet