diff --git a/labyrinthe/3-arduino_pyfirmata/3 - Interfacer avec Arduino par pyFirmata.odp b/labyrinthe/3-arduino_pyfirmata/3 - Interfacer avec Arduino par pyFirmata.odp index 70a91c2..5473d7c 100644 Binary files a/labyrinthe/3-arduino_pyfirmata/3 - Interfacer avec Arduino par pyFirmata.odp and b/labyrinthe/3-arduino_pyfirmata/3 - Interfacer avec Arduino par pyFirmata.odp differ diff --git a/labyrinthe/3-arduino_pyfirmata/3 - Interfacer avec Arduino par pyFirmata.pdf b/labyrinthe/3-arduino_pyfirmata/3 - Interfacer avec Arduino par pyFirmata.pdf index aa5f6bb..3959a25 100644 Binary files a/labyrinthe/3-arduino_pyfirmata/3 - Interfacer avec Arduino par pyFirmata.pdf and b/labyrinthe/3-arduino_pyfirmata/3 - Interfacer avec Arduino par pyFirmata.pdf differ diff --git a/labyrinthe/4-arduino_pyserial/4 - Interfacer avec Arduino par pySerial.odp b/labyrinthe/4-arduino_pyserial/4 - Interfacer avec Arduino par pySerial.odp index eb61a24..7bb8585 100644 Binary files a/labyrinthe/4-arduino_pyserial/4 - Interfacer avec Arduino par pySerial.odp and b/labyrinthe/4-arduino_pyserial/4 - Interfacer avec Arduino par pySerial.odp differ diff --git a/labyrinthe/4-arduino_pyserial/4 - Interfacer avec Arduino par pySerial.pdf b/labyrinthe/4-arduino_pyserial/4 - Interfacer avec Arduino par pySerial.pdf index 0a00b95..a32d54b 100644 Binary files a/labyrinthe/4-arduino_pyserial/4 - Interfacer avec Arduino par pySerial.pdf and b/labyrinthe/4-arduino_pyserial/4 - Interfacer avec Arduino par pySerial.pdf differ diff --git a/labyrinthe/5-microbit/5 - Interfacer avec microbit.odp b/labyrinthe/5-microbit/5 - Interfacer avec microbit.odp index 62db502..d011313 100644 Binary files a/labyrinthe/5-microbit/5 - Interfacer avec microbit.odp and b/labyrinthe/5-microbit/5 - Interfacer avec microbit.odp differ diff --git a/labyrinthe/5-microbit/5 - Interfacer avec microbit.pdf b/labyrinthe/5-microbit/5 - Interfacer avec microbit.pdf index 073b77b..08676b4 100644 Binary files a/labyrinthe/5-microbit/5 - Interfacer avec microbit.pdf and b/labyrinthe/5-microbit/5 - Interfacer avec microbit.pdf differ diff --git a/labyrinthe/5-microbit/5-labyrinthe-microbit.py b/labyrinthe/5-microbit/5-labyrinthe-microbit.py new file mode 100644 index 0000000..e11d3cc --- /dev/null +++ b/labyrinthe/5-microbit/5-labyrinthe-microbit.py @@ -0,0 +1,24 @@ +from microbit import * + +############################################################################### +# 5-labyrinthe-microbit.py +# @title: Programme pour la carte micro:bit de gestion de la centrale inertielle +# @project: Blender-EduTech - Tutoriel 5 : Labyrinthe à bille - Interfacer avec une carte micro:bit +# @lang: fr +# @authors: Philippe Roy +# @copyright: Copyright (C) 2023 Philippe Roy +# @license: GNU GPL +# +# Commandes déclenchées par UPBGE pour le scène du labyrinthe +# +############################################################################### + +while True: + accel_x=accelerometer.get_x() + if accel_x < -30 : + display.show(Image.ARROW_W) + if accel_x > 30 : + display.show(Image.ARROW_E) + if accel_x > -30 and accel_x < 30 : + display.show(Image.YES) + sleep(100) diff --git a/labyrinthe/5-microbit/5-labyrinthe.blend b/labyrinthe/5-microbit/5-labyrinthe.blend new file mode 100644 index 0000000..4b5382a Binary files /dev/null and b/labyrinthe/5-microbit/5-labyrinthe.blend differ diff --git a/labyrinthe/5-microbit/5-labyrinthe.py b/labyrinthe/5-microbit/5-labyrinthe.py new file mode 100644 index 0000000..fa9d0eb --- /dev/null +++ b/labyrinthe/5-microbit/5-labyrinthe.py @@ -0,0 +1,177 @@ +import bge # Bibliothèque Blender Game Engine (BGE) +import serial # Liaison série +import labyrinthe_carte # Liaison avec la carte + +############################################################################### +# 5-labyrinthe.py +# @title: Module (unique) de la scène 3D du labyrinthe à bille pilotable la centrale inertielle de la carte micro:bit +# @project: Blender-EduTech - Tutoriel 5 : Labyrinthe à bille - Interfacer avec une carte micro:bit +# @lang: fr +# @authors: Philippe Roy +# @copyright: Copyright (C) 2023 Philippe Roy +# @license: GNU GPL +# +# Commandes déclenchées par UPBGE pour le scène du labyrinthe +# +############################################################################### + +# Récupérer la scène 3D +scene = bge.logic.getCurrentScene() +# print("Objets de la scene : ", scene.objects) # Lister les objets de la scène + +# Constantes +JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED +JUST_RELEASED = bge.logic.KX_INPUT_JUST_RELEASED +ACTIVATE = bge.logic.KX_INPUT_ACTIVE + +# Communication avec la carte Arduino +# serial_baud=115200 +# # serial_comm = serial.Serial('COM4',serial_baud, timeout=0.016) # Windows +# serial_comm = serial.Serial('/dev/ttyACM1',serial_baud, timeout=0.016) # GNU/Linux +# print (serial_comm) + +# Détection de la carte avec la liaison série +serial_comm = labyrinthe_carte.init_serial() +if serial_comm is None: + bge.logic.endGame() + +############################################################################### +# Gestion de la centrale inertielle (capteur IMU (inertial measurement unit)) +############################################################################### + +# Lecture du capteur IMU +def capteur(cont): + obj = cont.owner # obj est l'objet associé au contrôleur donc 'Plateau' + obj_bille = scene.objects['Bille'] + echelle = 0.2 # Facteur d'échelle entre la capteur et la 3D + ecart=0.001 # Écart maxi sur la rotation + + # Touche ESC -> Quitter + keyboard = bge.logic.keyboard + if keyboard.inputs[bge.events.ESCKEY].status[0] == ACTIVATE: + serial_comm.close() + bge.logic.endGame() + + # Lecture de la liaison série : programme Arduino : 4-labyrinthe-imu.ino + serial_msg_in = str(serial_comm.readline()) + + # Mettre la bille à la position de départ avec une vitesse nulle + if serial_msg_in.find("start")>0: + if obj_bille['victoire'] or obj_bille['chute']: + depart() + + # Roll et Pitch + if serial_msg_in.find(",")>0: + txt = serial_msg_in.split(',',2) + x_txt = txt[0][2:] + y_txt = txt[1][:-5] + if x_txt != " NAN" and y_txt != " NAN": # NAN : Not A Number + x=-(float(x_txt)/57.3) * echelle # 1/ 360 / (2 * pi) + y=-(float(y_txt)/57.3) * echelle # 1/ 360 / (2 * pi) + while abs(x-obj.worldOrientation.to_euler().x) > ecart : + obj.applyRotation((x-obj.worldOrientation.to_euler().x, 0, -obj.worldOrientation.to_euler().z), False) + while abs(y-obj.worldOrientation.to_euler().y) > ecart : + obj.applyRotation((0, y-obj.worldOrientation.to_euler().y, -obj.worldOrientation.to_euler().z), False) + +############################################################################### +# Gameplay +############################################################################### + +# Initialisation de la scène +def init(cont): + obj = cont.owner # obj est l'objet associé au contrôleur donc 'Bille' + + # Mémorisation de la position de départ de la bille + obj['init_x']=obj.worldPosition.x + obj['init_y']=obj.worldPosition.y + obj['init_z']=obj.worldPosition.z + + # Cacher le panneau de la victoire et suspendre la physique du panneau cliquable + scene.objects['Panneau victoire'].setVisible(False,True) + scene.objects['Panneau victoire - plan'].suspendPhysics (True) + scene.objects['Bouton fermer'].color = (0, 0, 0, 1) # Noir + +# Cycle (boucle de contrôle de la bille) +def cycle(cont): + obj = cont.owner # obj est l'objet associé au contrôleur donc 'Bille' + obj['z']=obj.worldPosition.z # la propriété z est mis à jour avec la position globale en z de la bille + + # Écriture de la position de la bille sur la liaison série : programme Arduino : 4-labyrinthe-imu.ino + if obj['victoire']==False and obj['chute']==False: + # obj['x'] = obj.worldPosition.x # de -3.5 à 3.5 + # obj['y'] = obj.worldPosition.y # de 3.5 à -3.5 + obj['Lx']=-1*round(obj.worldPosition.x-3.5) # de 7 à 0 + if obj['Lx']<0: obj['Lx']=0 + if obj['Lx']>7: obj['Lx']=7 + obj['Ly']=-1*round(obj.worldPosition.y-3.5) # de 0 à 7 + if obj['Ly']<0: obj['Ly']=0 + if obj['Ly']>7: obj['Ly']=7 + serial_msg_out = str(obj['Lx'])+str(obj['Ly'])+"\n" + serial_comm.write(serial_msg_out.encode()) + + # Si l'altitude de bille < -10 et pas de victoire -> chute + if obj['z'] < -10 and obj['victoire'] == False : + + # Afficher image de chute sur la matrice de leds + serial_msg_out = "91\n" + serial_comm.write(serial_msg_out.encode()) + obj['chute'] = True + +# Départ de la bille +def depart(): + obj_bille = scene.objects['Bille'] + obj_plateau = scene.objects['Plateau'] + + # Replacement du plateau (tous les angles à 0 en plusieurs fois) + while obj_plateau.worldOrientation.to_euler().x != 0 and obj_plateau.worldOrientation.to_euler().y !=0 and obj_plateau.worldOrientation.to_euler().z !=0 : + obj_plateau.applyRotation((-obj_plateau.worldOrientation.to_euler().x, -obj_plateau.worldOrientation.to_euler().y, -obj_plateau.worldOrientation.to_euler().z), False) + + # Mettre la bille à la position de départ avec une vitesse nulle + obj_bille.worldLinearVelocity=(0, 0, 0) + obj_bille.worldAngularVelocity=(0, 0, 0) + obj_bille.worldPosition.x = obj_bille['init_x'] + obj_bille.worldPosition.y = obj_bille['init_y'] + obj_bille.worldPosition.z = obj_bille['init_z']+0.5 # On repose la bille + obj_bille['victoire']=False + obj_bille['chute'] = False + +# Victoire (collision de la bille avec l'arrivée) +def victoire(cont): + + # Afficher image de victoire sur la matrice de leds + serial_msg_out = "92\n" + serial_comm.write(serial_msg_out.encode()) + scene.objects['Bille']['victoire']=True + + # Animation du Panneau victoire + scene.objects['Panneau victoire'].setVisible(True,True) # Afficher le panneau de la victoire + scene.objects['Panneau victoire - plan'].restorePhysics() # Restaurer la physique du panneau cliquable + start = 1 + end = 100 + layer = 0 + priority = 1 + blendin = 1.0 + mode = bge.logic.KX_ACTION_MODE_PLAY + layerWeight = 0.0 + ipoFlags = 0 + speed = 1 + scene.objects['Panneau victoire'].playAction('Panneau victoireAction', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed) + +# Highlight du bouton Fermer +def victoire_fermer_hl(cont): + obj = cont.owner + + # Activation + if cont.sensors['MO'].status == JUST_ACTIVATED: + obj.color = (1, 1, 1, 1) # Blanc + + # Désactivation + if cont.sensors['MO'].status == JUST_RELEASED: + obj.color = (0, 0, 0, 1) # Noir + +# Fermer le panneau de la victoire (clic) +def victoire_fermer(cont): + if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive: + scene.objects['Panneau victoire'].setVisible(False,True) # Cacher le panneau de la victoire + scene.objects['Panneau victoire - plan'].suspendPhysics (True) # Suspendre la physique du panneau cliquable + depart() diff --git a/labyrinthe/5-microbit/labyrinthe_carte.py b/labyrinthe/5-microbit/labyrinthe_carte.py new file mode 100644 index 0000000..886531b --- /dev/null +++ b/labyrinthe/5-microbit/labyrinthe_carte.py @@ -0,0 +1,52 @@ +import serial # Liaison série +from serial.tools.list_ports import comports # Détection du port automatique + +############################################################################### +# labyrinthe_carte.py +# @title: Détection automatique de la carte Arduino ou microbit +# @project: Blender-EduTech - Tutoriel 5 : Labyrinthe à bille - Interfacer avec une carte micro:bit +# @lang: fr +# @authors: Philippe Roy +# @copyright: Copyright (C) 2023 Philippe Roy +# @license: GNU GPL +# +# Détection automatique de la carte Arduino ou microbit +# +############################################################################### + +############################################################################### +# Communication avec la carte Arduino +############################################################################### + +# Recherche automatique du port (microbit, Arduino Uno et Arduino Mega) +def autoget_port(): + # USB Vendor ID, USB Product ID + carte_dict={'microbit' :[3368, 516], + 'uno' :[9025, 67], + 'mega' :[9025, 66]} + for com in comports(): # micro:bit + if com.vid == carte_dict['microbit'][0] and com.pid == carte_dict['microbit'][1]: + return [com.device,"micro:bit"] + for com in comports(): # Arduino Uno + if com.vid == carte_dict['uno'][0] and com.pid == carte_dict['uno'][1]: + return [com.device,"Arduino Uno"] + for com in comports(): # Arduino Mega + if com.vid == carte_dict['mega'][0] and com.pid == carte_dict['mega'][1]: + return [com.device,"Arduino Mega"] + return [None,""] + + # Établir la communication avec la carte par la liaison série avec une vitesse +def init_serial(speed=115200): + [port, carte_name] =autoget_port() + print (port, carte_name) + if port is None: + print("Carte Arduino/microbit introuvable") + return None + else: + serial_comm = serial.Serial(port, speed, timeout=0.016) + if serial_comm is None: + print("Communication avec Carte Arduino/microbit impossible") + return None + else: + print("Communication avec Carte Arduino/microbit établie sur "+port+" à la vitesse "+str(speed)+" bauds") + return serial_comm diff --git a/labyrinthe/README.md b/labyrinthe/README.md index 7a44318..6652170 100644 --- a/labyrinthe/README.md +++ b/labyrinthe/README.md @@ -32,7 +32,7 @@ Il se décompose en 5 parties : - Inclure la bibliothèque pyFirmata avec l'exécutable - **Fichiers de départ : 2-labyrinthe.blend, 2-labyrinthe.py** - **Documents techniques : Carte de référence pyFirmata et interface Grove pour Arduino** -- **Fichiers résultats : 3-labyrinthe.blend, 3-labyrinthe.py** +- **Fichiers résultats : 3-labyrinthe.blend, 3-labyrinthe.py, labyrinthe_carte.py** ### Tutoriel 4 : Interfacer la scène 3D avec une carte Arduino par pySerial - Installer la bibliothèque pySerial @@ -41,14 +41,15 @@ Il se décompose en 5 parties : - Inclure la bibliothèque pySerial avec l'exécutable - **Fichiers de départ : 2-labyrinthe.blend, 2-labyrinthe.py** - **Document technique : Interface Grove pour Arduino** -- **Fichiers résultats : 4-labyrinthe.blend, 4-labyrinthe.py, 4-labyrinthe-imu.ino** +- **Fichiers résultats : 4-labyrinthe.blend, 4-labyrinthe.py, 4-labyrinthe-imu.ino, labyrinthe_carte.py** ### Tutoriel 5 : Interfacer la scène 3D avec une carte micro:bit - Installer la bibliothèque pySerial - Déplacer le plateau avec la centrale inertielle de la carte microbit +- Afficher la position de la bille sur la matrice de leds - Inclure la bibliothèque pySerial avec l'exécutable - **Fichiers de départ : 2-labyrinthe.blend, 2-labyrinthe.py** - **Document technique : Carte de référence carte micro:bit** -- **Fichiers résultats : 5-labyrinthe.blend, 5-labyrinthe.py, 5-labyrinthe-microbit.py** +- **Fichiers résultats : 5-labyrinthe.blend, 5-labyrinthe.py, 5-labyrinthe-microbit.py, labyrinthe_carte.py**