Thursday, February 3, 2011

Arduino controlled video recording using the LANC port

LANC is a SONY development and stands for "Local Application Control Bus". It is a two-way serial open collector 9600 baud protocol with inverted logic. The LANC line is pulled high to about +5v and is pulled low to send commands or status information.


The data stream is 8 bytes, followed by a longer than 5 millisecond pause until the end of the current frame. Then come another 8 bytes for the next frame and another pause and so on.
There's a short pause between individual bytes. Each byte is preceded by a start bit.

LANC is a single wire serial connection and because of this timing is critical. The camera can only listen to commands for the first half of the signal pattern.
The camera listens to the first 4 bytes and sends status information in the last 4 bytes. Only the first two bytes are needed to control a video camera. The rest can be ignored.

To send a command to the camera the command has to be synchronized to the LANC signal from the camera. The camera puts out a start bit before and a stop bit after each byte. The first command byte from the controller (Arduino) has to be transmitted exactly between the start bit that follows the long pause between the 8 byte data packages and the following short stop bit. Then the second byte must be send to the camera. After sending those two bytes the LANC signal must be be left alone and put back to LOW i.e +5V.


The commands for starting and stopping video recording are 18 and 33 in hexadecimal format or 00011000 and 00110011 in binary format. The bytes must be put out with the least significant, right-most bit (bit 0) first i.e. 00110011 is put out 11001100. Note that in a LANC signal LOW is +5V and HIGH is 0V. LANC commands must be repeated 4 times in order to be accepted by the camera.



Since we have to read from and write to a single wire an interface is required. Thanks to Ariel Rocholls simple interface circuit writing and reading can be done independently. D1 is a 5.1V zener diode.


Arduino sketch:
Copy and paste it into the Arduino editor for a better reading experience.

/*
Send a Start/Sop Recording command to the LANC port of a video camera.
Tested with a Canon XF300 camcorder
This code requires a simple interface see http://micro.arocholl.com
Feel free to use this code in any way you want.

Comprehensive LANC info: www.boehmel.de/lanc.htm

"LANC" is a registered trademark of SONY.
CANON calls their LANC compatible port "REMOTE".

2011, Martin Koch
http://controlyourcamera.blogspot.com/2011/02/arduino-controlled-video-recording-over.html
*/

#define cmdPin 7 
#define lancPin 11
#define recButton 2
int cmdRepeatCount;
int bitDuration = 104; //Duration of one LANC bit in microseconds. 

void setup() {

pinMode(lancPin, INPUT); //listens to the LANC line
pinMode(cmdPin, OUTPUT); //writes to the LANC line
pinMode(recButton, INPUT); //start-stop recording button
digitalWrite(recButton, HIGH); //turn on an internal pull up resistor
digitalWrite(cmdPin, LOW); //set LANC line to +5V
delay(5000); //Wait for camera to power up completly
bitDuration = bitDuration - 8; //Writing to the digital port takes about 8 microseconds so only 96 microseconds are left till the end of each bit
}

void loop() {
if (!digitalRead(recButton)) {
REC(); //send REC command to camera
delay(1000); //debounce button
}
}



