Pelco D PTZ Camera Control with Dual Axis Hall Joystick

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

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


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

Cool project :)

What baud rate are you transmitting at, 2400?

yes, 2400

Hi there, I'm trying to do this but thus far have had no success, please could you take a look at my project and offer me some advice.

I'd be eternally greatful to you :)

Regards, Rick.

Hello, your article is good!

Could you help me by indicating how you could try a panTilt without a joystick? I say this thinking that it moves only with code, in an automated way creating some simple sequences.

Thank you very much for your contribution!