Lens protocol ~(decode)~ & command through Serial

Hi folks,

Im working with a fujinon LENS(HR10G-10R-10S (HIROSE)) and trying to control it from ATmega uC ,it works with serial communication as follows:

Serial data format Communications standard: RS-232C
Bit rate: 38.4 kbps
Parity check: None
Stop bit: 1 bit

and to make it work(so that the lens starts taking commands) one needs to always make the DSR pin of the lens on so I connected it to steady +5v supply from arduino so it shouldn't be a problem

Connecting the other parts as follows:

HR10G-10R-10S Pin Designation

OPEN -- NOT Connected
RxD (RD) -- connected to Arduino Mega's Serial1 Tx
TxD (SD) -- connected to Arduino Mega's Serial1 Rx
DTR (ER) -- NOT Connected
GND (SG) -- Common
DSR (DR) -- Given +5v
RTS (RS) -- NOT Connected
CTS (CS) -- NOT Connected
OPEN -- NOT Connected
OPEN -- NOT Connected

I contacted the LENS Fujinon officials and they told me that this configuration is okay so no problem should be there.

ATTACHED is the protocol structure ON THE BASIS OF WHICH I HAVE WRITTEN THE CODE:

So I wrote the following programme to make the IRIS position control on the basis of example attached protocol structure with the PROTOCOL as follows:

void setup() {

  Serial1.begin(38400);
}

void loop() {

  Serial1.write(0x02);
  Serial1.write(0x20);
  Serial1.write(0x80);
  Serial1.write(0x80);
  delay(1);
  Serial1.write(0xDE);
  delay(20);
}

BUT nothing seems to be happening, can you folks get me on the correct track?

can you folks get me on the correct track?

I can't, but, I'm wondering why you have a delay(1) between the 4th and 5th serial byte, but not between the others?

I can't

If PaulS can't then its time to worry ,now who will solve this!

Nevermind!, the delay(1) is for 1 millisecond of delay as needed by the protocol if you will see the attachment in my first post named as protocol_structure ,ITS AN IMAGE just click on it to make it large

ITS AN IMAGE just click on it to make it large

I did. It shows the same time period between all bytes, not just the 4th and 4th.

Between data l and sum it shows a delay for 1ms or less

NI$HANT:
Between data l and sum it shows a delay for 1ms or less

It is showing that the gap width indicated is 1ms or less, and is the same for all gaps of that width. The 'or less' part would suggest that a delay() shouldn't be needed, and a delay of more than 1ms is to be avoided.

It is showing that the gap width indicated is 1ms or less, and is the same for all gaps of that width. The 'or less' part would suggest that a delay() shouldn't be needed, and a delay of more than 1ms is to be avoided.

So I guess I can go with the delays but they have to be maximum 1ms ,and its ok? am i right?

any other problem in-spite of this you may point out?

So I guess I can go with the delays but they have to be maximum 1ms ,and its ok? am i right?

Possibly, provided there is no overhead between the end of the delay, and the next byte being sent.

Is it necessary to keep sending the same sequence to the lens?

Is it necessary to keep sending the same sequence to the lens?

No, There is no need to repeat it as such for functioning but one just has to take care that any command is again sent after altleast 10ms or more time after the previous command is sent so this wait is necessary.

The Attached PDF document is the key which is to be used to talk to the system I READ it but may be IM getting it wrong, Starting from the page number 5 they have listed the way to talk to the LENS I have made the hardware connection correct as the Fujinon officials also suggested me the same with rx and tx and gnd with DTR on the LENS cable connected to arduino +5v so that the LENS just goes on receiving code.

RS232 communication digipower protocol for DIGI POWER.pdf (310 KB)

Serial data format Communications standard: RS-232C
Bit rate: 38.4 kbps
Parity check: None
Stop bit: 1 bit

You state it's RS232 but you feed it with just TTL levels. Some RS232 device may work with that but most don't. Use a MAX232 (or something similar) to feed the correct RS232 levels.

Hey. Im just adding in some tips in case any one else stumbles upon this (as I just did).
About a year ago i made arduino code for connecting to Canon lenses (that worked), and Fuji lenses, that i never got to test.

When looking at my code, i see that i first connect to the lens, checking response code, then asking for lens data if connection was successful. It looks to me like you skipped straight to the "asking for data" part.

