Computing stuff tied to the physical world

IR trigger for Nikon camera

In AVR, Hardware, Software on Jun 12, 2010 at 00:01

Here’s a fun project: sending out infrared remote codes to takes snapshots :)

This is the code:

Screen Shot 2010 06 10 at 17.19.44

This sketch is doing everything in software, and it’s sort of pushing the limits by pulsing a TSKS5400S IR emitter LED at 38.4 KHz using software delay loops.

The timing diagram on this website was a great help to get this working in no time. Here’s another site.

With the 33 Ω resistor in series, total current through the IR LED should be somewhere between 20 and 50 mA. Since the latter is beyond the ATmega’s current sourcing capapbility, I suspect that the pin voltage will actually drop quite a bit below VCC. A transistor or MOSFET could be added for more power. As it is, this seems to trigger reliably up to about a meter away.

Here’s the setup, triggering my trusty D40 Nikon:

Dsc 1692

a self-portrait!

Lot’s of people have already done this ages ago, btw. Here’s a sketch which uses assembler to get the timing more accurate. But the above does work – the main point is to avoid digitalWrite(), which is relatively slow.

  1. Electronic camera and flash triggers are fun. Hook up a piezo transducer (zener across it to protect the ATmega port) and use that to trigger the camera. Place the piezo under a sheet of glass, put the camera on manual focus and prefocus to your target spot… Now drop an egg onto it… If your camera reacts fast enough you have instant action shot. You can do the same with a glass of water, once everything has settled the piezo will pick up the shock of a drip hitting the surface of the liquid in the glass.

    If your camera isn’t fast enough you can either swap the piezo for a light beam which the egg/drip cuts en route (adjust the delay in the ATmega software) or put the camera, egg, et al in complete darkness, open the shutter in bulb mode, and use the ATmega to trigger the flash via a flash PC cable instead… (Best deploy an optotriac isolator for this, some old flashes have several hundred volts across their trigger connections).

  2. I cannot comment on the old post about IO speed but: 1. SBIC and SBIS instructions read the port, extract the bit and skip the next instruction based on the value (1 or 2/3 cycles depending on the result and next instruction length). 2. SBI and CBI instructions that unconditionally clear the given (constant) bit in the IO port (2 cycles). 3. GCC optimizes the PORT &= ~(1<<7) and other voodoo into this instructions then possible. 4. Beware however because many registers in bigger AVRs are not in the IO space but are only mapped to RAM (and require an LDS for RAM to register read (2 cycles), SBR for setting a bit in register (1 cycle) and STS for register to RAM store (2 cycles); the LDS and STS each take 2 words (4 bytes) of flash)).

    I was inspired several years ago by the Arduino digitalWrite (and the ability to change all the pin assignments in one place it offers) but the code was terrifyingly inefficient (especially to someone who started AVR programming in assembly). What I came up with after many iterations was to make the calls inline and let the compiler optimize everything (including the selection of register addresses) based on one integer. It works beautifully and we use it in every product we are doing now.

    Unfortunately I did not release the code but I have available a similar thing [1] for the NXP LPC17xx Cortex M3 processors. I would love to make a version for AVR if someone could volunteer to help with the multitude of the processor versions and maintenance.

    [1] This is for an ARM but I hope the idea is clear:

  3. Why wouldn’t you use the hardware PWM for producing the carrier? and then use software to modulate it?

    • I wanted to see how far this software-only approach could go. But you’re right – there are 3 PWM’s on the port headers (DIO2, DIO3, and IRQ), so one of those could be used.

      The reason I also wanted to try out software PWM is that the next project (upcoming posts) needs 1..8 PWMs (2 of 6 are unavailable, used for SPI/RFM12B). Lower speed, so there s/w PWM is much more practical.

  4. jcw: The code is almost the same as what I wrote (although I prefer inline functions to macros). However there is no mention of DDR setting or digitalRead and the whole thing seems to be written by hand (mine is generated).

Comments are closed.