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")