Zoom and focus commands using Arduino
What is Arduino
Arduino is an open-source platform that can be used for creating electronics projects. Arduino is made up of both a physical programmable circuit board (referred to as a microcontroller) and a piece of software, or IDE (Integrated Development Environment) that is run on your computer and is used to write and upload computer code to the physical board.
The Arduino platform has gained popularity with people who are new to electronics, and for good reason. Unlike most previous programmable circuit boards, the Arduino does not need a separate piece of hardware (called a programmer) in order to load new code onto the board – you can simply use a USB cable. Additionally, the Arduino IDE uses a simplified version of C++, making it much easier to learn to program. Finally, Arduino provides a standard form factor that breaks out the functions of the micro-controller into a more accessible package.
The code
Today we want to share some code that shows how to send zoom and focus commands to a Dome Camera with an Arduino using Pelco-D protocol.
Parts you may need:
- Dome Camera
- Arduino Mega
- Switch to send zoom or focus commands
- RS485 breakout board
In the code below there is example code of how do zoom, focus, pan and tilt, but for this example we are going to use only zoom. To wire the switch use the common to 5V and the other two to pin 13 and pin 14 on arduino. In the RS485 board add solder to the solder jumper , connect DE to pin 12 and DI to Serial1, 5V and GND.
#include
// RS485 Enable //
//#define rsEnable 12 //uncomment this lines
//#define f0Mask B00000001
//#define f1Mask B00000010
//#define f2Mask B00000100
//#define f3Mask B00001000
//#define f4Mask B00010000
//#define f5Mask B00100000
//#define f6Mask B01000000
//#define f7Mask B10000000
// PTZ Camera
int cameraAddress = 0x01;
int ZoomInPin = 13, ZoomOutPin = 14;// Definition of digital pin input
int zoomin = 0, zoomout = 0;
int pan, tilt, digital;
Stream* serialPort;
void setup() {
Serial.begin(9600); Serial1.begin(9600);
ptzCam(Serial1, cameraAddress);
initialize();
pinMode(ZoomInPin, INPUT);
pinMode(ZoomOutPin, INPUT);
}
void loop() {
zoomin = digitalRead(ZoomInPin);
zoomout = digitalRead(ZoomOutPin);
}
void ptzCam(Stream &serial, unsigned char _cameraAddress)
{
serialPort = &serial;
cameraAddress = _cameraAddress;
sendPTZcommand();
}
void initialize() {
pinMode(rsEnable, OUTPUT); digitalWrite(rsEnable, HIGH);
}
void sendPTZcommand()
{
char cmd1, cmd2;
char data1, data2;
char checksum;
char id;
int temp = 0;
//Serial.print("Tilt1: "); Serial.print(tilt);
tilt = tilt >> 1; pan = pan >> 1;
if (pan > 127) { pan = 127; }
if (tilt > 127) { tilt = 127; }
// Reduce and Deadband the pan and tilts
if (pan < 65 && pan > 61) { pan = 63; }
if (tilt < 65 && tilt > 61) { tilt = 63; }
//Serial.print(" Tilt2: "); Serial.println(tilt);
// Command 1
// *************************
// Bit 7: Sense (Unused)
// Bit 6: Reserved
// Bit 5: Reserved
// Bit 4: Auto / Manual Sean
// Bit 3: Camera On/Off
// Bit 2: Iris Close
// Bit 1: Iris Open
// Bit 0: Focus Near
// Command 2
// *************************
// Bit 7: Focus Far
// Bit 6: Zoom Wide
// Bit 5: Zoom Tele
// Bit 4: Down
// Bit 3: Up
// Bit 2: Left
// Bit 1: Right
// Bit 0: Always 0
// Data 1 - Pan Speed
// *************************
// Expects 0 - 63, where 63 is full speed and 0 is stopped
// Data 2 - Tilt Speed
// *************************
// Expects 0 - 63, where 63 is full speed and 0 is stopped
digitalWrite(rsEnable, HIGH);
id = cameraAddress;
cmd1 = 0;
cmd2 = 0;
data1 = 0;
data2 = 0;
//in this code we are only using zoom in and out
// Zoom
if ( (zoomin) && !(zoomout) ) { cmd2 = 32; } // wide
else if ( !(zoomin) && (zoomout) ) { cmd2 = 64; } // tele
// Focus
if ( (digital & f2Mask) && (!digital & f3Mask) ) { cmd1 = 1; cmd2 = 0; } // wide
else if ( !(digital & f2Mask) && (digital & f3Mask) ) { cmd1 = 0; cmd2 = 128; } // tele
// Pan
if (pan > 63) {
cmd2 = cmd2 + 2; // Set direction bit
data1 = pan - 63; // We're on the upper end, so shift down
}
else if (pan < 63) { cmd2 = cmd2 + 4; // Set direction bit data1 = 63 - pan; } // Tilt if (tilt > 63) {
cmd2 = cmd2 + 16; // Set direction bit
data2 = tilt - 63; // We're on the upper end, so shift down
}
else if (tilt < 63) {
cmd2 = cmd2 + 8; // Set direction bit
data2 = 63 - tilt;
}
// Bound data to safe margin
if (data1 < 2) { data1 = 0; if (cmd2 & f2Mask) { cmd2 -= 4; } if (cmd2 & f1Mask) { cmd2 -= 2; } } if (data1 > 61) { data1 = 61; }
// Bound data to safe margin
if (data2 < 2) { data2 = 0; if (cmd2 & f4Mask) { cmd2 -= 16; } if (cmd2 & f3Mask) { cmd2 -= 8; } } if (data2 > 61) { data2 = 61; }
checksum = id + cmd1 + cmd2 + data1 + data2;
serialPort->write(0xFF);
serialPort->write(id);
serialPort->write(cmd1);
serialPort->write(cmd2);
serialPort->write(data1);
serialPort->write(data2);
serialPort->write(checksum);
/* debug print
//Serial.print("PTZ Command: ");
Serial.write(0xFF);ac
Serial.write(id);
Serial.write(cmd1);
Serial.write(cmd2);
Serial.write(data1);
Serial.write(data2);
Serial.write(checksum);
//Serial.println();
*/
//digitalWrite(rsEnable, LOW);
}
I’ve been struggling with this project for 2 days, but I don’t get it working.
When connecting a camera by the RS485 ports, it doens’t zoom at all by switching the switch.
I’ve removed the ‘//’ on the begin of the script, to get it working, connected the RS485 module and switch as you described. Can you please help me out?
Thanks in advance.
Kind regards,
Erwin
Hey Erwin
Are you able to successfully send any commands to your camera? If not, please check your hardware connections between the three devices: Arduino, RS485 breakout board, and the camera. Also, make sure the baud rate on the camera and Arduino match.
Hello,
Sorry for my late reply, I didn’t got a notification about a new email.
I were able to send commands to the camera, but the zoom didn’t worked correctly. Now we have solved it with another solution. Thank you for your reply.
Kind regards,
Erwin
Hi Erwin!
There is the correction of the code. I tryied it and works fine!
[code]
// RS485 Enable //
#define rsEnable 12 //uncomment this lines
#define f0Mask B00000001
#define f1Mask B00000010
#define f2Mask B00000100
#define f3Mask B00001000
#define f4Mask B00010000
#define f5Mask B00100000
#define f6Mask B01000000
#define f7Mask B10000000
// PTZ Camera
int cameraAddress = 0x01;
int ZoomInPin = 13, ZoomOutPin = 14;// Definition of digital pin input
int zoomin = 0, zoomout = 0;
int pan, tilt, digital;
Stream* serialPort;
void setup() {
Serial.begin(9600);// Serial1.begin(9600);
ptzCam(Serial, cameraAddress);
initialize();
pinMode(ZoomInPin, INPUT);
pinMode(ZoomOutPin, INPUT);
}
void loop() {
zoomin = digitalRead(ZoomInPin);
zoomout = digitalRead(ZoomOutPin);
sendPTZcommand();
}
void ptzCam(Stream &serial, unsigned char _cameraAddress) {
serialPort = &serial;
cameraAddress = _cameraAddress;
sendPTZcommand();
Serial.print(“ID: “);
Serial.println(cameraAddress);
}
void initialize() {
pinMode(rsEnable, OUTPUT); digitalWrite(rsEnable, HIGH);
}
void sendPTZcommand() {
char cmd1, cmd2;
char data1, data2;
char checksum;
char id;
int temp = 0;
//Serial.print(“Tilt1: “); Serial.print(tilt);
//
//tilt = tilt >> 1; pan = pan >> 1;
//
//if (pan > 127) { pan = 127; }
//if (tilt > 127) { tilt = 127; }
//
//// Reduce and Deadband the pan and tilts
//if (pan 61) { pan = 63; }
//if (tilt 61) { tilt = 63; }
//
//Serial.print(” Tilt2: “); Serial.println(tilt);
// Command 1
// *************************
// Bit 7: Sense (Unused)
// Bit 6: Reserved
// Bit 5: Reserved
// Bit 4: Auto / Manual Sean
// Bit 3: Camera On/Off
// Bit 2: Iris Close
// Bit 1: Iris Open
// Bit 0: Focus Near
// Command 2
// *************************
// Bit 7: Focus Far
// Bit 6: Zoom Wide
// Bit 5: Zoom Tele
// Bit 4: Down
// Bit 3: Up
// Bit 2: Left
// Bit 1: Right
// Bit 0: Always 0
// Data 1 – Pan Speed
// *************************
// Expects 0 – 63, where 63 is full speed and 0 is stopped
// Data 2 – Tilt Speed
// *************************
// Expects 0 – 63, where 63 is full speed and 0 is stopped
digitalWrite(rsEnable, HIGH);
id = cameraAddress;
cmd1 = 0;
cmd2 = 0; //VALOR A MODIFICAR
data1 = 0;
data2 = 0;
//in this code we are only using zoom in and out
// Zoom
if ( (zoomin) && !(zoomout) ) {
cmd2 = 32;
} // wide
else if ( !(zoomin) && (zoomout) ) {
cmd2 = 64;
} // tele
/*// Focus
if ( (digital & f2Mask) && (!digital & f3Mask) ) {
cmd1 = 1; cmd2 = 0;
} // wide
else if ( !(digital & f2Mask) && (digital & f3Mask) ) {
cmd1 = 0; cmd2 = 128;
} // tele
*/
/* // Pan
if (pan > 63) {
cmd2 = cmd2 + 2; // Set direction bit
data1 = pan – 63; // We’re on the upper end, so shift down
}
else if (pan 63) {
cmd2 = cmd2 + 16; // Set direction bit
data2 = tilt – 63; // We’re on the upper end, so shift down
}
else if (tilt < 63) {
cmd2 = cmd2 + 8; // Set direction bit
data2 = 63 – tilt;
}
*/
// Bound data to safe margin
if (data1 61) {
data1 = 61;
}
// Bound data to safe margin
if (data2 61) {
data2 = 61;
}
checksum = id + cmd1 + cmd2 + data1 + data2;
serialPort->write(0xFF);
serialPort->write(id);
serialPort->write(cmd1);
serialPort->write(cmd2);
serialPort->write(data1);
serialPort->write(data2);
serialPort->write(checksum);
//// debug print
//Serial.print(“PTZ Command: “);
//Serial.write(0xFF);//ac
//Serial.write(id);
//Serial.write(cmd1);
//Serial.write(cmd2);
//Serial.write(data1);
//Serial.write(data2);
//Serial.write(checksum);
//Serial.println();
digitalWrite(rsEnable, LOW);
}
[/code]
Hello how are you doing.
Please can you help me with the code to only move a Pantilt without using the camera.
I have a PanTilt outodoor IP67 that uses the Pelco D protocol as indicated by the manufacturer.
Do you know if it works for me?
Thank you! :)
Hi Cesar,
We don’t have any pre made code for that, but you should be able to accomplish what you need to do the Arduino. You will need an RS485 shield or RS485 Breakout Board between the camera and the arduino to communicate together. From there, you should be able to modify the above code to just send the pan and tilt commands.
How is the dome connected to the RS485 breakout board? Are the wires labeled clearly? I didn’t see any description of the wiring in the Sony manual that accompanies the dome [https://www.superdroidrobots.com/product_info/WC-072-000_sony-700TV-10x-zoom-AF.pdf].
The dome camera has cables coming out of it that expose the video, power (12V), and RS485 A/B lines. It should be pretty clear what each of the wires are. I don’t have one handy right now but I believe the connections are BNC for the video, barrel jack for the power, and two bare wires for the RS485 A and B.
Hi, im a complete novice when it comes to this but want to do this project. I have a thermal ptz camera that says the following :Compatible with ONVIF Profile S IP, MPX (HDCVI) and analog VMS systems
Can be powered via PoE or 24 VAC supply and takes Pelco D commands.
I have managed so far to borrow a ptz joystick controller from a friend to try.
It was wireed directly to the camera with its rs485 connector and i got it to work the pan and tilt of this camera. Zoom does not work though and i have no access to any other functions like motion detection or zoom unless i connect to a pc.
What i want is to mount the camera on my sons treehouse, powered by the 12v supply he already has up there. AV will be connected by bnc to a 12v monitor.
I want him to be able to access the pan/tilt/zoom options and be able to change the colour settings with a simple joystick to control pab and tilt, and button presses that control zoom in/out and colour change.
Being able to control motion detection would be great too, but is a compromise i would make.
If anyone can help me with this i would be hugely grateful.