diff --git a/monte_charge/montchg.py b/monte_charge/montchg.py new file mode 100644 index 0000000..487fc51 --- /dev/null +++ b/monte_charge/montchg.py @@ -0,0 +1,306 @@ +import bge # Bibliothèque Blender Game Engine (UPBGE) +import twin # Bibliothèque de l'environnement 3D des jumeaux numériques +import math +import time + +############################################################################### +# montchg.py +# @title: Commandes pour le monte-charge +# @project: Blender-EduTech +# @lang: fr +# @authors: Philippe Roy +# @copyright: Copyright (C) 2022 Philippe Roy +# @license: GNU GPL +# +# Commandes déclenchées par/sur le simulateur (sml_*) +# +############################################################################### + +# Récupérer la scène UPBGE +scene = bge.logic.getCurrentScene() + +# Couleurs + +couleur_magenta = (0.800, 0.005, 0.315,1) # bouton non activable : magenta +couleur_orange = (0.799, 0.130, 0.063,1) # bouton activable : orange +couleur_blanc = (0.8, 0.8, 0.8, 1) # bouton focus : blanc +couleur_jaune = (0.8, 0.619, 0.021, 1) # bouton activé : jaune + +# Constantes UPBGE + +JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED +JUST_RELEASED = bge.logic.KX_INPUT_JUST_RELEASED +ACTIVATE = bge.logic.KX_INPUT_ACTIVE +# JUST_DEACTIVATED = bge.logic.KX_SENSOR_JUST_DEACTIVATED + +############################################################################### +# Initialisation de la scène +############################################################################### + +def init(cont): + if cont.sensors['Init'].positive == False: # 1 seule fois + return False + + twin.manip_init() # Manipulation du modèle 3D + twin.cmd_init() # Commandes + + # Mémorisation de la position et orientation des composants du système + scene.objects['Portail']['init_lx']=scene.objects['Portail'].worldPosition.x + scene.objects['Portail']['init_ly']=scene.objects['Portail'].worldPosition.y + scene.objects['Portail']['init_lz']=scene.objects['Portail'].worldPosition.z + scene.objects['Engrenage']['init_rx']=scene.objects['Engrenage'].worldOrientation.to_euler().x + scene.objects['Engrenage']['init_ry']=scene.objects['Engrenage'].worldOrientation.to_euler().y + scene.objects['Engrenage']['init_rz']=scene.objects['Engrenage'].worldOrientation.to_euler().z + + system_init() # Initialisation du système + +############################################################################### +# Actionneurs +############################################################################### + +## +# Action du simulateur pour le clignotant +## + +def sml_clignotant (cont): + if scene.objects['System']['run']: + obj = cont.owner + if obj['actif'] and scene.objects['Led allumee'].visible == False: + scene.objects['Led allumee'].setVisible(True,False) + scene.objects['Led'].setVisible(False,False) + # print ("Clignotant allumée") + if obj['actif']==False and scene.objects['Led allumee'].visible == True: + scene.objects['Led'].setVisible(True,False) + scene.objects['Led allumee'].setVisible(False,False) + # print ("Clignotant éteint") + +## +# Action du simulateur pour le moteur +## + +def sml_moteur (cont): + if scene.objects['System']['run']: + obj = cont.owner + pas_rot = math.pi/7 # z = 14 + pas = 2.35619/0.3 # pas echelle 1:1 = 2.35619 -> pas à l'échelle de la maquette (0,3) : 2.35619/0.3 = 7,85396 + vitesse = 0.05 + engrenage_obj = scene.objects['Engrenage'] + portail_obj = scene.objects['Portail'] + if obj['actif_ouvrir']: + # print (scene.objects['Portail'].worldPosition.x) + engrenage_obj.applyRotation((0, 0, -pas_rot*vitesse), True) + portail_obj.applyMovement((-pas*vitesse, 0, 0), True) + # else: + if obj['actif_fermer']: + # print (scene.objects['Portail'].worldPosition.x) + engrenage_obj.applyRotation((0, 0, pas_rot*vitesse), True) + portail_obj.applyMovement((pas*vitesse, 0, 0), True) + +############################################################################### +# Capteurs fin de course +############################################################################### + +## +# Etat capteur fin de course portail ouvert +## + +def sml_fdc_ouvert (cont): + if scene.objects['System']['run'] : + obj = cont.owner + obj_etat=obj['actif'] + obj_microrupteur=scene.objects['Microrupteur fdc ouvert'] + # Etat capteur en fonction de la grille : worldPosition.x : 0 -> 65.5 et localPosition.x : 0 -> 218 + if scene.objects['Portail'].localPosition.x <= 0 and obj['actif'] == False : + obj['actif'] = True + if scene.objects['Portail'].localPosition.x > 0 and obj_microrupteur['actif'] == False and obj['actif'] == True : + obj['actif'] = False + #Forçage + if obj_microrupteur['actif'] == True: + obj['actif'] = True + #Couleurs + if obj['actif'] == True and obj_microrupteur.color !=couleur_jaune: + obj_microrupteur.color =couleur_jaune + if obj['actif'] == False : + if obj_microrupteur['MO'] == True and obj_microrupteur.color !=couleur_blanc: + obj_microrupteur.color =couleur_blanc + if obj_microrupteur['MO'] == False and obj_microrupteur.color !=couleur_orange: + obj_microrupteur.color =couleur_orange + +## +# Etat capteur fin de course portail fermé +## + +def sml_fdc_ferme (cont): + if scene.objects['System']['run'] : + obj = cont.owner + obj_etat=obj['actif'] + obj_microrupteur=scene.objects['Microrupteur fdc ferme'] + # Etat capteur en fonction de la grille : worldPosition.x : 0 -> 65.5 et localPosition.x : 0 -> 218 + if scene.objects['Portail'].localPosition.x >= 218 and obj['actif'] == False : + obj['actif'] = True + if scene.objects['Portail'].localPosition.x < 218 and obj_microrupteur['actif'] == False and obj['actif'] == True : + obj['actif'] = False + #Forçage + if obj_microrupteur['actif'] == True: + obj['actif'] = True + #Couleurs + if obj['actif'] == True and obj_microrupteur.color !=couleur_jaune: + obj_microrupteur.color =couleur_jaune + if obj['actif'] == False : + if obj_microrupteur['MO'] == True and obj_microrupteur.color !=couleur_blanc: + obj_microrupteur.color =couleur_blanc + if obj_microrupteur['MO'] == False and obj_microrupteur.color !=couleur_orange: + obj_microrupteur.color =couleur_orange + +## +# Forçage capteur fin de course avec la souris +## + +def sml_microrupteur (cont): + if scene.objects['System']['run'] : + system_click(cont, cont.owner) + +############################################################################### +# Capteur barrage +############################################################################### + +## +# Emetteur IR +## + +def sml_emet_ir (cont): + if scene.objects['System']['run'] : + obj = cont.owner + obj_emetteur_ir=scene.objects['Emetteur IR'] + obj_recepteur_ir=scene.objects['Recepteur IR'] + if obj['actif'] and scene.objects['Emetteur IR Led allumee'].visible == False: + scene.objects['Emetteur IR Led allumee'].setVisible(True,False) + scene.objects['Emetteur IR Led'].setVisible(False,False) + obj_emetteur_ir.color = couleur_orange + obj_recepteur_ir.color = couleur_orange + if obj['actif']==False and scene.objects['Emetteur IR Led allumee'].visible == True: + scene.objects['Emetteur IR Led'].setVisible(True,False) + scene.objects['Emetteur IR Led allumee'].setVisible(False,False) + obj_emetteur_ir.color = couleur_magenta + obj_recepteur_ir.color = couleur_magenta + +## +# Récepteur IR +## + +def sml_recep_ir (cont): + if scene.objects['System']['run'] and scene.objects['Module emetteur IR']['actif'] : + obj = cont.owner + system_click(cont, scene.objects['Module recepteur IR']) + if scene.objects['Module recepteur IR']['actif']==True : + scene.objects['Emetteur IR'].color = couleur_jaune + scene.objects['Recepteur IR'].color = couleur_jaune + +############################################################################### +# Boutons poussoirs +############################################################################### + +## +# Bouton pousssoir coté rue +## + +def sml_bp_rue (cont): + if scene.objects['System']['run'] : + system_click(cont, scene.objects['Module bouton cote rue']) + +## +# Bouton pousssoir coté cour +## + +def sml_bp_cour (cont): + if scene.objects['System']['run'] : + system_click(cont, scene.objects['Module bouton cote cour']) + +############################################################################### +# Système +############################################################################### + +## +# Initialisation du système +# Le moteur est géré en continue. +## + +def system_init (): + + # Clignotant + scene.objects['Module led']['actif']=False + scene.objects['Led allumee'].setVisible(False,False) + scene.objects['Led'].setVisible(True,False) + + # Emetteur IR + scene.objects['Module emetteur IR']['actif']=False + scene.objects['Emetteur IR Led allumee'].setVisible(False,False) + scene.objects['Emetteur IR Led'].setVisible(True,False) + scene.objects['Emetteur IR'].color = couleur_magenta + scene.objects['Recepteur IR'].color = couleur_magenta + +## +# Réinitialisation du système +## + +def system_reset (): + + # Grille à l'état initial + # applyRotationTo(scene.objects['System'], 0, 0, 0) + scene.objects['Portail'].worldPosition.x = scene.objects['Portail']['init_lx'] + scene.objects['Portail'].worldPosition.y = scene.objects['Portail']['init_ly'] + scene.objects['Portail'].worldPosition.z = scene.objects['Portail']['init_lz'] + + # Moteur à l'état initial + rres=0.001 # resolution rotation + obj1=scene.objects['Engrenage'] + while (obj1.localOrientation.to_euler().y) > 1.1*rres : + obj1.applyRotation((0, 0, -rres), True) + while (obj1.localOrientation.to_euler().y) < -1.1*rres : + obj1.applyRotation((0, 0, rres), True) + + # Led à l'état initial + scene.objects['Led'].setVisible(True,False) + scene.objects['Led allumee'].setVisible(False,False) + + # Capteur barrage IR + scene.objects['Emetteur IR Led'].setVisible(True,False) + scene.objects['Emetteur IR Led allumee'].setVisible(False,False) + scene.objects['Emetteur IR'].color = couleur_magenta + scene.objects['Recepteur IR'].color = couleur_magenta + + # I/O à l'état initial + scene.objects['Module led']['actif']=False + scene.objects['Ensemble moteur']['actif_ouvrir']=False + scene.objects['Ensemble moteur']['actif_fermer']=False + scene.objects['Capteur fdc ouvert']['actif'] =True + scene.objects['Capteur fdc ferme']['actif'] =False + scene.objects['Module emetteur IR']['actif'] =False + scene.objects['Module recepteur IR']['actif'] =False + scene.objects['Module bouton cote rue']['actif'] =False + scene.objects['Module bouton cote cour']['actif'] =False + +## +# Click sur les éléments cliquables du systèmes +## + +def system_click(cont, obj_activation): + obj = cont.owner + if cont.sensors['MO'].status == JUST_ACTIVATED : + obj.color = couleur_blanc + obj['MO']=True + if cont.sensors['Click'].status == JUST_ACTIVATED and scene.objects['System']['manip_mode']==0: + if obj['MO']: + obj_activation['actif'] = True + obj.color = couleur_jaune + if cont.sensors['MO'].status == JUST_RELEASED : + obj['MO']=False + if cont.sensors['Click'].status == ACTIVATE : + obj.color = couleur_jaune + else: + obj.color = couleur_orange + if cont.sensors['Click'].status == JUST_RELEASED: + obj_activation['actif'] = False + obj.color = couleur_blanc + if cont.sensors['MO'].status != ACTIVATE : + obj.color = couleur_orange diff --git a/monte_charge/montchg_cmd.py b/monte_charge/montchg_cmd.py new file mode 100644 index 0000000..60b1ba2 --- /dev/null +++ b/monte_charge/montchg_cmd.py @@ -0,0 +1,59 @@ +from porcou_lib import * # Bibliothèque portail coulissant + +############################################################################### +# monte-charge_cmd.py +# @title: Commandes du monte-charge +############################################################################### + +############################################################################### +# Instructions élémentaires pour le monte-charge +# +# Actions (ordre = True ou False) : +# - Allumer voyant niveau 0 : voy_0 (True|False) +# - Allumer voyant niveau 1 : voy_1 (True|False) +# - Monter le monte-charge (moteur sens trigo) : mot_m (True|False) +# - Descendre le monte-charge (moteur sens horaire) : mot_d (True|False) +# +# Capteurs (valeur retournée = True ou False) : +# - Capteur présence cabine niveau 0 : pc_0() +# - Capteur présence cabine niveau 1 : pc_1() +# +# Pupitre (valeur retournée = True ou False) : +# - Bouton poussoir appel niveau 0 : ba_0() +# - Bouton poussoir appel niveau 1 : ba_1() +# +# Gestion du temps : +# - Temporisation en seconde : tempo(duree) +# +############################################################################### + +# Brochage du monte-charge +brochage={} + +############################################################################### +# Fonctions +############################################################################### + +############################################################################### +# Commandes +############################################################################### + +def commandes(): + + # Ecrire votre code ici ... + voy_0(True) # Activer le voyant du niveau 0 + while True: + pass + + fin() # A garder + + +############################################################################### +# En: External call << DONT CHANGE THIS SECTION >> +# Fr: Appel externe << NE PAS MODIFIER CETTE SECTION >> +############################################################################### + +if __name__=='start': + thread_cmd_start(commandes) +if __name__=='stop': + thread_cmd_stop() diff --git a/monte_charge/montchg_doc.py b/monte_charge/montchg_doc.py new file mode 100644 index 0000000..d30338f --- /dev/null +++ b/monte_charge/montchg_doc.py @@ -0,0 +1,94 @@ +############################################################################### +# montchg_doc.py +# @title: Documentation du monte-charge +# @project: Blender-EduTech +# @lang: fr +# @authors: Philippe Roy +# @copyright: Copyright (C) 2022 Philippe Roy +# @license: GNU GPL +############################################################################### + +################################################################################ +# Documentation du système +################################################################################ + +system_card=["twins-card", "serial-card", "movement-card", "sensor-card", "gyro-card", "board-card", "model-card", "arduino-card"] +card_description ={} + +# Jumeau numérique +# Message envoyé (asynchrone) : \n avancer : a, reculer : r, droite : d, \n gauche g, marquer : m et forer : f \n\n\n """ +card_twins_title="Jumeau numérique" +card_twins_text=""" jumeau() \n -> Active le jumeau réel.\n + jumeau_config(port, vitesse) \n -> Définit la configuration de la liaison \n série.\n + Si le port n\"est pas spécifié, il sera \n recherché automatiquement (carte \n Arduino Uno ou Mega). \n + La vitesse par défaut est 115200 baud.""" +card_twins_url=[] +card_description.update({"twins-card" : [card_twins_title, card_twins_text, card_twins_url]}) + +# Liaison série +card_serial_title="Liaison série" +card_serial_text=""" serie_msg(texte) \n -> Envoi un message \n + texte=serie_rcpt() \n -> Reçoit un message""" +card_serial_url=[["Liaison série : pySerial","https://pythonhosted.org/pyserial/"], + ["Protocole Firmata : pyFirmata","https://github.com/tino/pyFirmata"]] +card_description.update({"serial-card" : [card_serial_title, card_serial_text, card_serial_url]}) + +# Ouvrir et fermer +card_movement_title="Ouvrir et fermer" +card_movement_text=""" mot_o (True | False) \n -> Ouvre le portail (moteur sens trigo) \n + mot_f (True | False) \n -> Ferme le portail (moteur sens horaire) \n + fdc_o() \n -> Capteur fin de course portail ouvert\n Retourne True si le portail est ouvert. \n + fdc_f() \n -> Capteur fin de course portail fermé\n Retourne True si le portail est fermé.""" +card_movement_url=[] +card_description.update({"movement-card" : [card_movement_title, card_movement_text, card_movement_url]}) + +# Capteurs +card_sensor_title="Capteur Infrarouge" +card_sensor_text=""" ir_emet(True | False) \n -> Active l\"émetteur infrarouge (IR) \n + ir_recep() \n -> Récepteur barrage infrarouge (IR)\n Retourne True s\"il n\"y a pas d\"obstacle.""" +card_sensor_url=[] +card_description.update({"sensor-card" : [card_sensor_title, card_sensor_text, card_sensor_url]}) + +# Gyrophare +card_gyro_title="Gyrophare" +card_gyro_text=""" gyr (True | False) \n -> Active le gyrophare""" +card_gyro_url=[] +card_description.update({"gyro-card" : [card_gyro_title, card_gyro_text, card_gyro_url]}) + +# Pupitre +card_board_title="Pupitre" +card_board_text= """ bp_ext() \n -> Bouton poussoir coté rue\n Retourne True si le bouton est pressé.\n + bp_int() \n -> Bouton poussoir coté cour\n Retourne True si le bouton est pressé.""" +card_board_url=[] +card_description.update({"board-card" : [card_board_title, card_board_text, card_board_url]}) + +# Maquette +card_model_title="Maquette" +card_model_text=""" Le modèle 3D est basé sur la maquette \n développée par l\"entreprise A4 Technologie. \n + Les documents techniques et \n pédagogiques signés A4 Technologie \n sont diffusés librement sous licence \n Creative Commons BY-NC-SA. \n + Le pilotage de la maquette se fait par une \n carte Arduino (Uno ou Mega) reliée à \n l"ordinateur via la liaison série (USB) et le \n protocole Firmata.""" +card_model_url=[["A4 Technologie","https://www.a4.fr"], + ["Maquette A4 Technologie","https://www.a4.fr/wiki/index.php?title=Portail_coulissant_(BE-APORT-COUL)"]] +card_description.update({"model-card" : [card_model_title, card_model_text, card_model_url]}) + +# Arduino +card_arduino_title="Arduino" +card_arduino_text=""" Arduino une plateforme open-source de \n développement électronique basée sur \n le microcontrôleur de la famille ATmega. + + Elle est utilisée pour la création d"objets \n électroniques interactifs et connectés : \n IoT, domotique, robotique, ... + + Le langage de programmation est le C. Par \n la bibliothèque Arduino il est particulièrement \n aisé d"accéder aux entrées/sorties de la + carte. Les platines permettent l"ajout \n d"extensions : relais, Grove, RFID, GPS, ... """ + +card_arduino_url=[["Plateforme Arduino","https://www.arduino.cc/"]] +card_description.update({"arduino-card" : [card_arduino_title, card_arduino_text, card_arduino_url]}) + +## +# Envoi des données +## + +def get_system_card(): + return system_card + +def get_card_description(): + return card_description diff --git a/monte_charge/montchg_lib.py b/monte_charge/montchg_lib.py new file mode 100644 index 0000000..47bc568 --- /dev/null +++ b/monte_charge/montchg_lib.py @@ -0,0 +1,406 @@ +import bge # Bibliothèque Blender Game Engine (UPBGE) +import threading # Multithreading +import trace +import sys +import time + +import serial # Liaison série +import pyfirmata # Protocole Firmata +from serial.tools.list_ports import comports # Détection du port automatique + +############################################################################### +# montchg_lib.py +# @title: Bibliothèque utilisateur du monte-charge +# @project: Blender-EduTech +# @lang: fr +# @authors: Philippe Roy +# @copyright: Copyright (C) 2022 Philippe Roy +# @license: GNU GPL +############################################################################### + +scene = bge.logic.getCurrentScene() + +# Threads +threads_cmd=[] +debug_thread = scene.objects['System']['debug_thread'] + +# Jumeau numérique +board = None +board_it = None # Iterator (input) +bp_int_pin = None +bp_ext_pin = None +fdc_o_pin = None +fdc_f_pin = None +ir_emett_pin = None +ir_recept_pin = None +mot_o_pin = None +mot_f_pin = None +gyr_pin = None + +# UPBGE constants +JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED +JUST_RELEASED = bge.logic.KX_INPUT_JUST_RELEASED +ACTIVATE = bge.logic.KX_INPUT_ACTIVE +# JUST_DEACTIVATED = bge.logic.KX_SENSOR_JUST_DEACTIVATED + +############################################################################### +# Méthode kill pour les tâches (threads) +############################################################################### + +class thread_with_trace(threading.Thread): + def __init__(self, *args, **keywords): + threading.Thread.__init__(self, *args, **keywords) + self.killed = False + + def start(self): + self.__run_backup = self.run + self.run = self.__run + threading.Thread.start(self) + + def __run(self): + sys.settrace(self.globaltrace) + self.__run_backup() + self.run = self.__run_backup + + def globaltrace(self, frame, event, arg): + if event == 'call': + return self.localtrace + else: + return None + + def localtrace(self, frame, event, arg): + if self.killed: + if event == 'line': + raise SystemExit() + return self.localtrace + + def kill(self): + self.killed = True + +############################################################################### +# Start et stop des tâches (threads) +############################################################################### + +def thread_start(threads, type_txt, fct): + threads.append(thread_with_trace(target = fct)) + threads[len(threads)-1].start() + if (debug_thread): + print ("Thread",type_txt, "#", len(threads)-1, "open.") + +def thread_stop(threads, type_txt): + i=0 + zombie_flag=False + for t in threads: + if not t.is_alive(): + if (debug_thread): + print ("Thread",type_txt, "#",i,"closed.") + else: + if (debug_thread): + print ("Thread",type_txt, "#",i,"still open ...") + t.kill() + t.join() + if not t.is_alive(): + if (debug_thread): + print ("Thread",type_txt, "#",i,"killed.") + else: + if (debug_thread): + print ("Thread",type_txt, "#",i,"zombie...") + zombie_flag=True + i +=1 + if zombie_flag==False: + if (debug_thread): + print ("All threads",type_txt, "are closed.") + scene.objects['System']['thread_cmd']=False + return True + else: + if (debug_thread): + print ("There are zombies threads",type_txt, ".") + return False + +def thread_cmd_start(fct): + thread_start(threads_cmd, "commands", fct) + +def thread_cmd_stop(): + thread_stop(threads_cmd, "commands") + +def end(): + + # Jumeau numérique + if scene.objects['System']['twins']: + # serial_msg = "FI\n" + # twins_serial.write(serial_msg.encode()) # Communication série : modele 3d -> carte communication ( arduino | micro:bit ) + jumeau_close() + + # Thread + if (debug_thread): + print ("Thread commands is arrived.") + time.sleep(0.125) + scene.objects['System']['thread_cmd']=False + time.sleep(0.125) + +def fin(): + end() + +def quit(): + end() + +############################################################################### +# Actionneurs +############################################################################### + +# Ordres utilisateur du clignotant +def gyr (ordre): + global gyr_pin + scene.objects['Module led']['actif']=ordre + if scene.objects['System']['twins'] : + if ordre : + gyr_pin.write(1) + else: + gyr_pin.write(0) + +# Ordres utilisateur du moteur +def mot_o (ordre): + scene.objects['Ensemble moteur']['actif_ouvrir']=ordre + +def mot_f (ordre): + scene.objects['Ensemble moteur']['actif_fermer']=ordre + +# Ordre utilisateur du capteur barrage IR +def ir_emet(ordre): + scene.objects['Module emetteur IR']['actif']=ordre + +############################################################################### +# Capteurs +############################################################################### + +# Compte-rendu utilisateur du capteur fin de course portail ouvert +def fdc_o (): + return scene.objects['Capteur fdc ouvert']['actif'] + +# Compte-rendu utilisateur du capteur fin de course portail ouvert +def fdc_f (): + return scene.objects['Capteur fdc ferme']['actif'] + +# Compte-rendu utilisateur du capteur barrage IR +def ir_recep (): + if scene.objects['Module recepteur IR']['actif'] : + return False + else: + return True + +############################################################################### +# Boutons poussoirs +############################################################################### + +# Compte-rendu utilisateur du bouton pousssoir coté rue +def bp_ext (): + return scene.objects['Module bouton cote rue']['actif'] + +# Compte-rendu utilisateur du bouton pousssoir coté cour +def bp_int (): + return scene.objects['Module bouton cote cour']['actif'] + +############################################################################### +# Temporisation +############################################################################### + +def tempo (duree): + time.sleep(duree) + +############################################################################### +# Jumeau numérique +############################################################################### + +## +# Recherche automatique du port +## + +def serial_autoget_port(): + # USB Vendor ID, USB Product ID + board_dict={'microbit' :[3368, 516], + 'uno' :[9025, 67], + 'mega' :[9025, 66]} + for com in comports(): # Arduino Uno + if com.vid == board_dict["uno"][0] and com.pid == board_dict["uno"][1]: + return [com.device,"Arduino Uno"] + for com in comports(): # Arduino Mega + if com.vid == board_dict["mega"][0] and com.pid == board_dict["mega"][1]: + return [com.device,"Arduino Mega"] + return [None,""] + +## +# Création de l'objet carte (protocole Firmata) +## + +def board_init(port): + try: + return pyfirmata.Arduino(port) + except: + return None + +## +# Création de l'objet serial (communication série) +## + +def serial_init(port,speed): + try: + return serial.Serial(port,speed) + except: + return None + +## +# Affiche la liste des cartes (communication série) +## + +def serial_devices(): + for com in comports(): + print ("Name : "+str(com.name)+"\n" + +" Device : "+str(com.device)+"\n" + +" Hardware ID : "+str(com.hwid)+"\n" + +" USB Vendor ID : "+str(com.vid)+"\n" + +" USB Product ID : "+str(com.pid)+"\n" + +" USB device location : "+str(com.location)+"\n" + +" USB manufacturer : "+str(com.manufacturer)+"\n" + +" USB product : "+str(com.product)+"\n" + +" Interface-specific : "+str(com.interface)) + +## +# Activation de la communication avec la carte de communication (Arduino, Micro:bit) +# Vitesse : 115200 -> 7 fps, 38400 -> 6 fps, 9600 -> 2 fps +# pyserial : baudrate=115200 +# pyfirmata : baudrate=57600 +## + +def jumeau(pins): + global board + # global gyr_pin + + # UI : étape 1 + scene.objects['Twins-icon'].setVisible(True,True) + scene.objects['Twins-text']['Text'] = "Connection en cours ..." + scene.objects['Twins-text'].setVisible(True,False) + + # Mise en place de la carte + speed = 57600 + [device,board_name] =serial_autoget_port() # Recherche automatique du port + if device is None: + scene.objects['System']['twins'] = False + scene.objects['Twins-text']['Text'] = "Aucune connection disponible : jumeau réel débranché." + return False + board = board_init(device) + if board is None: + scene.objects['System']['twins'] = False + scene.objects['Twins-text']['Text'] = "Aucune connection disponible : port "+device+" pas prêt" + return False + scene.objects['System']['twins'] = True + # scene.objects['System']['twins_close'] = False + scene.objects['System']['twins_port'] = device + scene.objects['System']['twins_speed'] = speed + # scene.objects['System']['twins_readline'] = "" + board_it = pyfirmata.util.Iterator(board) # Itérateur pour les entrées + board_it.start() + + # UI : étape 2 + if board =="": + scene.objects['Twins-text']['Text'] = "Connection ouverte : "+device+" - "+str(speed)+" baud" + else: + scene.objects['Twins-text']['Text'] = "Connection ouverte : "+board_name+" sur "+device+" à "+str(speed)+" baud" + tempo (0.1) + + # Déclaration des entrées - sorties + for pin in pins: + print (pin) + # if + # bp_ext_pin = board_io('d:'+str(es_dict['bp_ext'])+':i') # Bouton poussoir coté rue + # bp_int_pin = board_io('d:'+str(es_dict['bp_int'])+':i') # Bouton poussoir coté cour + # fdc_o_pin = board_io('d:'+str(es_dict['fdc_o'])+':i') # Capteur fin de course portail ouvert + # fdc_f_pin = board_io('d:'+str(es_dict['fdc_f'])+':i') # Capteur fin de course portail fermé + # ir_recept_pin = board_io('d:'+str(es_dict['ir_recept'])+':i') # Recepteur pour le capteur barrage IR + + # gyr_pin = board_io('d:'+str(es_dict['gyr'])+':o') # Gyrophare + # mot_o_pin = board_io('d:'+str(es_dict['mot_o'])+':o') # Ouvrir le portail (moteur sens trigo) + # mot_f_pin = board_io('d:'+str(es_dict['mot_f'])+':o') # Fermer le portail (moteur sens horaire + # ir_emett_pin = board_io('d:'+str(es_dict['ir_emett'])+':o') # Emetteur pour le capteur barrage IR + return True + +# def board_io(da,pin,io): +# if pin_def is not None: +# return board.get_pin(da+':'+pin_def) +# else: +# print ("Définition entrée-sortie non trouvée : "+pin_def) + +## +# Fermeture de la communication série +## + +def jumeau_close(): + global board + # twins_serial.close() # Fermer proprement le port série + board.exit() # Fermer proprement la communication avec la carte + scene.objects['System']['twins'] = False + scene.objects['Twins-text']['Text'] = "Connection fermée" + +# Configuration du port +# FIXME +def jumeau_config(port, speed): + # global board + pass + # global twins_serial + # if scene.objects['System']['twins']: + # serial_msg1 = "CF\n" + # twins_serial.write(serial_msg1.encode()) + # tempo (1) + # serial_msg2 = str(speed)+"\n" + # twins_serial.write(serial_msg2.encode()) + # tempo (1) + # serial_msg3 = str(temps_avancer)+"\n" + # twins_serial.write(serial_msg3.encode()) + # tempo (1) + # serial_msg4 = str(temps_tourner)+"\n" + # twins_serial.write(serial_msg4.encode()) + # tempo (1) + # serial_msg5 = "FC\n" + # twins_serial.write(serial_msg5.encode()) + +## +# Envoi d'un message vers la communication série +## + +# def serie_msg(text): +# global twins_serial +# text2= text+"\n" +# scene.objects['Twins-text']['Text'] = "Communication : envoi message : "+text +# twins_serial.write(text2.encode()) + +## +# Mise en écoute de jumeau numérique (figeage de la scène) +## + +# def twins_listen(cont): +# global twins_serial +# if scene.objects['System']['twins']: +# if scene.objects['System']['twins_readline'] != "": +# scene.objects['Twins-text']['Text'] = "Écoute de la connection figeage de la scène.... Message reçu : "+scene.objects['System']['twins_readline'] +# else: +# scene.objects['Twins-text']['Text'] = "Écoute de la connection figeage de la scène..." +# if cont.sensors['Property'].positive: +# if scene.objects['System']['twins_listen'] : +# serial_msg = twins_serial.readline() +# if serial_msg is not None: +# scene.objects['System']['twins_readline'] = str(serial_msg) +# # scene.objects['Twins-text']['Text'] = "Message reçu : "+str(serial_msg) +# scene.objects['System']['twins_listen'] = False + +## +# Réception d'un message de la communication série +## + +# def serie_rcpt(): +# # scene.objects['Twins-text']['Text'] = "Écoute de la \nconnection\n figeage de \n la scène" +# scene.objects['System']['twins_readline'] = "" +# scene.objects['System']['twins_listen'] = True +# while scene.objects['System']['twins_readline'] == "": +# if scene.objects['System']['twins_readline'] != "": +# break +# # scene.objects['Twins-text']['Text'] = "Connection\nouverte :\n"+scene.objects['System']['twins_port']+"\n"+str(scene.objects['System']['twins_speed'])+" baud" +# return scene.objects['System']['twins_readline'] diff --git a/monte_charge/monte_charge-1.blend b/monte_charge/monte_charge-1.blend new file mode 100644 index 0000000..7d871ec Binary files /dev/null and b/monte_charge/monte_charge-1.blend differ diff --git a/monte_charge/twin.py b/monte_charge/twin.py new file mode 120000 index 0000000..f8f5c2f --- /dev/null +++ b/monte_charge/twin.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin.py \ No newline at end of file diff --git a/monte_charge/twin_about.py b/monte_charge/twin_about.py new file mode 120000 index 0000000..5a76f30 --- /dev/null +++ b/monte_charge/twin_about.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_about.py \ No newline at end of file diff --git a/monte_charge/twin_config.xml b/monte_charge/twin_config.xml new file mode 120000 index 0000000..e44857d --- /dev/null +++ b/monte_charge/twin_config.xml @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_config.xml \ No newline at end of file diff --git a/monte_charge/twin_doc.py b/monte_charge/twin_doc.py new file mode 120000 index 0000000..64dc410 --- /dev/null +++ b/monte_charge/twin_doc.py @@ -0,0 +1 @@ +/home/phroy/Bureau/seriousgames/blender-edutech/git/digital_twin/twin_doc.py \ No newline at end of file