Category Archives: Hacks

Shutter emulation EOS1100D, part 2

Plan of approach

If you plan to do this mod yourself, please read the postscript first!

This post describes how to replace the shutter by the microcontroller that will emulate the signals. Any micro can be used; the only requirement is enough GPIOs for the 5 signals and trigger, and sufficient effective speed to handle sequential timings up to about +- 100us resolution. I like ARM, so I go with a STM32F042 I had lying around. If you prefer Arduino, go ahead. It will work, too.

One additional requirement for me is to be able to fit all the parts back in the camera body, leaving it outwardly intact. Because of these, the STM32F042 works nicely. It is a large package to hand-solder, yet small enough to fit inside the EOS1100D body. The body has plenty of free space inside, so that’s no problem.

eos1100d_shutter_mcu1

Figure1: the STM32F042 on the operation table. Some wires are already soldered on, and fixated with some glue.

Except for signal P1, the remainders are simple limit switches that are mechanically connected to GND. P1 is the output of a phototransistor, and typically this is also pulled to ground. All signals are pulled-up by the camera PCB. This was explicitly confirmed by measuring signal levels without the flatcable being connected. This means we can hook up to the signals by just using a N-MOSFET with the source connected to GND, and we don’t need to care about any bias resistors.

Figure 2: Schematic of the microcontroller interface based on the STM32F042 ports. The comparator is necessary to convert the trigger level to CMOS/TTL levels. Alternatively, the signal can be pulled off the “6B” chip as indicated in part1 of the post, but then consequently, the “mod” is not flatcable-only.

Finally, to activate (active-LOW) a signal, one needs to drive PA[3:7] high. This way, the interface is complete, once the timings are taken care of.

Implementation

I decided to hand-solder a small PCB that would fit inside the EOS1100D body. First, all the necessary wires were soldered to the MCU, see the table for reference. When this was done, I selected some small strip PCB unused from another project, and layed out the FETs to minimize the wiring (i.e. dead-bug style source pins tied together). The FETs, MCU were fixed to the PCB with a drop of super glue. Next, two “bars” were placed, one for GND and one for VDD (+3.3V). This makes it easier to solder many wires to the GND/VDD without risking dislodging the previously soldered wires. The wire is thin coil wire, the ends burned away with the soldering iron to expose the bare copper.

PinFunctionInput/OutputSpecialFunction AfterRemarks
7NRSTInput/OutputSWD resetOnly for programming
8VSSAPowerGNDUsed for Reset+RCC subsystem
9VDDAPower3.3VUsed for Reset+RCC subsystem
13PA3Outputpush-pullFC-P1
14PA4Outputpush-pullFC-P9
15PA5Outputpush-pullFC-P10
16PA6Outputpush-pullFC-P8
17PA7Outputpush-pullFC-P12
18PB0Inputpull-downFC-P5
20PB2Inputpull-down, 5V tolerant I/OFC-P7
23VSSPowerGND
24VDDPower3.3V
34PA13Input/OutputSWDIOOnly for programming
35VSSPowerGND
36VDDIO2Power3.3V
37PA15Input/OutputSWCLKOnly for programming
44BOOT0InputPulled to GND for flash boot
47VSSPowerGND
48VDDPower3.3V
EOS1100D shutter emulation MCU pinout
ALT

Figure3: the emulation logic, with the FETs and STM32F042C6T6 MCU.

Figure 4: The completed work with the emulation PCB and the EOS1100D mainboard. Except for P5, all signals are intercepted from the flatcable test points. The only connections to the main board are for the 3.3V power and trigger P5.

Figure 4: The completed work with the emulation PCB and the EOS1100D mainboard. Except for P5, all signals are intercepted from the flatcable test points. The only connections to the main board are for the 3.3V power and trigger P5.

Finally, using Gary Honis’ excellent camera disassembly instructions (link), the camera can be put together easily again. After the shutter and mirror have been removed, there is a lot more space available than I first anticipated, so the emulation PCB didn’t need to be that small. Of course, the PCB can also be left outside – perfect if you want to implement this with an Arduino or STM32-DISCOVERY. Just keep the wires as short as possible, because long wires can pick up noise that couples back into the camera electronics.

The picture below shows the final product. The camera looks like new and unmodified, except for the missing mirror and shutter.

Figure 5: the finished product. The only sign of modification are the missing shutter and mirror.

Figure 5: the finished product. The only sign of modification are the missing shutter and mirror.

Source code

