Boitier d'apprentissage du BRAILLE : Différence entre versions

(Page créée avec « {{Tuto Details |Licences=Attribution (CC BY) |Description=<translate>Ce projet a pour but de faciliter l'apprentissage du braille à travers un boîtier interactif contrô... »)
 
 
(12 révisions intermédiaires par le même utilisateur non affichées)
Ligne 1 : Ligne 1 :
 
{{Tuto Details
 
{{Tuto Details
 +
|Main_Picture=Boitier_d_apprentissage_du_BRAILLE_IMG_8518.JPG
 
|Licences=Attribution (CC BY)
 
|Licences=Attribution (CC BY)
 
|Description=<translate>Ce projet a pour but de faciliter l'apprentissage du braille à travers un boîtier interactif contrôlé par reconnaissance vocale, synthèse vocale . Il utilise des servomoteurs pour afficher les caractères en braille, et propose deux modes d'apprentissage différents. Il a été réalisé dans le cadre du projet de terminale STI2D.</translate>
 
|Description=<translate>Ce projet a pour but de faciliter l'apprentissage du braille à travers un boîtier interactif contrôlé par reconnaissance vocale, synthèse vocale . Il utilise des servomoteurs pour afficher les caractères en braille, et propose deux modes d'apprentissage différents. Il a été réalisé dans le cadre du projet de terminale STI2D.</translate>
Ligne 12 : Ligne 13 :
 
}}
 
}}
 
{{Introduction
 
{{Introduction
|Introduction=<translate></translate>
+
|Introduction=<translate>Ce projet consiste en la réalisation d’un boîtier interactif permettant l’apprentissage du braille, à destination des personnes non-voyantes ou malvoyantes ou toutes personnes voulant apprendre le braille. Conçu dans le cadre d’un projet de Terminale STI2D, ce dispositif utilise des servomoteurs, un Raspberry Pi, et un système de reconnaissance vocale pour traduire des lettres en braille physique.
 +
 
 +
Le boîtier propose deux modes d’apprentissage :
 +
 
 +
-Un mode où l’utilisateur prononce une lettre, et le système la répète à voix haute avant de l’afficher en braille tactile.
 +
 
 +
-Un mode aléatoire où le boîtier choisit une lettre, la prononce, et laisse l’utilisateur deviner.
 +
 
 +
Le projet a été imaginé pour favoriser l’autonomie des personnes déficientes visuelles tout en rendant l’apprentissage du braille plus ludique et accessible. Il mêle électronique, programmation Python, impression 3D et design inclusif.</translate>
 
}}
 
}}
 
{{Materials
 
{{Materials
|Material=<translate></translate>
+
|Material=<translate>-1 raspberry pi 3
|Tools=<translate></translate>
+
 
}}
+
-6 servo moteurs
{{Tuto Step
+
 
|Step_Title=<translate>Installation des bibliothèques Python</translate>
+
-1 shield Grove raspberry pi  (Module Grove Base Hat 103030275)
|Step_Content=<translate>Pour faire fonctionner le code de votre projet, il est nécessaire d’installer plusieurs bibliothèques Python. Certaines ne sont pas directement disponibles et nécessitent la création d’un '''environnement virtuel''' Python. Voici les étapes détaillées à suivre.
 
  
=== 1. Mettre à jour votre Raspberry Pi ===
+
-6 câbles Groves
Avant toute chose, assurez-vous que votre Raspberry Pi est à jour en lançant les commandes suivantes dans le terminal :
 
  
'''sudo apt update'''
+
-1 haut parleur (Module haut-parleur SKU00101)
  
'''sudo apt upgrade'''
+
-2 Câbles femelle femelle
  
=== 2. Installer le module pour créer un environnement virtuel ===
+
-1 microphone (Microphone dongle USB ADA3367)
Si ce n’est pas déjà fait, installez le package '''python3-venv''' qui permet de créer un environnement virtuel Python :
 
  
'''sudo apt install python3-venv'''
+
-1 Cordon Jack CA35M</translate>
 +
|Tools=<translate></translate>
 +
|Tuto_Attachments={{Tuto Attachments}}
 +
}}
 +
{{Tuto Step
 +
|Step_Title=<translate>Installer le module pour créer un environnement virtuel</translate>
 +
|Step_Content=<translate>Si ce n’est pas déjà fait, installez le package '''python3-venv''' qui permet de créer un environnement virtuel Python :
  
=== 3. Créer et activer un environnement virtuel ===
+
'''sudo apt install python3-venv'''</translate>
Placez-vous dans le dossier où vous souhaitez créer votre projet (par exemple, '''~/mon_projet_braille''') avec la commande :
+
}}
 +
{{Tuto Step
 +
|Step_Title=<translate>Créer et activer un environnement virtuel</translate>
 +
|Step_Content=<translate>Placez-vous dans le dossier où vous souhaitez créer votre projet (par exemple, '''~/mon_projet_braille''') avec la commande :
  
 
'''cd ~/mon_projet_braille'''
 
'''cd ~/mon_projet_braille'''
Ligne 45 : Ligne 60 :
 
Activez ensuite cet environnement avec la commande :
 
Activez ensuite cet environnement avec la commande :
  
'''source nom_de_lenvironnement/bin/activate'''
+
'''source nom_de_lenvironnement/bin/activate'''</translate>
 +
}}
 +
{{Tuto Step
 +
|Step_Title=<translate>Installer les bibliothèques Python nécessaires</translate>
 +
|Step_Content=<translate>Avec l’environnement virtuel activé, installez les bibliothèques suivantes :
  
=== 4. Installer les bibliothèques Python nécessaires ===
+
'''pip install vosk pyaudio numpy'''</translate>
Avec l’environnement virtuel activé, installez les bibliothèques suivantes :
+
}}
 +
{{Tuto Step
 +
|Step_Title=<translate>Installer les dépendances système pour PyAudio</translate>
 +
|Step_Content=<translate>PyAudio nécessite des paquets système spécifiques pour fonctionner avec le microphone. Installez-les avec :
  
'''pip install vosk pyaudio numpy'''
+
'''sudo apt install portaudio19-dev python3-pyaudio'''</translate>
 
+
}}
Pour contrôler les servomoteurs, installez également les bibliothèques Adafruit nécessaires :
+
{{Tuto Step
 
+
|Step_Title=<translate>Installer le modèle Vosk pour la reconnaissance vocale</translate>
'''pip install adafruit-pca9685 adafruit-circuitpython-pca9685 adafruit-circuitpython-motor'''
+
|Step_Content=<translate>Pour que Vosk puisse effectuer la reconnaissance vocale en français, il faut télécharger et décompresser un modèle de langue.
 
 
=== 5. Installer les dépendances système pour PyAudio ===
 
PyAudio nécessite des paquets système spécifiques pour fonctionner avec le microphone. Installez-les avec :
 
 
 
'''sudo apt install portaudio19-dev python3-pyaudio'''
 
 
 
=== 6. Installer le modèle Vosk pour la reconnaissance vocale ===
 
Pour que Vosk puisse effectuer la reconnaissance vocale en français, il faut télécharger et décompresser un modèle de langue.
 
  
 
Téléchargez le modèle ici :
 
Téléchargez le modèle ici :
Ligne 68 : Ligne 82 :
 
https://alphacephei.com/vosk/models/vosk-model-small-fr-0.22.zip
 
https://alphacephei.com/vosk/models/vosk-model-small-fr-0.22.zip
  
Puis décompressez-le dans le même dossier que votre script Python avec la commande :
+
Puis décompressez-le avec la commande :
  
 
'''unzip vosk-model-small-fr-0.22.zip'''
 
'''unzip vosk-model-small-fr-0.22.zip'''
  
=== 7. Désactiver l’environnement virtuel (optionnel) ===
+
Ensuite mettez le modèle dans le même dossier que votre script Python.</translate>
Lorsque vous avez fini d’installer les bibliothèques et de travailler dans l’environnement virtuel, vous pouvez le désactiver avec la commande :
+
}}
 +
{{Tuto Step
 +
|Step_Title=<translate>Désactiver l’environnement virtuel (optionnel)</translate>
 +
|Step_Content=<translate>Lorsque vous avez fini d’installer les bibliothèques et de travailler dans l’environnement virtuel, vous pouvez le désactiver avec la commande :
  
 
'''deactivate'''</translate>
 
'''deactivate'''</translate>
 
}}
 
}}
 
{{Tuto Step
 
{{Tuto Step
|Step_Title=<translate>Installation des bibliothèques Python</translate>
+
|Step_Title=<translate>Code</translate>
|Step_Content=<translate>Pour faire fonctionner le code de votre projet, il est nécessaire d’installer plusieurs bibliothèques Python. Certaines ne sont pas directement disponibles et nécessitent la création d’un '''environnement virtuel''' Python. Voici les étapes détaillées à suivre.
+
|Step_Content=<translate>Ce programme Python tourne sur un Raspberry Pi et permet de piloter les 6 servomoteurs qui affichent les lettres en braille, selon les commandes vocales de l'utilisateur.
 +
 
 +
Le système fonctionne en deux modes :
 +
 
 +
-Un mode d’apprentissage : l’utilisateur dit une lettre, elle est reconnue, prononcée et affichée en braille.
 +
 
 +
-Un mode test : le système choisit aléatoirement des lettres à afficher pour entraîner l’utilisateur.
 +
 
 +
Le code gère :
 +
 
 +
-la configuration des moteurs via les broches GPIO,
 +
 
 +
-la reconnaissance vocale (grâce au module Vosk),
 +
 
 +
-la synthèse vocale (avec espeak),
 +
 
 +
-la gestion des différents modes.
 +
 
 +
Ce script permet donc d’assurer à la fois l’interaction avec l’utilisateur, le traitement de la voix, et l’affichage mécanique du braille.
 +
 
 +
 
 +
from vosk import Model, KaldiRecognizer
 +
 
 +
import pyaudio
 +
 
 +
import json
 +
 
 +
import RPi.GPIO as GPIO
 +
 
 +
import time
 +
 
 +
import subprocess
 +
 
 +
import random
 +
 
 +
import logging
 +
 
 +
import os
 +
 
 +
import sys
 +
 
 +
<nowiki>#</nowiki> Configuration du système de journalisation
 +
 
 +
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
 +
 
 +
logger = logging.getLogger(__name__)
 +
 
 +
<nowiki>#</nowiki> Chemins de configuration - à ajuster selon votre environnement
 +
 
 +
MODEL_PATH = os.getenv("VOSK_MODEL_PATH", "/home/sin2025/models/vosk-model-small-fr-0.22")
 +
 
 +
AUDIO_PATH = os.getenv("AUDIO_PATH", "/home/sin2025/ressources")
 +
 
 +
<nowiki>#</nowiki> Configuration des GPIO pour les servomoteurs
 +
 
 +
servo_pins = [18, 26, 16, 24, 5, 22]
 +
 
 +
<nowiki>#</nowiki> Définition des positions des servos pour représenter les lettres en braille
 +
 
 +
definitions_braille = {
 +
 
 +
"A": [1, 0, 0, 0, 0, 0], "B": [1, 1, 0, 0, 0, 0],
 +
 
 +
"C": [1, 0, 0, 1, 0, 0], "D": [1, 0, 0, 1, 1, 0],
 +
 
 +
"E": [1, 0, 0, 0, 1, 0], "F": [1, 1, 0, 1, 0, 0],
 +
 
 +
"G": [1, 1, 0, 1, 1, 0], "H": [1, 1, 0, 0, 1, 0],
 +
 
 +
"I": [0, 1, 0, 1, 0, 0], "J": [0, 1, 0, 1, 1, 0],
 +
 
 +
"K": [1, 0, 1, 0, 0, 0], "L": [1, 1, 1, 0, 0, 0],
 +
 
 +
"M": [1, 0, 1, 1, 0, 0], "N": [1, 0, 1, 1, 1, 0],
 +
 
 +
"O": [1, 0, 1, 0, 1, 0], "P": [1, 1, 1, 1, 0, 0],
 +
 
 +
"Q": [1, 1, 1, 1, 1, 0], "R": [1, 1, 1, 0, 1, 0],
 +
 
 +
"S": [0, 1, 1, 1, 0, 0], "T": [0, 1, 1, 1, 1, 0],
 +
 
 +
"U": [1, 0, 1, 0, 0, 1], "V": [1, 1, 1, 0, 0, 1],
 +
 
 +
"W": [0, 1, 0, 1, 1, 1], "X": [1, 0, 1, 1, 0, 1],
 +
 
 +
"Y": [1, 0, 1, 1, 1, 1], "Z": [1, 0, 1, 0, 1, 1]
 +
 
 +
}
 +
 
 +
<nowiki>#</nowiki> Vocabulaire de reconnaissance vocale avec correspondances phonétiques
 +
 
 +
mots_vers_lettres = {
 +
 
 +
"ah": "A", "a": "A",
 +
 
 +
"mais": "B", "b": "B",
 +
 
 +
"c'est": "C", "c": "C",
 +
 
 +
"des": "D", "d": "D",
 +
 
 +
"euh": "E", "eux": "E", "e": "E",
 +
 
 +
"f": "F",
 +
 
 +
"j'ai": "G", "g": "G",
 +
 
 +
"hache": "H", "h": "H",
 +
 
 +
"i": "I", "aïe": "I", "hey": "I",
 +
 
 +
"j": "J",
 +
 
 +
"k": "K", "ca": "K",
 +
 
 +
"l": "L", "elle": "L",
 +
 
 +
"m": "M",
 +
 
 +
"n": "N",
 +
 
 +
"o": "O", "oh": "O", "eau": "O",
 +
 
 +
"p": "P", "pet": "P", "paix": "P",
 +
 
 +
"q": "Q", "cul": "Q",
 +
 
 +
"r": "R", "air": "R",
 +
 
 +
"s": "S",
 +
 
 +
"the": "T", "t": "T",
 +
 
 +
"u": "U", "hu": "U",
 +
 
 +
"v": "V", "vais": "V",
 +
 
 +
"w": "W", "double v": "W",
 +
 
 +
"x": "X",
 +
 
 +
"y": "Y", "ii grec": "Y", "les grecs": "Y", "grec": "Y", "le grec": "Y",
 +
 
 +
"z": "Z",
 +
 
 +
"mode un": "Mode 1",
 +
 
 +
"mode deux": "Mode 2",
 +
 
 +
"mode de": "Mode 2",
 +
 
 +
"fin": "Fin"
 +
 
 +
}
 +
 
 +
class BrailleReader:
 +
 
 +
def __init__(self):
 +
 
 +
<nowiki>#</nowiki> Initialiser les servomoteurs
 +
 
 +
self.initialize_servos()
 +
 
 +
 
 +
<nowiki>#</nowiki> Initialiser l'audio et la reconnaissance vocale
 +
 
 +
self.initialize_audio()
 +
 
 +
 
 +
<nowiki>#</nowiki> Mode actuel de l'application (0 = sélection de mode, 1 = Mode 1, 2 = Mode 2)
 +
 
 +
self.current_mode = 0
 +
 
 +
 
 +
<nowiki>#</nowiki> Indicateur si l'application est en cours d'exécution
 +
 
 +
self.running = True
 +
 
 +
 
 +
<nowiki>#</nowiki> Indicateur si le système est en train de parler
 +
 
 +
self.is_speaking = False
 +
 
 +
 
 +
<nowiki>#</nowiki> Heure de fin de la dernière synthèse vocale (pour éviter l'auto-écoute)
 +
 
 +
self.last_speech_time = 0
 +
 
 +
 
 +
<nowiki>#</nowiki> Délai minimum après synthèse vocale pour éviter l'auto-écoute (en secondes)
 +
 
 +
self.speech_cooldown = 1.0
 +
 
 +
 
 +
logger.info("Lecteur Braille initialisé et prêt")
 +
 
 +
def initialize_servos(self):
 +
 
 +
"""Initialiser les GPIO et les servomoteurs"""
 +
 
 +
logger.info("Initialisation des GPIO et servomoteurs")
 +
 
 +
 
 +
<nowiki>#</nowiki> Nettoyer toutes les configurations GPIO précédentes
 +
 
 +
GPIO.cleanup()
 +
 
 +
 
 +
<nowiki>#</nowiki> Configurer le mode GPIO
 +
 
 +
GPIO.setmode(GPIO.BCM)
 +
 
 +
 
 +
<nowiki>#</nowiki> Initialiser les servomoteurs
 +
 
 +
self.servos = []
 +
 
 +
for pin in servo_pins:
 +
 
 +
GPIO.setup(pin, GPIO.OUT)
 +
 
 +
servo = GPIO.PWM(pin, 50)  # Fréquence PWM de 50Hz
 +
 
 +
servo.start(0)
 +
 
 +
self.servos.append(servo)
 +
 
 +
 
 +
<nowiki>#</nowiki> Remettre tous les servos en position 0
 +
 
 +
self.reset_servos()
 +
 
 +
 
 +
logger.info("Servomoteurs initialisés")
 +
 
 +
def initialize_audio(self):
 +
 
 +
"""Initialiser l'entrée audio et la reconnaissance vocale"""
 +
 
 +
logger.info("Initialisation de l'audio et de la reconnaissance vocale")
 +
 
 +
 
 +
try:
 +
 
 +
<nowiki>#</nowiki> Initialiser le modèle Vosk
 +
 
 +
self.model = Model(MODEL_PATH)
 +
 
 +
 
 +
<nowiki>#</nowiki> Créer la chaîne de vocabulaire à partir du dictionnaire mots_vers_lettres
 +
 
 +
vocabulaire = "[ \"" + "\", \"".join(mots_vers_lettres.keys()) + "\" ]"
 +
 
 +
 
 +
<nowiki>#</nowiki> Initialiser le reconnaisseur avec le vocabulaire
 +
 
 +
self.rec = KaldiRecognizer(self.model, 44100, vocabulaire)
 +
 
 +
 
 +
<nowiki>#</nowiki> Initialiser PyAudio
 +
 
 +
self.p = pyaudio.PyAudio()
 +
 
 +
self.stream = self.p.open(
 +
 
 +
format=pyaudio.paInt16,
 +
 
 +
channels=1,
 +
 
 +
rate=44100,
 +
 
 +
input=True,
 +
 
 +
frames_per_buffer=8000
 +
 
 +
)
 +
 
 +
self.stream.start_stream()
 +
 
 +
 
 +
logger.info("Audio et reconnaissance vocale initialisés")
 +
 
 +
except Exception as e:
 +
 
 +
logger.error(f"Erreur lors de l'initialisation audio: {e}")
 +
 
 +
sys.exit(1)
 +
 
 +
def set_servo_angle(self, servo, angle):
 +
 
 +
"""Définir l'angle du servomoteur"""
 +
 
 +
duty_cycle = (angle / 18) + 2
 +
 
 +
servo.ChangeDutyCycle(duty_cycle)
 +
 
 +
time.sleep(0.3)
 +
 
 +
servo.ChangeDutyCycle(0)
 +
 
 +
def reset_servos(self):
 +
 
 +
"""Remettre tous les servos en position 0"""
 +
 
 +
for servo in self.servos:
 +
 
 +
self.set_servo_angle(servo, 0)
 +
 
 +
def afficher_braille(self, lettre):
 +
 
 +
"""Afficher une lettre en Braille en utilisant les servomoteurs"""
 +
 
 +
if lettre in definitions_braille:
 +
 
 +
for i in range(6):
 +
 
 +
self.set_servo_angle(
 +
 
 +
self.servos[i],
 +
 
 +
90 if definitions_braille[lettre][i] else 0
 +
 
 +
)
 +
 
 +
return True
 +
 
 +
return False
 +
 
 +
def speak_text(self, text):
 +
 
 +
"""Utiliser espeak pour convertir le texte en parole"""
 +
 
 +
try:
 +
 
 +
<nowiki>#</nowiki> Marquer que nous commençons à parler
 +
 
 +
self.is_speaking = True
 +
 
 +
 
 +
<nowiki>#</nowiki> Mettre en pause la reconnaissance pour éviter l'auto-écoute
 +
 
 +
self.toggle_recognition_stream(pause=True)
 +
 
 +
 
 +
subprocess.run(
 +
 
 +
["espeak", "-v", "fr", "-s", "200", "-p", "100", "-a", "1000", text],
 +
 
 +
stdout=subprocess.DEVNULL,
 +
 
 +
stderr=subprocess.DEVNULL
 +
 
 +
)
 +
 
 +
 
 +
<nowiki>#</nowiki> Enregistrer quand nous avons fini de parler
 +
 
 +
self.last_speech_time = time.time()
 +
 
 +
 
 +
<nowiki>#</nowiki> Marquer que nous avons fini de parler
 +
 
 +
self.is_speaking = False
 +
 
 +
 
 +
<nowiki>#</nowiki> Attendre un court délai avant de reprendre la reconnaissance
 +
 
 +
time.sleep(0.5)  # Courte attente pour s'assurer qu'espeak est complètement terminé
 +
 
 +
 
 +
<nowiki>#</nowiki> Reprendre la reconnaissance
 +
 
 +
self.toggle_recognition_stream(pause=False)
 +
 
 +
 
 +
<nowiki>#</nowiki> Ajouter un délai pour éviter la reconnaissance immédiate (auto-écoute)
 +
 
 +
time.sleep(0.5)
 +
 
 +
 
 +
except Exception as e:
 +
 
 +
logger.error(f"Erreur avec la synthèse vocale: {e}")
 +
 
 +
self.is_speaking = False
 +
 
 +
self.toggle_recognition_stream(pause=False)
 +
 
 +
def play_audio(self, file_name):
 +
 
 +
"""Lire un fichier audio en utilisant ffmpeg"""
 +
 
 +
try:
 +
 
 +
<nowiki>#</nowiki> Marquer que nous commençons à parler
 +
 
 +
self.is_speaking = True
 +
 
 +
 
 +
<nowiki>#</nowiki> Mettre en pause la reconnaissance pour éviter l'auto-écoute
 +
 
 +
self.toggle_recognition_stream(pause=True)
 +
 
 +
 
 +
file_path = os.path.join(AUDIO_PATH, file_name)
 +
 
 +
if os.path.exists(file_path):
 +
 
 +
subprocess.run(
 +
 
 +
["ffmpeg", "-i", file_path, "-f", "alsa", "default"],
 +
 
 +
stdout=subprocess.DEVNULL,
 +
 
 +
stderr=subprocess.DEVNULL
 +
 
 +
)
 +
 
 +
else:
 +
 
 +
logger.warning(f"Fichier audio introuvable: {file_path}")
 +
 
 +
<nowiki>#</nowiki> Utiliser espeak comme solution de repli si le fichier n'est pas trouvé
 +
 
 +
self.speak_text(file_name.replace(".mp3", ""))
 +
 
 +
 
 +
<nowiki>#</nowiki> Enregistrer quand nous avons fini de parler
 +
 
 +
self.last_speech_time = time.time()
 +
 
 +
 
 +
<nowiki>#</nowiki> Marquer que nous avons fini de parler
 +
 
 +
self.is_speaking = False
 +
 
 +
 
 +
<nowiki>#</nowiki> Attendre un court délai avant de reprendre la reconnaissance
 +
 
 +
time.sleep(0.5)
 +
 
 +
 
 +
<nowiki>#</nowiki> Reprendre la reconnaissance
 +
 
 +
self.toggle_recognition_stream(pause=False)
 +
 
 +
 
 +
except Exception as e:
 +
 
 +
logger.error(f"Erreur lors de la lecture audio: {e}")
 +
 
 +
self.is_speaking = False
 +
 
 +
self.toggle_recognition_stream(pause=False)
 +
 
 +
def toggle_recognition_stream(self, pause=True):
 +
 
 +
"""Mettre en pause ou reprendre le flux de reconnaissance audio"""
 +
 
 +
if pause:
 +
 
 +
self.stream.stop_stream()
 +
 
 +
else:
 +
 
 +
self.stream.start_stream()
 +
 
 +
def recognize_speech(self, timeout=5):
 +
 
 +
"""Écouter la parole et retourner le texte reconnu"""
 +
 
 +
<nowiki>#</nowiki> Si nous sommes en train de parler ou venons de finir, ne pas écouter encore
 +
 
 +
if self.is_speaking:
 +
 
 +
return None
 +
 
 +
 
 +
<nowiki>#</nowiki> Vérifier si nous sommes encore dans la période de délai après avoir parlé
 +
 
 +
if time.time() - self.last_speech_time < self.speech_cooldown:
 +
 
 +
return None
 +
 
 +
 
 +
start_time = time.time()
 +
 
 +
while time.time() - start_time < timeout:
 +
 
 +
data = self.stream.read(4000, exception_on_overflow=False)
 +
 
 +
 
 +
if self.rec.AcceptWaveform(data):
 +
 
 +
result = json.loads(self.rec.Result())
 +
 
 +
if "text" in result and result["text"].strip():
 +
 
 +
recognized_text = result["text"].lower()
 +
 
 +
logger.debug(f"Recognized: {recognized_text}")
 +
 
 +
return recognized_text
 +
 
 +
 
 +
return None
 +
 
 +
def mode_selection(self):
 +
 
 +
"""Interface de sélection du mode"""
 +
 
 +
logger.info("Entrée dans la sélection de mode")
 +
 
 +
 
 +
<nowiki>#</nowiki> Remettre les servos à zéro
 +
 
 +
self.reset_servos()
 +
 
 +
 
 +
<nowiki>#</nowiki> Message de bienvenue
 +
 
 +
self.speak_text("Bienvenue au système d'apprentissage de Braille")
 +
 
 +
self.speak_text("Dites Mode un ou Mode deux pour commencer")
 +
 
 +
 
 +
while self.current_mode == 0 and self.running:
 +
 
 +
<nowiki>#</nowiki> Écouter pour la sélection de mode
 +
 
 +
recognized_text = self.recognize_speech()
 +
 
 +
 
 +
if recognized_text:
 +
 
 +
if recognized_text in mots_vers_lettres:
 +
 
 +
command = mots_vers_lettres[recognized_text]
 +
 
 +
 
 +
<nowiki>#</nowiki> Gérer la sélection de mode
 +
 
 +
if command == "Mode 1":
 +
 
 +
self.speak_text("Mode un sélectionné")
 +
 
 +
self.current_mode = 1
 +
 
 +
logger.info("Mode 1 sélectionné")
 +
 
 +
elif command == "Mode 2":
 +
 
 +
self.speak_text("Mode deux sélectionné")
 +
 
 +
self.current_mode = 2
 +
 
 +
logger.info("Mode 2 sélectionné")
 +
 
 +
elif command == "Fin":
 +
 
 +
self.speak_text("Au revoir")
 +
 
 +
self.running = False
 +
 
 +
else:
 +
 
 +
self.speak_text("Commande non reconnue")
 +
 
 +
else:
 +
 
 +
self.speak_text("Commande non reconnue")
 +
 
 +
def mode_1(self):
 +
 
 +
"""Mode 1: L'utilisateur dit une lettre, le système la prononce et l'affiche"""
 +
 
 +
logger.info("Démarrage du Mode 1")
 +
 
 +
 
 +
<nowiki>#</nowiki> Introduction pour le Mode 1
 +
 
 +
self.speak_text("Mode un. Dites une lettre, je vais la prononcer et l'afficher en braille")
 +
 
 +
self.speak_text("Dites fin pour revenir au menu principal")
 +
 
 +
 
 +
while self.current_mode == 1 and self.running:
 +
 
 +
<nowiki>#</nowiki> Attendre l'entrée d'une lettre
 +
 
 +
recognized_text = self.recognize_speech()
 +
 
 +
 
 +
if recognized_text and not self.is_speaking:
 +
 
 +
if recognized_text in mots_vers_lettres:
 +
 
 +
command = mots_vers_lettres[recognized_text]
 +
 
 +
 
 +
<nowiki>#</nowiki> Vérifier si l'utilisateur veut sortir
 +
 
 +
if command == "Fin":
 +
 
 +
self.speak_text("Fin du mode un")
 +
 
 +
self.current_mode = 0
 +
 
 +
logger.info("Sortie du Mode 1")
 +
 
 +
break
 +
 
 +
 
 +
<nowiki>#</nowiki> Gérer l'affichage de la lettre
 +
 
 +
if len(command) == 1 and command in definitions_braille:
 +
 
 +
logger.info(f"Affichage de la lettre: {command}")
 +
 
 +
 
 +
<nowiki>#</nowiki> Afficher d'abord la lettre en braille
 +
 
 +
self.afficher_braille(command)
 +
 
 +
 
 +
<nowiki>#</nowiki> Puis prononcer la lettre avec reconnaissance désactivée pour éviter l'auto-écoute
 +
 
 +
self.speak_text(command)
 +
 
 +
else:
 +
 
 +
self.speak_text("Ce n'est pas une lettre valide")
 +
 
 +
else:
 +
 
 +
self.speak_text("Commande non reconnue")
 +
 
 +
def mode_2(self):
 +
 
 +
"""Mode 2: Le système affiche aléatoirement des lettres"""
 +
 
 +
logger.info("Démarrage du Mode 2")
 +
 
 +
 
 +
<nowiki>#</nowiki> Introduction pour le Mode 2
 +
 
 +
self.speak_text("Mode deux. Je vais afficher des lettres aléatoires en braille")
 +
 
 +
self.speak_text("Dites fin pour revenir au menu principal")
 +
 
 +
 
 +
while self.current_mode == 2 and self.running:
 +
 
 +
<nowiki>#</nowiki> Afficher une lettre aléatoire
 +
 
 +
random_letter = random.choice(list(definitions_braille.keys()))
 +
 
 +
logger.info(f"Affichage de la lettre aléatoire: {random_letter}")
  
=== 1. Mettre à jour votre Raspberry Pi ===
 
Avant toute chose, assurez-vous que votre Raspberry Pi est à jour en lançant les commandes suivantes dans le terminal :
 
  
'''sudo apt update'''
+
<nowiki>#</nowiki> Prononcer et afficher la lettre
  
'''sudo apt upgrade'''
+
self.afficher_braille(random_letter)
  
=== 2. Installer le module pour créer un environnement virtuel ===
+
self.speak_text(random_letter)
Si ce n’est pas déjà fait, installez le package '''python3-venv''' qui permet de créer un environnement virtuel Python :
 
  
'''sudo apt install python3-venv'''
 
  
=== 3. Créer et activer un environnement virtuel ===
+
<nowiki>#</nowiki> Attendre un moment pour permettre à l'utilisateur de dire "fin" si nécessaire
Placez-vous dans le dossier où vous souhaitez créer votre projet (par exemple, '''~/mon_projet_braille''') avec la commande :
 
  
'''cd ~/mon_projet_braille'''
+
time.sleep(2) 
 +
 
 +
 
 +
<nowiki>#</nowiki> Vérifier les commandes vocales (même pendant la séquence d'affichage)
 +
 
 +
recognized_text = self.recognize_speech(timeout=1)
 +
 
 +
 
 +
if recognized_text and recognized_text in mots_vers_lettres:
 +
 
 +
command = mots_vers_lettres[recognized_text]
 +
 
 +
 
 +
if command == "Fin":
 +
 
 +
self.speak_text("Fin du mode deux")
 +
 
 +
self.current_mode = 0
 +
 
 +
logger.info("Sortie du Mode 2")
 +
 
 +
return
 +
 
 +
def cleanup(self):
 +
 
 +
"""Nettoyer les ressources à la sortie"""
 +
 
 +
logger.info("Nettoyage des ressources")
 +
 
 +
 
 +
<nowiki>#</nowiki> Remettre les servos à zéro
 +
 
 +
self.reset_servos()
 +
 
 +
 
 +
<nowiki>#</nowiki> Arrêter tous les servos
 +
 
 +
for servo in self.servos:
 +
 
 +
servo.stop()
 +
 
 +
 
 +
<nowiki>#</nowiki> Nettoyer les GPIO
 +
 
 +
GPIO.cleanup()
 +
 
 +
 
 +
<nowiki>#</nowiki> Arrêter et fermer le flux audio
 +
 
 +
if hasattr(self, 'stream'):
 +
 
 +
self.stream.stop_stream()
 +
 
 +
self.stream.close()
 +
 
 +
 
 +
<nowiki>#</nowiki> Terminer PyAudio
 +
 
 +
if hasattr(self, 'p'):
 +
 
 +
self.p.terminate()
 +
 
 +
 
 +
logger.info("Nettoyage terminé")
 +
 
 +
def run(self):
 +
 
 +
"""Boucle principale de l'application"""
 +
 
 +
logger.info("Démarrage de l'application Lecteur Braille")
 +
 
 +
 
 +
try:
 +
 
 +
while self.running:
 +
 
 +
<nowiki>#</nowiki> Sélection de mode
 +
 
 +
if self.current_mode == 0:
 +
 
 +
self.mode_selection()
 +
 
 +
<nowiki>#</nowiki> Mode 1
 +
 
 +
elif self.current_mode == 1:
 +
 
 +
self.mode_1()
 +
 
 +
<nowiki>#</nowiki> Mode 2
 +
 
 +
elif self.current_mode == 2:
 +
 
 +
self.mode_2()
 +
 
 +
except KeyboardInterrupt:
 +
 
 +
logger.info("Application terminée par l'utilisateur")
 +
 
 +
except Exception as e:
 +
 
 +
logger.error(f"Erreur inattendue: {e}")
 +
 
 +
finally:
 +
 
 +
self.cleanup()
  
Puis créez un environnement virtuel en remplaçant '''nom_de_lenvironnement''' par le nom que vous souhaitez donner à cet environnement :
+
if __name__ == "__main__":
  
'''python3 -m venv nom_de_lenvironnement'''
+
reader = BrailleReader()
  
Activez ensuite cet environnement avec la commande :
+
reader.run()</translate>
 +
}}
 +
{{Tuto Step
 +
|Step_Title=<translate>Branchement</translate>
 +
|Step_Content=<translate>Branchez les servo-moteurs comme sur la photo à gauche sur les broches D18, D26, D16, D24, D5, D22.
  
'''source nom_de_lenvironnement/bin/activate'''
 
  
=== 4. Installer les bibliothèques Python nécessaires ===
+
Branchez le haut parleur sur la prise jack et sur les broches du shield comme sur l'image.
Avec l’environnement virtuel activé, installez les bibliothèques suivantes :
 
  
'''pip install vosk pyaudio numpy'''
 
  
Pour contrôler les servomoteurs, installez également les bibliothèques Adafruit nécessaires :
+
Branchez le Microphone sur un port USB.</translate>
 +
|Step_Picture_00=Boitier_d_apprentissage_du_BRAILLE_branchement_servo.png
 +
|Step_Picture_01=Boitier_d_apprentissage_du_BRAILLE_1.png
 +
}}
 +
{{Tuto Step
 +
|Step_Title=<translate>Conception SolidWorks</translate>
 +
|Step_Content=<translate>Afin d'avoir un support pour les composants assurez vous de crée un boitier dimensionné en fonction de vos composants :
  
'''pip install adafruit-pca9685 adafruit-circuitpython-pca9685 adafruit-circuitpython-motor'''
+
- Premièrement crée un socle qui accueillera la source d'énergie (batterie externe)
  
=== 5. Installer les dépendances système pour PyAudio ===
+
- Ensuite crée un boite qui servira de pièce intermédiaire et qui accueillera la carte Raspberry pi avec son microphone
PyAudio nécessite des paquets système spécifiques pour fonctionner avec le microphone. Installez-les avec :
 
  
'''sudo apt install portaudio19-dev python3-pyaudio'''
+
-Enfin crée un couvercle en vous assurant de laisser apparaitre la matrice 3*2 et des sortis de son pour le haut parleur</translate>
 +
|Step_Picture_00=Boitier_d_apprentissage_du_BRAILLE_boitier_batterie.png
 +
|Step_Picture_01=Boitier_d_apprentissage_du_BRAILLE_piece_millieux.png
 +
|Step_Picture_02=Boitier_d_apprentissage_du_BRAILLE_couvercle_boitier.png
 +
}}
 +
{{Tuto Step
 +
|Step_Title=<translate>Impression</translate>
 +
|Step_Content=<translate>Pour matérialisé notre boitier conçu précédemment sur SolidWorks munissez vous d'une imprimante 3D et du logiciel cura. Configuré les paramètres d'impression des différentes partis du boitier (vitesse de la buse, support) et lancé l'impression.</translate>
 +
|Step_Picture_00=Boitier_d_apprentissage_du_BRAILLE_vitesse.png
 +
|Step_Picture_01=Boitier_d_apprentissage_du_BRAILLE_adherence.png
 +
|Step_Picture_02=Boitier_d_apprentissage_du_BRAILLE_impresion.png
 +
}}
 +
{{Tuto Step
 +
|Step_Title=<translate>Assemblage</translate>
 +
|Step_Content=<translate>Une fois toute les étapes précédente réalisé, placez tout les composant a leur place sans oublier des les fixer a l'aide de vis ou colle liquide, puis fermer le boitier à l'aide des clips précédemment fabriquer pendant l'étape "SOLIDWORKS "et testez votre système d'apprentissage du braille</translate>
 +
|Step_Picture_00=Boitier_d_apprentissage_du_BRAILLE_assemblage_boitier.png
 +
|Step_Picture_01=Boitier_d_apprentissage_du_BRAILLE_carte.jpg
 +
|Step_Picture_02=Boitier_d_apprentissage_du_BRAILLE_moteur.jpg
 +
}}
 +
{{Tuto Step
 +
|Step_Title=<translate>Conseils, erreurs à éviter et pistes d'amélioration</translate>
 +
|Step_Content=<translate>Lors de la réalisation du boîtier, il est important de bien tester chaque élément séparément avant de tout assembler. Les servomoteurs, le micro et le haut-parleur doivent être fonctionnels de manière indépendante pour éviter de perdre du temps en cas de problème. Il est aussi conseillé de bien calibrer les servos avant de fixer le couvercle ou les pièces internes, car un mauvais alignement peut fausser l'affichage en braille.
  
=== 6. Installer le modèle Vosk pour la reconnaissance vocale ===
+
La reconnaissance vocale fonctionne mieux si le vocabulaire est restreint. Il est donc préférable de limiter les mots utilisés à ceux réellement nécessaires. De même, il faut penser à ajouter un petit délai après chaque message vocal pour éviter que le système ne se déclenche tout seul à cause de sa propre voix (problème de "self-listening").
Pour que Vosk puisse effectuer la reconnaissance vocale en français, il faut télécharger et décompresser un modèle de langue.
 
  
Téléchargez le modèle ici :
+
Plusieurs erreurs sont à éviter. Par exemple, sous-estimer la puissance nécessaire pour les électroaimants peut mener à un système inefficace ou instable. C’est l’une des raisons pour lesquelles nous avons choisi les servomoteurs, plus simples à gérer. Autre point à surveiller : l’alimentation électrique. Si elle est mal dimensionnée, cela peut provoquer des coupures ou des bugs sur le Raspberry Pi. Il est aussi risqué de vouloir tout tester d’un coup sans passer par des essais progressifs, car cela rend le diagnostic des erreurs plus compliqué.
  
https://alphacephei.com/vosk/models/vosk-model-small-fr-0.22.zip
+
Pour améliorer le projet, plusieurs pistes sont possibles. Le site web (Mode 3), qui permet l'envoi de texte depuis un navigateur. On pourrait aussi imaginer un système avec batterie ou alimentation mobile pour rendre le boîtier totalement autonome. Enfin, des ajouts comme un retour sonore d’erreur ou des vibrations pourraient guider davantage l’utilisateur, surtout en cas de mauvaise commande.</translate>
 +
}}
 +
{{Tuto Step
 +
|Step_Title=<translate>Crédits</translate>
 +
|Step_Content=<translate>Le Ray Gabin T15
  
Puis décompressez-le dans le même dossier que votre script Python avec la commande :
+
Sylvestre Valentin T15
  
'''unzip vosk-model-small-fr-0.22.zip'''
+
Mur Damien T13
  
=== 7. Désactiver l’environnement virtuel (optionnel) ===
+
2025
Lorsque vous avez fini d’installer les bibliothèques et de travailler dans l’environnement virtuel, vous pouvez le désactiver avec la commande :
 
  
'''deactivate'''</translate>
+
Lycée le Likes Quimper</translate>
 
}}
 
}}
 
{{Notes
 
{{Notes
Ligne 140 : Ligne 942 :
 
}}
 
}}
 
{{PageLang
 
{{PageLang
 +
|Language=fr
 
|SourceLanguage=none
 
|SourceLanguage=none
 
|IsTranslation=0
 
|IsTranslation=0
|Language=fr
 
 
}}
 
}}
 
{{Tuto Status
 
{{Tuto Status
|Complete=Draft
+
|Complete=Published
 
}}
 
}}

Version actuelle datée du 27 mai 2025 à 06:58

Auteur avatarDamien Mur | Dernière modification 27/05/2025 par Damien Mur

Boitier d apprentissage du BRAILLE IMG 8518.JPG
Ce projet a pour but de faciliter l'apprentissage du braille à travers un boîtier interactif contrôlé par reconnaissance vocale, synthèse vocale . Il utilise des servomoteurs pour afficher les caractères en braille, et propose deux modes d'apprentissage différents. Il a été réalisé dans le cadre du projet de terminale STI2D.

Introduction

Ce projet consiste en la réalisation d’un boîtier interactif permettant l’apprentissage du braille, à destination des personnes non-voyantes ou malvoyantes ou toutes personnes voulant apprendre le braille. Conçu dans le cadre d’un projet de Terminale STI2D, ce dispositif utilise des servomoteurs, un Raspberry Pi, et un système de reconnaissance vocale pour traduire des lettres en braille physique.

Le boîtier propose deux modes d’apprentissage :

-Un mode où l’utilisateur prononce une lettre, et le système la répète à voix haute avant de l’afficher en braille tactile.

-Un mode aléatoire où le boîtier choisit une lettre, la prononce, et laisse l’utilisateur deviner.

Le projet a été imaginé pour favoriser l’autonomie des personnes déficientes visuelles tout en rendant l’apprentissage du braille plus ludique et accessible. Il mêle électronique, programmation Python, impression 3D et design inclusif.

Matériaux

-1 raspberry pi 3

-6 servo moteurs

-1 shield Grove raspberry pi (Module Grove Base Hat 103030275)

-6 câbles Groves

-1 haut parleur (Module haut-parleur SKU00101)

-2 Câbles femelle femelle

-1 microphone (Microphone dongle USB ADA3367)

-1 Cordon Jack CA35M

Outils

Étape 1 - Installer le module pour créer un environnement virtuel

Si ce n’est pas déjà fait, installez le package python3-venv qui permet de créer un environnement virtuel Python :

sudo apt install python3-venv

Étape 2 - Créer et activer un environnement virtuel

Placez-vous dans le dossier où vous souhaitez créer votre projet (par exemple, ~/mon_projet_braille) avec la commande :

cd ~/mon_projet_braille

Puis créez un environnement virtuel en remplaçant nom_de_lenvironnement par le nom que vous souhaitez donner à cet environnement :

python3 -m venv nom_de_lenvironnement

Activez ensuite cet environnement avec la commande :

source nom_de_lenvironnement/bin/activate

Étape 3 - Installer les bibliothèques Python nécessaires

Avec l’environnement virtuel activé, installez les bibliothèques suivantes :

pip install vosk pyaudio numpy

Étape 4 - Installer les dépendances système pour PyAudio

PyAudio nécessite des paquets système spécifiques pour fonctionner avec le microphone. Installez-les avec :

sudo apt install portaudio19-dev python3-pyaudio

Étape 5 - Installer le modèle Vosk pour la reconnaissance vocale

Pour que Vosk puisse effectuer la reconnaissance vocale en français, il faut télécharger et décompresser un modèle de langue.

Téléchargez le modèle ici :

https://alphacephei.com/vosk/models/vosk-model-small-fr-0.22.zip

Puis décompressez-le avec la commande :

unzip vosk-model-small-fr-0.22.zip

Ensuite mettez le modèle dans le même dossier que votre script Python.

Étape 6 - Désactiver l’environnement virtuel (optionnel)

Lorsque vous avez fini d’installer les bibliothèques et de travailler dans l’environnement virtuel, vous pouvez le désactiver avec la commande :

deactivate

Étape 7 - Code

Ce programme Python tourne sur un Raspberry Pi et permet de piloter les 6 servomoteurs qui affichent les lettres en braille, selon les commandes vocales de l'utilisateur.

Le système fonctionne en deux modes :

-Un mode d’apprentissage : l’utilisateur dit une lettre, elle est reconnue, prononcée et affichée en braille.

-Un mode test : le système choisit aléatoirement des lettres à afficher pour entraîner l’utilisateur.

Le code gère :

-la configuration des moteurs via les broches GPIO,

-la reconnaissance vocale (grâce au module Vosk),

-la synthèse vocale (avec espeak),

-la gestion des différents modes.

Ce script permet donc d’assurer à la fois l’interaction avec l’utilisateur, le traitement de la voix, et l’affichage mécanique du braille.


from vosk import Model, KaldiRecognizer

import pyaudio

import json

import RPi.GPIO as GPIO

import time

import subprocess

import random

import logging

import os

import sys

# Configuration du système de journalisation

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

logger = logging.getLogger(__name__)

# Chemins de configuration - à ajuster selon votre environnement

MODEL_PATH = os.getenv("VOSK_MODEL_PATH", "/home/sin2025/models/vosk-model-small-fr-0.22")

AUDIO_PATH = os.getenv("AUDIO_PATH", "/home/sin2025/ressources")

# Configuration des GPIO pour les servomoteurs

servo_pins = [18, 26, 16, 24, 5, 22]

# Définition des positions des servos pour représenter les lettres en braille

definitions_braille = {

"A": [1, 0, 0, 0, 0, 0], "B": [1, 1, 0, 0, 0, 0],

"C": [1, 0, 0, 1, 0, 0], "D": [1, 0, 0, 1, 1, 0],

"E": [1, 0, 0, 0, 1, 0], "F": [1, 1, 0, 1, 0, 0],

"G": [1, 1, 0, 1, 1, 0], "H": [1, 1, 0, 0, 1, 0],

"I": [0, 1, 0, 1, 0, 0], "J": [0, 1, 0, 1, 1, 0],

"K": [1, 0, 1, 0, 0, 0], "L": [1, 1, 1, 0, 0, 0],

"M": [1, 0, 1, 1, 0, 0], "N": [1, 0, 1, 1, 1, 0],

"O": [1, 0, 1, 0, 1, 0], "P": [1, 1, 1, 1, 0, 0],

"Q": [1, 1, 1, 1, 1, 0], "R": [1, 1, 1, 0, 1, 0],

"S": [0, 1, 1, 1, 0, 0], "T": [0, 1, 1, 1, 1, 0],

"U": [1, 0, 1, 0, 0, 1], "V": [1, 1, 1, 0, 0, 1],

"W": [0, 1, 0, 1, 1, 1], "X": [1, 0, 1, 1, 0, 1],

"Y": [1, 0, 1, 1, 1, 1], "Z": [1, 0, 1, 0, 1, 1]

}

# Vocabulaire de reconnaissance vocale avec correspondances phonétiques

mots_vers_lettres = {

"ah": "A", "a": "A",

"mais": "B", "b": "B",

"c'est": "C", "c": "C",

"des": "D", "d": "D",

"euh": "E", "eux": "E", "e": "E",

"f": "F",

"j'ai": "G", "g": "G",

"hache": "H", "h": "H",

"i": "I", "aïe": "I", "hey": "I",

"j": "J",

"k": "K", "ca": "K",

"l": "L", "elle": "L",

"m": "M",

"n": "N",

"o": "O", "oh": "O", "eau": "O",

"p": "P", "pet": "P", "paix": "P",

"q": "Q", "cul": "Q",

"r": "R", "air": "R",

"s": "S",

"the": "T", "t": "T",

"u": "U", "hu": "U",

"v": "V", "vais": "V",

"w": "W", "double v": "W",

"x": "X",

"y": "Y", "ii grec": "Y", "les grecs": "Y", "grec": "Y", "le grec": "Y",

"z": "Z",

"mode un": "Mode 1",

"mode deux": "Mode 2",

"mode de": "Mode 2",

"fin": "Fin"

}

class BrailleReader:

def __init__(self):

# Initialiser les servomoteurs

self.initialize_servos()


# Initialiser l'audio et la reconnaissance vocale

self.initialize_audio()


# Mode actuel de l'application (0 = sélection de mode, 1 = Mode 1, 2 = Mode 2)

self.current_mode = 0


# Indicateur si l'application est en cours d'exécution

self.running = True


# Indicateur si le système est en train de parler

self.is_speaking = False


# Heure de fin de la dernière synthèse vocale (pour éviter l'auto-écoute)

self.last_speech_time = 0


# Délai minimum après synthèse vocale pour éviter l'auto-écoute (en secondes)

self.speech_cooldown = 1.0


logger.info("Lecteur Braille initialisé et prêt")

def initialize_servos(self):

"""Initialiser les GPIO et les servomoteurs"""

logger.info("Initialisation des GPIO et servomoteurs")


# Nettoyer toutes les configurations GPIO précédentes

GPIO.cleanup()


# Configurer le mode GPIO

GPIO.setmode(GPIO.BCM)


# Initialiser les servomoteurs

self.servos = []

for pin in servo_pins:

GPIO.setup(pin, GPIO.OUT)

servo = GPIO.PWM(pin, 50) # Fréquence PWM de 50Hz

servo.start(0)

self.servos.append(servo)


# Remettre tous les servos en position 0

self.reset_servos()


logger.info("Servomoteurs initialisés")

def initialize_audio(self):

"""Initialiser l'entrée audio et la reconnaissance vocale"""

logger.info("Initialisation de l'audio et de la reconnaissance vocale")


try:

# Initialiser le modèle Vosk

self.model = Model(MODEL_PATH)


# Créer la chaîne de vocabulaire à partir du dictionnaire mots_vers_lettres

vocabulaire = "[ \"" + "\", \"".join(mots_vers_lettres.keys()) + "\" ]"


# Initialiser le reconnaisseur avec le vocabulaire

self.rec = KaldiRecognizer(self.model, 44100, vocabulaire)


# Initialiser PyAudio

self.p = pyaudio.PyAudio()

self.stream = self.p.open(

format=pyaudio.paInt16,

channels=1,

rate=44100,

input=True,

frames_per_buffer=8000

)

self.stream.start_stream()


logger.info("Audio et reconnaissance vocale initialisés")

except Exception as e:

logger.error(f"Erreur lors de l'initialisation audio: {e}")

sys.exit(1)

def set_servo_angle(self, servo, angle):

"""Définir l'angle du servomoteur"""

duty_cycle = (angle / 18) + 2

servo.ChangeDutyCycle(duty_cycle)

time.sleep(0.3)

servo.ChangeDutyCycle(0)

def reset_servos(self):

"""Remettre tous les servos en position 0"""

for servo in self.servos:

self.set_servo_angle(servo, 0)

def afficher_braille(self, lettre):

"""Afficher une lettre en Braille en utilisant les servomoteurs"""

if lettre in definitions_braille:

for i in range(6):

self.set_servo_angle(

self.servos[i],

90 if definitions_braille[lettre][i] else 0

)

return True

return False

def speak_text(self, text):

"""Utiliser espeak pour convertir le texte en parole"""

try:

# Marquer que nous commençons à parler

self.is_speaking = True


# Mettre en pause la reconnaissance pour éviter l'auto-écoute

self.toggle_recognition_stream(pause=True)


subprocess.run(

["espeak", "-v", "fr", "-s", "200", "-p", "100", "-a", "1000", text],

stdout=subprocess.DEVNULL,

stderr=subprocess.DEVNULL

)


# Enregistrer quand nous avons fini de parler

self.last_speech_time = time.time()


# Marquer que nous avons fini de parler

self.is_speaking = False


# Attendre un court délai avant de reprendre la reconnaissance

time.sleep(0.5) # Courte attente pour s'assurer qu'espeak est complètement terminé


# Reprendre la reconnaissance

self.toggle_recognition_stream(pause=False)


# Ajouter un délai pour éviter la reconnaissance immédiate (auto-écoute)

time.sleep(0.5)


except Exception as e:

logger.error(f"Erreur avec la synthèse vocale: {e}")

self.is_speaking = False

self.toggle_recognition_stream(pause=False)

def play_audio(self, file_name):

"""Lire un fichier audio en utilisant ffmpeg"""

try:

# Marquer que nous commençons à parler

self.is_speaking = True


# Mettre en pause la reconnaissance pour éviter l'auto-écoute

self.toggle_recognition_stream(pause=True)


file_path = os.path.join(AUDIO_PATH, file_name)

if os.path.exists(file_path):

subprocess.run(

["ffmpeg", "-i", file_path, "-f", "alsa", "default"],

stdout=subprocess.DEVNULL,

stderr=subprocess.DEVNULL

)

else:

logger.warning(f"Fichier audio introuvable: {file_path}")

# Utiliser espeak comme solution de repli si le fichier n'est pas trouvé

self.speak_text(file_name.replace(".mp3", ""))


# Enregistrer quand nous avons fini de parler

self.last_speech_time = time.time()


# Marquer que nous avons fini de parler

self.is_speaking = False


# Attendre un court délai avant de reprendre la reconnaissance

time.sleep(0.5)


# Reprendre la reconnaissance

self.toggle_recognition_stream(pause=False)


except Exception as e:

logger.error(f"Erreur lors de la lecture audio: {e}")

self.is_speaking = False

self.toggle_recognition_stream(pause=False)

def toggle_recognition_stream(self, pause=True):

"""Mettre en pause ou reprendre le flux de reconnaissance audio"""

if pause:

self.stream.stop_stream()

else:

self.stream.start_stream()

def recognize_speech(self, timeout=5):

"""Écouter la parole et retourner le texte reconnu"""

# Si nous sommes en train de parler ou venons de finir, ne pas écouter encore

if self.is_speaking:

return None


# Vérifier si nous sommes encore dans la période de délai après avoir parlé

if time.time() - self.last_speech_time < self.speech_cooldown:

return None


start_time = time.time()

while time.time() - start_time < timeout:

data = self.stream.read(4000, exception_on_overflow=False)


if self.rec.AcceptWaveform(data):

result = json.loads(self.rec.Result())

if "text" in result and result["text"].strip():

recognized_text = result["text"].lower()

logger.debug(f"Recognized: {recognized_text}")

return recognized_text


return None

def mode_selection(self):

"""Interface de sélection du mode"""

logger.info("Entrée dans la sélection de mode")


# Remettre les servos à zéro

self.reset_servos()


# Message de bienvenue

self.speak_text("Bienvenue au système d'apprentissage de Braille")

self.speak_text("Dites Mode un ou Mode deux pour commencer")


while self.current_mode == 0 and self.running:

# Écouter pour la sélection de mode

recognized_text = self.recognize_speech()


if recognized_text:

if recognized_text in mots_vers_lettres:

command = mots_vers_lettres[recognized_text]


# Gérer la sélection de mode

if command == "Mode 1":

self.speak_text("Mode un sélectionné")

self.current_mode = 1

logger.info("Mode 1 sélectionné")

elif command == "Mode 2":

self.speak_text("Mode deux sélectionné")

self.current_mode = 2

logger.info("Mode 2 sélectionné")

elif command == "Fin":

self.speak_text("Au revoir")

self.running = False

else:

self.speak_text("Commande non reconnue")

else:

self.speak_text("Commande non reconnue")

def mode_1(self):

"""Mode 1: L'utilisateur dit une lettre, le système la prononce et l'affiche"""

logger.info("Démarrage du Mode 1")


# Introduction pour le Mode 1

self.speak_text("Mode un. Dites une lettre, je vais la prononcer et l'afficher en braille")

self.speak_text("Dites fin pour revenir au menu principal")


while self.current_mode == 1 and self.running:

# Attendre l'entrée d'une lettre

recognized_text = self.recognize_speech()


if recognized_text and not self.is_speaking:

if recognized_text in mots_vers_lettres:

command = mots_vers_lettres[recognized_text]


# Vérifier si l'utilisateur veut sortir

if command == "Fin":

self.speak_text("Fin du mode un")

self.current_mode = 0

logger.info("Sortie du Mode 1")

break


# Gérer l'affichage de la lettre

if len(command) == 1 and command in definitions_braille:

logger.info(f"Affichage de la lettre: {command}")


# Afficher d'abord la lettre en braille

self.afficher_braille(command)


# Puis prononcer la lettre avec reconnaissance désactivée pour éviter l'auto-écoute

self.speak_text(command)

else:

self.speak_text("Ce n'est pas une lettre valide")

else:

self.speak_text("Commande non reconnue")

def mode_2(self):

"""Mode 2: Le système affiche aléatoirement des lettres"""

logger.info("Démarrage du Mode 2")


# Introduction pour le Mode 2

self.speak_text("Mode deux. Je vais afficher des lettres aléatoires en braille")

self.speak_text("Dites fin pour revenir au menu principal")


while self.current_mode == 2 and self.running:

# Afficher une lettre aléatoire

random_letter = random.choice(list(definitions_braille.keys()))

logger.info(f"Affichage de la lettre aléatoire: {random_letter}")


# Prononcer et afficher la lettre

self.afficher_braille(random_letter)

self.speak_text(random_letter)


# Attendre un moment pour permettre à l'utilisateur de dire "fin" si nécessaire

time.sleep(2)


# Vérifier les commandes vocales (même pendant la séquence d'affichage)

recognized_text = self.recognize_speech(timeout=1)


if recognized_text and recognized_text in mots_vers_lettres:

command = mots_vers_lettres[recognized_text]


if command == "Fin":

self.speak_text("Fin du mode deux")

self.current_mode = 0

logger.info("Sortie du Mode 2")

return

def cleanup(self):

"""Nettoyer les ressources à la sortie"""

logger.info("Nettoyage des ressources")


# Remettre les servos à zéro

self.reset_servos()


# Arrêter tous les servos

for servo in self.servos:

servo.stop()


# Nettoyer les GPIO

GPIO.cleanup()


# Arrêter et fermer le flux audio

if hasattr(self, 'stream'):

self.stream.stop_stream()

self.stream.close()


# Terminer PyAudio

if hasattr(self, 'p'):

self.p.terminate()


logger.info("Nettoyage terminé")

def run(self):

"""Boucle principale de l'application"""

logger.info("Démarrage de l'application Lecteur Braille")


try:

while self.running:

# Sélection de mode

if self.current_mode == 0:

self.mode_selection()

# Mode 1

elif self.current_mode == 1:

self.mode_1()

# Mode 2

elif self.current_mode == 2:

self.mode_2()

except KeyboardInterrupt:

logger.info("Application terminée par l'utilisateur")

except Exception as e:

logger.error(f"Erreur inattendue: {e}")

finally:

self.cleanup()

if __name__ == "__main__":

reader = BrailleReader()

reader.run()

Étape 8 - Branchement

Branchez les servo-moteurs comme sur la photo à gauche sur les broches D18, D26, D16, D24, D5, D22.


Branchez le haut parleur sur la prise jack et sur les broches du shield comme sur l'image.


Branchez le Microphone sur un port USB.



Étape 9 - Conception SolidWorks

Afin d'avoir un support pour les composants assurez vous de crée un boitier dimensionné en fonction de vos composants :

- Premièrement crée un socle qui accueillera la source d'énergie (batterie externe)

- Ensuite crée un boite qui servira de pièce intermédiaire et qui accueillera la carte Raspberry pi avec son microphone

-Enfin crée un couvercle en vous assurant de laisser apparaitre la matrice 3*2 et des sortis de son pour le haut parleur


Étape 10 - Impression

Pour matérialisé notre boitier conçu précédemment sur SolidWorks munissez vous d'une imprimante 3D et du logiciel cura. Configuré les paramètres d'impression des différentes partis du boitier (vitesse de la buse, support) et lancé l'impression.


Étape 11 - Assemblage

Une fois toute les étapes précédente réalisé, placez tout les composant a leur place sans oublier des les fixer a l'aide de vis ou colle liquide, puis fermer le boitier à l'aide des clips précédemment fabriquer pendant l'étape "SOLIDWORKS "et testez votre système d'apprentissage du braille


Étape 12 - Conseils, erreurs à éviter et pistes d'amélioration

Lors de la réalisation du boîtier, il est important de bien tester chaque élément séparément avant de tout assembler. Les servomoteurs, le micro et le haut-parleur doivent être fonctionnels de manière indépendante pour éviter de perdre du temps en cas de problème. Il est aussi conseillé de bien calibrer les servos avant de fixer le couvercle ou les pièces internes, car un mauvais alignement peut fausser l'affichage en braille.

La reconnaissance vocale fonctionne mieux si le vocabulaire est restreint. Il est donc préférable de limiter les mots utilisés à ceux réellement nécessaires. De même, il faut penser à ajouter un petit délai après chaque message vocal pour éviter que le système ne se déclenche tout seul à cause de sa propre voix (problème de "self-listening").

Plusieurs erreurs sont à éviter. Par exemple, sous-estimer la puissance nécessaire pour les électroaimants peut mener à un système inefficace ou instable. C’est l’une des raisons pour lesquelles nous avons choisi les servomoteurs, plus simples à gérer. Autre point à surveiller : l’alimentation électrique. Si elle est mal dimensionnée, cela peut provoquer des coupures ou des bugs sur le Raspberry Pi. Il est aussi risqué de vouloir tout tester d’un coup sans passer par des essais progressifs, car cela rend le diagnostic des erreurs plus compliqué.

Pour améliorer le projet, plusieurs pistes sont possibles. Le site web (Mode 3), qui permet l'envoi de texte depuis un navigateur. On pourrait aussi imaginer un système avec batterie ou alimentation mobile pour rendre le boîtier totalement autonome. Enfin, des ajouts comme un retour sonore d’erreur ou des vibrations pourraient guider davantage l’utilisateur, surtout en cas de mauvaise commande.

Étape 13 - Crédits

Le Ray Gabin T15

Sylvestre Valentin T15

Mur Damien T13

2025

Lycée le Likes Quimper

Commentaires

Published