Saturday, November 26, 2016

Reducing Current Draw

My previous post introduced my Teensy-based hearing aid.  While my primary goal was to make a platform for developing audio processing algorithms, I am interested in exploring its performance as an actual hearing assistive device.  From this viewpoint, battery life is important.  In assembling my device, however, I gave no thought to minimizing power consumption.  Does it draw too much current?  Will it have a usable battery life?  Let's find out!

Initial Measurements:  With my baseline Teensy Hearing Aid, I measuring the current being drawn from the battery during normal operation.  At this early stage of development, the Teensy isn't doing very much -- it is simply applying digital gain to the audio stream.  Because it is doing so little, I am hoping that we'll see the lowest power consumption.  My results are below.  Note that I measured the power consumption across a range of processor speeds.  You can set the speed of the processor via the Arduino IDE when you compile the sketch.

That's A Lot of Current!  I was surprised to find that at its normal speed (180 MHz) the system was drawing almost 91 mA of current.  That's a lot of current.  My battery has a capacity of 350 mA-hours, so my battery life will only be about (350 mA-hrs / 91 mA) = 3.8 hours.  For a "hearing aid", this is pretty short.  Yes, I could slow down the processor to reduce my power consumption, but this is an inelegant solution that requires me (the programmer) to ensure that my software will always live happily within the limits of the slower speed.  I'd prefer a more dynamic approach, where the code itself will switch between low-power and high-performance modes as the workload demands.  I don't know how to do that.

Sleep During Idle:  Luckily, I have a friend who is experienced with low power embedded systems.  He suggested that I could save a lot of power by putting the processor to sleep during idle periods.  Knowing that I'm working with an ARM processor (the heart of the Teensy board), he suggested that I insert the ARM-specific command asm(" WFI") into my main loop (yes, you do need the space before the W).  When the processor hits this command, it'll go to sleep and consume less power.  It'll stay asleep and "Wait For Interrupt" (hence "WFI") before waking to resume its work.

Wait for Interrupt:   Since I don't want it to sleep forever, I need to make sure that there is an interrupt (such as a timer) that'll wake the system periodically so that it can do its work.  As I don't know how to do this, I have a problem.  Luckily, I know that the Teensy Audio Library already uses interrupts to do its work.  I know that it fires at least one interrupt every 128 audio samples.  As any interrupt will trigger the WFI to wake up, I don't need to do anything more.  I can just add the WFI command and rely upon the Audio Library to wake the system.  The system will automatically go back and forth between sleep and wake.  One line of code -- what a simple solution.

It Works!  After adding the WFI command (my code is here), I measured the current draw again.  The WFI command works!  At the default speed of 180 MHz, the system now draws only 57 mA, instead of 91 mA as seen before.  That's a 34 mA savings with no impact on system performance.  Fantastic.

Battery Life:  By adding the WFI command, power consumption has dropped to 2/3 of its original value.  My system will now have 50% more battery life.  Using my 350 mA-hr battery, I'll now get 6 hours of life instead of 4 hours.  That's a great improvement for adding just a single line of code.

More Power Savings?  While increasing my battery life by 50% is great, I went back to my friend asking if more savings could be had so easily.  He said that I could save more power, but not nearly as easily.  He said that the next step would be to identify and disable peripherals that I don't need.  But, to do this, I'd have to read through and understand my processor's datasheet, which is not an easy task for a newbie such as myself.  So, for now, I think that I'll be content with the easy savings provided by the WFI command.

For Fellow Nerds...My Raw Data:  For anyone who is really interested, my raw data is in the table below (or here).  It is interesting that, even at very slow processor speeds, I still see power savings when using the WFI command.  Clearly, my "Gain Only" audio processing algorithm requires very little effort from the processor.  That Teensy 3.6 sure is fast!


  1. Oh man this post reminded me of my physics days back when i was giving me Alevels. Thanks for posting mate. It was good nostalgia for me.

  2. Very interesting. I'm in Auckland, trying to use Teensy (3.1 for now) and the Teensy Audio board and library to develop a passive sonar capable of detecting fishing boats that are actually fishing. I have taken notes from several of your blog pages already, please keep them up!