[SOLVED] Problems communicating with Sony PTZ Camera- VISCA protocol (RS232)

Hi Folks,

I know a few other people have posted this same problem, but nobody has posted their working code or solutions, so I'll try to be as clear as possible, and post my working code + wiring ASAP!

Overall Objective: Control Sony D70 PTZ Camera using Arduino via Max232 circuit and VISCA protocol. Final product will be an analog joystick controller that allows museum visitors to control pan, tilt, and zoom.

Current objective: For now, I'm just trying to establish communication with the Camera, and execute one command when I press the button (Zoom telephoto)

Problem: I'm not getting any response from the camera. When I test out the circuit with the computer (by sending commands from computer to Arduino), it works fine. However, communicating between Arduino>Camera or Computer>Camera doesn't work.

Controller: Arduino Uno
IDE: Arduino 1.0.3

All about the Camera: Sony EVI-D70
Product Page: Search Results - Sony Pro
Technical Manual (includes very well-documented protocol starting on page 31):Search Results - Sony Pro
Some key points from the Tech Manual:

"Data flow will take place with the LSB first" (p32)
How to start communication with the camera http://melikebike.files.wordpress.com/2013/02/capture1.jpg
Wiring:
http://melikebike.files.wordpress.com/2013/02/capture2.jpg
How to zoom:
http://melikebike.files.wordpress.com/2013/02/capture3.jpg

My code:

/*
Based on soft serial example
 */
#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

//Camera commands (taken from Technical Manual)
uint8_t address_command[4]= {0x88, 0x30, 0x01, 0xFF};
uint8_t if_clear[5]= {0x88, 0x01, 0x00, 0x01, 0xFF};
uint8_t zoom_tele[6]= {0x81, 0x01, 0x04, 0x07, 0x02, 0xFF};
int delayTime= 100;   //Time between commands

const int buttonPin=2;  //Button to activate sending the command
const int ledPin =  13;      //Indicator LED


void setup()  
{
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  Serial.println("Goodnight moon!");
  
  //SEND SETUP COMMANDS>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  //mySerial.println("Hello, world?");
  
  //Send Address command
  for (int i=0; i<6; i++){
    mySerial.print(address_command[i],HEX);
  }
  
  //plenty of delay to allow camera time for next command
  delay(500);  
  
  //Send IF_clear command
  for (int i=0; i<5; i++){
    mySerial.print(if_clear[i],HEX);
    delay(100);  //For USB testing-- NOT FOR ACTUAL CONTROLLER
  }

}

void loop() // run over and over
{
  //If button is pressed, send 'Zoom_Tele' command and light up LED
  int buttonState=digitalRead(buttonPin);
  if(buttonState==HIGH){
    digitalWrite(ledPin, HIGH);
    sendCommands();
  }
  else{
    digitalWrite(ledPin,LOW);
  }
  
  //Take softSerial (RS232) input and send via Serial
  if (mySerial.available())
    Serial.write(mySerial.read());
  //Take Serial input (from Arduino Serial monitor) and send to RS232 output:
  if (Serial.available())
    mySerial.write(Serial.read());
  
}

void sendCommands(){
   delay(500);  //Delay before sending commands to avoid sending multiples
  Serial.println("Sending commands");
  //Send Zoom tele command
  for (int i=0; i<6; i++){
    mySerial.print(zoom_tele[i],HEX);
  }
}

Wiring diagram:


Note on wiring diagram: I switch the TX and RX wires in order to communicate with the computer.

What I've tried:

  1. Sending hex values from computer to camera using a Keyspan USB>RS232 converter and RealTerm (maybe I'm doing this wrong??). Here's how I did it:
    9600-8N1 , no flow control
    View setup:

    Send commands:

    Result of RealTerm test: no response from camera. I tried sending Zoom_tele command just for kicks, but nothing happens.
    Note: the port was not active in these screenshots, but I know it works. I used an Arduino Uno and the above code to send commands to Realterm, and vice versa.
  2. Tested continuity on all wires. Yes, it's really hooked up like this.
  3. Switching RX and TX wires between MAX232 chip and Camera. I've tried all things with wires in both configs.
  4. Tried 2 Arduino Uno's... same results

Some things I'm thinking about trying:

Use hardware serial port to communicate with camera, and softSerial port to communicate with computer
any other ideas??

Thanks so much in advance, and let me know if I can provide any other info.
-S

When I test out the circuit with the computer (by sending commands from computer to Arduino), it works fine.

So how do you know this? Did you use a loopback wire on the max232 cam side instead of the cam?

Final product will be an analog joystick controller that allows museum visitors to control pan, tilt, and zoom.

Some time back I looked at a commercial joystick controller for these types of cams (like below) and the price was ~$1500. In thinking of making a DIY joystick controller, I looked at the control protocol, and decided that going with the absolute position commands for pan, tilt, and zoom, would be the simpliest setup to implement. I never got one of the cams, so never followedn up with the DIY joystick control.

http://compare.ebay.com/like/181084550838?var=lv&ltyp=AllFixedPriceItemTypes&var=sbar

Did you check if you have all the dipswitches on the bottom of the D70 in the OFF position? This would mean they all point to the back side of the camera.

Doing that will config the camera into 9600 Baud and RS232 instead of 422.

Then to check it and to see how the commando structure works for the D70 you could download the evi d70 demo software from sony. > http://pro.sony.com/bbsc/ssr/product-EVID70P/ Go to TAB "resources" and then at the bottom. Install the software, run a cable to your PC and check if the cam works. (had a few cam's over time that died on the serial port for no reason)

I developed a controller like this about 6 years ago on a basic compiler. If needed i can check my old software. But as Basic isn't C it should be rewritten completly..

zoomkat:
So how do you know this? Did you use a loopback wire on the max232 cam side instead of the cam?

I unplugged the RS232 cable from the cam, and plugged it into my computer. When I send text thru USB serial connection (via Arduino Serial monitor), it shows up correctly on RS232 serial connection (Hyperterminal). Just read about loopback testing-- I'll have to try that, too.

Did you check if you have all the dipswitches on the bottom of the D70 in the OFF position? This would mean they all point to the back side of the camera.

Yes, all dipswitches are off.

I did a bit more reading about RealTerm and realized that the random website that told me to put commas between Hex codes seems to be incorrect. I'll try putting spaces between my hex codes ASAP.

Then to check it and to see how the commando structure works for the D70 you could download the evi d70 demo software from sony.

I tried this, but software only supports COM1 thru COM6. I tried changing the port assigned to the adapter, with no luck, but maybe I'll have another go at that if these other things don't work out...

Thanks for help folks, I'll get back once I try these things...

If the camworks with the computer,then that is a good start. What is the arduino code you are using to communicate between the arduino and cam?

U need RS232 Sniffer;-

DIY RS232 serial spy monitor cable

http://www.lammertbies.nl/comm/cable/RS-232-spy-monitor.html#full

RS232 Sniffer Passive Tap - USB Port

http://www.stratusengineering.com/EZTap.html

all u do is reverse engineering to make Arduino output same as PC.

electronics is art, not science.

SOLVED! Thanks for your help folks...

So I guess you could say I had 3 main problems:

  1. Couldn't operate using Sony Demo software
  2. Couldn't operate using RealTerm
  3. Couldn't properly send hex codes via Arduino software serial Serial library

Here's how I solved them:

1. (Demo software). My problem was that the Keyspan USB>RS232 adapter was on COM10, and the demo software only supported COM1-COM6. According to the manual, it's possible to re-map to another COM port, but I just installed the software on my Windows 7 laptop, and it mapped to COM1. Tested out the software... it works! It also has a nice readout that tells you what hex codes you're sending to the camera
2. (Realterm woes). I read the realTerm info (on the download page) from top to bottom, and realized I was making a couple of mistakes in setting up the ports. I wasn't using the "Change" buttons(so I thought I was making changes to the settings, but I really wasn't), and I was sending commands incorrectly. Sent the address (0x88,0x30,0x01,0xFF), IF_clear (0x88,0x01,0x00,0x01,0xFF), and zoom_tele commands(0x81, 0x01, 0x04, 0x07, 0x02, 0xFF) and the camera responded as expected! The only strange thing was that I didn't get the expected responses from the camera... but that's not important to me for this project, so I'll let it slide. Lesson learned: read the dang manual.
3. (Arduino woes) Using the Arduino Uno and software serial library, I was sending hex codes to realTerm and reading unexpected values. I replaced the Uno with a Mega 2560, used the Serial1 port to send commands to the camera, and it works! Serial0 is used for debugging. Maybe it's not the simplest solution, but it works for me. Also, you'll note that I used the serial write() command rather than print(x,HEX) where x a byte. Maybe only newbies like me make this mistake, but I had a hard time understanding which one I should use. Serial.write() definitely is the way to go.

I've copied my working HelloWorld code below, and I'll post my final code and wiring when the project is done!

Arduino Mega 2560 (IDE 1.0.3) + Sony EVI-D70 hello world code (WORKS):

/*
SUCCESSFUL:
2 BUTTONS- 1 TO ZOOM IN, AND ANOTHER TO ZOOM OUT
 
 */
 
 
  byte address_command[4]= {0x88, 0x30, 0x01, 0xFF};
 byte if_clear[5]= {0x88, 0x01, 0x00, 0x01, 0xFF};
 //ZOOM BYTE ARRAYS
 byte zoom_tele[6]= {0x81, 0x01, 0x04, 0x07, 0x02, 0xFF};   //Not exactly sure how this works yet
 byte zoom_wide[6]= {0x81, 0x01, 0x04, 0x07, 0x03, 0xFF};  //Not exactly sure how this works yet
 byte zoom_teleVar[6]= {0x81, 0x01, 0x04, 0x07, 0x25, 0xFF};  //Zoom In: 81 01 04 07 2x FF , where x is speed- 0(low)-7(hi);
 byte zoom_wideVar[6]= {0x81, 0x01, 0x04, 0x07, 0x35, 0xFF};  //Zoom Out: 81 01 04 07 3x FF , where x is speed- 0(low)-7(hi);
 byte zoom_stop[6]= {0x81, 0x01, 0x04, 0x07, 0x00, 0xFF};  //Stop all zooming
 byte commandCancel[3]= {0x81,0x21,0xFF};
const int delayTime= 250;   //Time between commands

const int button1=2;  //Zoom in
const int button2=3;  //Zoom out
const int ledPin =  13;      // the number of the LED pin



void setup() {
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(ledPin, OUTPUT);
  // initialize both serial ports:
  Serial.begin(9600);
  Serial1.begin(9600);
  
  
 //Send Address command
  for (int i=0; i<4; i++){
    Serial1.write(address_command[i]);
  }
  //delay(delayTime);
  delay(500);  //delay to allow camera time for next command
  
  //Send IF_clear command
  for (int i=0; i<5; i++){
    Serial1.write(if_clear[i]);
    delay(100);  //For USB testing-- NOT FOR ACTUAL CONTROLLER
  }
}





void loop() {
  // read from port 1, send to port 0:
  if (Serial1.available()) {
    int inByte = Serial1.read();
    Serial.write(inByte); 
  }
  
  // read from port 0, send to port 1:
  if (Serial.available()) {
    int inByte = Serial.read();
    Serial1.write(inByte); 
  }
  
    //ZOOM TELE
  int button1State=digitalRead(button1);
  if(button1State==HIGH){
    Serial.print("Button 1 high");
    //digitalWrite(ledPin, HIGH);
    //Cancel previous commands
    //sendCommandCancel();
    delay(delayTime);
    //Send zoom tele command
    for (int i=0; i<6; i++){
      Serial1.write(zoom_teleVar[i]);
      Serial.print(zoom_teleVar[i]);   //for debugging
    }
  }
  
    //ZOOM WIDE
  int button2State=digitalRead(button2);
  if(button2State==HIGH){
    Serial.print("Button 2 high");
    //Cancel prev commands
    //sendCommandCancel();
    delay(delayTime);
    //digitalWrite(ledPin, HIGH);
    for (int i=0; i<6; i++){
      Serial1.write(zoom_wideVar[i]);
      Serial.print(zoom_teleVar[i]);  //for debugging
    }
  }
  
  if(button2State==LOW && button1State==LOW){
    for (int i=0; i<6; i++){
      Serial1.write(zoom_stop[i]);
      Serial.print(zoom_stop[i]);  //for debugging
    }
  }
  
  Serial.println();
}





void sendCommandCancel(){
  for (int i=0; i<3; i++){
    Serial1.write(commandCancel[i]);
  }
}

I'll post my final code and wiring when the project is done!

Please do, I have a few Sony CVD-1000 Hi-8mm “Vdeck” videotape recorders, sit in basement storage. I manage to repair them, and they are in working condition. CVD-1000 is one of first Sony product support VISCA protocol. Your code could bring them back to life.