Teardown and Project: Clone Nikon ML-L3 IR Remote and Emulation

Users of Nikon cameras, including the D3200, have had several choices for remote triggering. The use of a wired remote is traditional, with infrared (IR) remotes being common accessories for many and Wi-Fi just becoming the latest craze.

The Product

The Nikon D3200 is compatible with the Nikon ML-L3 IR remote. A quick look on eBay reveals a large number of clone (compatible, non OEM) remotes available for as little as AU$1.20 posted. That includes the CR2025 battery as well. For that price, you’d be silly to go without one (or two, or three)!

Nikon-Remote-Clone

I’m not sure what the original ML-L3 is made of, but this is very much like the cheap “flat” remotes provided with many TV tuners. It is constructed of a single PCB, using a single CR2025 coin battery. The buttons are made by carbon-coated dome-formed thick self-adhesive plastic sheet which sits over the PCB interlocking finger pattern traces. It’s not particularly glorious or durable with repeated use, but that’s the way things are.

Nikon-Remote-Internals

Tearing it apart reveals an extremely simple construction. The PCB underside is marked with KD301B-A054-002 and FS3423. The plastic mold is marked with KD301B. The PCB utilizes a single IC, capacitor and IR LED. There are no resistors, or even ceramic oscillators (455khz commonly seen on IR remotes, as 455khz/12 = 37.91khz).

Remote IC PRT-P08

There’s no real information I can find on the IC, it’s marked PRT-P08 TX0917. This IC must be able to generate the IR code pattern (including the timing) and limit the current to the LED on the on-phase. I can’t say all clone remotes would use this chip – others may opt for chip-on-board construction.

Tracing the very-simple traces gives me the following schematic:

NikonRemoteSchematic

Simple ain’t it? You could probably alter the circuit board to generate the IR code on other triggers. I don’t know what the unconnected pins are used for – or if they are used at all. Maybe it’s programmable? Maybe there are other modes?

The remote itself fires off the D3200 very reliably, and it’s cheap. I can’t complain of the quality given the price, but I wouldn’t want to rely on having just one in an emergency. Infrared trigger isn’t as “reliable” as wired triggering, since you do need to have a working battery and be within range of the sensor. The sensor has to be activated through the menus, and the camera will time out and sleep the sensor if it’s not been used for a while, so the applications are limited. But it’s nice since it involves no touching the camera (after set-up) and no possibility of conducting any vibrations through trigger cables.

Analyzing the Code

It’s not the first time I’ve worked on emulating infrared remotes. I had posted two videos earlier, which are quite long which does show my previous work (although isn’t easy to follow from the video). I think it’s much more illustrative to write about it instead.

Incidentally, this remote proves to be one of the simplest to emulate.

The first thing you need to do is “record” the signal from the remote. You can do this directly by reading the voltage across the LED (which is most direct, and gives you the raw data including the carrier frequency of the IR system). Another way is to use an IR receiver like the ones used in TV tuners and probe with TTL output (high for presence of 38khz IR carrier, low for absence of 38khz IR carrier).

IR-Receiver

An IR receiver from a TV tuner.

The method with the IR receiver was used in my former emulation attempts, but it’s not ideal as the sensor may not be able to give you data for non-38khz IR systems. Most of them are 38khz, but there are some using other rates.

IR transmission mostly involves the keying on-and-off of a 38khz signal. The use of 38khz allows for the filtering of “steady” IR background and general noise.

It’s important to capture the IR pulse train using an oscilloscope, high rate data-logger or something similar. I used my Poscope basic2. I cannot recommend users to buy this product, as it only supports Windows, triggering has no hold-off options and is hit and miss, there’s no anti-aliasing filter, the software is pretty broken in Recorder mode when recording at high rates, the data is recorded in a format needing conversion by their tools and it is very limited in sampling rate. I have a heap of trouble with it in general under Windows 7, although older versions of software on Windows XP with specific USB controllers can work semi-reliably. But with enough patience, even something this basic like this is sufficient.

Measured Remote Train Overall

The first thing to understand is that IR remotes tend to send the same code over and over when the button is depressed. In this case, the remote actually sends its code three times over – here we can see just one iteration which takes about 100ms, which repeats.

Most of the time is with the IR LED off, the code itself is very simple. Re-acquiring zoomed in (noting polarity is due to the way the connections were made):

Measured Remote Train Detail

We can see the remote starts with a 2ms burst of 38khz, followed by 28ms rest, 0.5ms burst, 1.5ms rest, 0.5ms burst, 3.5ms rest, 0.5ms burst, 63.5ms rest. That is the IR code we need to emulate to make it “work”. Note that slight timing and frequency differences are expected – say different battery levels and component tolerances.

Take it from me, it’s 38khz – I looked closely into it.

Making it Work

The first thing you need to emulate something like this is a suitable IR LED. Instead of buying it off the shelf, I decided to pinch one from a “useless” remote I had from my RTL-SDR purchases. I’m never going to use the remote – so why waste the LED?

