I've had a PTZ camera for a while and finally tried to control pan and tilt with a home made shield. It makes use of the Pelco D protocol on RS-485 and with a little patience it works pretty good. The check sum is calculated "on the fly" since I was expecting it to change with the variable speeds. While it works, I stopped short of finishing the speed control because my camera does not support it. Maybe if I get another camera.
The only other additions I'm currently considering is controlling zoom/focus when the green button on the joystick is pressed and adding a couple of buttons to select which camera to operate.
Since the RS-485 is only transmitting, the wiring is very simple.
/*
Pelco D pan/tilt camera control using a dual axis hall effect joystick and a SP485EE, RS-485 transceiver IC with software serial
Original intention was to have variable speeds but abandoned it when I found my camera didn't support it
Buttons and IR remote were also implemented satisfactorily
unclebone 2011
SP485EE
____
nc --- 1| |8 --- +5
+5 --- 2| |7 --- RS-485 - black wire to cam
+5 --- 3| |6 --- RS-485 + white wire to cam
pin8 - 4|____|5 --- GND
*/
#include <SoftwareSerial.h>
const byte recPin = 7; //not receiving anything back, any unused pin will do
const byte xMitPin = 8;
const int xAxis = A1; //Up Down - Joystick output to analog pin 1
const int yAxis = A2; //Left Right - Joystick output to analog pin 2
const byte tiltDown = 0x10;
const byte tiltUp = 0x08;
const byte panLeft = 0x04;
const byte panRight = 0x02;
int xVal = 0;
int yVal = 0;
SoftwareSerial mySerial = SoftwareSerial(recPin, xMitPin);
void setup(){
pinMode(recPin, INPUT);
pinMode(xMitPin, OUTPUT);
mySerial.begin(2400);
}
void loop(){
yVal = analogRead(yAxis);
xVal = analogRead(xAxis);
if(xVal > 600){
functionXmit(0x01, tiltUp, 0x00);
while(xVal > 600){
xVal = analogRead(xAxis);
}
}
if(xVal < 450){
functionXmit(0x01, tiltDown, 0x00);
while(xVal < 450){
xVal = analogRead(xAxis);
}
}
if(yVal > 600){
functionXmit(0x01, panLeft, 0x00);
while(yVal > 600){
yVal = analogRead(yAxis);
}
}
if(yVal < 450){
functionXmit(0x01, panRight, 0x00);
while(yVal < 450){
yVal = analogRead(yAxis);
}
}
halt();
}
//Camera #, Speed 0x00 - 0x3F. SPEED NOT IMPLEMENTED. MY CAMERA DOES NOT SUPPORT!!!!!!
void functionXmit(byte camNum, byte funcVal, byte speedVal){
int modSum = 0;
byte dataVal[6] ={0xFF, camNum, 0x00, funcVal, speedVal, speedVal};
for(int i=0; i<6; i++){
mySerial.print(dataVal[i], BYTE);
if(i > 0) //dont add in the SYNC byte to calculate the check sum
modSum += dataVal[i];
}
modSum %= 100; //PelcoD calls for the check sum to to be the sum of bits 2 - 6 modulo 256. 256 decimal, or 100 hex
mySerial.print(modSum, BYTE);
}
void halt(){
//sync cam# Command1 Command2 Data1 Data2 CheckSum
byte dataVal[7] ={0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01}; //This is the most basic instruction. Camera 1, four zeros and a check sum of one
for(int i=0; i<7; i++){
mySerial.print(dataVal[i], BYTE);
}
}