Other than that. Adding a 1ms delay when spec is saying MAX 1ms sounds bad. The 1ms delay of an arduino can easily be a bit longer than 1ms, so i would play it safe and use delay_us(500) instead.

Here is my UNTESTED code:

// UDP STUFF
#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet2.h>
#include <EthernetUdp2.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008
EthernetUDP Udp;
IPAddress remote_ip(10, 0, 10, 10);
unsigned int localPort = 4444;


//END UDP STUFF

//#include <SoftwareSerial_rs422.h>
#include <SoftwareSerial.h>
#include "stdio.h"
#define ERROR_RETURN_NUM -1

//ip and port stuff
#define CAMERA_NUM 10
unsigned int remote_port = 4444+CAMERA_NUM;
IPAddress local_ip(10, 0, 10, 240+CAMERA_NUM);
byte mac[] = {0x90, 0xA2, 0xDA, 0x10, 0xE5, 0xD0+CAMERA_NUM}; //this is on a sticker on the backside

//config
enum message_types {CANON,CMOTION,FUJI,MOSYS};
#define UDP_MESSAGE_TYPE CMOTION
#define START_STATE HANDSHAKE
#define UDP_ENABLED 0
#define ENABLE_DEBUG_PRINT 1
#define INPUT_BUF_LEN 128
#define OUTPUT_BUF_LEN 64
#define experimental_rx_wait 1
#define experimental_rx_wait_us 100
#define LOOP_DELAY 5 //5ms delay gives ~120 hz
#define RETRY_COUNT_MAX 10
#define RETRY_DELAY_MS 100
#define PATIENCE 4
enum tx_methods {MOXA,UDP};
#define TX_METHOD UDP
#define TX_FREQUENCY 120
#define TX_INTERVAL_US (1000000/TX_FREQUENCY)




//printing
#if ENABLE_DEBUG_PRINT
#define PRINTLN(a) (Serial.println(a))
#define PRINT(a) (Serial.print(a))
#else
#define PRINTLN(a)
#define PRINT(a)
#endif


//#include <SoftwareSerial.h>
int PIN_TX = A0;
int PIN_RX = A1;
SoftwareSerial fuji_port(PIN_RX, PIN_TX, false); // RX, TX
enum states {BOOT,HANDSHAKE,LENS_NAME,COMPLETE_INIT,BAUD_CHANGE,OPERATIONAL};
int state = START_STATE;
unsigned long prev_tx_time = 0; 

int focus_position = 0;
int zoom_position = 0;
int extender_value = 0;
int iris_position = 0;

uint8_t input_buf[INPUT_BUF_LEN];
char output_buf[OUTPUT_BUF_LEN];
void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  PRINTLN("Goodnight moon!");
  PRINT("TX INTERVAL_US: ");PRINTLN(TX_INTERVAL_US);
  // set the data rate for the SoftwareSerial port
  fuji_port.begin(38400);
  state = START_STATE;
  udp_setup();


  //TODO SET DSR PIN
  
  main_loop();
}

void loop() { // run over and over
  
  //request_lens_data();
  //lens_read_response();
  //delay(loop_delay);
}
uint8_t zero = 0;


