Category: robot

Robot MR25 – Détecter le frappement de main avec le microphone

On souhaite programmer le robot MR25 afin de contrôler ces mouvements via la détection des frappements de main :

👏 =>  Le robot MR25 avance

👏👏 =>  Le robot MR25 tourne à gauche

👏👏👏 =>  Le robot MR25 tourne à droite

👏👏👏👏 =>  Le robot MR25 s’arrête

Le microphone détecte les frappements en analysant le niveau sonore.

Algorithme

Voici un exemple de programme pour contrôler le robot avec le frappement de main :

import subprocess # permet de lancer le programme arecord pour récupérer le son du microphone.
import numpy as np # permet de traiter les données audio et de calculer le RMS.
import MR25
import time

DEVICE = "hw:0,0"
RATE = 48000
CHANNELS = 1
CHUNK = 1024

THRESHOLD = 0.01 # le seuil sonore.

# Temps minimum entre deux frappes
DEBOUNCE_TIME = 0.20

# Temps maximum pour regrouper les frappes
GROUP_TIMEOUT = 0.80
# Le programme attend au maximum 0,8 seconde après la dernière frappe.

cmd = [
"arecord",
"-D", DEVICE,
"-f", "S16_LE",
"-r", str(RATE),
"-c", str(CHANNELS),
"-t", "raw",
"-"
]

process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL
)

nombre_frappes = 0
derniere_frappe = 0
dernier_signal = 0

print("Écoute du microphone...")
print("1 frappe = LED rouge")
print("3 frappes = LED verte")
print("Ctrl+C pour arrêter.\n")

try:
while True:

data = process.stdout.read(CHUNK * 2)

if len(data) != CHUNK * 2:
break

audio = np.frombuffer(data, dtype=np.int16)
audio = audio.astype(np.float32) / 32768.0

volume = np.sqrt(np.mean(audio ** 2))

maintenant = time.time()

# Affichage du volume
bar = min(50, int(volume * 50))

print(
f"\rVolume : {volume:.3f} "
f"[{'#' * bar:<50}] "
f"Frappes : {nombre_frappes}",
end="",
flush=True
)

# Détection d'une frappe
if volume > THRESHOLD:

# Évite de compter plusieurs fois la même frappe
if maintenant - derniere_frappe > DEBOUNCE_TIME:

nombre_frappes += 1
derniere_frappe = maintenant

print(f"\n>>> Frappe {nombre_frappes}")

# Si le délai entre les frappes est dépassé,
# on analyse le nombre de frappes
if (
nombre_frappes > 0
and maintenant - derniere_frappe > GROUP_TIMEOUT
):

if nombre_frappes == 1:
print(">>> 1 FRAPPE : avancer")
MR25.ledRGB("100")
MR25.forward(30)
time.sleep(0.5)
MR25.ledRGB("000")

elif nombre_frappes == 2:
print(">>> 2 FRAPPES : tourner à gauche")
MR25.ledRGB("010")
MR25.turnLeft(30)
time.sleep(0.5)
MR25.ledRGB("000")

elif nombre_frappes == 3:
print(">>> 3 FRAPPES : tourner à droite")
MR25.ledRGB("001")
MR25.turnRight(30)
time.sleep(0.5)
MR25.ledRGB("000")

elif nombre_frappes == 4:
print(">>> 4 FRAPPES : STOP")
MR25.ledRGB("111")
MR25.stop()
time.sleep(0.5)
MR25.ledRGB("000")

else:
print(f">>> {nombre_frappes} frappes : aucune action")

# Réinitialisation
nombre_frappes = 0

except KeyboardInterrupt:
print("\n\nArrêt du robot.")
MR25.stop()

finally:
process.terminate()

Fin du tuto !

Réparation d’un robot mobile SCOUT 2.0

