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

Résultat

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *