Tech Thursday

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.

arduino

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:

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


6 Comments
  1. Erwin 2 years ago

    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

    • Author
      SuperDroid 2 years ago

      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.

  2. Erwin 1 year ago

    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

  3. Sebastian 8 months ago

    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]

  4. Cesar 6 months ago

    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! :)

  5. Author
    SuperDroid 6 months ago

    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.

Leave a reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

©2020 SDRobots.com | All rights reserved.

Log in with your credentials

or    

Forgot your details?

Create Account