Aujourd’hui, Macé Robotics à réparer un robot mobile SCOUT 2.0. Ce robot, dédié à la recherche et à l’enseignement, présentait un dysfonctionnement au niveau d’un moteur : celui-ci ne tournait pas correctement, avec une perte de couple et une vitesse de rotation insuffisante. Les trois autres moteurs fonctionnent, quant à eux, correctement.

Robot SCOUT 2.0

Ce robot est équipé de quatre moteurs brushless, chacun piloté par un driver dédié. Les quatre drivers sont reliés à la carte mère du robot via un bus de communication CAN.

Le driver d’un moteur

Après démontage du robot et inspection de la carte driver, j’en déduis que le problème provient de la carte capteur du moteur BLDC. Un moteur Brushless DC (BLDC) doit connaître en permanence la position de son rotor afin que le driver puisse déterminer quelles phases alimenter et à quel moment. Cette information permet de synchroniser le champ magnétique généré par le stator avec la position du rotor et ainsi d’assurer une rotation correcte du moteur. En cas de défaut de détection de la position du rotor, cette synchronisation n’est plus assurée. Le moteur peut alors présenter différents symptômes : vibrations, perte de couple, vitesse de rotation incorrecte, rotation dans le mauvais sens ou encore impossibilité de démarrer. Ces symptômes correspondent précisément au comportement observé sur le moteur concerné du robot, ce qui oriente le diagnostic vers un dysfonctionnement de la carte capteur du moteur BLDC.

Démontage de la carte capteur du moteur

Ensuite, la carte capteur du moteur a été démontée afin d’effectuer une inspection plus approfondie. Cette carte est équipée d’un encodeur magnétique MT6825 ainsi que de deux drivers RS422 TPT4031. L’encodeur magnétique utilise les propriétés du champ magnétique pour mesurer avec précision la position angulaire du rotor. Pour permettre cette mesure, un aimant est fixé directement sur l’axe du moteur (voir photo). Lorsque le rotor tourne, l’aimant entraîne une variation du champ magnétique perçue par l’encodeur, qui peut ainsi déterminer la position angulaire du rotor et transmettre cette information à la carte driver.

Carte capteur du moteur BLDC

Après réparation de la carte capteur, la roue du robot fonctionne à nouveau correctement. Les performances du moteur sont revenues à la normale et le robot est désormais pleinement opérationnel. Le SCOUT 2.0 est donc prêt à reprendre du service et à partir pour de nouvelles aventures !

Bonne journée,

Nicolas

IA – Neurone artificiel avec le robot MR25 (Partie 2)

Présentation

Dans cet article nous allons apprendre au robot MR25 à éviter les obstacles en utilisant un neurone perception avec 5 entrées. Avec les 5 capteurs du robot, il est préférable de ne plus simplement décider avance / stop comme dans la partie n°1, mais aussi de choisir une direction lorsque l’on détecte un obstacle.

Voici l’idée :

  • Capteurs 1 et 2 → surveillent la gauche.
  • Capteur 3 → surveille le centre.
  • Capteurs 4 et 5 → surveillent la droite.

  • Distance proche de 0 mm → obstacle très proche.
  • Distance proche de 250 mm → espace libre.

On peut entraîner un perceptron à 5 entrées qui décide si le robot peut avancer, puis utiliser les capteurs pour déterminer le sens de rotation lorsqu’il ne peut pas avancer.

#!/usr/bin/python3

import MR25 # Bibliothèque de contrôle du robot MR25
import time # Pour les pauses dans la boucle principale

# ============================================================
# PERCEPTRON — Neurone artificiel à seuil
# ============================================================
# Un perceptron calcule une somme pondérée de ses entrées,
# puis applique une fonction d'activation pour décider : 0 ou 1.

def activation(x):
"""Fonction d'activation en échelon (step function).
Retourne 1 si x >= 0 (voie libre), 0 sinon (obstacle)."""
return 1 if x >= 0 else 0

