Monter un pan/tilt sur la caméra
Pour installer la caméra sur le châssis et lui permettre de tourner sur 2 dimensions, on l’installe sur un support pan/tilt. Il ne s’agit que d’un montage de 2 servomoteurs montés l’un sur l’autre.
Support Pan/Tilt BPT-KT
J’ai choisis le modèle BPT-KT de chez Lynxmotion.
Il est livré avec 2 servomoteurs Hitec HS-422.
- Tension : 4.8 – 6.0 V
- Couple :
- 3.3 kg.cm à 4.8V
- 4.1 kg.cm à 6V
- Vitesse :
- 0.21sec/60° à 4.8V
- 0.16sec/60° à 6V
- Taille : 39.88 x 19.82 x 36.02 mm
- Poids : 45.5 g
- Pignons : Résine
Datasheet du servomoteur Hitec HS-422
Le guide de montage n’est disponible qu’en ligne : Guide de montage
Attention lors du montage à bien positionner les pignons au centre de sa plage de rotation.
Support de la caméra
Il n’existe malheureusement pas de support pour la caméra Raspberry Pi qui puisse être directement installé sur le servomoteur. J’ai choisi d’utiliser un support fait maison ( merci Papa 🙂 )
Pilotage depuis la manette Xbox 360
Nous avons déjà vu comment piloter un servomoteur avec le contrôleur T’REX. Contrôler un pan/tilt revient à pilote 2 servomoteurs.
On doit tout d’abord trouver les valeurs d’impulsion à envoyer aux servomoteurs pour avoir les positions extrêmes de chaque sens. Pour ça il n’y a pas de secret, il faut y aller à tatillon. Il faut éviter d’arriver à la position où le servomoteur arrive en bout de course, et se met à vibrer. Dans ce cas là, il utilise son couple maximal pour tenter d’atteindre une position physiquement impossible, ce qui peut l’endommager sur le long terme. Pour ma part, j’ai récupéré ces valeurs :
Axe X : Gauche 750 —– Centre 1575 —– Droite 2400
Axe Y : Bas 1150 —– Centre 1850 —– Haut 2350
Il convient également de récupérer les valeurs du joystick utilisé pour faire bouger la caméra. J’utilise le joystick droit de la manette.
X2 : Gauche -32768—– Centre 0—– Droite 32766
Y2 : Bas -32768 —– Centre 0 —– Haut 32766
Il ne reste plus qu’à faire un étalonnage des valeurs X2 et Y2 reçues de la manette pour les faire correspondre aux valeurs voulues pour les servomoteurs.
Lors de l’arrêt du programme, il ne faut pas oublier d’envoyer une impulsion 0 aux servomoteurs pour ne plus envoyer de position et ainsi les libérer.
#!/usr/bin/python3 # -*- coding: utf-8 -*- from __future__ import division # Pour division float from pprint import pprint from lib import xbox_read import pigpio import time # Cablage TREX_ADDRESS = 0x07 SDA=2 # Pin no 3 SCL=3 # Pin no 5 # Connexion de pigpiod pigpio = pigpio.pi() def trex_command(): ''' Envoi une requete de commande au T'REX ''' # Verification de la connexion de pigpiod if not pigpio.connected: exit(0) # Preparation de la requete Bit Bang pigpio.bb_i2c_open(SDA, SCL, baud=100000) # Preparation des donnees right_motor_bytes = right_motor_speed.to_bytes(2, byteorder='big', signed=True) left_motor_bytes = left_motor_speed.to_bytes(2, byteorder='big', signed=True) servo_0_bytes = servo_x.to_bytes(2, byteorder='big'); servo_1_bytes = servo_y.to_bytes(2, byteorder='big'); servo_2_bytes = (0).to_bytes(2, byteorder='big'); servo_3_bytes = (0).to_bytes(2, byteorder='big'); servo_4_bytes = (0).to_bytes(2, byteorder='big'); servo_5_bytes = (0).to_bytes(2, byteorder='big'); impact_bytes = (50).to_bytes(2, byteorder='big'); battery_bytes = (550).to_bytes(2, byteorder='big'); # Envoi de la requete pigpio.bb_i2c_zip(SDA, [ 4, TREX_ADDRESS, # Set I2C adress to TREX_ADDRESS 2, # Start condition 7, 27, # Write 27 bytes of data 0x0F, # 1. Start byte 0x06, # 2. PWM frequency -> 122Hz left_motor_bytes[0], left_motor_bytes[1], # 3-4. Left motor speed 0x00, # 5 Left motor brake right_motor_bytes[0], right_motor_bytes[1], # 6-7. Right motor speed 0x00, # 8. Right motor brake servo_0_bytes[0], servo_0_bytes[1], # 9-10. Servo 0 position servo_1_bytes[0], servo_1_bytes[1], # 11-12. Servo 1 position servo_2_bytes[0], servo_2_bytes[1], # 13-14. Servo 2 position servo_3_bytes[0], servo_3_bytes[1], # 15-16. Servo 3 position servo_4_bytes[0], servo_4_bytes[1], # 17-18. Servo 4 position servo_5_bytes[0], servo_5_bytes[1], # 19-20. Servo 5 position 0x32, # 21. Accelerometer de-vibrate -> 50 impact_bytes[0], impact_bytes[1], # 22-23. Impact sensitivity battery_bytes[0], battery_bytes[1], # 24-25. Low battery TREX_ADDRESS, # 26. I2C address 0x00, # 27. Clock frequency 3, # Stop condition 0 # No more commands ]) # Fin de la requete Bit Bang pigpio.bb_i2c_close(SDA) def valmap(value, istart, istop, ostart, ostop): ''' Etalonnage d'une valeur, d'une echelle d'entree vers une echelle de sortie ''' return int(ostart + (ostop - ostart) * ((value - istart) / (istop - istart))) if __name__ == '__main__': try: # Initialisation des variables left_motor_speed = 0 right_motor_speed = 0 servo_x = 0 # Commande du servo X servo_y = 0 # Commande du servo Y servo_buttons = ['X2','Y2'] # Boutons de controle du pan/tilt servo_x_left = 750 # Impulsion min X servo_x_right = 2400 # Impulsion max X servo_y_down = 1150 # Impulsion min Y servo_y_up = 2350 # Impulsion max Y x2 = 0 y2 = 0 # En attente d'evenement de la manette for event in xbox_read.event_stream(deadzone=12000): # On n'envoie une commande au TREX seulement si c'est un bouton qui concerne le pan/tilt if event.key in servo_buttons: print(event) # Axe X if event.key == 'X2': x2 = event.value # De -32768 a 32766 # Axe Y if event.key == 'Y2': y2 = event.value # De -32768 a 32766 # Calcul des pulsations à envoyer aux servomoteurs servo_x = valmap(x2, -32768, 32766, servo_x_left, servo_x_right) print(servo_x) servo_y = valmap(y2, -32768, 32766, servo_y_down, servo_y_up) print(servo_y) # Envoi de la commande trex_command() except KeyboardInterrupt: # Arret d'urgence left_motor_speed = 0 right_motor_speed = 0 servo_x = 0 servo_y = 0 trex_command() # Deconnexion de pigpiod pigpio.stop() print("\nAdieu monde cruel")