Full source code for the MCU is available on the github project. The code is “bare-bones”, no IDE or special tools are needed to compile it. Just run the make file with a GCC ARM-CORTEX toolchain. Here is an excerpt for the relevant parts of the source code.

Below are the interrupt handlers. The first, “irq_trigger”, will take action based on P5 rising or falling edge. It will simply pass the event to the active state machine.

/**
 * @brief Handle the P5 IRQ (rising & falling edges)
 */
__attribute__((__interrupt__)) void irq_trigger(void)
{
    if (EXTI_GetITStatus(EXTI_Line0) != RESET) {
        uint8_t const set = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0);
        if (set == Bit_SET) {
            /* Rising Edge */
            shutter.state(&shutter, TRIG1_ACTIVATE);
        } else {
            shutter.state(&shutter, TRIG1_DEACTIVATE);
        }
    }

    EXTI_ClearITPendingBit(EXTI_Line0);
}

/**
 * @brief Handle the application timer
 */
__attribute__((__interrupt__)) void irq_tim2(void)
{
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

        timer_do(&shutter);
    }
}

The state machine implementation is done in the following blocks. The most interesting one is “handler_state_open()”, which has to decide, based on P7, if the shutter is going into a “short” exposure mode (1/50s or less), or will stay in long mode. It does this by monitoring signal P7 in a certain time window.

The “timer_do()” function should be called with sufficient timer granularity so as to keep up to date with the timings. In this code, it is tuned to run at +- 100us intervals. It doesn’t matter so much, as long as it is faster than 500us. The function will toggle the outputs according to the timings.

/**
 * @brief Handle events when shutter is in the close state
 */
static void handler_state_close(T_SHUTTER* const sh, T_TRIGGER const action)
{
    __disable_irq();
    if (action == TRIG1_ACTIVATE) {
        start_timebase();
        sh->active = 1;
    } else if (action == TIMER) {
        if (!sh->timing->trig) {
            stop_timebase();
            sh->phase = PHASE_IDLE;
            sh->state = handler_state_idle;
            sh->timing = NULL;
            sh->active = 0;
        }
    }
    __enable_irq();
}

/**
 * @brief Handle events when the shutter is in the open state
 */
static void handler_state_open(T_SHUTTER* const sh, T_TRIGGER const action)
{
    __disable_irq();

    if (action == TIMER) {
        // Assume we are in long mode, unless
        // Trig2/P7 signfies we are short mode instead
        if ((TIMESTAMP() >= TRIG2_P7_SAMPLE_WAIT) && (TIMESTAMP() < TRIG2_P7_SAMPLE_HOLD) &&
           (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2)==Bit_SET)) {
            start_timebase();               // reset counter
            sh->phase = PHASE_CLOSE_SHORT;
            sh->state = handler_state_close;
            sh->timing = timing_close_short;
        }
    } else if (action == TRIG1_DEACTIVATE) {
        // Reset P1 (in line with falling edge of P5/Trig1
        GPIO_WriteBit(GPIOA, GPIO_Pin_3, Bit_RESET);
        sh->active = 0;
        stop_timebase();
        sh->phase = PHASE_CLOSE_LONG;
        sh->state = handler_state_close;
        sh->timing = timing_close_long;

    }

    __enable_irq();
}

/**
 * @brief Handle events when the shutter is in the idle state
 */
static void handler_state_idle(T_SHUTTER* const sh, T_TRIGGER const action)
{
    __disable_irq();

    if (action == TRIG1_ACTIVATE) {
        start_timebase();
        sh->phase   = PHASE_OPEN;
        sh->state   = handler_state_open;
        sh->timing  = timing_open;
        sh->active  = 1;
    }

    __enable_irq();
}

/**
 * @brief Called every 100us or so for timekeeping
 */
static void timer_do(T_SHUTTER* const sh)
{
    if (!sh->active)
        return;

    /* Check for the I/O timings and set them */
    if (sh->timing && sh->timing->trig && (TIMESTAMP() >= sh->timing->trig)) {
        *sh->timing->io_reg = sh->timing->state;
        sh->timing++;
    }

    /* Handle state dependent timer events */
    sh->state(sh, TIMER);
}

Finally, all the timings are contained in tables, and are organized in the relevant shutter states. The first line shows the trigger time in microseconds, since elapse of initial trigger from P5. The second column shows the pin action, i.e. P9_CLR means turning P9 GPIO “low”, which has the effect of making P9 high, because it is pulled up by the EOS mainboard. On the other hand, P1_SET means energizing the FET gate, making the Source-drain channel conductive, hence pulling P1 to GND (making it “low”).

/** Shutter-open timings */
static const T_SHUTTER_TIMING timing_open[] =
{
     {25850/TB,        P9_CLR},
     {34000/TB,        P1_SET},
     {35100/TB,        P10_SET},
     {39400/TB,        P1_CLR},
     {42000/TB,        P1_SET},
     {62900/TB,        P10_CLR},
     {71400/TB,        P12_SET},

     {0, 0, 0},       // END
};

/** Shutter-close timings for long mode */
static const T_SHUTTER_TIMING timing_close_long[] =
{
     {200/TB,           P1_SET},
     {5900/TB,          P1_CLR},
     {7200/TB,          P1_SET},
     {8600/TB,          P1_CLR},
     {34800/TB,         P12_CLR},
     {71100/TB,         P8_SET},
     {107600/TB,        P8_CLR},
     {108000/TB,        P9_SET},

     {0,0, 0},         // END
};

/** Shutter-close timings for short mode */
static const T_SHUTTER_TIMING timing_close_short[] =
{
     {2800/TB,          P1_CLR},
     {4300/TB,          P1_SET},
     {5600/TB,          P1_CLR},
     {31600/TB,         P12_CLR},
     {67800/TB,         P8_SET},
     {104000/TB,        P8_CLR},
     {105000/TB,        P9_SET},

     {0,0, 0},         // END
};

Postscript

This mod has a big impact on the function of your camera. So beware! To name a few we came across:

  • Removal of the mirror (mandatory in this EOS1100D mod, but not so for more advanced models that support an independent mirror-lock-up function) causes you to loose automatic metering and the ability to look through the viewfinder/lens. You can still use the movie-mode though.
  • Movie mode works, but will give “err. 20” after you switch back. So you have to power off the camera to restore function (remove battery).
  • The shutter is necessary for bright scenes to keep the chip from over-exposing. It turns out that while the camera is reading out the image sensor, the “lower part” is still sensitive to light. After this mod, the camera is totally useless in bright scenes like daylight! It will only work if the exposure time is about equal the read-out time (i.e. 1″ or more). In dusk or night conditions its fine. Alternatively, if aperature can be really fixed, then daylight might also be okay, but I didn’t test this.

Credits

  • Kanoa Withington, (CFHT, pikotek), who started the EOS450 mod, and for many helpful discussions and encouragements during development
  • Gary Honis, for his excellent EOSxxx disassembly page
  • Mark-Jaap ten Hove & Jaap van ‘t Leven for donating a EOS1100D for the mod. (link, link)
  • Volkssterrenwacht Bussloo, for testing out the mod (link)

Shutter emulation on Canon EOS1100D DSLR

Canon must be proud to produce one of the most hacked cameras out there. From custom ROMs (see the brilliant Magic Lantern project), IR-cut filter removal, to full peltier-cooled mods.

This post describes how to add yet another EOS mod to this increasing list.
Besides astro-photography, a major application for DSLRs is in all-sky stations for weather, night-time or meteorite observations. Not to mention time-lapse photography. The bane of these frontiers is the fact that the mechanical shutter in the camera body tends to wear out after so many clicks. Then either a new body must be found, or the shutter unit replaced.

Fortunately, it turns out that there is an easy alternative! The shutter unit can be removed entirely, and the signals can be generated by an off-board processor that emulates the proper signals to keep the camera happy. In essence, the camera thinks its happily talking to a (non-existent) healthy shutter. This way, the body can be used indefinitely,

Theory of operation

Shutter assemblyThe EOS1100D shutter basically consists of two connected and spring-loaded blades. An electromagnetic coil triggers the main tension spring that folds the shutter blades to the bottom of the assembly, thereby opening the shutter. Another spring then opens the blades again, closing the shutter. In the end, the DC motor (top, with red/black wires) re-tensions the springs for the next actuation.

Although the shutter is mostly mechanical in nature, with a simple triggering mechanism, the camera still wants to monitor the various components to see if they are in working order (if not, report an error). Here comes in the flatcable.

Flatcable

shutter_flatcableFigure 1: flatcable (pins marked 1 through 12)
This 12-pin flatcable interfaces the shutter to the camera electronics. Two of these pins, marked “coil”, trigger the shutter actuation. The rest is used for status & feedback to the camera, either the optical feedback and (limit-)switch feedback from the big rotary disk.

Below is a picture that shows the optical feedback part deep inside the shutter housing. On lid contains the IR-LED, the other lid (blue, bottom) shows the phototransistor. One of the gears has a kind of lid that slides in the gap, unblocking the IR-light, and generating a signal pulse.
eos1100d_opto1

Mirror lock-up

The EOS1100d is an entry level DSLR. At the time of its introduction, it was the cheapest canon DSLR to buy. With decent resolution, cheap price, and ability to be controlled remotely by gPhoto2, it formed the ideal candidate for an automatic camera station.
A cost-cutting consequence in the EOS1100D when compared to its more expensive siblings, is that it has no dedicated mirror lock-up subsystem. Instead, the mirror lock-up mechanism is directly driven by a pin attached to the shutter assembly. This also explains why there is no mirror lock-up support in the firmware for this camera (or in Magic Latern, for that matter).

Consequently, for this particular mod for the EOS1100D, the MLU assembly must also be removed. The advantage is that there are no more mechanical parts left to fail. But it also means that we lose the ability for electronic metering, i.e., we have to try exposure times manually to find the correct shutter/aperature/ISO for the scene. For night time photography, this is not such a big deal, because using sun elevation and moon phase the exposure can be appropriately programmed. For daytime, its a different matter! Either gamble, or program some smart digital metering as a substitute. After all, exposures are now really free of charge!

Implementation

From reverse engineering point of view, we only need to identify a few properties of the FC pins. Is the pin used? Is it an input or output? If an output, what type? And finally, what is the trigger? At first, I attempted by treating the shutter as a black box, and reverse engineer by looking at the electrical properties of the signals alone. In this I eventually succeeded with the emulation, but at the cost of a great deal of time. After inspecting the actual shutter assembly, and the FC, it became instantly apparent what the FC pins are used for. So, if you attempt to repeat this exercise for another camera – don’t do as I did – just disassemble the thing immediately.

Approach

For the reverse engineering, we need to measure the FC pin signals. This can only be done if you can access the pins. Of course, the back panel of the camera must be removed. It is quite tiresome to remove the back panel, make some adjustment, and re-adjust the backpanel again. Luckily, we can leave the backpanel off, and control the camera by laptop using gPhoto2.

Results

The following is a list of flatcable pins as best as I could identify. I regard this list with a high degree of probability.

EOS1100D shutter flatcable pins

FC pinInput/OutputEmulatedDescription
P1InputYesOpto-feedback
P2GNDNoReturn GND for phototransistor/diode.
P5OutputTrigger!On/Off IR-LED
P6OutputNoCoil pin 1
P7OutputNoCoil pin 2 (67Ohm ESR w.r.t. P6)
P8InputYesRotary FB
P9InputYesRotary FB
P10InputYesRotary FB
P11GNDNoReturn GND for Rotary
P12InputYesRotary FB
P3UnknownUnknownNot used / model extension
P4UnknownUnknownNot used / model extension

Next in line are the signal timings. There are two distinct modes of shutter operation – a long exposure mode, and a short exposure mode. The long exposure mode starts for exposure times of 1/60s and longer. For 1/50s and lower, the shutter works in short exposure mode. The key difference is that in long exposure mode, there are two separate triggers, shifted in time depending on the actual exposure time, for shutter-open and shutter-close.

Shutter signal timing sequence for the long mode

 

The curvy blue lines indicate the offset of the various signals with respect to the start of the trigger (rising edge). The other lines show the duration of the various pulses. In between, the time is indeterminate and depends on the actual exposure time. That is why there are two separate trigger pulses in this mode, one for shutter-open, and one for shutter-close.

 

Shutter signal timing sequence for the short mode

 

 

 

 
 

 

 

 

 

 

In the short mode, there is only one trigger pulse, and all the signals can be related against the rising edge. In short mode, the trigger pulse varies between 130ms and 120ms, again depending on exposure time (120ms @ 1/2000s). In long mode, the first trigger pulse is always 110ms. That is how they can be told apart. Alternatively, the coil signal P7 can be monitored for de-activation (rising edge again).

The idea is now to hook the used signal wires off the FC (best to use the big circular test pads, see Figure1), monitor the trigger signal, and pump out the feedback signals with the proper timings. For the trigger, the coil signal is not used. It turns out that the IR-LED is activated a little bit before the coil is activated (which makes sense!), and we might need to change the P1 signal level even before the coil is energized. However, a small complication is that the trigger signal, P5, is not CMOS/TTL compatible. Idle it is 800mV, and triggered it is 1200mV. This is because the trigger signal is actually an output stage of the dual BJT package indicated with the arrow in figure 2. One solution is to catch this signal with a comparator, the other solution is to hook the TTL signal off the base of the BJT package, indicated as the middle pin by the arrow. The nice thing about the first solution, is that you can fully connect the emulation on the flatcable only. The connector pins are very small, and it takes quite some patience to solder wires with such small pitch.
shutter_pcb1Figure 2: Camera point of view, white shows FC receptacle. The indicated package is a dual BJT, likely a Toshiba RN4982FE or similar, and drives the IR-LED. The big SOT23 MOSFET in the bottom drives the coil.

The actual modification will continue here.

Acer Aspire 5520G reflow fix

I got my hands on a mint condition Acer Aspire 5520G which was stuck in an endless power loop. The laptop was, of course, just months out of warranty. One night it was left installing updates before powering down, the next, it wouldn’t power on. To be exact, the power led and fan would go on for 2 seconds, and then off again. This repeats endlessly. It becomes impossible to stop it by pressing the power button, and all power has to be removed.

Holding the power button for 60 seconds also didn’t help.

This notebook has an Nvidia MCP67 chipset and a Turion X2 processor from AMD. The graphics card is a swappable MXM-II highish-end Nvidia 8600M with 512MB dedicated on-board memory.

Aspire 5520G motherboard, top side

The main assembly has two separate heatpipes, one for the chipset+cpu, the other for the graphics card. The CPU side and graphics card side were neatly screwed down, however, the chipset only had a token heat pad and cannot be screwed down. In fact, there is just a 2mm thick layer of blue thermal padding to make the thermal connection.

Notebooks do not typically commit suicide overnight without anything happening. The CPU and graphics aren’t even being initialized yet, so the culprit has to be the northbridge.

The chipset cooling is obviously sub-par causing excessive thermal stresses, so everything points to bad solder work. Its well known that especially nvidia has problems with the die packaging. This called for some simple reflow work.

First try, I used my rework station. Started gently preheating at 140C for about 2 minutes. Then, ramp up the temperature to 200C in 1 minute, and then hit 240C for about 30 seconds. After that, lower the temperature back to 140C for a minute or so, and then let it cool.

It didn’t work.

Then I retried it raising the reflow temperature to 350C.

Again failure, with the same initial symptoms. Fearing the board very dead, I figured I had nothing more to lose. So I removed the whole mainboard, removed the CPU, graphics card, plastic, connectors, and the battery. I also took care to weigh down the chipset with some metal coins, taking care not to touch the small caps on the package. Then I put it in a normal hot-air oven. First – with board inside – preheated to 140C for 5 minutes, then at 200C for 2 minutes, and finally 220C for 4 minutes. The board didn’t look any different, and none of the plastic was molten.

I then quickly repopulated the CPU and memory, and hooked up the button panel and LCD to the bare motherboard. The symptoms were still the same, power led on, fan on, and then fan off. As I sat in utter disappointment for 15 seconds, I was suddenly greeted by the big white ACER logo on the LCD! I had failed to notice that though the fan did turn off, the power led was ON the whole time!

So apparently it does pay to try to apply the oven trick as a last resort. It can bring success even if the hot-air station didn’t work!

Postscript
Apparantly a lot of nvidia parts are failing. Background story can be found here, here, here, here, here, here, here, and here.

Canon EOS 40D modification

I finally decided to proceed with the hot mirror replacement on my Canon 40D body. An excellent photo-guide on how to do this can be found here. Comparing my mod and this guide I suggest a few changes. First of all, there is a pesky power connector at the bottom of the main board. It is a pain to remove when the main board is still in place. Its more convenient to unscrew it first, and lift is slightly, making the fragile connector more accessible.

Finally, if you remove the side panel with the holes for USB and video, and check that you haven’t left the CF-card inside accidentally, you can save yourself a lot of grief (as I found out the hard way).

The first try went a little bad, because I forgot the backpanel TFT datacable, resulting in a static white screen. I also left the piezo-element and low-pass filter out, which doesn’t seem to matter at all. Of course, the autofocus will be off because the optical path is changed.

Do *not* attempt to do this if you’re unsure or feel uncomfortable around miniature, ESD-sensitive, and fragile electronics!

Here are the works,

Backside removed from the body

Backside removed from the body

Back cover and ESI metal shield removed

Back cover and ESI metal shield removed

Mainboard disassembled

Mainboard disassembled

CMOS board removed from the body

CMOS board removed from the body

CMOS board

CMOS board

Canon 40D CMOS

Canon 40D CMOS

Filter assembly

Filter assembly