# 5 poids — un par capteur de proximité (c1 à c5)
w = [0.0, 0.0, 0.0, 0.0, 0.0]
b = 0.0 # Biais : ajuste le seuil de décision
eta = 0.1 # Taux d'apprentissage (learning rate) : amplitude des corrections

# ============================================================
# DONNÉES D'ENTRAÎNEMENT
# ============================================================
# Chaque exemple est un couple ([c1,c2,c3,c4,c5], étiquette)
# Les valeurs des capteurs sont normalisées entre 0.0 et 1.0 :
# - Proche de 0.0 → obstacle détecté (capteur saturé)
# - Proche de 1.0 → voie dégagée (capteur à portée max)
# Étiquette : 0 = obstacle → s'arrêter/tourner, 1 = avancer

training_data = [
# --- Cas OBSTACLE : capteurs faibles (obstacles proches) ---
([0.1, 0.1, 0.1, 0.1, 0.1], 0), # Obstacles partout
([0.2, 0.2, 0.2, 0.2, 0.2], 0), # Obstacles proches
([0.3, 0.2, 0.1, 0.2, 0.3], 0), # Obstacle central fort
([0.2, 0.2, 0.2, 0.8, 0.8], 0), # Obstacles proches
([0.8, 0.8, 0.2, 0.2, 0.2], 0), # Obstacles proches

# --- Cas AVANCER : capteurs forts (voie libre) ---
([0.8, 0.8, 0.8, 0.8, 0.8], 1), # Voie totalement libre
([0.9, 0.8, 0.9, 0.8, 0.9], 1), # Voie très dégagée
([0.7, 0.9, 0.8, 0.9, 0.7], 1), # Voie dégagée (légère variation)
]

# ============================================================
# PHASE D'APPRENTISSAGE — Règle de Hebb / Perceptron
# ============================================================
# Pour chaque exemple, on calcule la sortie et on corrige les
# poids proportionnellement à l'erreur : Δw = η × erreur × entrée

for epoch in range(100): # Maximum 100 passes sur les données

erreur_totale = 0

for inputs, target in training_data:

# Calcul de la somme pondérée : s = Σ(wi × xi) + b
s = sum(wi * xi for wi, xi in zip(w, inputs)) + b

# Application de la fonction d'activation
y = activation(s)

# Erreur = différence entre valeur attendue et valeur calculée
erreur = target - y # 0, +1 ou -1

# Mise à jour des poids : correction proportionnelle à l'erreur
for i in range(5):
w[i] += eta * erreur * inputs[i]

# Mise à jour du biais (entrée fictive toujours égale à 1)
b += eta * erreur

erreur_totale += abs(erreur)

# Arrêt anticipé si le perceptron classe tout correctement
if erreur_totale == 0:
break

# Affichage des paramètres appris
print("Poids :", w)
print("Biais :", b)

# ============================================================
# PILOTAGE EN TEMPS RÉEL — Boucle principale
# ============================================================

SEUIL_MAX = 250.0 # Distance maximale de détection (en cm ou unité capteur)
# Au-delà, on considère la voie comme libre

try:
while True:

# --- Lecture et normalisation des 5 capteurs de proximité ---
# proxSensor(n) retourne une valeur brute ; on la plafonne à SEUIL_MAX,
# puis on divise pour obtenir un ratio entre 0.0 et 1.0
p1 = MR25.proxSensor(1)
p2 = MR25.proxSensor(2)
p3 = MR25.proxSensor(3)
p4 = MR25.proxSensor(4)
p5 = MR25.proxSensor(5)

capteurs = [p1, p2, p3, p4, p5]
print(capteurs)

c1 = min(p1, SEUIL_MAX) / SEUIL_MAX # Capteur avant-gauche extrême
c2 = min(p2, SEUIL_MAX) / SEUIL_MAX # Capteur avant-gauche
c3 = min(p3, SEUIL_MAX) / SEUIL_MAX # Capteur avant-centre
c4 = min(p4, SEUIL_MAX) / SEUIL_MAX # Capteur avant-droite
c5 = min(p5, SEUIL_MAX) / SEUIL_MAX # Capteur avant-droite extrême