void REC() {

cmdRepeatCount = 0;

while (cmdRepeatCount < 5) {  //repeat 5 times to make sure the camera accepts the command

                while (pulseIn(lancPin, HIGH) < 5000) {   
                  //"pulseIn, HIGH" catches any 0V TO +5V TRANSITION and waits until the LANC line goes back to 0V 
                  //"pulseIn" also returns the pulse duration so we can check if the previous +5V duration was long enough (>5ms) to be the pause before a new 8 byte data packet
//Loop till pulse duration is >5ms
}

//LOW after long pause means the START bit of Byte 0 is here
delayMicroseconds(bitDuration);  //wait START bit duration

//Write the 8 bits of byte 0 
//"18hex" or “00011000”  tells the camera that there will be a normal command to camera in the next byte
//Note that the command bits have to be put out in reverse order with the least significant, right-most bit (bit 0) first
digitalWrite(cmdPin, LOW);  //Write bit 0. 
delayMicroseconds(bitDuration); 
digitalWrite(cmdPin, LOW);  //Write bit 1 
delayMicroseconds(bitDuration);  
digitalWrite(cmdPin, LOW);  //Write bit 2
delayMicroseconds(bitDuration); 
digitalWrite(cmdPin, HIGH);  //Write bit 3
delayMicroseconds(bitDuration);  
digitalWrite(cmdPin, HIGH);  //Write bit 4
delayMicroseconds(bitDuration);
digitalWrite(cmdPin, LOW);  //Write bit 5 
delayMicroseconds(bitDuration);
digitalWrite(cmdPin, LOW);  //Write bit 6
delayMicroseconds(bitDuration); 
digitalWrite(cmdPin, LOW);  //Write bit 7
delayMicroseconds(bitDuration);
//Byte 0 is written now put LANC line back to +5V
digitalWrite(cmdPin, LOW);
delayMicroseconds(10); //make sure to be in the stop bit before byte 1

while (digitalRead(lancPin)) { 
//Loop as long as the LANC line is +5V during the stop bit
}

//0V after the previous stop bit means the START bit of Byte 1 is here
delayMicroseconds(bitDuration);  //wait START bit duration

//Write the 8 bits of Byte 1
//"33hex" or “00110011” sends the  Record Start/Stop command
//Note that the command bits have to be put out in reverse order with the least significant, right-most bit (bit 0) first
digitalWrite(cmdPin, HIGH);  //Write bit 0 
delayMicroseconds(bitDuration);
digitalWrite(cmdPin, HIGH);  //Write bit 1 
delayMicroseconds(bitDuration); 
digitalWrite(cmdPin, LOW);  //Write bit 2
delayMicroseconds(bitDuration); 
digitalWrite(cmdPin, LOW);  //Write bit 3
delayMicroseconds(bitDuration);
digitalWrite(cmdPin, HIGH);  //Write bit 4 
delayMicroseconds(bitDuration); 
digitalWrite(cmdPin, HIGH);  //Write bit 5
delayMicroseconds(bitDuration);
digitalWrite(cmdPin, LOW);  //Write bit 6
delayMicroseconds(bitDuration);
digitalWrite(cmdPin, LOW);  //Write bit 7
delayMicroseconds(bitDuration);
//Byte 1 is written now put LANC line back to +5V
digitalWrite(cmdPin, LOW); 

cmdRepeatCount++;  //increase repeat count by 1

/*Control bytes 0 and 1 are written, now don’t care what happens in Bytes 2 to 7
and just wait for the next start bit after a long pause to send the first two command bytes again.*/


}//While cmdRepeatCount < 5
}

I've tested the Arduino sketch with a Canon XF300 camcorder and I suppose that the timing will work with the entire XF family. Other cameras may require experimenting with different "delayMicroseconds" values.
The prototype LANC interface is built onto a shield board that sits on top of the Arduino. The Arduino is powered by the LANC port. Although the XF300 puts out only +5V the Arduino worked without problems. During development I had the USB cable connected to the camera at the same time as the Interface was connected to the camera. I suppose since the Arduino chooses automatically to use either the external or the +5V USB power supply this should be safe.
Always turn the camera off before plugging or unplugging the LANC cable!
"LANC" is a registered trademark of SONY. CANON calls their LANC compatible port "REMOTE". Comprehensive LANC info can be found at boehmel.de/lanc.htm

