mirror of
https://forge.apps.education.fr/blender-edutech/jumeaux-numeriques.git
synced 2024-01-27 06:56:18 +01:00
Bugfix capteur barrage du portail, documentation avec plusieurs textes suivante la variante de la maquette
This commit is contained in:
parent
e113cb8dff
commit
38d41d9b69
107
README.md
107
README.md
@ -1,107 +0,0 @@
|
||||
# Jumeaux numériques
|
||||
<!-- # Digital Twin -->
|
||||
|
||||
Un jumeau numérique d'un système technique permet de visualiser son comportement à travers une maquette numérique. Le principal intérêt est de valider un
|
||||
modèle comportemental d'abords par la simulation (avant mise en oeuvre du jumeau réel) puis expérimentalement (mesure des écarts entre les deux jumeaux).
|
||||
|
||||
Ici le jumeau numérique d'un système pluritechnologique va nous servir à programmer le système en simulant (hors ligne) son évolution. Nous pourrons alors
|
||||
mettre en lien les deux jumeaux et appliquer les règles programmées sur le jumeau réel.
|
||||
|
||||
Lors de l'exécution du cycle, tous écarts entre les deux jumeaux seront mesurés afin de corriger le modèle comportemental. Par aileurs, les évènements
|
||||
numériques impacteront le jumeau réel et les évènements réels impacteront aussi le jumeau numérique.
|
||||
|
||||
**Systèmes** :
|
||||
|
||||
* [Monte-charge](https://forge.aeif.fr/blender-edutech/jumeau-numerique/-/tree/main/monte_charge)
|
||||
* [Portail coulissant](https://forge.aeif.fr/blender-edutech/jumeau-numerique/-/tree/main/portail_coulissant)
|
||||
* [Volet roulant](https://forge.aeif.fr/blender-edutech/jumeau-numerique/-/tree/main/volet_roulant)
|
||||
|
||||
Systèmes dont le jumeau numérique est cours de développement :
|
||||
* Labyrinthe à bille : [tutoriel à destination des enseignants souhaitant découvrir la plateforme UPBGE](https://forge.aeif.fr/blender-edutech/blender-edutech-tuto/-/tree/main/labyrinthe)
|
||||
* Bras robotisé Poppy Ergo Jr ([Poppy](https://www.poppy-project.org/en/robots/poppy-ergo-jr/))
|
||||
* Robot haptique ([SET](https://setdidact.com/voie-generale-et-technologique/sciences-de-lingenieur/))
|
||||
* Cobot souple ([Dossier personnel](https://nuage03.apps.education.fr/index.php/s/PMFdMPWprEZoWiR?path=%2F2022))
|
||||
|
||||
[![Jumeaux numériques présentation](img/lien_video.png)](https://tube-sciences-technologies.apps.education.fr/w/7B1BtC92PTW5dmRfJPsKhk)
|
||||
|
||||
## Jumelage numérique
|
||||
|
||||
Le jumelage numérique est basé sur la liaison série entre l'ordinateur (port USB) et un microcontrôleur Arduino (Uno ou Mega). Suivant les jumeaux numériques,
|
||||
le protocole de communication peut être le protocole générique Firmata ou un protocole spécifique.
|
||||
|
||||
[![Vidéo du test de jumelage du portail coulissant](img/lien_video-2.png)](https://tube-sciences-technologies.apps.education.fr/w/sVSgBfGssESLBhHGMg98AR)
|
||||
|
||||
## Téléchargement
|
||||
|
||||
Les binaires (Game Engine Runtime) sont hébergés sur [phroy.org](https://www.phroy.org/twin.html).
|
||||
|
||||
## Ressources pédagogiques
|
||||
|
||||
Les applications pédagogique se trouvent dans le [dépôt des ressouces pédagogiques du projet Blender-EduTech](https://forge.aeif.fr/blender-edutech/blender-edutech-peda) :
|
||||
- [Enseignements de la spécialité Sciences de l'Ingénieur](https://forge.aeif.fr/blender-edutech/blender-edutech-peda/-/tree/main/Lycee/programmation_python/si/jumeau_numerique).
|
||||
|
||||
## Développement
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td> <div> <a href="https://forge.aeif.fr"> <img src="img/la_forge-brigit_et_komit.svg" alt="Brigit et Komit"> </a> </div> </td>
|
||||
<td> <div> Les fichiers sources sont dans le projet <b>Blender-Edutech / Jumeaux numériques</b> de La Forge des Communs Numériques Éducatifs :
|
||||
https://forge.aeif.fr/blender-edutech/jumeau-numerique . </div> <div> </div> <div> L'environnement de développement est basé sur : la plateforme de
|
||||
modélisation et d'animation 3D [Blender](https://blender.org), le langage [Python](https://python.org) et le moteur de jeu 3D
|
||||
[UPBGE](https://upbge.org). </div> <div> </div> <div> La version de Blender/UPBGE utilisée pour le développement est la version 0.36.1 (20 août
|
||||
2023).</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Les bibliothèques suivantes ne sont pas incluses par défaut dans l'environnement UPBGE :
|
||||
- [**Pylint**](https://pylint.pycqa.org) : vérificateur de code Python
|
||||
- [**pySerial**](https://pyserial.readthedocs.io) : communication sur le port série
|
||||
- [**pyFirmata**](https://pyfirmata.readthedocs.io) : protocole Firmata (protocole générique de communication entre un logiciel et un microcontrôleur)
|
||||
- [**Matplotlib**](https://matplotlib.org) : grapheur (visualisation de données)
|
||||
- [**wxPython**](https://www.wxpython.org/) : interface graphique utilisateur (GUI, utilisé ici pour Windows)
|
||||
- [**pyQt6**](https://www.riverbankcomputing.com/software/pyqt/) : interface graphique utilisateur (GUI, utilisé ici pour GNU/Linux)
|
||||
|
||||
<!-- - [**whell**](https://pyfirmata.readthedocs.io) : format de paquet Python -->
|
||||
|
||||
Il faut donc les installer localement (dans UPBGE), les étapes sont :
|
||||
- **GNU/Linux** : La configuration ici présente est UPBGE installé sur ~ avec Python 3.10 :
|
||||
- Aller dans le répertoire local de Python de UPBGE: $ cd ~/upbge-0.36.1-linux-x86_64/3.6/python/bin
|
||||
- Télécharger le script ['get-pip.py'](https://bootstrap.pypa.io/get-pip.py) pour installer le gestionnaire de paquet [**Pip**](https://pip.pypa.io)
|
||||
- Installer le gestionnaire de paquet Pip : $ ./python3.10 get-pip.py
|
||||
- Installer Pylint : $ ./pip install pylint
|
||||
- Installer pySerial : $ ./pip install pyserial
|
||||
- Installer pyFirmata : $ ./pip install pyfirmata
|
||||
- Installer Matplotlib : $ ./pip install matplotlib
|
||||
- Installer PyQt6 : $ ./pip install PyQt6
|
||||
|
||||
<!-- - Installer Pylint : $ ./pip install pylint -t ~/UPBGE-0.30-linux-x86_64/3.0/python/lib/python3.9/site-packages -->
|
||||
<!-- - Installer pySerial : $ ./pip install pyserial -t ~/UPBGE-0.30-linux-x86_64/3.0/python/lib/python3.9/site-packages -->
|
||||
<!-- - Installer pyFirmata : $ ./pip install pyfirmata -t ~/UPBGE-0.30-linux-x86_64/3.0/python/lib/python3.9/site-packages -->
|
||||
<!-- - Installer Matplotlib : $ ./pip install matplotlib -t ~/UPBGE-0.30-linux-x86_64/3.0/python/lib/python3.9/site-packages -->
|
||||
<!-- - Installer PyQt6 : $ ./pip install PyQt6 -t ~/UPBGE-0.30-linux-x86_64/3.0/python/lib/python3.9/site-packages -->
|
||||
|
||||
- **Windows** : La configuration ici présente est UPBGE installé sur le bureau utilisateur (prenom.nom) :
|
||||
- Ouvrir un terminal Powershell (éventuellement en passant par Anaconda Navigator)
|
||||
- Aller dans le répertoire local de Python de UPBGE: cd C:\Users\prenom.nom\Desktop\upbge-0.36.1-windows-x86_64\3.6\python\bin
|
||||
- Télécharger le script ['get-pip.py'](https://bootstrap.pypa.io/get-pip.py) pour installer le gestionnaire de paquet [**Pip**](https://pip.pypa.io)
|
||||
- Installer le gestionnaire de paquet Pip : python.exe get-pip.py
|
||||
- Aller dans le répertoire 'Scripts' : cd C:\Users\prenom.nom\Desktop\upbge-0.36.1-windows-x86_64\3.6\python\Scripts
|
||||
- Installer Pylint : pip.exe install pylint
|
||||
- Installer pySerial : pip.exe install pyserial
|
||||
- Installer pyFirmata : pip.exe install pyfirmata
|
||||
- Installer Matplotlib : pip.exe install matplotlib
|
||||
- Installer wxPython : pip.exe install wxpython
|
||||
|
||||
- Si l'installation des paquets Python ne se fait pas dans le bon répertoire ('site-packages' des bibliothèques du Python embarqué par UPBGE), il faut allors spécifier le répertoire cible avec
|
||||
l'option '-t target' lors de la commande 'pip install'. Par exemple pour Pylint :
|
||||
- **GNU/Linux** : $ ./pip install pylint -t ~/upbge-0.36.1-linux-x86_64/3.6/python/lib/python3.10/site-packages
|
||||
- **Windows** : $ pip.exe install pylint -t C:\Users\prenom.nom\Desktop\upbge-0.36.1-windows-x86_64\3.6\python\lib\site-packages
|
||||
|
||||
<!-- - **Windows** : La configuration ici présente est UPBGE installé sur le bureau utilisateur (prenom.nom) avec la distribution Anaconda installée : -->
|
||||
<!-- - Avec Anaconda Navigator ouvrir un terminal Powershell -->
|
||||
<!-- - Installer Pylint : pip install pylint -t C:\Users\prenom.nom\Desktop\UPBGE-0.30-windows-x86_64\3.0\python\lib\site-packages -->
|
||||
<!-- - Installer pySerial : pip install pyserial -t C:\Users\prenom.nom\Desktop\UPBGE-0.30-windows-x86_64\3.0\python\lib\site-packages -->
|
||||
<!-- - Installer pyFirmata : pip install pyfirmata -t C:\Users\prenom.nom\Desktop\UPBGE-0.30-windows-x86_64\3.0\python\lib\site-packages -->
|
||||
<!-- - Installer Matplotlib : pip install matplotlib -t C:\Users\prenom.nom\Desktop\UPBGE-0.30-windows-x86_64\3.0\python\lib\site-packages -->
|
||||
<!-- - Installer wxPython : pip install wxpython -t C:\Users\prenom.nom\Desktop\UPBGE-0.30-windows-x86_64\3.0\python\lib\site-packages -->
|
||||
|
@ -315,64 +315,53 @@ def fdc_f (cont):
|
||||
def ir_emet (cont):
|
||||
if scene.objects['System']['run'] :
|
||||
obj = cont.owner
|
||||
obj_off = scene.objects['Emetteur IR Led']
|
||||
obj_on = scene.objects['Emetteur IR Led-on']
|
||||
|
||||
# Gestion de la led (Physique du modèle 3D)
|
||||
if obj['activated']:
|
||||
if obj_on.visible == False and obj['prior']:
|
||||
obj_on.setVisible(True,False)
|
||||
obj_off.setVisible(False,False)
|
||||
else:
|
||||
if obj_on.visible == True and obj['prior']:
|
||||
obj_on.setVisible(False,False)
|
||||
obj_off.setVisible(True,False)
|
||||
|
||||
# Mouse over
|
||||
if obj['mo'] == True and obj['click'] == False and obj.color !=color_hl:
|
||||
obj.color =color_hl
|
||||
return
|
||||
|
||||
# Passif
|
||||
if obj['active'] == False and obj.color !=color_passive:
|
||||
obj.color =color_passive
|
||||
|
||||
# Physique du modèle 3D
|
||||
if obj['prior']:
|
||||
scene.objects['Emetteur IR Led'].setVisible(True,False)
|
||||
scene.objects['Emetteur IR Led-on'].setVisible(False,False)
|
||||
scene.objects['Recepteur IR']['active'] = False
|
||||
# Activation
|
||||
if obj['activated']:
|
||||
|
||||
# Modele 3D -> Arduino
|
||||
if scene.objects['System']['twins'] and obj['prior_real']:
|
||||
if scene.objects['Emetteur IR']['pin'] is not None:
|
||||
scene.objects['Emetteur IR']['pin'].write(0)
|
||||
return
|
||||
if obj['pin'] is not None:
|
||||
obj['pin'].write(1)
|
||||
|
||||
# Active
|
||||
if obj['active']:
|
||||
|
||||
# Allumage
|
||||
if scene.objects['Emetteur IR Led-on'].visible == False:
|
||||
|
||||
# Physique du modèle 3D
|
||||
if obj['prior']:
|
||||
scene.objects['Emetteur IR Led-on'].setVisible(True,False)
|
||||
scene.objects['Emetteur IR Led'].setVisible(False,False)
|
||||
obj.color = color_active
|
||||
scene.objects['Recepteur IR']['active'] = True
|
||||
# Désactivation
|
||||
if obj['activated']==False:
|
||||
|
||||
# Modele 3D -> Arduino
|
||||
if scene.objects['System']['twins'] and obj['prior_real']:
|
||||
if scene.objects['Emetteur IR']['pin'] is not None:
|
||||
scene.objects['Emetteur IR']['pin'].write(1)
|
||||
if obj['pin'] is not None:
|
||||
obj['pin'].write(0)
|
||||
|
||||
# Forçage par clic
|
||||
if obj['click'] == True and obj['prior']:
|
||||
obj['activated'] = True
|
||||
scene.objects['Recepteur IR']['activated'] = True
|
||||
|
||||
# Couleurs
|
||||
# FIXME : à faire
|
||||
# twin.cycle_sensitive_color(obj)
|
||||
if obj['activated'] == True and obj.color !=color_activated:
|
||||
obj.color =color_activated
|
||||
if obj['activated'] == False :
|
||||
if obj['mo'] == True and obj.color !=color_hl:
|
||||
obj.color =color_hl
|
||||
if obj['mo'] == False and obj.color !=color_active:
|
||||
elif obj['activated'] == False and obj.color !=color_active:
|
||||
obj.color =color_active
|
||||
|
||||
##
|
||||
# Récepteur IR
|
||||
# FIXME : Modele 3D -> Arduino à faire
|
||||
##
|
||||
|
||||
def ir_recep (cont):
|
||||
@ -384,36 +373,34 @@ def ir_recep (cont):
|
||||
obj.color =color_hl
|
||||
return
|
||||
|
||||
# Lien avec l'émetteur
|
||||
if obj['click'] == False:
|
||||
if scene.objects['Emetteur IR']['activated'] == False and obj['active']:
|
||||
obj['active'] = False
|
||||
obj['actived'] = False
|
||||
if scene.objects['Emetteur IR']['activated'] and obj['active'] == False:
|
||||
obj['active'] = True
|
||||
obj['actived'] = True
|
||||
|
||||
# Passif
|
||||
if obj['active'] == False and obj.color !=color_passive:
|
||||
obj.color =color_passive
|
||||
return
|
||||
|
||||
# Active
|
||||
if obj['active']:
|
||||
|
||||
# Arduino -> Modele 3D (activé si Pin = False) FIXME : à vérifier avec le jumeau réel
|
||||
# Arduino -> Modele 3D
|
||||
if scene.objects['System']['twins'] and obj['prior_real']:
|
||||
if obj['pin'] is not None:
|
||||
if obj['pin'].read()==False and obj['activated_real'] == False :
|
||||
if obj['pin'].read()==True and obj['activated_real'] == False :
|
||||
obj['activated_real'] = True
|
||||
if obj['pin'].read()==True and obj['activated_real'] == True :
|
||||
if obj['pin'].read()==False and obj['activated_real'] == True :
|
||||
obj['activated_real'] = False
|
||||
|
||||
# Forçage par clic
|
||||
if obj['click'] == True and obj['prior']:
|
||||
obj['activated'] = True
|
||||
scene.objects['Emetteur IR']['activated'] = True
|
||||
obj['activated'] = False
|
||||
|
||||
# Couleurs
|
||||
# FIXME : à faire
|
||||
if obj['activated'] == True and obj.color !=color_activated:
|
||||
obj.color =color_activated
|
||||
if obj['activated'] == False :
|
||||
if obj['mo'] == True and obj.color !=color_hl:
|
||||
obj.color =color_hl
|
||||
if obj['mo'] == False and obj.color !=color_active:
|
||||
obj.color =color_active
|
||||
twin.cycle_sensitive_color(obj)
|
||||
|
||||
###############################################################################
|
||||
# Système
|
||||
@ -440,9 +427,6 @@ def system_reset ():
|
||||
for obj in objs:
|
||||
scene.objects[obj]['activated']=False
|
||||
scene.objects[obj]['activated_real']=False
|
||||
scene.objects['Recepteur IR']['activated'] =False
|
||||
scene.objects['Recepteur IR']['active'] =False
|
||||
scene.objects['Recepteur IR']['activated_real'] =True # Absence d'obstacle -> True, présence d'obstacle -> False
|
||||
|
||||
# Grille à l'état initial
|
||||
scene.objects['Portail']['x']=0
|
||||
@ -474,12 +458,14 @@ def system_reset ():
|
||||
scene.objects['Led-on'].setVisible(False,False)
|
||||
|
||||
# Capteur barrage IR
|
||||
scene.objects['Emetteur IR'].color = color_active
|
||||
scene.objects['Emetteur IR']['activated'] =False
|
||||
scene.objects['Emetteur IR']['active'] =False
|
||||
scene.objects['Emetteur IR Led'].setVisible(True,False)
|
||||
scene.objects['Emetteur IR Led-on'].setVisible(False,False)
|
||||
scene.objects['Emetteur IR'].color = color_passive
|
||||
scene.objects['Recepteur IR'].color = color_passive
|
||||
scene.objects['Recepteur IR']['active'] =False
|
||||
scene.objects['Recepteur IR']['activated'] =True # Absence d'obstacle -> True, présence d'obstacle -> False
|
||||
scene.objects['Recepteur IR']['activated_real'] =True # Absence d'obstacle -> True, présence d'obstacle -> False
|
||||
|
||||
# Priorités activées
|
||||
objs= ['Led', 'Moteur', 'Microrupteur fdc ouvert', 'Microrupteur fdc ferme',
|
||||
|
@ -13,7 +13,7 @@ from porcou_lib import * # Bibliothèque utilisateur du portail coulissant
|
||||
# - Ouvrir le portail (moteur sens trigo) : mot_o(True | False)
|
||||
# - Fermer le portail (moteur sens horaire) : mot_f(True | False)
|
||||
# - Définir la vitesse du moteur jumeau numérique : mot_vitesse (vitesse) , vitesse en rad / s, si vitesse est omis la valeur par défaut est 125.6 rad /s ( 20 tr / s ))
|
||||
# - Définir la vitesse du moteur jumeau réel : mot_vitesse_r (vitesse) , vitesse de 0 à 255, la valeur par défaut est 255
|
||||
# - Définir la vitesse du moteur jumeau réel : mot_vitesse_r (vitesse) , vitesse de 0 à 255, la valeur par défaut est 255 (uniquement sur la maquette Grove)
|
||||
# - Emetteur pour le capteur barrage IR : ir_emet(True | False)
|
||||
#
|
||||
# Capteurs (valeur retournée = True ou False) :
|
||||
@ -54,9 +54,11 @@ brochage={
|
||||
'bp_ext' : ['d',6,'i'],'bp_int' : ['d',5,'i'],
|
||||
'fdc_o' : ['a',1,'i'],'fdc_f' : ['a',0,'i'],
|
||||
'mot_v' : ['d',3,'p'], 'mot_s' : ['d',4,'o'],
|
||||
'gyr' : ['d',2,'o'],
|
||||
'gyr' : [],
|
||||
'ir_emet' : ['d',7,'o'],'ir_recep' : ['d',8,'i']}
|
||||
|
||||
# 'gyr' : ['d',2,'o'],
|
||||
|
||||
# Motor Direction(Forward/Backward) Speed Speed range
|
||||
# M1 4 LOW HIGH 3 0-255
|
||||
# M2 12 HIGH LOW 11 0-255
|
||||
@ -75,30 +77,27 @@ def fermer():
|
||||
gyr(True)
|
||||
mot_o(False)
|
||||
mot_f(True)
|
||||
tempo(0.1) # Donne du temps à communication avec le jumeau réel
|
||||
# if ir_recep()==False or bp_int() or bp_ext() : # Ouverture en cas présence d'obstacle ou boutons
|
||||
if bp_int() or bp_ext() : # Ouverture en cas présence d'obstacle ou boutons
|
||||
mot_f(False)
|
||||
tempo(0.1) # Donne du temps à communication avec le jumeau réel
|
||||
if ir_recep()==False or bp_int() or bp_ext() : #Ouverture en cas présence d'obstacle ou boutons
|
||||
ouvrir()
|
||||
print ("Temporisation")
|
||||
tempo(2) # Temporisation 2s
|
||||
ir_emet(True)
|
||||
tempo(0.1) # Donne du temps à communication avec le jumeau réel
|
||||
gyr(False)
|
||||
mot_f(False)
|
||||
ir_emet(False)
|
||||
tempo(0.1) # Donne du temps à communication avec le jumeau réel
|
||||
|
||||
# Ouvrir le portail
|
||||
def ouvrir():
|
||||
print ("Ouverture")
|
||||
mot_f(False)
|
||||
ir_emet(False)
|
||||
while fdc_o() ==False:
|
||||
gyr(True)
|
||||
mot_o(True)
|
||||
tempo(0.1) # Donne du temps à communication avec le jumeau réel
|
||||
gyr(False)
|
||||
mot_o(False)
|
||||
tempo(0.1) # Donne du temps à communication avec le jumeau réel
|
||||
print ("Temporisation")
|
||||
tempo(2) # Temporisation 2s
|
||||
|
||||
###############################################################################
|
||||
# Commandes
|
||||
@ -113,23 +112,27 @@ def commandes():
|
||||
mot_vitesse_r(100)
|
||||
fermer()
|
||||
|
||||
# Données
|
||||
# daq(['mot_angle', 'mot_vitesse', 'portail_x', 'portail_vitesse', 'mot_v', 'mot_s'])
|
||||
# plot(['mot_angle', 'mot_vitesse', 'portail_x', 'portail_vitesse', 'mot_v', 'mot_s'])
|
||||
# reset_t()
|
||||
|
||||
# Jumelage
|
||||
print ("Attente")
|
||||
jumeau(brochage)
|
||||
# jumeau(brochage)
|
||||
|
||||
# Fonctionnement normal
|
||||
while True :
|
||||
tempo(0.1) # Donne du temps à communication avec le jumeau réel
|
||||
|
||||
# Ouverture
|
||||
# Ouverture + Tempo
|
||||
if bp_int() or bp_ext() :
|
||||
mot_vitesse(1000)
|
||||
mot_vitesse_r(200)
|
||||
ouvrir()
|
||||
|
||||
print ("Temporisation")
|
||||
tempo(2) # Temporisation 2s
|
||||
|
||||
# Fermeture
|
||||
mot_vitesse(100)
|
||||
mot_vitesse_r(100)
|
||||
fermer()
|
||||
print ("Attente")
|
||||
@ -138,8 +141,8 @@ def commandes():
|
||||
# En: External call << DONT CHANGE THIS SECTION >>
|
||||
# Fr: Appel externe << NE PAS MODIFIER CETTE SECTION >>
|
||||
#
|
||||
# Variante 1 (par défaut) : version Grove : la carte moteur est le shield moteur Arduino CC 4 x 1,2 A DRI0039 (DFROBOT)
|
||||
# Variante 2 : version AutoProg : la carte moteur est le module AutoProg K-AP-MMOT-KIT
|
||||
# Variante 1 (par défaut) : Maquette Grove : la carte moteur est le shield moteur Arduino CC 4 x 1,2 A DRI0039 (DFROBOT)
|
||||
# Variante 2 : Maquette AutoProg (A4 Technologie) : la carte moteur est le module AutoProg K-AP-MMOT-KIT
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
@ -152,4 +155,4 @@ if __name__=='start':
|
||||
if __name__=='stop':
|
||||
stop()
|
||||
if __name__=='init':
|
||||
variant(1) # Variante Grove
|
||||
variant(1) # Variante maquette Grove
|
||||
|
@ -60,7 +60,7 @@ card_pin_text_autoprog=""" Le brochage est un dictionnaire d'association \n des
|
||||
Pour le moteur (maquette AutoProg) : \n 'mot_o' (ouvrir) et 'mot_f' (fermer) """
|
||||
|
||||
card_pin_url=[]
|
||||
system_card_description.update({"pin-card" : [card_pin_title, card_pin_text_grove, card_pin_url, card_pin_text_autoprog]}) # Deux descriptions
|
||||
system_card_description.update({"pin-card" : [card_pin_title, [card_pin_text_grove, card_pin_text_autoprog] , card_pin_url]}) # Deux descriptions
|
||||
|
||||
# Données
|
||||
card_data_title="Accès aux données"
|
||||
|
@ -55,14 +55,14 @@ def mot_f (order):
|
||||
def mot_vitesse (speed=125.6):
|
||||
scene.objects['Moteur']['speed_setting']=speed # Vitesse du moteur numérique : 125.6 rad /s ( 20 tr / s )
|
||||
|
||||
# Réglage de la vitesse du moteur réel (uniquement sur la maquette Grove, de 0 à 255)
|
||||
# Réglage de la vitesse du moteur réel (de 0 à 255, uniquement sur la maquette Grove)
|
||||
# Valeur par défaut est 255
|
||||
def mot_vitesse_r (speed=255):
|
||||
scene.objects['Moteur']['speed_real_setting']=speed
|
||||
|
||||
# Ordre pour le capteur barrage IR
|
||||
def ir_emet(order):
|
||||
scene.objects['Emetteur IR']['active']=order
|
||||
scene.objects['Emetteur IR']['activated']=order
|
||||
|
||||
###############################################################################
|
||||
# Capteurs
|
||||
@ -81,11 +81,11 @@ def fdc_f ():
|
||||
return False
|
||||
|
||||
# Compte-rendu du capteur barrage IR
|
||||
# Absence d'obstacle -> True, présence d'obstacle -> False
|
||||
# Absence d'obstacle -> True (par défaut), présence d'obstacle -> False
|
||||
def ir_recep ():
|
||||
if scene.objects['Recepteur IR']['activated'] or scene.objects['Recepteur IR']['activated_real']:
|
||||
return True
|
||||
if scene.objects['Recepteur IR']['activated'] == False or scene.objects['Recepteur IR']['activated_real'] == False:
|
||||
return False
|
||||
return True
|
||||
|
||||
###############################################################################
|
||||
# Boutons poussoirs
|
||||
@ -165,29 +165,6 @@ def variant(variant_num):
|
||||
print ("Variante de la maquette numérique :", variant_num)
|
||||
scene.objects['System']['variant']=variant_num
|
||||
|
||||
# FIXME : MaJ de la documentation dynamique -> plus tards
|
||||
# if 'Doc_text-l1-pin-card' in scene.objects:
|
||||
# card_description ={}
|
||||
# system=importlib.import_module(scene.objects['System']['system']+'_doc') # Système
|
||||
# card_description.update(system.get_system_card_description())
|
||||
# if variant_num == 1 : # Grove (par défaut)
|
||||
# lines = card_description["pin-card"][1].split("\n")
|
||||
# if variant_num == 2 : # Autoprog (par défaut)
|
||||
# lines = card_description["pin-card"][3].split("\n")
|
||||
|
||||
# print (lines)
|
||||
# print (scene.objects)
|
||||
|
||||
# for i in range (13):
|
||||
# if i >= len(lines):
|
||||
# scene.objects['Doc_text-l'+str(i+1)+'-pin-card']['Text']=""
|
||||
# else:
|
||||
# if len(lines[i]) ==0:
|
||||
# scene.objects['Doc_text-l'+str(i+1)+'-pin-card']['Text']=""
|
||||
# else:
|
||||
# scene.objects['Doc_text-l'+str(i+1)+'-pin-card'].blenderObject.data.body=lines[i] # Bug de la propriétés 'Text' (UPBGE) -> passage par 'body' de bpy (Blender)
|
||||
|
||||
|
||||
# FIXME : Affichage de la maquette Grove -> plus tards
|
||||
# variant_dict = {'Bp auto':[1], 'Bg auto':[2], 'Bg auto-on':[2]}
|
||||
# variant_list = list(variant_dict)
|
||||
|
Binary file not shown.
72
twin.py
72
twin.py
@ -641,7 +641,7 @@ def cycle_hl(cont):
|
||||
obj.color = color_active
|
||||
|
||||
##
|
||||
# Click sur les éléments cliquables du système (activation numérique)
|
||||
# Click sur les éléments cliquables normalement ouverts (NO) du système (activation numérique)
|
||||
##
|
||||
|
||||
def cycle_click(cont):
|
||||
@ -662,7 +662,7 @@ def cycle_click(cont):
|
||||
obj['click'] = True
|
||||
|
||||
# Désactivation
|
||||
if cont.sensors['Click'].status == JUST_RELEASED and obj['prior']:
|
||||
if cont.sensors['Click'].status == JUST_RELEASED and cont.sensors['MO'].positive and obj['prior']:
|
||||
obj['activated'] = False
|
||||
obj['click'] = False
|
||||
if cont.sensors['MO'].positive:
|
||||
@ -670,6 +670,72 @@ def cycle_click(cont):
|
||||
else:
|
||||
obj.color = color_active
|
||||
|
||||
##
|
||||
# Click sur les éléments cliquables normalement fermés (NC)
|
||||
# Lors de l'activation la valeur est False
|
||||
##
|
||||
|
||||
def cycle_click_nc(cont):
|
||||
obj = cont.owner
|
||||
if scene.objects['System']['run'] ==False:
|
||||
return
|
||||
|
||||
# Passif
|
||||
if "active" in obj.getPropertyNames():
|
||||
if obj['active'] == False:
|
||||
obj.color = color_passive
|
||||
return
|
||||
|
||||
# Activation
|
||||
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive and scene.objects['System']['manip_mode']==0 and obj['prior']:
|
||||
obj.color = color_active
|
||||
obj['activated'] = False
|
||||
obj['click'] = True
|
||||
|
||||
# Désactivation
|
||||
if cont.sensors['Click'].status == JUST_RELEASED and cont.sensors['MO'].positive and obj['prior']:
|
||||
obj['activated'] = True
|
||||
obj['click'] = False
|
||||
if cont.sensors['MO'].positive:
|
||||
obj.color = color_hl
|
||||
else:
|
||||
obj.color = color_activated
|
||||
|
||||
##
|
||||
# Click sur les éléments rémanents (activation numérique)
|
||||
# Lors de la désactivation, activated reprend la valeur d'avant le click
|
||||
##
|
||||
|
||||
def cycle_click_persistent(cont):
|
||||
obj = cont.owner
|
||||
if scene.objects['System']['run'] ==False:
|
||||
return
|
||||
|
||||
# Passif
|
||||
if "active" in obj.getPropertyNames():
|
||||
if obj['active'] == False:
|
||||
obj.color = color_passive
|
||||
return
|
||||
|
||||
# Activation
|
||||
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive and scene.objects['System']['manip_mode']==0 and obj['prior']:
|
||||
obj.color = color_activated
|
||||
obj['activated_prev'] = obj['activated']
|
||||
obj['activated'] = True
|
||||
obj['click'] = True
|
||||
|
||||
# Désactivation
|
||||
if cont.sensors['Click'].status == JUST_RELEASED and cont.sensors['MO'].positive and obj['prior']:
|
||||
obj['activated'] = obj['activated_prev']
|
||||
obj['click'] = False
|
||||
if cont.sensors['MO'].positive:
|
||||
obj.color = color_hl
|
||||
else:
|
||||
if obj['activated_prev'] :
|
||||
obj.color = color_activated
|
||||
else:
|
||||
obj.color = color_active
|
||||
obj['activated_prev'] = False
|
||||
|
||||
##
|
||||
# Click sur les éléments commutables du système (activation numérique)
|
||||
@ -716,7 +782,7 @@ def cycle_switch(cont):
|
||||
|
||||
##
|
||||
# Couleurs sur les éléments sensibles du système
|
||||
# obj : objet numérique
|
||||
# obj : objet numériquegb
|
||||
# obj_on : objet numérique à l'état activé (si différent)
|
||||
##
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
<data>
|
||||
<screen>
|
||||
<width>1609</width>
|
||||
<height>905</height>
|
||||
<quality>0</quality>
|
||||
<width>1341</width>
|
||||
<height>754</height>
|
||||
<quality>4</quality>
|
||||
</screen>
|
||||
<plot>
|
||||
<config>True</config>
|
||||
|
@ -578,6 +578,12 @@ def text_dynamic_load():
|
||||
|
||||
# Création des objets 3D
|
||||
for card in card_description:
|
||||
if len(card_description[card][1][0])>1:
|
||||
if scene.objects['System']['variant']-1 >len(card_description[card][1]):
|
||||
lines = card_description[card][1][scene.objects['System']['variant']-1].split("\n") # Plusieurs versions de la description (fonction de la variante)
|
||||
else:
|
||||
lines = card_description[card][1][0].split("\n") # Si le nombre de description est inférieur au numéro de variante -> la description 1 est prise par défaut
|
||||
else:
|
||||
lines = card_description[card][1].split("\n")
|
||||
for i in range (13):
|
||||
doc_text= scene.addObject('Doc_text-l'+str(i+1), None, 0.00, True)
|
||||
|
@ -99,12 +99,14 @@ def serial_open():
|
||||
if device is None:
|
||||
scene.objects['System']['twins'] = False
|
||||
scene.objects['Twins-text']['Text'] = "Aucune connection disponible : jumeau réel débranché."
|
||||
return False
|
||||
print ("Jumelage : aucune connection disponible, jumeau réel débranché.")
|
||||
return None, 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
|
||||
print ("Jumelage : aucune connection disponible : port "+device+" pas prêt.")
|
||||
return None, False
|
||||
scene.objects['System']['twins'] = True
|
||||
board_it = pyfirmata.util.Iterator(board) # Itérateur pour les entrées
|
||||
board_it.start()
|
||||
@ -115,7 +117,7 @@ def serial_open():
|
||||
else:
|
||||
scene.objects['Twins-text']['Text'] = "Connection ouverte : "+board_name+" sur "+device+" à "+str(speed)+" baud."
|
||||
time.sleep(0.1)
|
||||
return (board)
|
||||
return board, True
|
||||
|
||||
##
|
||||
# Fermeture de la communication série
|
||||
@ -127,6 +129,7 @@ def serial_close(board):
|
||||
board.exit() # Fermer proprement la communication avec la carte
|
||||
time.sleep(0.1)
|
||||
scene.objects['System']['twins'] = False
|
||||
print ("Jumelage : connection fermée.")
|
||||
|
||||
# Configuration manuelle du port
|
||||
# FIXME : plus tard
|
||||
@ -161,7 +164,10 @@ def config(port, speed):
|
||||
def jumeau_get_pin(board, name, brochage):
|
||||
for pin in brochage :
|
||||
if pin ==name:
|
||||
if len (brochage[pin])==3:
|
||||
return board.get_pin(brochage[pin][0]+':'+str(brochage[pin][1])+':'+brochage[pin][2])
|
||||
else:
|
||||
print ("Jumelage : adressage incomplet de l'objet 3D :", pin)
|
||||
return None
|
||||
|
||||
##
|
||||
@ -171,9 +177,11 @@ def jumeau_get_pin(board, name, brochage):
|
||||
def jumeau (brochage=None):
|
||||
|
||||
# Carte
|
||||
board =serial_open()
|
||||
board, board_ok =serial_open()
|
||||
if board_ok == False:
|
||||
return None
|
||||
scene.objects['System']['board']=board
|
||||
# print ("jumeau : ", scene.objects['System']['board'])
|
||||
print ("Jumelage :", scene.objects['System']['board'])
|
||||
|
||||
# Brochage
|
||||
if brochage is not None:
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user