Home PanTilt JMux Contact

pantilt.py

# Program to communicate with PanTilt Controller
#
# Uses libusb 1.0 and PyUSB
# To install libusb: "sudo apt-get install libusb-dev"
# Useful page about installing libusb here:
# https://hackintoshrao.com/tag/libusb-in-linux/
#
# To install PyUSB, download and extract the zip file from PyUSB
# Then install by executing this command from inside the extracted archive
# sudo ./setup.py install
# The libray should be built and installed here:
# build/lib.linux-armv7l-2.7/usb
# And here:
# /usr/local/lib/python2.7/dist-packages/usb
# This only installs for Python 2.7, to install for Python 3, see this:
# https://raspberrypi.stackexchange.com/questions/6774/installed-pyusb-still-importerror-no-module-named-core
# I didn't try it, just wrote Python 2 code.
#
# Getting the PanTilt Controller to mount may be non-trivial, see this:
# http://blog.damnsoft.org/raspberry-pi-c-and-custom-hid-devices/

import usb.core
import usb.util
import sys
import time

print("Hello from PyUSB test program\n")

# Find our device
devices = usb.core.find(idVendor=0x04d8, idProduct=0xff17)
#devices = usb.core.find(idVendor=0x04d8, idProduct=0xf003)

# Was it found?
if devices is None:
raise ValueError('Device not found')

# Lets assume here that we only find one PanTilt Controller device
# Set the active configuration. With no arguments, the first configuration will be the active one
print (str(devices))

reattach = False
if devices.is_kernel_driver_active(0):
reattach = True
devices.detach_kernel_driver(0)
print("Detached kernel driver")

devices.set_configuration()

# This is needed to release interface, otherwise attach_kernel_driver fails
# due to "Resource busy"
usb.util.dispose_resources(devices)

# End of initialisation, following code is functions to use the device

def GetSerialNumber():
outData = bytearray([0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
devices.write(0x01, outData)
inData = devices.read(0x81, 10)
return(inData[2:].tostring())

# Move the Power Head
# Direction values:
# 0 Stop
# 1 Up
# 2 Up & Right
# 3 Right
# 4 Down & Right
# 5 Down
# 6 Down & Left
# 7 Left
# 8 Up & Left
# panSpeed and tiltSpeed should be 0 - 128
# fast boosts the head speed and effects both panning and tilting
def Move(direction, panSpeed, tiltSpeed, fast = False):
if fast:
panSpeed |= 0x80
tiltSpeed |= 0x80
outData = bytearray([0x70, direction, panSpeed, tiltSpeed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
bytes_written = devices.write(0x01, outData)
print(str(bytes_written) + " bytes written to EP1")
return

# Get the data being transmitted from the camera
# This is camera status information
def EnquiryLANC():
inData = bytearray(8)
outData = bytearray([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
devices.write(0x01, outData)
inData = devices.read(0x81, 8)
return(inData)

# Send a LANC frame repeatedly, e.g. to start recording
def SendLANC_Once(byte0, byte1 = 0x00, byte2 = 0x00, byte3 = 0x00, byte4 = 0x00, byte5 = 0x00, byte6 = 0x00, byte7 = 0x00):
outData = bytearray([0x02, byte0, byte1, byte2, byte3, byte4, byte5, byte6, byte7, 0x00])
bytes_written = devices.write(0x01, outData)
print(str(bytes_written) + " bytes written to EP1")
return

# Send a LANC frame continuously, e.g. to zoom a camera
def SendLANC_Continuous(byte0, byte1 = 0x00, byte2 = 0x00, byte3 = 0x00, byte4 = 0x00, byte5 = 0x00, byte6 = 0x00, byte7 = 0x00):
outData = bytearray([0x03, byte0, byte1, byte2, byte3, byte4, byte5, byte6, byte7, 0x00])
bytes_written = devices.write(0x01, outData)
print(str(bytes_written) + " bytes written to EP1")
return

# Terminate a SendLANC_Continuous
def StopLANC():
outData = bytearray([0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
bytes_written = devices.write(0x01, outData)
print(str(bytes_written) + " bytes written to EP1")
return

# Check if the Controller is connected to a LANC camera
def CheckLANC():
inData = bytearray(8)
outData = bytearray([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
devices.write(0x01, outData)
inData = devices.read(0x81, 8)
return(inData[1] == 0x01)

# Zoom the camera
# Direction values:
# 0 Stop zooming
# 1 Zoom in
# 2 Zoom out
# Speed should be 0 - 7
def Zoom(direction, speed = 3):
if direction == 0:
StopLANC()
elif direction == 1:
SendLANC_Continuous(0x28, speed << 1)
else:
SendLANC_Continuous(0x28, 0x10 | (speed << 1))
return

# Power on the camera, only works if the camera is sleeping, not hard off
def PowerOn():
outData = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
bytes_written = devices.write(0x01, outData)
print("Camera power on command sent")
return

# Put the camera into sleep mode
def PowerOff():
outData = bytearray([0x02, 0x1E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
bytes_written = devices.write(0x01, outData)
print("Camera power off command sent")
return

# Start (or stop) video recording
def Record():
outData = bytearray([0x02, 0x18, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
bytes_written = devices.write(0x01, outData)
print("Record on/off command sent")
return

# Trigger shutter
def TakeStill():
outData = bytearray([0x02, 0x18, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
bytes_written = devices.write(0x01, outData)
print("Take photo command sent")
return