void main_loop(){
  uint8_t connect_request[3] = {0x00,0x01,0xFF};
  uint8_t connect_request_response[3] = {0x00,0x01,0xFF};
  uint8_t reset_request[4] = {0x01,0x01,0x00,0xFE};
  uint8_t reset_request_response[4] = {0x01,0x01,0x00,0xFE};
  //uint8_t lens_name_request[7] = {0xBE,0x80,0x81,zero,zero,zero,0xBF};
  //uint8_t complete_init[6] = {0x86,0xC0,zero,zero,zero,0xBF};
  uint8_t lens_focus_request[3] = {0x00,0x32,0xCE};
  uint8_t lens_zoom_request[3] = {0x00,0x31,0xCF};
  uint8_t lens_iris_request[3] = {0x00,0x30,0xD0};
  //uint8_t lens_extender_request[3] = {0x94,0xC0,0xBF};
  //uint8_t lens_baud_request[3] = {0x9F,0xC1,0xBF};
  int retry_count = RETRY_COUNT_MAX;
  
  while(1){
    retry_count = RETRY_COUNT_MAX;
    while (state == HANDSHAKE){
      PRINTLN("Doing handshake");
      lens_send_cmd(connect_request,3);

      //TODO sjekk om den sender reset command eller ikke
      if (lens_confirm_response(connect_request_response, 3)){
        state = OPERATIONAL;
        retry_count = RETRY_COUNT_MAX;
      }
      delay(RETRY_DELAY_MS);
    }
    while(state == OPERATIONAL){
      while (micros()-prev_tx_time <TX_INTERVAL_US){
        //wait
      }
      
      lens_send_cmd(lens_focus_request,3);
      focus_position = lens_read_response();
      
      lens_send_cmd(lens_zoom_request,3);
      zoom_position = lens_read_response();
      
      lens_send_cmd(lens_iris_request,3);
      iris_position = lens_read_response();
      //PRINT("iris_position: ");PRINT(iris_position);
      //TODO check response
      bool extraction_success = true;
      if ((focus_position + zoom_position + iris_position) == (3*ERROR_RETURN_NUM)){
        state = HANDSHAKE;
        retry_count = RETRY_COUNT_MAX;
        PRINTLN("Response invalid, Going to handshake");
        break;
      }
      create_and_send_packet();
      prev_tx_time = micros();
      //delay(LOOP_DELAY);
      
    }
  }
}
bool print_rx(){
  while(!fuji_port.available()){
    //wait
  }
  while (fuji_port.available()) {
    //PRINT(fuji_port.read(),HEX);
    delay(experimental_rx_wait); //to catch all bytes and not quit too early. Can wait for oxBF as well
  }
  PRINTLN("");
  return true;
}

int lens_read_response(){
  uint8_t counter = 0;
  memset(input_buf,0,INPUT_BUF_LEN);
  uint8_t tempy,tempy2;
  uint8_t msg_len,msg_type,msg_checksum;
  int return_value = 0;
  //wait for data
  int patience_counter = PATIENCE;
  while (!fuji_port.available() && (patience_counter-- > 0)){
    //PRINTLN("Waiting for data");
    delay(1);
  }
  while (fuji_port.available()) {
    input_buf[counter] = (uint8_t)fuji_port.read();
    counter++;
    if (counter >=INPUT_BUF_LEN) break;
    delayMicroseconds(experimental_rx_wait_us); //to catch all bytes and not quit too early. Can wait for oxBF as well
  }
  //PRINTLN(counter);
  if (counter >=4){
    msg_len = input_buf[0];
    msg_type = input_buf[1];
    uint8_t checksum_index = msg_len+2;
    if (checksum_index <=counter){
      msg_checksum = input_buf[checksum_index];
    }
    if (msg_len !=2){
      PRINTLN("UNSUPPORTED MESSAGE LENGTH");
      return ERROR_RETURN_NUM;
    }
    if ((msg_type > 0x32) || (msg_type <0x30)){
      PRINTLN("UNSUPPORTED MESSAGE TYPE");
      return ERROR_RETURN_NUM;
    }
    tempy = input_buf[2];
    return_value = tempy <<8;
    tempy2 = input_buf[3];
    return_value += tempy2;
    return return_value;
  }
  else {
    PRINTLN("ERROR IN RECEIVING FROM CAMERA");
    return ERROR_RETURN_NUM;
  }
}

AndersStrand:
About a year ago i made arduino code for connecting to Canon lenses (that worked), and Fuji lenses, that i never got to test.

Hi Anders,

Is it the same code that is supposed to work with both brands CANON and FUJINON ?

Can you also explain the role of :
{CANON,CMOTION,FUJI,MOSYS};
I can find in the code
I know CMOTION and MOSYS are 2 brands whose equipment able to control CANON and FUJINON lenses. Does it mean the program may/must be used with CMOTION or MOSYS equipment ?

Thank you for your help

Hi. The different brands have different protocols, so no they wont work with the same code. This code might work with Fuji lenses.

The enum {CANON,CMOTION,FUJI,MOSYS}; seems to only affect the udp output portion of the code, not the serial input portion. (I used an ethernet shield to forward tracking data over UDP).

I noticed a include of softwareserial_rs422, which is a library hosted on my github here: GitHub - anderss90/softwareSerial_RS422: An rs422 version of the Arduino softwareSerial library.