Computing stuff tied to the physical world

First goal: just some blips

The next step in this project, is to create a little test application for the LPC810 which shows that it can be powered from the circuit described earlier. There will not be much energy, and definitely not enough to keep the µC running all the time. Instead, let’s create an example “blips” demo, which does the following:

  • on power-up, immediately enter the lowest possible “deep power down” mode
  • wake up again after about 3 seconds
  • enter a very brief “busy loop”, for about 1 millisecond
  • go into deep power down again, and repeat this whole cycle after 3 seconds

This gives us a way to measure how fast an LPC810 can go back to sleep, and what its power consumption will be in sleep mode. Every second “blip” will be one whereby the processor does a little bit of work (twitching thumbs in this case, but still).

There is no external I/O pin change, but we can watch the change in current consumption – if we see it alternate between short and long activity blips, with three seconds of minimal power consumption in between, we’ll know that the application is working as expected.

It may all sound a bit over-cautious, but the slightest energy waste could work against us.

Here is the blips code, also available on GitHub:

#include "LPC8xx.h"                                                              

// do something deemed useful, this is the actual "payload" of this application
// after that, main will be restarted and call this again, hence the name "loop"
static void loop () {                                                        
    if (LPC_PMU->GPREG0) {                                                   
        // idle loop to keep the LED turned on                               
        for (int count = 0; count < 1000; ++count)                           
            __ASM(""); // waste time while drawing current                   
    }                                                                        

    LPC_PMU->GPREG0 ^= 1; // toggle a bit which will be saved across resets  
}                                                                            

int main () {                                                                
    LPC_SYSCON->SYSAHBCLKCTRL |= 1<<9;  // SYSCTL_CLOCK_WKT                  
    LPC_WKT->CTRL = 1<<0;               // WKT_CTRL_CLKSEL                   

    NVIC_EnableIRQ(WKT_IRQn);                                                

    LPC_SYSCON->STARTERP1 = 1<<15;      // wake up from alarm/wake timer     
    SCB->SCR |= 1<<2;                   // enable SLEEPDEEP mode             
    LPC_PMU->DPDCTRL = 0xE;             // no wakeup, LPOSCEN and LPOSCDPDEN 
    LPC_PMU->PCON = 3;                  // enter deep power-down mode        
    LPC_WKT->COUNT = 30000;             // set sleep counter to 3 seconds                

    loop();                             // do some work                      

    __WFI();                            // wait for interrupt, powers down   
    // waking up from deep power-down leads to a full reset, no need to loop 
}                                                                            

extern "C" void WKT_IRQHandler () {                                          
    LPC_WKT->CTRL = LPC_WKT->CTRL;      // clear the alarm interrupt         
}

The trouble with the LPC8xx’s deep power-down mode, is that it can only end in a reset of the µC once the low-power watchdog timer fires. Which means the entire application will restart from the beginning. Fortunately a few hardware registers are retained across these resets, so we can tell where we came from, i.e. what the state of our previous run was.

This is used here via LPC_PMU->GPREG0, which contains either 0 or 1, depending on which part of the blip cycle we are in. In one case, we just return immediately, in the other we spend a little time keeping the µC busy (and therefore consuming a few mA of current).

All the settings have been optimised to achieve minimal power consumption. An important one is turning the WAKEUP pin functionality off. This shaved another few hundred nanoamps off the power-down consumption, which is now down to about 0.3 µA.

We can test this code in our bare programmer with the voltage-dropping red LED: the varying current consumption will cause the in-series LED to blink once every 3 seconds, one very brief blip, the other slightly longer and brighter.

With a 10Ω resistor in series and a sensitive oscilloscope, we can see that current pattern:

SCR62 4

This was taken from a more elaborate experiment – the relevant signal here is the yellow one at the bottom. Because “persistence” was enabled, we can see both the short and the long blips, superimposed. The vertical scale is 1 mA per division (10 mV over 10 Ω).

There’s some startup time which is identical in both cases, and then there’s the immediate power-down vs. the power-down after a little bit of idle-looping. Those 1000 cycles in the code above show up as a 330 µs time difference. The µC is running at 12 MHz, i.e. an 83 ns cycle time, so each cycle through the loop needs 4 clock cycles – a plausible value.

The startup time from power-up to the time our code gets control takes about 230 µs. This corresponds nicely with the diagram in section 4.7.2 of the LPC81x manual (UM10601):

Power up timing

What this also gives us, is the bottom line for powering up the LPC810 (or waking up from a deep power-down): even if we make the µC power down as very first step, it’ll need to be supplied with enough power to get through those initial 230 µs, drawing up to 2 mA.

One reason for powering down right away, is that we are operating in a severely power-constrained context. That startup of the µC is bound to eat up some of the precious energy – as you can in fact see in the above oscilloscope trace as a dip in the voltage (in purple).

To recover, the best we can probably do is enter our lowest-power mode for a while, to let the supply charge up a little further. When we wake up again, there will be slightly more stored energy and we’ll have a better opportunity to perform some real work.

So there you have it: a first test application, which we can now use to find out whether our Current Transformer plus Delon bridge is able to keep that little LPC810 going.

Note that these are all baby steps, far removed still from driving a radio and sending out packets. But that’s just how such projects go – from one ultra low-power step to the next.

[Back to article index]