Système de traduction et d'apprentissage du Braille : Différence entre versions

 
(23 révisions intermédiaires par 4 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
 
{{Tuto Details
 
{{Tuto Details
|Main_Picture=Syst_me_de_traduction_et_d_apprentissage_du_Braille_20250526_144220_1_.jpg
+
|Main_Picture=Boitier.png
|Main_Picture_annotation={"version":"3.5.0","objects":[{"type":"image","version":"3.5.0","originX":"left","originY":"top","left":601.2,"top":-33,"width":3468,"height":4624,"fill":"rgb(0,0,0)","stroke":null,"strokeWidth":0,"strokeDashArray":null,"strokeLineCap":"butt","strokeDashOffset":0,"strokeLineJoin":"miter","strokeMiterLimit":4,"scaleX":0.15,"scaleY":0.15,"angle":90,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"crossOrigin":"","cropX":0,"cropY":0,"src":"https://wikifab.org/images/f/f9/Syst_me_de_traduction_et_d_apprentissage_du_Braille_20250526_144220_1_.jpg","filters":[]}],"height":449.2718446601942,"width":600}
+
|Main_Picture_annotation={"version":"3.5.0","objects":[{"type":"image","version":"3.5.0","originX":"left","originY":"top","left":108,"top":54,"width":1920,"height":1659,"fill":"rgb(0,0,0)","stroke":null,"strokeWidth":0,"strokeDashArray":null,"strokeLineCap":"butt","strokeDashOffset":0,"strokeLineJoin":"miter","strokeMiterLimit":4,"scaleX":0.2,"scaleY":0.2,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"crossOrigin":"","cropX":0,"cropY":0,"src":"https://wikifab.org/images/1/15/Boitier.png","filters":[]}],"height":450.2664298401421,"width":600}
 
|Licences=Attribution (CC BY)
 
|Licences=Attribution (CC BY)
|Description=<translate>Objet qui permet de traduire et d'apprendre le braille.</translate>
+
|Description=<translate>Présentation d'un tutoriel notre projet de classe de terminale STI2D afin de le reproduire chez soi</translate>
 
|Area=Electronics, Health and Wellbeing
 
|Area=Electronics, Health and Wellbeing
 
|Type=Creation
 
|Type=Creation
Ligne 14 : Ligne 14 :
 
}}
 
}}
 
{{Introduction
 
{{Introduction
|Introduction=<translate>Présentation d'un tutoriel notre projet de classe de terminale STI2D afin de le reproduire chez soi</translate>
+
|Introduction=<translate></translate>
 
}}
 
}}
 
{{Materials
 
{{Materials
Ligne 23 : Ligne 23 :
 
|Step_Picture_04=Syst_me_de_traduction_et_d_apprentissage_du_Braille_61L4aoIqYOL._AC_SX679_.jpg
 
|Step_Picture_04=Syst_me_de_traduction_et_d_apprentissage_du_Braille_61L4aoIqYOL._AC_SX679_.jpg
 
|Step_Picture_05=Syst_me_de_traduction_et_d_apprentissage_du_Braille_Capture_d_cran_2025-05-26_153426.png
 
|Step_Picture_05=Syst_me_de_traduction_et_d_apprentissage_du_Braille_Capture_d_cran_2025-05-26_153426.png
|Material=<translate>-Bois 3mm
+
|Material=<translate><u>'''Matériaux pour le boitier'''</u>
  
-Plastique pour découpeuse laser ( ici du PLA)</translate>
+
-Planche en bois 3mm d'épaisseur / 30cm de large  / 60 cm de long
|Tools=<translate>-Découpeuse laser
 
  
-Imprimante 3D (ici la Ultimaker 2+)</translate>
+
-Plastique pour découpeuse laser ( ici du PLA) environ (100g)  
}}
 
{{Tuto Step
 
|Step_Title=<translate>Découpe des pièces en bois du boitier</translate>
 
|Step_Content=<translate>-Connecter l'ordinateur à la découpeuse laser
 
  
-Ouvrir le logiciel Trotek ( Nécessaire à la découpe)
 
  
-Ouvrir les pièces à découper en format dxf dans le logiciel
+
'''<u>Composants électroniques</u>'''
  
-Optimiser l'espace sur la planche afin d'avoir les moins de perte de matière et déplaçant les pièces
+
-1x Raspberry pi 3
  
-Lancer la découpe
+
-6x Servo moteurs linéaires
  
-Nettoyer les pièces afin d'éviter des tâches dues au bois brûlé.</translate>
+
-1x Mini Haut parleur (Module haut-parleur SKU00101)
}}
 
{{Tuto Step
 
|Step_Title=<translate>Assemblage des pièces en bois</translate>
 
|Step_Content=<translate></translate>
 
}}
 
{{Tuto Step
 
|Step_Title=<translate></translate>
 
|Step_Content=<translate></translate>
 
}}
 
{{Tuto Step
 
|Step_Title=<translate></translate>
 
|Step_Content=<translate></translate>
 
}}
 
{{Tuto Step
 
|Step_Title=<translate>Branchement entre les carte électroniques et les servo-moteurs</translate>
 
|Step_Content=<translate>==== - Brancher les servo moteur sur la carte arduino  - inséré le code arduino<syntaxhighlight lang="c">
 
Servo servos[6];  // Tableau de 6 servos
 
const int pinsServos[6] = {3, 5, 6, 9, 10, 11};  // Broches des servos
 
  
unsigned long tempsServo = 0;
+
-1x Cordon Jack CA35M
bool servosActifs = false;
 
  
void setup() {
+
- 1x Carte Arduino Uno
    Serial.begin(9600);  // Initialisation du moniteur série
 
    Serial.println("✅ Arduino prêt, en attente des commandes I2C...");
 
  
    Wire.begin(8); // Arduino en esclave I2C (adresse 8)
+
- 5x boutons poussoirs
    Wire.onReceive(recevoirCommande);
 
  
    // Initialiser les servos à la position souhaitée (par exemple, 45°)
+
- 1x Capteur Ultrason
    for (int i = 0; i < 6; i++) {
 
        servos[i].attach(pinsServos[i]);
 
        servos[i].write(45);  // Position initiale (en bas)
 
    }
 
}
 
  
void loop() {
+
- 1x Caméra compatible Raspberry pi disponible chez Kubii
    if (servosActifs && millis() - tempsServo >= 3000) {
 
        Serial.println("🔄 Retour des servos à la position initiale.");
 
        for (int i = 0; i < 6; i++) {
 
            servos[i].write(45);  // Retour à la position initiale (en bas)
 
        }
 
        servosActifs = false;
 
    }
 
}
 
  
void recevoirCommande(int nombreOctets) {
+
-40x Fils de connexion électronique</translate>
    if (Wire.available()) {
+
|Tools=<translate>-Découpeuse laser
        int valeur = Wire.read();  // Lire le nombre envoyé par le Raspberry Pi
 
        Serial.print("📩 Commande reçue: ");
 
        Serial.println(valeur, BIN); // Afficher la valeur en binaire (code Braille)
 
  
        // Déplacer chaque servo un par un avec un petit délai
+
-Imprimante 3D (ici la Ultimaker 2+)
        for (int i = 0; i < 6; i++) {
 
            if (valeur & (1 << (5 - i))) {  // Vérifier si le bit i est actif
 
                Serial.print("🔼 Servo ");
 
                Serial.print(i);
 
                Serial.println(" activé.");
 
                servos[i].write(135);  // Position haute (en haut)
 
            } else {
 
                Serial.print("🔽 Servo ");
 
                Serial.print(i);
 
                Serial.println(" désactivé.");
 
                servos[i].write(45);  // Position initiale (en bas)
 
            }
 
            delay(100);  // Petite pause entre les déplacements des servos
 
        }
 
  
        tempsServo = millis(); // Démarrer le timer pour retour automatique
+
-Ordinateur</translate>
        servosActifs = true;
+
|Tuto_Attachments={{Tuto Attachments
    }
+
|Attachment=support servomoteur .stl
}  
+
}}{{Tuto Attachments
</syntaxhighlight>    - Se munir de la carte raspery Pi    - Brancher relier les broches  Gpio raspery Pi avec celle de arduino(gnd,vcc) taper sur internet broche raspery pi  - inséré ce code<syntaxhighlight lang="python">
+
|Attachment=joint servomoteur .stl
import smbus
+
}}{{Tuto Attachments
import time
+
|Attachment=lettre braille 1.stl
import RPi.GPIO as GPIO 
+
}}{{Tuto Attachments
import random
+
|Attachment=lettre braille 2.stl
import os 
+
}}{{Tuto Attachments
import threading
+
|Attachment=lettre braille 3.stl
import cv2
+
}}{{Tuto Attachments
import pytesseract
+
|Attachment=Piece_arriere_file.dxf
import numpy as np
+
}}{{Tuto Attachments
 +
|Attachment=Piece_base_1.dxf
 +
}}{{Tuto Attachments
 +
|Attachment=Piece_base_2.dxf
 +
}}{{Tuto Attachments
 +
|Attachment=Piece_bouton_d.dxf
 +
}}{{Tuto Attachments
 +
|Attachment=Piece_camera.dxf
 +
}}{{Tuto Attachments
 +
|Attachment=Piece_enceinte.dxf
 +
}}{{Tuto Attachments
 +
|Attachment=Arduino_code.ino
 +
}}{{Tuto Attachments
 +
|Attachment=Raspberry_code.docx
 +
}}
 +
}}
 +
{{Tuto Step
 +
|Step_Title=<translate>Découpe des pièces en bois du boitier</translate>
 +
|Step_Content=<translate>-Connecter l'ordinateur à la découpeuse laser.
  
I2C_ADDR = 8 
+
-Ouvrir le logiciel Trotek ( Nécessaire à la découpe).
bus = smbus.SMBus(1)
 
  
# GPIO des boutons
+
-Ouvrir les pièces à découper en format dxf dans le logiciel.
BOUTON_PRECEDENT = 17 
 
BOUTON_SUIVANT = 27   
 
BOUTON_LECON = 23 
 
BOUTON_EXERCICE = 24
 
BOUTON_CAMERA = 22  # Bouton pour la caméra
 
  
# GPIO du capteur ultrason HCSR04
+
-Optimiser l'espace sur la planche afin d'avoir les moins de perte de matière et déplaçant les pièces.
TRIG = 5  # GPIO pour le trigger du capteur
 
ECHO = 6  # GPIO pour l'echo du capteur
 
  
# Configuration des GPIO
+
-Lancer la découpe.
try:
 
    GPIO.cleanup()
 
except:
 
    pass
 
  
GPIO.setmode(GPIO.BCM)
+
-Nettoyer les pièces afin d'éviter des tâches dues au bois brûlé.</translate>
GPIO.setup(BOUTON_PRECEDENT, GPIO.IN, pull_up_down=GPIO.PUD_UP)
+
|Step_Picture_00=Découpe.jpg
GPIO.setup(BOUTON_SUIVANT, GPIO.IN, pull_up_down=GPIO.PUD_UP)
+
}}
GPIO.setup(BOUTON_LECON, GPIO.IN, pull_up_down=GPIO.PUD_UP)
+
{{Tuto Step
GPIO.setup(BOUTON_EXERCICE, GPIO.IN, pull_up_down=GPIO.PUD_UP)
+
|Step_Title=<translate>Assemblage des pièces en bois</translate>
GPIO.setup(BOUTON_CAMERA, GPIO.IN, pull_up_down=GPIO.PUD_UP)
+
|Step_Content=<translate>-Assembler les pièces découpées grâce aux images ci-contre.
  
# Configuration du capteur ultrason
+
-Les coller via de la colle à bois.</translate>
GPIO.setup(TRIG, GPIO.OUT)
+
|Step_Picture_00=Assemblage.jpg
GPIO.setup(ECHO, GPIO.IN)
+
}}
GPIO.output(TRIG, False)  # S'assurer que le trigger est bas au démarrage
+
{{Tuto Step
 +
|Step_Title=<translate>Configuration de la carte électronique Raspberry pi v3</translate>
 +
|Step_Content=<translate>-Configurer votre carte Raspberry pi.
  
# Dictionnaire Braille
+
-Alimenter la carte Raspberry pi via son câble d'alimentation à l'ordinateur et en hdmi à l'écran.
braille_dict = {
 
    "a": 0b100000, "b": 0b110000, "c": 0b101000, "d": 0b101100,
 
    "e": 0b100100, "f": 0b111000, "g": 0b111100, "h": 0b110100,
 
    "i": 0b011000, "j": 0b011100, "k": 0b100010, "l": 0b110010,
 
    "m": 0b101010, "n": 0b101110, "o": 0b100110, "p": 0b111010,
 
    "q": 0b111110, "r": 0b110110, "s": 0b011010, "t": 0b011110,
 
    "u": 0b100011, "v": 0b110011, "w": 0b011101, "x": 0b101011,
 
    "y": 0b101111, "z": 0b100111, " ": 0b000000
 
}
 
  
texte = "bonjour" # Texte par défaut
+
-Copier le code "Raspberry_code" dans un fichier python au même nom.
index = 0
 
lecon_en_cours = False
 
exercice_en_cours = False
 
attente_texte = False  # Pour savoir si on attend une saisie de texte
 
camera_en_cours = False  # Pour indiquer si une capture par caméra est en cours
 
  
# Paramètres de capture d'image
+
-Avant de lancer ce fichier, vous devez d’abord créer et démarrer un environnement virtuel à l’aide du terminal. Cela permet de préparer un espace propre pour faire fonctionner votre programme.
IMAGE_PATH = "capture.jpg"
 
CROPPED_PATH = "cropped.jpg"
 
DISTANCE_OPTIMALE = 15  # Distance optimale en cm
 
MARGE_DISTANCE = 2.5    # Marge de tolérance en cm (+/-)
 
  
def mesurer_distance():
+
-Dans le terminal, tapper "python3 Raspberry_code.py".
    """Mesure la distance avec le capteur ultrason HCSR04."""
 
    # Envoyer une impulsion de 10µs au trigger
 
    GPIO.output(TRIG, True)
 
    time.sleep(0.00001)  # 10µs
 
    GPIO.output(TRIG, False)
 
   
 
    # Attendre que l'écho commence
 
    start_time = time.time()
 
    timeout = start_time + 1.0  # Timeout de 1 seconde
 
   
 
    while GPIO.input(ECHO) == 0:
 
        if time.time() > timeout:
 
            return -1  # Erreur: pas de signal
 
        pulse_start = time.time()
 
   
 
    # Attendre que l'écho se termine
 
    while GPIO.input(ECHO) == 1:
 
        if time.time() > timeout:
 
            return -1  # Erreur: signal trop long
 
        pulse_end = time.time()
 
   
 
    # Calculer la durée de l'impulsion
 
    pulse_duration = pulse_end - pulse_start
 
   
 
    # Calculer la distance (vitesse du son = 34300 cm/s)
 
    # Diviser par 2 car le signal fait l'aller-retour
 
    distance = (pulse_duration * 34300) / 2
 
   
 
    return round(distance, 1)  # Arrondir à 1 décimale
 
  
def guide_position():
+
-Le code devrait se lancer.
    """Guide l'utilisateur pour positionner correctement le texte."""
 
    global camera_en_cours
 
   
 
    print("📏 Positionnement du texte...")
 
    os.system('espeak -v fr "Positionnez le texte" --stdout | aplay')
 
   
 
    # Attendre que la distance soit stable dans la plage optimale
 
    position_stable = False
 
    nb_mesures_stables = 0
 
   
 
    while camera_en_cours and not position_stable:
 
        distance = mesurer_distance()
 
       
 
        if distance < 0:
 
            print("⚠️ Erreur de mesure de distance")
 
            time.sleep(0.5)
 
            continue
 
           
 
        print(f"📏 Distance mesurée : {distance} cm")
 
       
 
        if distance < DISTANCE_OPTIMALE - MARGE_DISTANCE:
 
            # Trop proche
 
            os.system('espeak -v fr "Reculez" --stdout | aplay')
 
            nb_mesures_stables = 0
 
        elif distance > DISTANCE_OPTIMALE + MARGE_DISTANCE:
 
            # Trop loin
 
            os.system('espeak -v fr "Avancez" --stdout | aplay')
 
            nb_mesures_stables = 0
 
        else:
 
            # Distance correcte
 
            print(f"✅ Distance correcte : {distance} cm")
 
            nb_mesures_stables += 1
 
           
 
            # Si 3 mesures consécutives sont dans la plage, on considère la position comme stable
 
            if nb_mesures_stables >= 3:
 
                position_stable = True
 
                os.system('espeak -v fr "Position correcte" --stdout | aplay')
 
       
 
        time.sleep(0.5)  # Attendre avant la prochaine mesure
 
   
 
    return position_stable
 
  
def envoyer_nombre(nombre, mode=None):
+
-Si c'est le cas, débrancher la carte raspberry pi, sinon regarder un tutoriel sur internet.</translate>
    """Envoie une lettre en Braille et annonce (avec délai optionnel en mode exercice)."""
+
|Step_Picture_00=raspberry.jpg
    try:
+
}}
        lettre = [key for key, val in braille_dict.items() if val == nombre][0] 
+
{{Tuto Step
        bus.write_byte(I2C_ADDR, nombre)
+
|Step_Title=<translate>Configuration de la carte électronique Arduino Uno</translate>
        print(f"✅ Lettre envoyée: {lettre.upper()} ({bin(nombre)})")
+
|Step_Content=<translate>-Alimenter la carte Arduino Uno via son câble d'alimentation à ordinateur.
       
 
        # Si c'est le mode exercice, attendre 2 secondes avant d'énoncer la lettre
 
        if mode == "exercice":
 
            # Vérifier périodiquement si l'exercice a été arrêté pendant l'attente
 
            debut = time.time()
 
            while time.time() - debut < 2 and exercice_en_cours:
 
                time.sleep(0.1)
 
           
 
            # Ne prononcer la lettre que si l'exercice est toujours en cours
 
            if exercice_en_cours:
 
                os.system(f'espeak -v fr "{lettre}" --stdout | aplay')
 
        else:
 
            # Pour les autres modes, énoncer la lettre immédiatement
 
            os.system(f'espeak -v fr "{lettre}" --stdout | aplay'
 
    except IOError:
 
        print("❌ Erreur de communication avec l'Arduino")
 
    except IndexError:
 
        print("❌ Erreur: code braille non trouvé dans le dictionnaire")
 
    except Exception as e:
 
        print(f"❌ Erreur inattendue: {str(e)}")
 
  
def demander_nouveau_texte():
+
-Ouvrir Le logiciel Arduino IDE.
    """Demande un nouveau texte et réinitialise l'index."""
 
    global texte, index, attente_texte
 
   
 
    # Annonce vocale
 
    os.system('espeak -v fr "Entrez un nouveau texte" --stdout | aplay')
 
   
 
    # Lancer un thread pour attendre la saisie sans bloquer le reste du programme
 
    def attendre_saisie():
 
        global texte, index, attente_texte
 
        nouveau_texte = input("\n🆕 Entrez un texte (ou appuyez sur Entrée pour garder 'bonjour') : ").lower()
 
        if nouveau_texte:  # Si l'utilisateur a entré quelque chose
 
            texte = nouveau_texte
 
        index = 0
 
        print(f"🔠 Texte actuel : {texte}")
 
        print("📌 Appuyez sur le bouton 'Suivant' pour parcourir le texte, ou sur 'Leçon'/'Exercice' pour ces modes.")
 
        attente_texte = False  # Fin de l'attente
 
   
 
    attente_texte = True  # Début de l'attente
 
    t = threading.Thread(target=attendre_saisie)
 
    t.daemon = True
 
    t.start()
 
  
def bouton_precedent(channel):
+
-Ouvrir le fichier "Arduino_code.ino".
    """Affiche la lettre précédente pendant la lecture du texte."""
 
    global index
 
   
 
    # Ne pas exécuter si un mode est en cours ou si on attend une saisie
 
    if lecon_en_cours or exercice_en_cours or attente_texte or camera_en_cours:
 
        return
 
   
 
    time.sleep(0.2)  # Anti-rebond
 
    if GPIO.input(BOUTON_PRECEDENT) == GPIO.LOW:
 
        if index > 0:
 
            index -= 1
 
            envoyer_nombre(braille_dict.get(texte[index], 0))
 
            print(f"🔙 Lettre précédente: {texte[index]}")
 
        else:
 
            print("🚫 Déjà à la première lettre.")
 
            os.system('espeak -v fr "Première lettre" --stdout | aplay')
 
  
def bouton_suivant(channel):
+
-Uploader le code.
    """Affiche la lettre suivante et lit le mot en entier à la fin."""
 
    global index
 
   
 
    # Ne pas exécuter si un mode est en cours ou si on attend une saisie
 
    if lecon_en_cours or exercice_en_cours or attente_texte or camera_en_cours:
 
        return
 
   
 
    time.sleep(0.2)  # Anti-rebond
 
    if GPIO.input(BOUTON_SUIVANT) == GPIO.LOW:
 
        if texte and index < len(texte):
 
            envoyer_nombre(braille_dict.get(texte[index], 0))
 
            index += 1
 
            print(f"🔜 Lettre suivante: {texte[index-1]}")
 
            if index == len(texte):
 
                print("🔁 Fin du texte, lecture complète...")
 
                os.system(f'espeak -v fr "{texte}" --stdout | aplay')
 
                demander_nouveau_texte()
 
  
def lancer_lecon():
+
-Si le code parvient à s'uploader, débrancher la carte Arduino, sinon regarder un tutoriel sur internet.</translate>
    """Fonction pour lancer la leçon dans un thread séparé."""
+
|Step_Picture_00=Syst_me_de_traduction_et_d_apprentissage_du_Braille_61AvdQOxFzL.jpg
    global lecon_en_cours
+
|Step_Picture_01=arduino ide image.jpg
   
+
|Step_Picture_02=code.png
    # Si on attend une saisie de texte, annuler cette attente
+
}}
    global attente_texte
+
{{Tuto Step
    attente_texte = False
+
|Step_Title=<translate>Branchement des composants</translate>
   
+
|Step_Content=<translate>-Une fois les 2 cartes débranchées, les connecter en I2C via 3 fils de connexion M>F.(SDA; SCL; GND)
    # Marquer le début de la leçon
 
    lecon_en_cours = True
 
    print("📖 Début de la leçon...")
 
    os.system('espeak -v fr "Début de la leçon" --stdout | aplay')
 
   
 
    # Parcourir l'alphabet
 
    for lettre in "abcdefghijklmnopqrstuvwxyz":
 
        # Vérifier si la leçon a été arrêtée
 
        if not lecon_en_cours:
 
            return
 
       
 
        # Afficher et annoncer la lettre
 
        print(f"📝 Leçon : Lettre {lettre.upper()}")
 
        envoyer_nombre(braille_dict[lettre])
 
       
 
        # Attendre 8 secondes, en vérifiant si la leçon a été arrêtée
 
        debut = time.time()
 
        while time.time() - debut < 8:
 
            if not lecon_en_cours:
 
                return  # Sortir immédiatement si la leçon a été arrêtée
 
            time.sleep(0.1)
 
   
 
    # Fin normale de la leçon
 
    print("✅ Leçon terminée !")
 
    os.system('espeak -v fr "Leçon terminée" --stdout | aplay')
 
    lecon_en_cours = False
 
   
 
    # Proposer d'entrer un nouveau texte sans bloquer
 
    demander_nouveau_texte()
 
  
def lancer_exercice():
+
-Bancher la caméra à la carte raspberry pi.
    """Fonction pour lancer l'exercice dans un thread séparé."""
 
    global exercice_en_cours
 
   
 
    # Si on attend une saisie de texte, annuler cette attente
 
    global attente_texte
 
    attente_texte = False
 
   
 
    # Marquer le début de l'exercice
 
    exercice_en_cours = True
 
    print("🎲 Début de l'exercice...")
 
    os.system('espeak -v fr "Début de l\'exercice" --stdout | aplay')
 
   
 
    # Préparer les lettres dans un ordre aléatoire
 
    lettres = list("abcdefghijklmnopqrstuvwxyz")
 
    random.shuffle(lettres)
 
   
 
    # Parcourir les lettres aléatoires
 
    for lettre in lettres:
 
        # Vérifier si l'exercice a été arrêté
 
        if not exercice_en_cours:
 
            return
 
       
 
        # Afficher et annoncer la lettre avec délai de 2 secondes
 
        print(f"📝 Exercice : Lettre {lettre.upper()}")
 
        envoyer_nombre(braille_dict[lettre], mode="exercice")
 
       
 
        # Attendre le reste des 8 secondes (moins les 2 secondes d'attente déjà écoulées),
 
        # en vérifiant si l'exercice a été arrêté
 
        debut = time.time()
 
        while time.time() - debut < 6:  # 8 - 2 = 6 secondes restantes
 
            if not exercice_en_cours:
 
                return  # Sortir immédiatement si l'exercice a été arrêté
 
            time.sleep(0.1)
 
   
 
    # Fin normale de l'exercice
 
    print("🏆 Exercice terminé !")
 
    os.system('espeak -v fr "Exercice terminé" --stdout | aplay')
 
    exercice_en_cours = False
 
   
 
    # Proposer d'entrer un nouveau texte sans bloquer
 
    demander_nouveau_texte()
 
  
def capturer_et_lire_texte():
+
-Connecter le capteur de distance via 4 fils de connexion F>F à la carte Raspberry pi(VCC; GND; TRIG; ECHO)
    """Fonction pour capturer une image avec la caméra et en extraire le texte."""
 
    global camera_en_cours, texte, index, attente_texte
 
   
 
    # Si on attend une saisie de texte, annuler cette attente
 
    attente_texte = False
 
   
 
    # Marquer le début de la capture
 
    camera_en_cours = True
 
    print("📸 Préparation de la capture...")
 
    os.system('espeak -v fr "Préparation de la capture" --stdout | aplay')
 
   
 
    # Guide de positionnement avec le capteur ultrason
 
    if guide_position():
 
        # Capture de l'image (réduction du temps à 3s car on a déjà guidé l'utilisateur)
 
        print("📸 Capture en cours...")
 
        os.system('espeak -v fr "Capture en cours" --stdout | aplay')
 
        os.system(f"libcamera-jpeg -o {IMAGE_PATH} -t 3000 --width 1920 --height 1080 --quality 100")
 
       
 
        # Vérifier si l'image existe
 
        if not os.path.exists(IMAGE_PATH):
 
            print("❌ Erreur : L'image n'a pas été capturée.")
 
            os.system('espeak -v fr "Erreur de capture" --stdout | aplay')
 
            camera_en_cours = False
 
            return
 
       
 
        print("⚡ Optimisation de l'image...")
 
        try:
 
            # Chargement et conversion en niveaux de gris
 
            image = cv2.imread(IMAGE_PATH)
 
            gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 
           
 
            # Correction de l'orientation
 
            try:
 
                osd = pytesseract.image_to_osd(gray)
 
                angle = int(osd.split("\n")[1].split(":")[1].strip())
 
                if angle != 0:
 
                    (h, w) = gray.shape[:2]
 
                    center = (w // 2, h // 2)
 
                    M = cv2.getRotationMatrix2D(center, -angle, 1.0)
 
                    gray = cv2.warpAffine(gray, M, (w, h))
 
            except:
 
                print("⚠ Impossible de détecter l'orientation, passage à l'étape suivante.")
 
           
 
            # Prétraitement (amélioration du contraste et du bruit)
 
            gray = cv2.GaussianBlur(gray, (3, 3), 0)
 
            gray = cv2.equalizeHist(gray)  # Augmentation du contraste
 
            gray = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 10)
 
           
 
            # Détection des contours pour recadrer uniquement le texte
 
            print("📐 Détection du texte...")
 
            edges = cv2.Canny(gray, 50, 150)
 
            contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
 
           
 
            filtered_contours = [c for c in contours if cv2.contourArea(c) > 1000]
 
           
 
            if filtered_contours:
 
                x, y, w, h = cv2.boundingRect(cv2.convexHull(np.vstack(filtered_contours)))
 
                cropped = image[y:y+h, x:x+w]
 
                cropped = cv2.resize(cropped, None, fx=1.5, fy=1.5, interpolation=cv2.INTER_LINEAR)
 
                cv2.imwrite(CROPPED_PATH, cropped)
 
            else:
 
                print("⚠ Aucun texte clairement détecté, extraction sur l'image entière.")
 
                cropped = image
 
           
 
            # OCR optimisé
 
            print("🔍 Extraction du texte...")
 
            detected_text = pytesseract.image_to_string(cropped, lang="eng+fra", config="--psm 6 --oem 3").strip()
 
           
 
            # Nettoyer le texte détecté (supprimer les caractères spéciaux et garder lettres, chiffres et espaces)
 
            cleaned_text = ''.join(c.lower() for c in detected_text if c.isalnum() or c.isspace())
 
           
 
            # Si le texte est vide après nettoyage, afficher un message
 
            if not cleaned_text:
 
                print("⚠ Aucun texte détecté après nettoyage.")
 
                os.system('espeak -v fr "Aucun texte détecté" --stdout | aplay')
 
                camera_en_cours = False
 
                return
 
           
 
            # Afficher le texte détecté
 
            print(f"\n📄 Texte détecté : {cleaned_text}")
 
            os.system(f'espeak -v fr "Texte détecté" --stdout | aplay')
 
           
 
            # Mettre à jour le texte global et réinitialiser l'index
 
            texte = cleaned_text
 
            index = 0
 
            print(f"🔠 Nouveau texte : {texte}")
 
            print("📌 Appuyez sur le bouton 'Suivant' pour parcourir le texte.")
 
           
 
        except Exception as e:
 
            print(f"❌ Erreur lors du traitement de l'image : {str(e)}")
 
            os.system('espeak -v fr "Erreur de traitement" --stdout | aplay')
 
    else:
 
        print("❌ Positionnement annulé.")
 
        os.system('espeak -v fr "Positionnement annulé" --stdout | aplay')
 
   
 
    # Marquer la fin de la capture
 
    camera_en_cours = False
 
  
def bouton_lecon_presse(channel):
+
-Connecter les boutons sur les GPIO {17; 22; 23; 24; 27} de la Raspberry pi et les alimenter via la carte Arduino
    """Fonction appelée lorsque le bouton leçon est pressé."""
 
    global lecon_en_cours
 
   
 
    # Ne pas réagir si un autre mode est en cours
 
    if exercice_en_cours or camera_en_cours:
 
        return
 
   
 
    time.sleep(0.2)  # Anti-rebond
 
    if GPIO.input(BOUTON_LECON) == GPIO.LOW:
 
        # Basculer l'état de la leçon
 
        if lecon_en_cours:
 
            lecon_en_cours = False
 
            print("📖 Leçon arrêtée par l'utilisateur.")
 
            os.system('espeak -v fr "Leçon arrêtée" --stdout | aplay')
 
            # La leçon est arrêtée, sera nettoyée dans le thread
 
        else:
 
            # Lancer la leçon dans un thread séparé
 
            t = threading.Thread(target=lancer_lecon)
 
            t.daemon = True  # Le thread s'arrêtera quand le programme principal s'arrête
 
            t.start()
 
  
def bouton_exercice_presse(channel):
+
-Connecter le haut-parleur via 2 fils de connexion F>F.(VCC; GND) et le câble jack
    """Fonction appelée lorsque le bouton exercice est pressé."""
 
    global exercice_en_cours
 
   
 
    # Ne pas réagir si un autre mode est en cours
 
    if lecon_en_cours or camera_en_cours:
 
        return
 
   
 
    time.sleep(0.2)  # Anti-rebond
 
    if GPIO.input(BOUTON_EXERCICE) == GPIO.LOW:
 
        # Basculer l'état de l'exercice
 
        if exercice_en_cours:
 
            exercice_en_cours = False
 
            print("🎲 Exercice arrêté par l'utilisateur.")
 
            os.system('espeak -v fr "Exercice arrêté" --stdout | aplay')
 
            # L'exercice est arrêté, sera nettoyé dans le thread
 
        else:
 
            # Lancer l'exercice dans un thread séparé
 
            t = threading.Thread(target=lancer_exercice)
 
            t.daemon = True  # Le thread s'arrêtera quand le programme principal s'arrête
 
            t.start()
 
  
def bouton_camera_presse(channel):
+
<br /></translate>
    """Fonction appelée lorsque le bouton caméra est pressé."""
+
|Step_Picture_00=Caméra.jpg
    global camera_en_cours
+
|Step_Picture_01=capteur distance.jpg
   
+
|Step_Picture_02=Syst_me_de_traduction_et_d_apprentissage_du_Braille_5-mini-bouton-poussoir.jpg
    # Ne pas réagir si un autre mode est en cours
+
|Step_Picture_03=Syst_me_de_traduction_et_d_apprentissage_du_Braille_thumbnail_Afficher_les_photos_re_centes.jpg
    if lecon_en_cours or exercice_en_cours or camera_en_cours:
+
}}
        return
+
{{Tuto Step
   
+
|Step_Title=<translate>Branchement des servo-moteurs</translate>
    time.sleep(0.2)  # Anti-rebond
+
|Step_Content=<translate>-Connecter en PWM les 6 servo-moteurs linéaires à la carte Arduino en utilisant son alimentation et via les ports {3; 5; 6; 9; 10; 11}.</translate>
    if GPIO.input(BOUTON_CAMERA) == GPIO.LOW:
+
|Step_Picture_00=servomoteur.jpg
        # Lancer la capture dans un thread séparé
+
}}
        t = threading.Thread(target=capturer_et_lire_texte)
+
{{Tuto Step
        t.daemon = True  # Le thread s'arrêtera quand le programme principal s'arrête
+
|Step_Title=<translate>Test des codes</translate>
        t.start()
+
|Step_Content=<translate>-Alimenter les 2 carte électroniques.  
 
 
# Supprimer les détecteurs d'événements existants s'il y en a
 
try:
 
    GPIO.remove_event_detect(BOUTON_SUIVANT)
 
    GPIO.remove_event_detect(BOUTON_PRECEDENT)
 
    GPIO.remove_event_detect(BOUTON_LECON)
 
    GPIO.remove_event_detect(BOUTON_EXERCICE)
 
    GPIO.remove_event_detect(BOUTON_CAMERA)
 
except:
 
    pass
 
 
 
# Configuration des détecteurs d'événements
 
GPIO.add_event_detect(BOUTON_SUIVANT, GPIO.FALLING, callback=bouton_suivant, bouncetime=500)
 
GPIO.add_event_detect(BOUTON_PRECEDENT, GPIO.FALLING, callback=bouton_precedent, bouncetime=500)
 
GPIO.add_event_detect(BOUTON_LECON, GPIO.FALLING, callback=bouton_lecon_presse, bouncetime=500)
 
GPIO.add_event_detect(BOUTON_EXERCICE, GPIO.FALLING, callback=bouton_exercice_presse, bouncetime=500)
 
GPIO.add_event_detect(BOUTON_CAMERA, GPIO.FALLING, callback=bouton_camera_presse, bouncetime=500)
 
 
 
# Initialisation du capteur ultrason (attendre qu'il se stabilise)
 
print("⚙️ Initialisation du capteur ultrason...")
 
time.sleep(0.5)
 
GPIO.output(TRIG, False)
 
time.sleep(0.5)
 
  
# Afficher les instructions au démarrage
+
-Attendre quelques instants que la raspberry se lance.
print("👋 Bienvenue dans l'application d'apprentissage du Braille")
 
print("📋 Instructions:")
 
print("  - Bouton LEÇON: Apprendre l'alphabet (8s par lettre)")
 
print("  - Bouton EXERCICE: Pratiquer avec des lettres aléatoires (2s de réflexion, puis annonce)")
 
print("  - Bouton SUIVANT: Afficher la lettre suivante du texte")
 
print("  - Bouton PRÉCÉDENT: Afficher la lettre précédente du texte")
 
print("  - Bouton CAMÉRA: Guide le positionnement, puis capture une image et extrait le texte")
 
print("⚠️ Appuyez à nouveau sur LEÇON/EXERCICE pour arrêter à tout moment")
 
print(f"🔠 Texte par défaut : {texte}")
 
print("📌 Appuyez sur le bouton 'Suivant' pour parcourir le texte, ou choisissez un mode.")
 
  
# Boucle principale pour maintenir le programme actif
+
-Tester les boutons:
try:
 
    while True:
 
        time.sleep(0.1)
 
except KeyboardInterrupt:
 
    print("\n🛑 Arrêt du programme.")
 
    GPIO.cleanup()
 
</syntaxhighlight>  ====</translate>
 
|Step_Picture_00=Syst_me_de_traduction_et_d_apprentissage_du_Braille_nm_arduino-front.jpg
 
|Step_Picture_01=Syst_me_de_traduction_et_d_apprentissage_du_Braille_91zSu44_34L._AC_UF1000_1000_QL80_.jpg
 
|Step_Picture_02=Syst_me_de_traduction_et_d_apprentissage_du_Braille_images_1_.jpeg
 
|Step_Picture_02_annotation={"version":"3.5.0","objects":[{"type":"image","version":"3.5.0","originX":"left","originY":"top","left":-41,"top":7,"width":251,"height":200,"fill":"rgb(0,0,0)","stroke":null,"strokeWidth":0,"strokeDashArray":null,"strokeLineCap":"butt","strokeDashOffset":0,"strokeLineJoin":"miter","strokeMiterLimit":4,"scaleX":2.7,"scaleY":2.7,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","paintFirst":"fill","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"crossOrigin":"","cropX":0,"cropY":0,"src":"https://wikifab.org/images/7/7e/Syst_me_de_traduction_et_d_apprentissage_du_Braille_images_1_.jpeg","filters":[]}],"height":478.15384615384613,"width":600}
 
}}
 
{{Tuto Step
 
|Step_Title=<translate>Système d'interface homme-machine</translate>
 
|Step_Content=<translate>Le système est équipé de '''5 boutons physiques''' qui permettent de contrôler les différents modes d'apprentissage et la détection du texte.
 
  
-Brancher les bouton aux broches gpio correspondantes grâce au code inséré précédement</translate>
+
*Bouton 1:  Début du mode leçon ( Lettre dans l'ordre alphabétique)
|Step_Picture_00=Syst_me_de_traduction_et_d_apprentissage_du_Braille_raspberry-pi-camera-module-3-12mp-objectif-standard-haute-resolution-sc0872.jpg
+
*Bouton 2: Début du mode exercice ( Lettre dans le désordre)
|Step_Picture_01=Syst_me_de_traduction_et_d_apprentissage_du_Braille_images.jpeg
+
*Bouton 3: Lancement de la caméra:
 +
*#Positionner le capteur de distance à environ 15cm, +/- 1cm d'un texte
 +
*#Ne plus bouger
 +
*#Attendre quelques secondes que la raspberry pi reconnaisse des lettres
 +
*Bouton 4: Lettre suivante( Du texte détecté via la caméra)
 +
*Bouton 5: Lettre précédente (Du texte détecté via la caméra)</translate>
 +
|Step_Picture_00=Syst_me_de_traduction_et_d_apprentissage_du_Braille_thumbnail_Sujet_6_.png
 
}}
 
}}
 
{{Tuto Step
 
{{Tuto Step
|Step_Title=<translate>Système de détection de texte</translate>
+
|Step_Title=<translate>Assemblage</translate>
|Step_Content=<translate>===='''Le système utilise une caméra et un capteur à ultrasons pour détecter du texte .'''====
+
|Step_Content=<translate>-Assembler les composants dans le boitier afin de les protéger.
-Se munir du Capteur ultrason et le brancher sur la broche gpio (regardez le code rasperypi pour savoir )
 
  
- Brancher la camera à la Raspberry Pi, il y a un tuto [https://www.gotronic.fr/pj2-tutopicam-1585.pdf?srsltid=AfmBOorFOpsASuNtAhuMkrhdSImstiAlyNY9y20oJxfODo4Vyu3Cx9X6 ici]
+
-Utiliser des vis pour un meilleur maintien des composants si possible.</translate>
 
+
|Step_Picture_00=Syst_me_de_traduction_et_d_apprentissage_du_Braille_thumbnail_Sujet_4_.png
-Lancer en premier lieu sur raspery pi</translate>
+
|Step_Picture_01=Assemblage 2 Braille.png
|Step_Picture_00=Syst_me_de_traduction_et_d_apprentissage_du_Braille_capteur-de-distance-ultrason-hc-sr04.jpg
 
|Step_Picture_01=Syst_me_de_traduction_et_d_apprentissage_du_Braille_raspberry-pi-camera-module-3-12mp-objectif-standard-haute-resolution-sc0872.jpg
 
 
}}
 
}}
 
{{Tuto Step
 
{{Tuto Step
|Step_Title=<translate></translate>
+
|Step_Title=<translate>Test final</translate>
|Step_Content=<translate></translate>
+
|Step_Content=<translate>-Tester les boutons et valider les actions engendrées.</translate>
 +
|Step_Picture_00=Syst_me_de_traduction_et_d_apprentissage_du_Braille_thumbnail_Sujet_5_.png
 
}}
 
}}
 
{{Notes
 
{{Notes
Ligne 657 : Ligne 194 :
 
}}
 
}}
 
{{PageLang
 
{{PageLang
 +
|Language=fr
 
|SourceLanguage=none
 
|SourceLanguage=none
 
|IsTranslation=0
 
|IsTranslation=0
|Language=fr
 
 
}}
 
}}
 
{{Tuto Status
 
{{Tuto Status
 
|Complete=Published
 
|Complete=Published
 
}}
 
}}

Version actuelle datée du 26 mai 2025 à 22:29

Auteur avatarGOACOLO | Dernière modification 26/05/2025 par Yawen

Présentation d'un tutoriel notre projet de classe de terminale STI2D afin de le reproduire chez soi

Matériaux

Matériaux pour le boitier

-Planche en bois 3mm d'épaisseur / 30cm de large / 60 cm de long

-Plastique pour découpeuse laser ( ici du PLA) environ (100g)


Composants électroniques

-1x Raspberry pi 3

-6x Servo moteurs linéaires

-1x Mini Haut parleur (Module haut-parleur SKU00101)

-1x Cordon Jack CA35M

- 1x Carte Arduino Uno

- 5x boutons poussoirs

- 1x Capteur Ultrason

- 1x Caméra compatible Raspberry pi disponible chez Kubii

-40x Fils de connexion électronique

Outils

-Découpeuse laser

-Imprimante 3D (ici la Ultimaker 2+)

-Ordinateur

Étape 1 - Découpe des pièces en bois du boitier

-Connecter l'ordinateur à la découpeuse laser.

-Ouvrir le logiciel Trotek ( Nécessaire à la découpe).

-Ouvrir les pièces à découper en format dxf dans le logiciel.

-Optimiser l'espace sur la planche afin d'avoir les moins de perte de matière et déplaçant les pièces.

-Lancer la découpe.

-Nettoyer les pièces afin d'éviter des tâches dues au bois brûlé.




Étape 2 - Assemblage des pièces en bois

-Assembler les pièces découpées grâce aux images ci-contre.

-Les coller via de la colle à bois.




Étape 3 - Configuration de la carte électronique Raspberry pi v3

-Configurer votre carte Raspberry pi.

-Alimenter la carte Raspberry pi via son câble d'alimentation à l'ordinateur et en hdmi à l'écran.

-Copier le code "Raspberry_code" dans un fichier python au même nom.

-Avant de lancer ce fichier, vous devez d’abord créer et démarrer un environnement virtuel à l’aide du terminal. Cela permet de préparer un espace propre pour faire fonctionner votre programme.

-Dans le terminal, tapper "python3 Raspberry_code.py".

-Le code devrait se lancer.

-Si c'est le cas, débrancher la carte raspberry pi, sinon regarder un tutoriel sur internet.




Étape 4 - Configuration de la carte électronique Arduino Uno

-Alimenter la carte Arduino Uno via son câble d'alimentation à ordinateur.

-Ouvrir Le logiciel Arduino IDE.

-Ouvrir le fichier "Arduino_code.ino".

-Uploader le code.

-Si le code parvient à s'uploader, débrancher la carte Arduino, sinon regarder un tutoriel sur internet.


Étape 5 - Branchement des composants

-Une fois les 2 cartes débranchées, les connecter en I2C via 3 fils de connexion M>F.(SDA; SCL; GND)

-Bancher la caméra à la carte raspberry pi.

-Connecter le capteur de distance via 4 fils de connexion F>F à la carte Raspberry pi(VCC; GND; TRIG; ECHO)

-Connecter les boutons sur les GPIO {17; 22; 23; 24; 27} de la Raspberry pi et les alimenter via la carte Arduino

-Connecter le haut-parleur via 2 fils de connexion F>F.(VCC; GND) et le câble jack



Étape 6 - Branchement des servo-moteurs

-Connecter en PWM les 6 servo-moteurs linéaires à la carte Arduino en utilisant son alimentation et via les ports {3; 5; 6; 9; 10; 11}.




Étape 7 - Test des codes

-Alimenter les 2 carte électroniques.

-Attendre quelques instants que la raspberry se lance.

-Tester les boutons:

  • Bouton 1: Début du mode leçon ( Lettre dans l'ordre alphabétique)
  • Bouton 2: Début du mode exercice ( Lettre dans le désordre)
  • Bouton 3: Lancement de la caméra:
    1. Positionner le capteur de distance à environ 15cm, +/- 1cm d'un texte
    2. Ne plus bouger
    3. Attendre quelques secondes que la raspberry pi reconnaisse des lettres
  • Bouton 4: Lettre suivante( Du texte détecté via la caméra)
  • Bouton 5: Lettre précédente (Du texte détecté via la caméra)




Étape 8 - Assemblage

-Assembler les composants dans le boitier afin de les protéger.

-Utiliser des vis pour un meilleur maintien des composants si possible.



Étape 9 - Test final

-Tester les boutons et valider les actions engendrées.




Commentaires

Published