Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
openatelier:projet:tete_animatronique [2023/03/29 18:13] emoc [Impression résine] |
openatelier:projet:tete_animatronique [2023/06/16 21:57] (Version actuelle) emoc [Prototype 1] |
||
---|---|---|---|
Ligne 452: | Ligne 452: | ||
===== Rpi + Python + PCA9685 ===== | ===== Rpi + Python + PCA9685 ===== | ||
+ | |||
+ | Le montage se compose d'un Raspberry Pi qui communique, via I2C sur ses broches GPIO, à un contrôleur de 16 servos basé sur la puce PCA9685. Les servosmoteurs sont reliés à ce circuit. | ||
+ | |||
+ | ==== Multiplexeur PCA9685 ==== | ||
+ | |||
+ | {{:​openatelier:​projet:​tete_animatronique:​16-channel-pwm-controller-pca9685-module-overview.jpg?​direct&​600|}} | ||
+ | |||
+ | ==== Montage ==== | ||
+ | |||
+ | {{:​openatelier:​projet:​tete_animatronique:​adafruit_raspi_pca9685_i2c_with_servo.png?​direct&​600|}} | ||
+ | |||
+ | Source du schéma : https://​learn.adafruit.com/​adafruit-16-channel-servo-driver-with-raspberry-pi/​hooking-it-up | ||
+ | |||
+ | Pour le brochage du Raspberry Pi 4, voir : https://​lesporteslogiques.net/​wiki/​materiel/​raspberry_pi/​start#​raspberry_pi_4_model_b | ||
+ | |||
+ | === Préparation du Raspberry Pi pour I2C === | ||
+ | |||
+ | Installation de paquets | ||
+ | sudo apt-get install -y python-smbus ​ # support d'I2C dans python | ||
+ | sudo apt-get install -y i2c-tools ​ # entre autre pour scanner le port I2C | ||
+ | Configurer le support par le kernel | ||
+ | sudo raspi-config # choisir interface options/​I2C/​activer l'​interface | ||
+ | Puis redémarrer | ||
+ | sudo reboot | ||
+ | |||
+ | Ensuite on peut tester que le module PCA9685 est bien branché | ||
+ | sudo i2cdetect -y 1 # Le port I2C numéro 1 est utilisé sur les rpi > 512 MB de RAM | ||
+ | Ce qui devrait afficher (les adresses des ports utilisés sont indiquées) | ||
+ | |||
+ | {{:​openatelier:​projet:​tete_animatronique:​i2cdetect_resultat.png|}} | ||
==== Circuit complet ==== | ==== Circuit complet ==== | ||
Ligne 477: | Ligne 507: | ||
# Set channels to the number of servo channels on your kit. | # Set channels to the number of servo channels on your kit. | ||
# 8 for FeatherWing,​ 16 for Shield/​HAT/​Bonnet. | # 8 for FeatherWing,​ 16 for Shield/​HAT/​Bonnet. | ||
- | kit = ServoKit(channels=8) | + | kit = ServoKit(channels=16) |
kit.servo[0].angle = 180 | kit.servo[0].angle = 180 | ||
Ligne 490: | Ligne 520: | ||
</​accordion>​ | </​accordion>​ | ||
+ | ==== Test des servomoteurs ==== | ||
+ | |||
+ | Définir sur quelles broches sont reliés les servomoteurs,​ fixer minimum et maximum pour chacun. | ||
+ | |||
+ | <​accordion>​ | ||
+ | <panel title="​test_python_pca9685_servomoteurs.py (cliquer pour afficher le code)">​ | ||
+ | <code python test_python_pca9685_servomoteurs.py>​ | ||
+ | import time | ||
+ | from adafruit_servokit import ServoKit | ||
+ | |||
+ | # Set channels to the number of servo channels on your kit. | ||
+ | # 8 for FeatherWing,​ 16 for Shield/​HAT/​Bonnet. | ||
+ | kit = ServoKit(channels=16) | ||
+ | |||
+ | # Correspondances (gauche/​droite pour la tête) | ||
+ | # commands du côté droit inversées | ||
+ | # 0 : sourcil gauche (50, 135) | ||
+ | # 1 : sourcil droit (inv) (135, 50) | ||
+ | # 2 : machoire basse (?, ?) | ||
+ | # 3 : oeil gauche (50,​ 130) | ||
+ | # 4 : oeil droit ​ (50,​ 130) | ||
+ | # 5 : paupière gauche () PROBLEME | ||
+ | # 6 : paupière droite () ​ ​ PROBLEME | ||
+ | # 7 : bouche gauche (50,​ 110) PROB : refaire mécanisme | ||
+ | # 8 : bouche droite (inv) (110,​ 50) PROB : refaire mécanisme | ||
+ | # 9 : yeux (50,​ 130) | ||
+ | |||
+ | for boucle in range(0, 3) : | ||
+ | kit.servo[0].angle = 135 | ||
+ | kit.servo[1].angle = 50 | ||
+ | kit.servo[2].angle = 50 | ||
+ | kit.servo[3].angle = 130 | ||
+ | kit.servo[4].angle = 130 | ||
+ | # ~ kit.servo[5].angle = 80 | ||
+ | # ~ kit.servo[6].angle = 80 | ||
+ | kit.servo[7].angle = 50 | ||
+ | kit.servo[8].angle = 110 | ||
+ | kit.servo[9].angle = 50 | ||
+ | time.sleep(1) | ||
+ | |||
+ | kit.servo[0].angle = 50 | ||
+ | kit.servo[1].angle = 135 | ||
+ | kit.servo[2].angle = 120 | ||
+ | kit.servo[3].angle = 50 | ||
+ | kit.servo[4].angle = 50 | ||
+ | # ~ kit.servo[5].angle = 100 | ||
+ | # ~ kit.servo[6].angle = 100 | ||
+ | kit.servo[7].angle = 110 | ||
+ | kit.servo[8].angle = 50 | ||
+ | kit.servo[9].angle = 130 | ||
+ | time.sleep(1) | ||
+ | |||
+ | kit.servo[0].angle = 90 | ||
+ | kit.servo[1].angle = 90 | ||
+ | kit.servo[2].angle = 90 | ||
+ | kit.servo[3].angle = 90 | ||
+ | kit.servo[4].angle = 90 | ||
+ | # ~ kit.servo[5].angle = 90 | ||
+ | # ~ kit.servo[6].angle = 90 | ||
+ | kit.servo[7].angle = 90 | ||
+ | kit.servo[8].angle = 90 | ||
+ | kit.servo[9].angle = 90 | ||
+ | time.sleep(2) | ||
+ | </​code>​ | ||
+ | </​panel>​ | ||
+ | </​accordion>​ | ||
+ | |||
+ | ==== Expressions ==== | ||
+ | |||
+ | Test de quelques expressions du visage animatronique | ||
+ | |||
+ | <​accordion>​ | ||
+ | <panel title="​expressions.py (cliquer pour afficher le code)">​ | ||
+ | <code python expressions.py>​ | ||
+ | import time | ||
+ | from adafruit_servokit import ServoKit | ||
+ | |||
+ | # Set channels to the number of servo channels on your kit. | ||
+ | # 8 for FeatherWing,​ 16 for Shield/​HAT/​Bonnet. | ||
+ | kit = ServoKit(channels=16) | ||
+ | |||
+ | # Correspondances (gauche/​droite pour la tête) | ||
+ | # commands du côté droit inversées | ||
+ | # 0 : sourcil gauche (50, 135) | ||
+ | # 1 : sourcil droit (inv) (135, 50) | ||
+ | # 2 : machoire basse (?, ?) | ||
+ | # 3 : oeil gauche (50,​ 130) | ||
+ | # 4 : oeil droit ​ (50,​ 130) | ||
+ | # 5 : paupière gauche () PROBLEME | ||
+ | # 6 : paupière droite () ​ ​ PROBLEME | ||
+ | # 7 : bouche gauche (50,​ 110) PROB : refaire mécanisme | ||
+ | # 8 : bouche droite (inv) (110,​ 50) PROB : refaire mécanisme | ||
+ | # 9 : yeux (50,​ 130) | ||
+ | |||
+ | def moue(): | ||
+ | kit.servo[0].angle = 50 | ||
+ | kit.servo[1].angle = 135 | ||
+ | kit.servo[2].angle = 120 | ||
+ | kit.servo[3].angle = 70 | ||
+ | kit.servo[4].angle = 110 | ||
+ | # ~ kit.servo[5].angle = 100 | ||
+ | # ~ kit.servo[6].angle = 100 | ||
+ | kit.servo[7].angle = 110 | ||
+ | kit.servo[8].angle = 50 | ||
+ | kit.servo[9].angle = 130 | ||
+ | time.sleep(2) | ||
+ | |||
+ | def sleep(): | ||
+ | kit.servo[0].angle = 90 | ||
+ | kit.servo[1].angle = 90 | ||
+ | kit.servo[2].angle = 90 | ||
+ | kit.servo[3].angle = 90 | ||
+ | kit.servo[4].angle = 90 | ||
+ | # ~ kit.servo[5].angle = 90 | ||
+ | # ~ kit.servo[6].angle = 90 | ||
+ | kit.servo[7].angle = 90 | ||
+ | kit.servo[8].angle = 90 | ||
+ | kit.servo[9].angle = 90 | ||
+ | time.sleep(2) | ||
+ | |||
+ | def louche(): | ||
+ | kit.servo[0].angle = 135 | ||
+ | kit.servo[1].angle = 50 | ||
+ | kit.servo[2].angle = 120 | ||
+ | kit.servo[3].angle = 130 | ||
+ | kit.servo[4].angle = 50 | ||
+ | # ~ kit.servo[5].angle = 100 | ||
+ | # ~ kit.servo[6].angle = 100 | ||
+ | kit.servo[7].angle = 110 | ||
+ | kit.servo[8].angle = 50 | ||
+ | kit.servo[9].angle = 130 | ||
+ | time.sleep(2) | ||
+ | |||
+ | louche() | ||
+ | moue() | ||
+ | sleep() | ||
+ | louche() | ||
+ | sleep() | ||
+ | |||
+ | </​code>​ | ||
+ | </​panel>​ | ||
+ | </​accordion>​ | ||
+ | |||
+ | ==== Réception OSC ==== | ||
+ | |||
+ | Trouver l'​adresse IP du RPi | ||
+ | hostname -I | ||
+ | Pour tester la réception OSC : écouter le traffic sur le port UDP 12345 | ||
+ | nc -l -u 12345 | ||
+ | Version du système/​kernel installé | ||
+ | hostnamectl | ||
+ | ​ | ||
+ | Installer python OSC : pip3 install python-osc | ||
==== Communication série avec le joystick arduino ==== | ==== Communication série avec le joystick arduino ==== | ||
Ligne 554: | Ligne 737: | ||
{{:​openatelier:​projet:​tete_animatronique:​plateau_1.png?​direct&​600|}} {{:​openatelier:​projet:​tete_animatronique:​plateau_2.png?​direct&​600|}} | {{:​openatelier:​projet:​tete_animatronique:​plateau_1.png?​direct&​600|}} {{:​openatelier:​projet:​tete_animatronique:​plateau_2.png?​direct&​600|}} | ||
+ | |||
+ | Et comme ça marche plutôt bien, on en fait 2 autres! | ||
+ | |||
+ | {{:​openatelier:​projet:​tete_animatronique:​plateau_3.png?​direct&​600|}} {{:​openatelier:​projet:​tete_animatronique:​plateau_4.png?​direct&​600|}} | ||
+ | |||
+ | Et un petit dernier. (nb: ça aurait été plus malin de grouper les pièces par catégorie sur chaque plateau) | ||
+ | |||
+ | {{:​openatelier:​projet:​tete_animatronique:​plateau_5.png?​direct&​600|}} | ||
+ | |||
+ | |||
===== Installation du raspberry pi ===== | ===== Installation du raspberry pi ===== | ||
Ligne 623: | Ligne 816: | ||
{{:​openatelier:​projet:​tete_animatronique:​20230302_barbichette.jpg?​direct&​1200|}} | {{:​openatelier:​projet:​tete_animatronique:​20230302_barbichette.jpg?​direct&​1200|}} | ||
+ | **14 juin 2023** : électronique ok, prototype construit et actionné par script python depuis le raspberry, une vidéo des premiers essais d'​expression | ||
+ | |||
+ | {{:​openatelier:​projet:​tete_animatronique:​barbichette_20230614_175450.jpg?​direct&​800|}}{{:​openatelier:​projet:​tete_animatronique:​20230614_barbichette_prototype.mp4|}} | ||
+ | |||
+ | **15 juin 2023** scripts (à renommer en .gz) {{ :​openatelier:​projet:​tete_animatronique:​20230615_scripts_barbichette.gz.txt |}} | ||
+ | |||
+ | ==== Prototype 1 ==== | ||
+ | |||
+ | **16 juin 2023** scripts : {{ :​openatelier:​projet:​tete_animatronique:​20230616_scripts.gz.txt |}} (à renommer en .gz) | ||
+ | |||
+ | Quelques détails : | ||
+ | |||
+ | **ui_servo_expressions.py** contrôle par interface graphique (sliders, etc.) des servomoteurs de la tête animatronique | ||
+ | |||
+ | **osc_envoi_simulation.py** simulation d'​envoi OSC (utile si l'ordi de détection n'est pas relié) | ||
+ | |||
+ | **osc_reception_test.py** vérification que les messages OSC sont bien reçus (pas d'​action sur les servos) | ||
+ | |||
+ | **osc_reception_tracking_visage.py** script principal, reçoit les messages envoyés par l'ordi de détection et agit sur les servos en conséquence | ||
+ | |||
+ | **serie_read_test.py** réception des messages série d'​arduino | ||
+ | |||
+ | **servo_expressions.py** (obsolète) quelques tests d'​expressions | ||
+ | |||
+ | **servo_paupieres_test.py** (test seulement) | ||
+ | |||
+ | **servo_pca9685_test.py** (test seulement, I2C) | ||
+ | |||
+ | Parfois une erreur 121 dans I2C / Rpi / Python | ||
+ | * bus overloadé | ||
+ | * fils trop longs (30cm max pour I2C, capacitance maximum de 400 pF dépassée) | ||
+ | * pull ups trop forts (il y a déjà des pull-ups dans les broches GPIO du Pi) -> supprimer ceux de la carte | ||
+ | * cf. https://​raspberrypi.stackexchange.com/​questions/​124453/​error-121-remote-i-o-error-in-smbus-py-call | ||
+ | |||
+ | Et quelques notes | ||
+ | * TODO / code : ajouter la bouche dans le script ui_servo_expressions.py | ||
+ | * TODO / code : contrôle des mouvements par pure data (pratique pour séquencer) | ||
+ | * TODO / install : solidariser caméra et robot /!\ captation audio et moteurs | ||
+ | * TODO / install : enceinte derrière le robot | ||
+ | * TODO / tête : refixer paupière, limer quelques pièces | ||
+ | * TODO / install : mode veille ? | ||
+ | |||
+ | **Nécessite un réseau local dans cette version!** | ||
===== Ressources ===== | ===== Ressources ===== | ||