Need to do some thinking out loud… This coding stuff is getting a lot more complicated than I thought.
My long enforced layoff from coding perhaps had a silver lining? Before I left I was churning out code as fast as I could to get the ranging working. I didn’t manage to get it going, but I have left a pile of badly engineered, and undocumented code in my wake which I now find makes little sense. I decided to start off again by carefully reviewing everything I wrote, and taking the time to make sure I fully understand it all.
With TS06, I’m going to try to be more sophisticated in pursuit of power efficiency. It would be nice not to have to bother about this aspect yet, but I think I must. The problem is that I need to adopt a more reasonable real-time architecture to have any hope of improving battery life over TS05.
Old Scheme
TS05 (Atmel) handled everything in the simplest way possible – a giant polling loop. Two downsides of that were:
- It spent a lot of time polling devices that had no data ready. That was wasting processor nap opportunities.
- That seemed trivial at the time, especially when I was finding it such a challenge to get any response from the wide array of devices. In the light of all that experience I know that each of those polling operations involved sending commands between the processor and the device, at SPI, or I2C speeds. In the case of the SPI, all the devices were on a single bus, and the communication protocol sometimes had to be changed between devices that used incompatible communication protocols. That’s a pretty insignificant processor overhead.
Communication was at about 400Kb, and so a single average transaction took about 0.5 millisecond to discover that the peripheral had nothing to say! That’s not insignificant.
With about ten devices to poll, a single poll cycle took 5ms, which limited the maximum polling rate to 200Hz. This polling rate in itself was not a limitation – TS05 polled at about 10Hz, too slow for some devices, and way to fast for others. The 10Hz rate allowed samples to be collected at a regular rate which, to my mind at the time, made the signal processing easier to fathom. Stupidly, a lot of the time the processor was polling the clock to see if it was time to collect another round of samples. How dumb can you get?
This scheme meant that the the processor and all the devices were on and running for 5ms every second. As things worked out, the processor was almost never sleeping, and so the drain on power was substantial, and the huge battery would last for 1-2 days in continuous use.
New Scheme
for (;;)
{
sleep_till_interrupt();
run_scheduler();
}
In this scheme the processor’s prime strategic objective is to turn the power off to as many components as it can, and then go to sleep until something generates an interrupt.
Behind the scenes, when an interrupt occurs, the processor is woken up, and the Touchstone(TS) interrupt handle (IRQ) is automatically invoked by the hardware.
The interrupt handler does whatever it can to gather up and save the raw data pertaining to the interrupt. For an accelerometer, it might collect the x,y and z acceleration values, along with an accurate time stamp. Then it bundles up the data and posts it on the scheduler event queue: a queue of notifications that something significant has happened. TS maintains this queue behind-the-scenes. Finally the IRQ returns.
The main loop routine “sleep-till-interrupt” learns that an interrupt has occurred, and it returns control to the main loop, which immediately invokes the scheduler.
Now the scheduler takes each item of the head of the queue and calls a previously registered event handler to do the, possibly heavy, processing work required to transform the event data into some Touchstone activity. Normally this would simply involve transforming the data into some calibrated, standard form, and storing it, but it might eventually bubble up through the application layers to cause some alert message to be issued to the user, for example. Several interrupts may occur in quick succession, and so the scheduler works it’s way through them all before finally returning to the main loop, where the processor tries to go to sleep again.
Advantages of this approach
This approach has many advantages. Here are a few:
- The processor, and perhaps a bunch of subsystems can be turned off until some interrupt occurs. Depending on what has been left running, the sleep current can be a few uA, or even less.
- Events can be processed much sooner after they occur (lower latency).
- Some interrupts can be processed without even waking the processor – button de-bouncing for example.
- There is no pointless traffic on the SPI, and I2C bus which saves power.
- Changes in sensor data can be handled at a higher rate.