31 comments:

  1. I am shooting the last space shuttle landing and need to control a Sony CX700 or 560. The Arduino will have a RTC so I can use it to turn on power to camera and start/stop recording. the cameras will be put out a day ahead and will be autonomous until we can reach them again sometime after the landing. I am not a coder, how would I accomplish this. Also about the power, can I not connect the power from the camera to VIN, leave everything as is?

    Thanks

    ReplyDelete
  2. Robert, I'm sorry but I have no experience with Sony cameras. For such an important historical event I suggest you better find someone to help you in person and make it foolproof.

    ReplyDelete
  3. Isn't LANC supposed to be a standard more or less? I have been trying to find someone to help for months ad your blog is one of the few resources. I do have a person helping with some coding and he is great but doesn't have any LANC experience.

    ReplyDelete
  4. OK,if your camera has a LANC input and not the other SONY protocol (http://www.boehmel.de/slink.htm) then the solution above should work. A contact from the RTC (I suppose this means real time clock) will have to power camera and Arduino which after a delay will start recording over LANC.

    The best option would be putting the camera into sleep mode and waking it up over the LANC line. I don't know if your camera has this but if yes you need a SONY LANC controller to find the command using this method: http://controlyourcamera.blogspot.com/2011/02/finding-out-lanc-remote-commands.html or maybe you find the command at http://www.boehmel.de/lanc.htm

    Of course you can power the Arduino from the camcorder battery instead from the LANC line.

    Good luck!

    ReplyDelete
  5. Hello,

    I have built the prototype and uploaded the code to my Arduino. When I plug into the camera, it just keeps turning the camera on and off over and over again. Can anyone help?

    Thanks

    ReplyDelete
    Replies
    1. hello, thanks for the info in your blog.
      the best i found in web.
      it explains clear the info put in http://www.boehmel.de/lanc.htm
      i want to implement the rest of the codes like white balance or focus.
      have you try this?

      thanks again

      julian

      Delete
    2. Thanks. No I haven't. It's a lot of trial and error. Good luck!

      Delete
  6. Hi,

    I am looking for the LANC commands to turn the camera on and off. I have a HXR-MC1.

    Thanks for the great blog.

    ReplyDelete
  7. Sorry, I can't help. You can try to find the command yourself using this:
    http://controlyourcamera.blogspot.com/2011/02/finding-out-lanc-remote-commands.html Good luck.

    ReplyDelete
  8. I have made it work with the Vixia HF S20

    ReplyDelete
  9. Did you have any luck finding the special commands of the ZR-2000?

    ReplyDelete
  10. Any Similar sites out there to access the Panasonic Focus/Iris and Zoom/StartStop remote ports?

    ReplyDelete
  11. Martin this blog has been an amazing resource. But now I'm trying to work out using a Lanc Controller to send commands and control devices trough my an Arduino.

    Any thoughts on how I would make the Arduino emulate a video camera? When I do the sniffing on the controller to the camera. I can see the camera sending a constant 00000000 00000000 to the controller setting the sync.

    But when I try to build a sequence for of code in the void loop function acting like the camera, then listening for a response from the controller. I can't seem to get any thing back. I don't know if it's my timing or the circuity.

    I'm using the "Simple Start Stop" circuit layout shown above. But I have pulled out the start stop button.

    Thanks for your thoughts and Help!

    ReplyDelete
    Replies
    1. Daniel I'm afraid that I don't understand what you are trying to do.

      Delete
  12. I can confirm that this code works with the Canon C300.

    Cheers and thanks for the well written article.

    ReplyDelete
  13. The zener diode is to protect the Arduino from voltages higher than 5.1 Volts. Am I right?

    ReplyDelete
    Replies
    1. Correct. For a confirmation just follow the link to Ariel Rocholls page from where I got the circuit.

      Delete
  14. I'm reverse engineering the LANC command codes of the Blackmagic Pocket Cinema Camera.
    http://marcuswolschon.blogspot.de/2013/11/bmpcc-lanc-and-sysclk-dx-usbee-dx-clone.html

    I have already found 3 codes not mentioned anywhere else for iris+, iris- and autofocus.
    I know there is a command for auto-iris but I haven't found it yet.

    ReplyDelete
  15. ..oh and you can get rid of your -8ms adjustment by using the fastWrite macro I found. It makes the remote work much more reliable.
    ..and clean up your bit-banging while at it with the send_8() method I posted. (Link in the comment above.)

    ReplyDelete
  16. Hi Marcus, it's great to see your work on the BMPCC. Thanks for the tips. Why is it that camera manufacturers make such a secret about their LANC implementation. I had no luck with Canons support they said somthing like licensed work from Sony and that they can't give me any details. Well we find the codes nevertheless. Good luck!

    ReplyDelete
  17. For "normal" LANC signals I had success using this: http://controlyourcamera.blogspot.co.at/2011/02/finding-out-lanc-remote-commands.html

    ReplyDelete
  18. Hello, thank you for sharing your blog.

    Now, I'm looking for the information of startbit and bit-banging. In the Arduino codes above, I can not find/understand the startbit that you write, for example by Byte0, after ''while (pulseIn(lancPin, HIGH) < 5000 '' comes a ''delayMicroseconds(bitDuration)'' where is the startbit? is this ''delayMicroseconds(bitDuration)'' means startbit?

    When we connect the camera and the arduino like the circuit above, whether the camera send any signal to LANC line (Automatic)?

    Do you have any idea or data about this,the information from http://www.boehmel.de/lanc.htm is not comprehensive.
    and my E-mail is : pcw007pcw@hotmail.com
    Thank you

    ReplyDelete
  19. Hi, if you read the description above carefully again you will see that the start bit happens after the LANC line goes low after a long delay. So after waiting delayMicroseconds(bitDuration) - the start bit duration - you can write the two REC command bytes.

    The camera always and automatically sends the 8 byte pattern over the LANC line. After pushing the push switch the code above detects the "long" delay between the patterns, waits 1 start bit and then sends the REC command before the next status bytes come. I hope it is clearer now.

    ReplyDelete
  20. I asked Black Magic about their LANC codes, this is the reply from product manager:

    Please see the following LANC commands supported on our cameras:

    Name bytes[1:0]
    ---------------------------------
    Nop = 0x0000,
    RecordStart = 0x3318,
    RecordStop = 0x198C,
    IrisIncrement = 0x5528, // Used for IDLE state
    IrisDecrement = 0x5328, // Used for IDLE state
    IrisRecIncrement = 0x2A94, // Used for RECORD state
    IrisRecDecrement = 0x2994, // Used for RECORD state
    IrisAutoAdjust = 0xAF28,
    FocusShuttleFar = 0xE028, // Used for IDLE state (value mask 0x0F00: 1 3 5 7 9 B D F)
    FocusShuttleNear = 0xF028, // Used for IDLE state (value mask 0x0F00: 1 3 5 7 9 B D F)
    FocusShuttleRecFar = 0x7094, // Used for RECORD state (value mask 0x0700: 0 1 2 3 4 5 6 7)
    FocusShuttleRecNear = 0x7894, // Used for RECORD state (value mask 0x0700: 0 1 2 3 4 5 6 7)
    FocusFar = 0x4528, // Used for IDLE state
    FocusNear = 0x4728, // Used for IDLE state
    FocusRecFar = 0x2394, // Used for RECORD state
    FocusRecNear = 0x2294, // Used for RECORD state

    ReplyDelete
    Replies
    1. Hi Volker,
      that's very nice from you and also Blackmagic Design. Thanks for posting this.

      Delete
    2. Ive found that on the Blackmagic Camera it seems that when the chord is plugged in it does not send out 5v. When using the Arduino not plugged into USB its only sending out 0.81-0.82 v of power. Once the Arduino is on, however, it does send at least 4.5v which is lower powered, but enough to power the Arduino and start the program loop.

      Is there an initial starter pulse or power that is needed in order to start up the LANC power or does it just draw that much. Thanks!

      Delete
    3. i think you did something wrong. my BMPCC outputs 5v and powers the arduino (nano) fine.

      Delete
  21. Great contribution Volker,
    I need to find out if there is a code to control the zoom for powered zoom lens in black magic pocket camera.

    ReplyDelete
  22. If you find yourself running out of power with the Arduino you might consider the Propeller -- very powerful (with eight 32-bit cores), and easier to program than most know. I recently wrote a LANC object for a friend's multi-camera controller; it just showed well at NAB and has some government agencies interested.

    With the Power of the Propeller I'm able to send commands as well as read the rest of the stream back -- all in its own processor so the mainline code is not affected. On Saturday I was able to extract timecode data from the stream, something I wanted to do as soon as I started on LANC.

    There's thread you may find interesting in the Parallax Propeller forum

    http://forums.parallax.com/showthread.php/148752-LANC-control/page2

    ReplyDelete