Sunday, November 2, 2014

controlling camera with rc transmitter

I wanted to control the zoom of a Sony block camera from a normal RC transmitter.

For the test I used:

A Sony FCB EX11D camera with VISCA control

An Arduino Mini running at 3.3 V

A Spektrum DX6i transmitter

An AR6200 receiver

A monitor with a composite video input

The camera accepts approximately 6 to 12 V, has a 10 times optical zoom and produces NTSC composite video. The Arduino sends Sony VISCA commands at 9600 baud.

Connections

Camera RX to Arduino TX

Camera TX to Arduino RX

The camera TX connection is only needed if the program reads VISCA replies. With a 3.3 V controller it should be connected through the correct level conversion.

Camera ground to Arduino ground

Arduino digital pin 3 to the ELEV channel signal on the RC receiver

For this demonstration I powered the receiver from 3.3 V. A normal RC installation will often use 5 V, so the signal going into a 3.3 V Arduino may need a resistor divider or level converter.

The program measures the pulse width from the receiver. Moving the stick in one direction sends the VISCA zoom tele command, moving it in the other direction sends zoom wide, and returning it to the center sends zoom stop and autofocus.

Arduino and ATtiny85 versions of the code are below.

Build photos and code below.

Arduino version

#include <SoftwareSerial.h>

const byte rcPin = 3;
const byte cameraRxPin = 10;  // Leave disconnected for transmit only control
const byte cameraTxPin = 11;  // Connect to camera RX

SoftwareSerial cameraSerial(cameraRxPin, cameraTxPin);

const byte addressSet[] = {0x88, 0x30, 0x01, 0xFF};
const byte interfaceClear[] = {0x88, 0x01, 0x00, 0x01, 0xFF};
const byte zoomTele[] = {0x81, 0x01, 0x04, 0x07, 0x23, 0xFF};
const byte zoomWide[] = {0x81, 0x01, 0x04, 0x07, 0x33, 0xFF};
const byte zoomStop[] = {0x81, 0x01, 0x04, 0x07, 0x00, 0xFF};
const byte autoFocus[] = {0x81, 0x01, 0x04, 0x38, 0x02, 0xFF};

enum ZoomState { STOPPED, TELE, WIDE };
ZoomState lastState = STOPPED;

template <size_t N>
void sendPacket(const byte (&packet)[N]) {
  cameraSerial.write(packet, N);
}

void setup() {
  pinMode(rcPin, INPUT);
  cameraSerial.begin(9600);

  delay(500);
  sendPacket(addressSet);
  delay(250);
  sendPacket(interfaceClear);
  delay(250);
  sendPacket(autoFocus);
}

void loop() {
  unsigned long pulse = pulseIn(rcPin, HIGH, 25000UL);
  ZoomState nextState = STOPPED;

  if (pulse > 1550) {
    nextState = TELE;
  } else if (pulse != 0 && pulse < 1400) {
    nextState = WIDE;
  }

  if (nextState != lastState) {
    if (nextState == TELE) {
      sendPacket(zoomTele);
    } else if (nextState == WIDE) {
      sendPacket(zoomWide);
    } else {
      sendPacket(zoomStop);
      sendPacket(autoFocus);
    }
    lastState = nextState;
  }
}

ATtiny85 version

#include <SoftwareSerial.h>

#define rcPin PB0
#define cameraRxPin PB1
#define cameraTxPin PB2

SoftwareSerial cameraSerial(cameraRxPin, cameraTxPin);

const byte addressSet[] = {0x88, 0x30, 0x01, 0xFF};
const byte interfaceClear[] = {0x88, 0x01, 0x00, 0x01, 0xFF};
const byte zoomTele[] = {0x81, 0x01, 0x04, 0x07, 0x23, 0xFF};
const byte zoomWide[] = {0x81, 0x01, 0x04, 0x07, 0x33, 0xFF};
const byte zoomStop[] = {0x81, 0x01, 0x04, 0x07, 0x00, 0xFF};
const byte autoFocus[] = {0x81, 0x01, 0x04, 0x38, 0x02, 0xFF};

enum ZoomState { STOPPED, TELE, WIDE };
ZoomState lastState = STOPPED;

template <size_t N>
void sendPacket(const byte (&packet)[N]) {
  cameraSerial.write(packet, N);
}

void setup() {
  pinMode(rcPin, INPUT);
  pinMode(cameraRxPin, INPUT);
  pinMode(cameraTxPin, OUTPUT);
  cameraSerial.begin(9600);

  delay(500);
  sendPacket(addressSet);
  delay(250);
  sendPacket(interfaceClear);
  delay(250);
  sendPacket(autoFocus);
}

void loop() {
  unsigned long pulse = pulseIn(rcPin, HIGH, 25000UL);
  ZoomState nextState = STOPPED;

  if (pulse > 1550) {
    nextState = TELE;
  } else if (pulse != 0 && pulse < 1400) {
    nextState = WIDE;
  }

  if (nextState != lastState) {
    if (nextState == TELE) {
      sendPacket(zoomTele);
    } else if (nextState == WIDE) {
      sendPacket(zoomWide);
    } else {
      sendPacket(zoomStop);
      sendPacket(autoFocus);
    }
    lastState = nextState;
  }
}

Photos and videos

rc control for sony block camera, photograph 1
rc control for sony block camera, photograph 2
rc control for sony block camera, photograph 3
rc control for sony block camera, photograph 4
rc control for sony block camera, photograph 5

No comments:

Post a Comment