entree = [c1, c2, c3, c4, c5]
print(entree)

# --- Inférence : le perceptron décide d'avancer ou non ---
s = sum(wi * xi for wi, xi in zip(w, entree)) + b
print("s = ", s)
avance = activation(s) # 1 = avancer, 0 = éviter l'obstacle

print("avance = ", avance)

if avance:
# Voie libre → avancer à vitesse modérée
MR25.forward(25)
print("AVANCE")

else:
# Obstacle détecté → choisir le côté le plus dégagé pour tourner

gauche = c1 + c2 # Score d'espace à gauche (somme des 2 capteurs gauches)
droite = c4 + c5 # Score d'espace à droite (somme des 2 capteurs droits)

# Le côté avec le score le plus élevé est le plus dégagé
if gauche > droite:
MR25.turnLeft(40) # Plus d'espace à gauche → tourner à gauche
print("TOURNE GAUCHE")
else:
MR25.turnRight(40) # Plus d'espace à droite (ou égalité) → tourner à droite
print("TOURNE DROITE")

time.sleep(0.2) # Pause

except KeyboardInterrupt:
# Arrêt propre du robot lors d'une interruption clavier (Ctrl+C)
MR25.stop()
# en of file

Le neurone perceptron simple est un modèle de prédiction linéaire. Il est nécessaire d’utiliser plusieurs couches (réseau) pour résoudre des problèmes plus complexes.

Fin !

MR25 play music

Le robot MR25 joue Star Wars :

Voici le programme en langage Python3 :

import MR25
import time

def star_wars():
melody = [
(440, 500), # A
(440, 500), # A
(440, 500), # A
(349, 350), # F
(523, 150), # C
(440, 500), # A
(349, 350), # F
(523, 150), # C
(440, 800), # A

(659, 500), # E
(659, 500), # E
(659, 500), # E
(698, 350), # F
(523, 150), # C
(415, 500), # G#
(349, 350), # F
(523, 150), # C
(440, 800), # A
]

for note, duree in melody:
MR25.buzzer(note, duree)
time.sleep(duree / 1000.0 + 0.05)

MR25.buzzerStop()

# Lecture de la mélodie
star_wars()

Le robot MR25 est disponible en boutique !

A bientôt,

Nicolas

Présentation du robot MR-25

MR-25 est un petit robot mobile basé sur une carte Raspberry Pi. Il est très facile à programmer et personnalisable.  Sa petite taille vous permet de facilement le programmer sur une table de bureau.

Ce robot est fabriqué de manière artisanale en Bretagne !

MADE IN FRANCE

Caractéristiques techniques :

 

 

  • Dimensions :
    • Diamètre de 130 mm
    • Hauteur : 85 mm
  • Compatible avec la carte Raspberry Pi 3, 4, 2W ou 5
  • Une Led RGB
  • Coprocesseur : Raspberry Pi Pico
  • Un buzzer
  • Un capteur de courant, mesure tension batterie
  • Deux encodeurs magnétiques
  • Deux moteurs à courant continu 100 RPM
  • 5 capteurs de distances Time-of-Flight VL6180X.
  • Batterie : 3 accumulateurs 18650 lithuim
  • Un bouton on/off
  • Un connecteur de rechargement de la batterie

Exemple de création de carte avec les capteurs :

 

Robot programmable : 

Le robot MR-25 est programmable en langage Python3 :

/static/community_logos/python-logo.png

 

Traitement d’images

Le robot MR-25 peut être équipé d’une caméra Pi pour faire du traitement d’images avec Open Cv.

Documentation du robot MR-25

Lien du document PDF

 

Licences Hardware et Software: