Using An MSP430 For Time Lapse Photography

vistaquest_keychain_timelapse_msp430

Hackaday reader [onefivefour] had an old VistaQuest VQ1005 keychain camera kicking around, and wanted to do something useful with it. A while back he hooked up a 555 timer and did a bit of time lapse photography, but he wanted more control over the process. Specifically, he desired the ability to tweak the delay between shots in a more granular fashion, as well as way to prevent the VistaQuest from going to sleep after sitting idle for 60 seconds.

His weapon of choice to get this task done was an MSP430, since the microcontroller can be found quite cheaply, and because it is relatively easy to use. He added a few header pins to the LaunchPad board wiring them up to the camera’s trigger as well as the on/off switch. When the wire connected to the trigger is pulled low, the camera snaps a picture. The wire connected to the on/off switch is always held low, ensuring that the camera is on and ready to go whenever it’s time to take a shot.

It’s a relatively simple project, but definitely useful. While there are many ways to build an intervalometer, the MSP430 is a great platform to use, especially for beginners.

Stick around to see a quick video [onefivefour] put together, showing off his time lapse rig’s capabilities.

[youtube=http://www.youtube.com/watch?v=mBQEt9WRtK8&w=470]

14 thoughts on “Using An MSP430 For Time Lapse Photography

  1. Nifty project. Unfortunately code is “All Rights Reserved” and no license so can’t be reused even though he says “Modify it if you want.” Please give it an open license like GPLv3 or Creative Commons. Thanks!

  2. Things the author could have done better:
    1) Better explain the soldering locations (I don’t have the camera, so I don’t know how obvious it is)
    2) Get the terminology right (the MSP430 is just the MCU, whereas in the article, the Launchpad is constantly called “the MSP430.”
    3) Provide working code. The include is partially missing and the last for loop doesn’t have a correct head.

    This is a very basic MCU project, but sadly, that’s just the very first basic program you’d want to write for the MSP430. I see two points for improving it:
    First, some conceptual things. Currently, if I get this correctly, the camera will be turned on at the start of the loop whenever a picture is to be taken, but it’s not turned off after a picture is taken. Because there’s so much time between pictures and the camera will use large amounts of energy compared to everything else, the first step is to turn on the camera, take a picture and then turn it off again, and only then wait for the next picture.
    Then, the whole MSP430 stuff is about low-power. Generally for any MSP430 code, you do not want your processor to actually run. That means posing some questions: (a) IF it needs to run, what frequency does it need to run at? Does it really need to run at a high frequency or can you spare the time and run it at a lower frequency? Lower frequency = lower power and because the MSP430’s clock system is flexible, you can easily jump between CPU clocks almost anywhere in your code. (b) Does it really need to run? Most instructions in the code here boil down to waiting. The processor doesn’t do anything but waste clock cycles. Because the number of cycles it has to wait is rather large, the better way to do is is to clock the timer from a slow clock source, turn the CPU off and fire timer interrupts to change the state of a state machine and then wake up the CPU to toggle pins. There are a couple of infos on low-power optimization on the launchpad website.
    Of course, the downside is having to change the way the LEDs blink, but they’re just indicators that something is happening, so I suppose it’s perfectly okay to flash them once every (couple of) second(s) or so, which will then be compatible with low-power optimization techniques (you could use the WDT for flashing the LEDs, for example).

    1. [onefivefour] here…..

      All hacks and projects can use improvement. I’m just a dumb yuk wanna be coder with a geeky hobby, so feel free to modify and adjust the project to fit your needs.

      Thanks for checking out my hack.

      1. (Hopefully, the comment system here can take this somewhat lengthy comment.)
        I think low-power optimization is important. You’re a hobbyist, you seem to be smart enough to figure out how to program the MSP430, so there really is no excuse not to try optimizing your program.
        First, I couldn’t get it to run, so I guessed about the missing instructions and the timing was completely off. That’s a shame, because I really would have liked to use your program and convert it to something that needs much less power. However, I used it as a guideline to reimplement it, so not much was lost.

        Some advice: When programming, you absolutely need the Family User’s Guide (SLAU144). Without it, you’re totally helpless. It contains all the register settings you need to know, but beware the MSP430 is a large family of devices, so there are lots and lots of features which are described in the family user’s guide, but which don’t apply to the MSP430G2231 at all. And that’s just the guide for the MSP430x2xx series!

        So, first of all, a short list of some important concepts of low-power operation. A processor needs a clock to run. Higher clock means faster operation, but also more power needed. Usually, you can’t really decide on the clock as much as you’d like to, most likely because the clock system is somewhat inflexible or you absolutely need some component to be as responsible and as fast as possible (e.g. for communication). The MSP430 has a rather flexible clock system that allows the internal oscillator to be configured on-the-fly. One important thing to consider is the clock speed. Do you *really need* to be that fast? If you don’t, crank down the clock, it will save tons of energy.
        So, looking at your program, which really doesn’t do anything time-critical at all and just sets a few pins, you can be quite radical and set the clock to its lowest setting. I took some ballpark measurements on my launchpad with a program in an idle loop with the configuration the MSP430G2231 started in (so now low-power techniques like setting unused pins to outputs etc., so the energy consumption will now be exaggerated, but for the sake of comparison, that doesn’t really matter). When it was running at the “calibrated” 1 MHz, it was using about 420 µA. Running at 16 MHz (or rather 15.96 MHz), it used about 4.93 mA. Running at 102 kHz, the slowest DCO setting attainable, yielded a power consumption of about 120 µA. So, first thing to do is to set the clock to the lowest setting:
        DCOCTL = 0;
        BCSCTL1 &= ~(RSEL3 + RSEL2 + RSEL1 + RSEL0);

        When you’re doing things in bursts and the CPU is only on for a very short time, as we will be doing, it might actually be better to set the clock to the MIPS/W “sweet spot.” You can experiment with different clock settings to find that out.

        The next general technique in MCU programming in general, but one essential for low-power stuff, are state machines. Basically, you want to write programs which have “states” they’re in and a way to switch between states. It’s hard to explain, but your program is already written with states in mind.
        They are: (1) Turn on camera (2) Release camera on-switch (3) Trigger picture (4) Release trigger
        The transitions between states can be complicated things such as users pressing buttons or new data coming from a communication interface, but in your case, transitions happen if enough time has passed. Now the clue about structuring your program to be a state machine is that if the actual program in the state has finished running, you just have to wait for the event which will trigger the transition to the next state. And waiting without having to do anything is great, because then you can put the MCU in a low-power mode and wake it up as soon as the transition happens. Your code waits A LOT, so low-power optimization will be especially helpful there.

        Now, how do you tackle the problem? First things first, organize your program into states. That’s quite easy. We need the four methods described above and a new variable to store the current state:

        void boot_camera(); // will be state 0
        void release_on_switch(); // will be state 1
        void trigger_picture(); // will be state 2
        void release_trigger(); // will be state 3
        volatile char state = 0;

        The methods now look something like this. You can figure out the remaining methods, but in release_trigger(), the next state will of course be 0:
        void trigger_picture() {
        P1OUT &= ~BIT5; // Drive Trigger signal low to take pic
        state = 3; // advance state
        // Some delay to process pic, save to SD card, etc.
        }

        We still need to add the delay. Of course, we could just use the loops from the original code, but that would defy the low-power purpose, so we need something else. The MSP430 features a timer/counter peripheral, which will increment its value register every once in a while. You can also set an interrupt to be fired when a specific value is reached. Because we know how fast the timer increments its register, we can use this mechanism to wait for a specific amount of time. If the timer clock is slow, this can be rather large. Now the idea is to let the processor sleep almost all the time and then be woken up by the timer interrupt, then do the stuff in the state it’s in, then set the next timer value to fire an interrupt and then go to sleep again. Sounds complicated, but it’s not.

        We’ll first have to do the boring stuff, i.e. setting the clocks and dividers and whatnot correctly. This can be a real hassle. From your code, it seems like having about 5 minutes of time between pictures will be sufficient. We will source the timer from the MSP430’s VLO, which runs at about 12 kHz. Mine runs at about 10.4 kHz, but if you need to be exact on the time, populating the 32 KiHz watch crystal probably is a better idea. The timer will accept clock input from everything, so we could also use MCLK or SMCLK, but looking at the low-power modes, only ACLK won’t be turned off in LPM3.

        What follows now takes a long time of looking up stuff in the family user guide, measuring clock outputs to be sure etc., so I’ll just describe what’s important. Ideally, we want our whole delay to fit in the 16 bits provided by the timer. That way, we don’t have to write software to “extend” the timer value to more than 16 bits. The longest time we will have to wait is about 5 minutes, so let’s see if we can come up with a way to accomplish this easily. The timer can count up to 65535, so it has 65536 values. ACLK is about 12 kHz and can be further divided by 1, 2, 4, or 8 by the clock system. If we used ACLK directly, we’d get a timer overflow interrupt every 5.4 seconds. So, we divide it by 8 and get our new ACLK of 1500 Hz. This will take about 44 seconds for a timer overflow interrupt to be triggered. So much for the clock system, that’s about as slow as it will get. But the timer peripheral itself has another configurable clock divider–the input clock can be divided by 1, 2, 4, or 8 again. If we use 8 as a divider there, we get about 349.5 seconds until the timer overflow, which is about 5 minutes and 50 seconds and thus absolutely ideal for our purpose.

        So, the code:
        // aclk:
        BCSCTL3 = LFXT1S_2; // select VLOCLK as ACLK
        BCSCTL1 |= DIVA_3; // divide ACLK/8 –> ACLK is now about 1500 Hz

        // timer configuration
        TACCTL0 = CCIE; // enable capture/compare interrupt
        TACCR0 = 5*COUNTS_PER_S; // wait 5 seconds to start, just because
        TACTL = TASSEL_1 + ID_3 + MC_1; // select ACLK as the clock source; divide input by 8; count up (start the timer)
        // so, the timer needs 65536 / ((12000 Hz / 8)/8) = 350 s for one overflow

        Now we just need to configure the timer interrupt. This is slightly confusing and I can only recommend looking at lots of example code and reading the workshops and tutorials TI has posted somewhere on their site (e.g. http://processors.wiki.ti.com/index.php/Getting_Started_with_the_MSP430_LaunchPad_Workshop).
        The TimerA can trigger three interrupts: Capture/Compare0, Capture/Compare1 and Overflow. We’re using the Capture/Compare0 interrupt here, so it needs to be enabled by setting TACCTL0 = CCIE;
        To ease code development, I recommend putting some defines at the top of the code. I defined the number of counts per second the timer will make and the interval between pictures (not really the interval between pictures, but more the time the MCU will wait between having finished taking the picture in state 3 and starting at state 0 again):
        #define COUNTS_PER_S 187.5
        // COUNTS_PER_S = number of counts the timer is incremented in 1 second
        #define SECONDS_BETWEEN_PICTURES 30

        Now, we’re setting the TimerA’s capture compare register 0 (for Capture/Compare0) to 5*COUNTS_PER_S, so the timer will create the first interrupt 5 seconds after it was started, which we’re doing just for the fun of it. TACTL is configured to use ACLK as the clock source, divide the clock input by 8 and to count up until the value in CCR0 is reached, then reset the counter to 0. That way, we won’t get overflow interrupts.

        Then, what else do we need? Let’s decide on the timer interrupt. You could do all sorts of crazy stuff there, including handling the states of the state machine, but let’s just suppose you don’t want to do that. We just want the timer interrupt to wake up the processor from the LPM3 low-power state, so the timer interrupt is just:
        #pragma vector=TIMERA0_VECTOR
        __interrupt void Timer_A() {
        _bic_SR_register_on_exit(LPM3_bits); // just wake up from LPM
        }

        We’re almost done with the code, the only thing remaining is some structure to tie it all together, send the MCU into low-power operation and to actually call the methods based on the current state. We’re doing this in the classic while loop:
        while(1) {
        _bis_SR_register(LPM3_bits + GIE); // enter LPM3 + interrupts;

        switch (state) {
        case 0:
        boot_camera();
        break;
        case 1:
        release_on_switch();
        break;
        case 2:
        trigger_picture();
        break;
        case 3:
        release_trigger();
        break;
        default:
        break;
        }
        }

        _bis_SR_register(LPM3_bits + GIE); will enable interrupts (GIE) and set up LPM3. After this line, the processor basically stops and will only be woken up by the timer interrupt. After that, we’re deciding on what to do next based on the state, which by now should be somewhat self-explanatory.

        Of course, that’s not the only way to write code, nor is it probably the best way. Use your style and your experience to do things differently.

        So, what’s missing now?
        – Blinky LEDs like in the original code. This can be realized with the WDT, but I don’t have the nerve to go into that now. Probably later, if there’s some interest.
        – Even more low-power optimization. You’d tie all unused pins to VCC or GND externally, then enable the internal pull-up/pull-down resistor and make them outputs. That way, they won’t pick up signals and toggle. I didn’t do this because it’s a hassle to do on the Launchpad itself, requiring a whole loom of cables. Wouldn’t be much of a problem on a breadboard or in a circuit, however.

        So there you have it. Optimizing your code isn’t actually hard, it’s quite easy. Sure, it will take ages the first few times you do it, but if you structure your programs correctly, this will take less and less time and you’ll be able to do more things much quicker. For example, your code didn’t contain an actual formula to calculate time between pictures, so it was kind of a rough guess. By using timers with a defined clock source (the VLO could be calibrated with MCLK or even the 32 KiHz crystal), but now you can easily adjust time between pictures with a resolution of about 5 ms (depending on the actual VLO frequency, so to be exact, you’d have to measure it).

        -F.

    2. Regarding the ‘include’ statement in the blog. Since it is surrounded by a “” it was not not shown. You can send google an email and tell them to work on that…. I’m not a professional HTML web developer either. ;)

      I removed the . Anyone with the ambition to try the project will figure out the omission pretty quickly.

      1. Nice hack! I set up a similar thing to try to catch the big eclipse event (but sadly no results to show because of $#@!@ weather).

        I used the output pin to trigger a low-voltage sensing relay. I know this is probably overkill, I could use a transistor, etc… but I liked the idea of the camera trigger being on its own isolated circuit. I’m not an electronics guy, so I was going for what felt safe rather than what would make good engineering sense.

        From other programming experiences with Launchpad, I think the best route to tackle this for low power is to use interrupts triggered by the VLO. Use the internal clock and skip an external oscillator. Also set an interrupt for the P1.3 to toggle the modes. I guess this is where you could get creative, but maybe using a variable resistor pot and read it (appropriate the temp sensor code to help figure it out) that way you have a manual, tactile way of setting the duration.

        That being said, I used a single-shot for loop in my code and counted clock cycles. A total battery eater. Horrible style. But two AAA batteries lasted all night so I really couldn’t care less.

  3. I’m trying to learn to use the LaunchPad and know very little of C coding. The code here is extremely well commented and is a great place for new tinkerers to start.
    Thanks for sharing!

Leave a Reply to IronjungleCancel reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.