Tous les projets

Système embarqué de triage intelligent de graines

Classification binaire de haricots blancs (bonne/mauvaise graine) en temps réel, CNN Keras sur PC, ESP32-CAM pour la capture et le tri. Stage de fin d'études du DTS (niveau L2), Fablab Solidaire Mamiratra.

L'objectif
Trier automatiquement des haricots (bonne ou mauvaise graine) sur une chaîne, avec une caméra et une machine de tri.
Ma démarche
Un CNN Keras entraîné sur PC, un ESP32-CAM pour la capture et la commande du servomoteur, les images échangées en HTTP.
Le résultat
98 % d'exactitude sur le jeu de test ; mon premier projet mêlant mécanique, systèmes embarqués et machine learning.

Contexte

Stage de fin d'études du DTS Génie Industriel et Maintenance (niveau L2, IST-T Antananarivo), réalisé au Fablab Solidaire Mamiratra de juillet à août 2023. C'était mon premier projet qui mélangeait mécanique, systèmes embarqués et machine learning.

Objectif : concevoir une machine compacte et économique pour trier automatiquement les haricots blancs (bonnes vs mauvaises graines) en remplaçant le tri manuel par une classification CNN en temps réel : l'ESP32-CAM capture l'image et actionne le tri, l'inférence tourne sur un ordinateur.

Dataset

340 images de haricots blancs capturées en conditions contrôlées (luminosité constante, même angle, même appareil) :

ClasseImages
Mauvaise graine209
Bonne graine131
Total340

Split : 60% entraînement / 30% validation / 10% test. Les images sont redimensionnées à 224×224 pixels avant entraînement.

Architecture du modèle CNN

Réseau convolutif binaire avec extracteur de caractéristiques (blocs Conv2D + MaxPooling) suivi d'un classifieur dense. Sortie : 1 neurone sigmoïde (classification binaire). 31 561 441 paramètres entraînables.

model = Sequential([
    Conv2D(32, (3, 3), activation='relu', input_shape=(224, 224, 3)),
    MaxPooling2D(2, 2),
    Conv2D(64, (3, 3), activation='relu'),
    MaxPooling2D(2, 2),
    Conv2D(128, (3, 3), activation='relu'),
    MaxPooling2D(2, 2),
    Flatten(),
    Dense(512, activation='relu'),
    Dropout(0.5),
    Dense(1, activation='sigmoid')
])
 
model.compile(
    optimizer='adam',
    loss='binary_crossentropy',
    metrics=['accuracy']
)

Entraînement

10 époques sur les 204 images d'entraînement, avec validation en temps réel sur les 102 images de validation.

ÉpoqueLossAccuracyVal LossVal Accuracy
12.39080.44790.62650.6250
20.66370.59380.58010.6146
30.55580.69790.50580.9792
40.44340.91670.31620.9583
50.26510.97400.24640.9062
60.14850.95830.07460.9792
70.05660.99480.09190.9688
80.05020.99480.01611.0000
90.02070.98960.01021.0000
Courbes loss et val_loss sur 10 époques
Courbes loss / val_loss, convergence jusqu'à l'époque 6, légère divergence ensuite

Résultats

98% d'accuracy sur le jeu de test (34 images non vues pendant l'entraînement). Le modèle est sauvegardé sous image_model.h5 et rechargé par le script d'inférence Python qui pilote la bascule via HTTP.

model = load_model('image_model.h5')
 
resp = requests.get('http://192.168.1.100/capture')
img = preprocess(resp.content)          # resize 224x224, normalize
pred = model.predict(img)[0][0]         # sigmoid → [0, 1]
 
direction = 'droite' if pred > 0.5 else 'gauche'  # seuil 0.5, version fonctionnelle initiale
requests.get(f'http://192.168.1.100/servo?dir={direction}')

Seuil de décision fixé à 0.5, frontière naturelle de la fonction sigmoid pour une classification binaire. Valeur choisie pour cette première version fonctionnelle.