Unwanted IR Remote

IR LED MountedHaving extracted the LED, I have to ensure its safety. The voltage drop of my IR LED is about 1v at 1mA, and using a 5v Arduino, I decided to go with two 680 ohm resistors in parallel for an LED current of about 12mA. LEDs like these may be capable of currents up to 20mA, but I decided to play it safe. In fact, it’ll be safe to overdrive it slightly given the low duty cycle of the remote signal.

Of course, as a lazy person, I decided to solder it to some header pins air-wire style, and then cover it with globs of hot glue.

Positive in this case is the pin on the left. I decided to plug it straight into my Arduino Mega 2560 (clone) which I had handy, but you don’t need something this powerful.

IR LED on Arduino

The first thing is to write the code that approximates the timing. You’ll find that you will encounter some possible issues say if you use tone() with duration, so instead, use tone() and noTone() instead.

Here is the code – I tested my code, and it does fire off my D3200.

// Nikon Remote Emulator by Gough Lui (https://goughlui.com)
// A1 = IR +
// A0 = IR -

int count=0;

void setup() {
  pinMode(A0,OUTPUT);
  digitalWrite(A0,LOW);
  pinMode(A1,OUTPUT);
  digitalWrite(A1,LOW);
}

void loop() {
  // Send code three times, as the clone remote does
  // Delays are tuned to account for overhead of library code.
  while(count<3) {
    tone(A1,38000);
    delay(2);
    noTone(A1);
    delay(28);
    tone(A1,38000);
    delayMicroseconds(200);
    noTone(A1);
    delayMicroseconds(1500);
    tone(A1,38000);
    delayMicroseconds(200);
    noTone(A1);
    delayMicroseconds(3300);
    tone(A1,38000);
    delayMicroseconds(200);
    noTone(A1);
    delayMicroseconds(100);    
    delay(63);    
    count++;  
  }
}

Note that the delay timings are not as suggested by the scope capture – this is because there is overhead in the Arduino library functions which take time to execute. Instead, the times are trimmed through trial and error to result in a trace on the scope which closely mirrors the original (although slight timing deviations would be okay). You don’t need to match the original quite 100% as each remote may have slight component differences resulting in offset carrier frequencies and timing. As long as you’re within a few percent, the device should recognize the transmitted code.

Emulated-Pulse-Train

The pulse train, as measured by my crappy PoScope basic2 unit looks pretty damn close to the original remote – so now I’ve got the code to trigger my camera using IR. What to do now? Well, you could make some specialized trigger system algorithmically controlled by the Arduino … it’s really up to your imagination.

Besides, now you know what to do when you want to emulate a remote :).

About lui_gough

I'm a bit of a nut for electronics, computing, photography, radio, satellite and other technical hobbies. Click for more about me!
This entry was posted in Electronics, Photography and tagged , , , , . Bookmark the permalink.

9 Responses to Teardown and Project: Clone Nikon ML-L3 IR Remote and Emulation

  1. Does your project uses 2x 680 ohm resistor

    • lui_gough says:

      Yes, as stated in the article, I used 2×680 ohm resistors in parallel, mainly because that’s what I had available on hand. Check with your IR diode as to what the forward voltage and current requirements are and make the appropriate calculations if necessary. If you do so, you may be able to optimize the range of the transmission.

      – Gough

  2. Tim says:

    I have a camera gimbal with built in canon IR trigger designed for canon 5d. I would like to use this signal to trigger my Nikon d3300…. Is it possible?

  3. Marco says:

    Hello,
    Is it possible to short the two pins of the button using a transistor instead of mechanical contact?

    Thank you in advance

  4. Hey,

    I just want to inform, that I have done similar Nikon Remote Control about 10 years then
    http://remotesmart.wikidot.com/nikon-ir-remote-control

    It has PIC12F675 CPU and source code also.

    – OH3GDO

  5. tux says:

    It works, thank you!
    I use a D3000. I salvaged a LED from an old TV remote, connected with a 220ohm resistor to the Arduino.

  6. Peter Kaiser says:

    Hi, nice project! But why using A1 and A2 and not one digital Port and Ground?
    Regards
    Peter

    • lui_gough says:

      Dear Peter,

      You can use any digital pin and ground – conventionally, that is how it is often done.

      However, my choice of A0 and A1 is really arbitrary – it actually stems from a legacy of a previous IR remote emulator I made where I decided to put an IR LED + resistor onto a pair of header pins. This way, the +ve and -ve connections have to be next to one another. In that previous project, I chose A0 and A1 because it was “facing the right way” towards my satellite TV box with the USB cable powering the Arduino in a convenient location and since then, I haven’t been bothered to change it.

      Using analog pins for digital GPIO is perfectly fine assuming you don’t need them for anything else, although such a method of powering a peripheral really only works if it requires a small amount of current (<20mA in the case of the AVR) otherwise the voltages could be quite a bit lower than expected or the GPIO pin could become damaged.

      - Gough

Error: Comment is Missing!