Pipeline système

Chaîne de tri : la machine capture l'image, l'ordinateur prédit, le servomoteur trie
Chaîne de tri : la machine capture l'image, l'ordinateur prédit, le servomoteur trie

Limites

  • Dataset limité, 340 images au total, jeu de test de seulement 34 images. La valeur de 98% d'accuracy est statistiquement fragile sur un si petit échantillon de test.
  • Conditions contrôlées, luminosité fixe, angle fixe, même appareil. La robustesse du modèle en conditions réelles (variations d'éclairage, position des graines) n'a pas été testée.
  • Modèle surdimensionné, 31 561 441 paramètres pour une classification binaire simple. Un modèle beaucoup plus léger serait suffisant et plus adapté à un contexte embarqué.
  • Métriques basiques, seule l'accuracy a été mesurée. Matrice de confusion, F1-score et courbe ROC n'ont pas été calculés dans le cadre de ce projet L2.

Perspectives

  • Data augmentation, rotations, variations de luminosité, flips pour enrichir le dataset sans nouvelles captures
  • Transfer learning, remplacer le CNN custom par MobileNetV2, 10× plus léger et plus robuste sur petits datasets
  • Edge AI, déployer le modèle directement sur l'ESP32 via TensorFlow Lite pour éliminer la dépendance à l'ordinateur
  • Métriques complètes, calculer la matrice de confusion, précision et rappel par classe pour mieux évaluer les erreurs réelles du modèle

Système embarqué et mécanique

Un cylindre + disque perforé alimente les haricots un par un sur un plateau d'acquisition. L'ESP32-CAM capture la photo, l'ordinateur fait l'inférence CNN, puis commande le servomoteur SG90 qui bascule à droite (bonne graine) ou à gauche (mauvaise graine).

L'ESP32-CAM est programmée en C++ et configurée en point d'accès WiFi agissant comme serveur HTTP. L'ordinateur Python se connecte comme client.

Communication :

  • GET /capture.jpg, ESP32-CAM déclenche la rotation du disque, capture l'image et la retourne au PC
  • POST /prediction, PC envoie la décision CNN (0 ou 1), ESP32-CAM commande le servomoteur en conséquence

Composants partie opérative :

ComposantRôle
Moteur CC JgA25-370 (12V, 10 RPM)Rotation du disque perforé
Driver L298NRégulation vitesse et sens du moteur
Servomoteur SG90 (0°–180°)Bascule de tri droite/gauche
Vue éclatée du système
Vue éclatée, nomenclature des 9 pièces du mécanisme d'alimentation
Vue assemblée du système
Vue assemblée, cylindre et disque perforé montés
Système complet avec ESP32-CAM et servomoteur
Système complet, ESP32-CAM et servomoteur SG90 intégrés

Projets proches

Systèmes embarquésCybersécurité

Analyse et injection sur bus CAN automobile

Reverse engineering des trames CAN d'une maquette véhicule, cartographie des bus, décodage des signaux moteur/éclairage/confort, base DBC et DLL d'injection en C simulant un système ADAS.

2026Bus CANReverse EngineeringAutomotiveMuxTrace

Systèmes embarqués

Conception numérique en VHDL, de la simulation au FPGA Basys 3

En licence, une boîte à musique et le jeu de la vie décrits en VHDL et simulés sous ModelSim. En master, le passage sur FPGA Xilinx avec Vivado et une carte Basys 3, jusqu'à la conception complète d'un processeur 16 bits.

2026VHDLFPGAVivadoBasys 3

Systèmes embarqués

Distribution Linux embarquée avec Yocto pour une box domotique

Construction d'une distribution Linux sur mesure avec Yocto (Poky) pour la carte STM32MP135F-DK, avec une layer dédiée, une recette image systemd, un SDK et une application C qui lit un capteur I²C.

2026YoctoPokyBitBakeLinux embarqué