Hello and Welcome! If you have a technical question please check out our Forums. If you have an order or shipping question please refer to our Customer Support page. Please see all COVID-19 updates here and thank you for your continued support.

Enginursday: Battery Management

This post explores how to use the power control features of the Battery Babysitter to make a product with the features we expect from portable embedded electronics.

Favorited Favorite 1

In this modern age of cellphones, we've all come to expect a certain degree of elegance from our portable electronics' battery systems. But in DIY electronics it's common to find jumpers or switches that brutally disconnect the battery from its host. Or, no disconnect at all and puffy, discharged LiPos lying about haphazardly on the workbench. In my FLiR Pi Cam build, for instance, though voltage monitoring was built in, I left it to the user to isolate the batteries via a DPDT switch recessed in the body --- not very elegant at all!

This post explores how to use the power control features of the Battery Babysitter to make a product with the features we expect from portable embedded electronics.

The Host Project

alt text

This is an incident light meter I built inspired from another DIY project I found at kadookacameraworks.com. I built it partly because I wanted to try some menu stuff out on the screen, and partly because I could use it to help light scenes for photography.

Incident light meters need to be thrown in a camera bag and used on and off during a shoot, often from odd angles. It just wouldn't make sense to have a wire that needed to be plugged in, so this is a great platform to try out the Battery Babysitter in order to make a product that performs as people expect.

The "actual" functions of the device are really just obtained by connecting the TSL2561 sensor to the I2C bus and whacking on a TeensyView, followed by coding, coding and more coding. And maybe a little math mixed in there. At the end I'll leave you with a schematic and repository, but this isn't about how light is measured; it's about batteries and usability. So let's get to it!

Design Goals

It's a good idea to specify what you want in the beginning when designing something. Here's what I came up with for adding battery support to my project.

  • Low off-power requirements/no mechanical isolator. This thing should take months to discharge while off.
  • Screen icons for battery:
    • Must display quantity of "% use remaining"
    • May display battery charging state.
  • Minimize number of buttons.
  • Sleep after some length of time (self power-down function).

Fulfilling Those Goals

alt text

Before stuffing the project in the box, the entire project was developed on a breadboard. This allows the circuits in question to be tested and the construction to be well thought-out, avoiding sudden last-minute changes to the design after mechanical production has begun.

If we can describe how each goal is met, and how we can test each goal in the prototype, we can have confidence that the circuit will work as expected. So let's do that now.

Low Off Power

  • The Battery Babysitter must be able to go into SYSOFF mode. We'll test this by measuring the off current through the battery terminal.

Pouring through the Battery Babysitter's schematic, power flow goes first through the fuel gauge IC, through the charger IC, then to the user. Looking for off currents in the respective datasheets,

alt text

The charger is a bit cryptic in off current. The SYSOFF pin is pulled up with a 5 meg resistor, so the control load connected internally must be quite low, below 1uA. This is good, but the charger is downstream of the fuel gauge, so this pin alone can't turn everything off.

alt text

The fuel gauge specifies a few operational modes. For lowest operation, the device should be commanded to shut down by I2C.

Ideally, I expect less than 5uA of drain during off time, which would take years to drain a 1000mAh battery. In reality, I found that the process of shutting down the fuel gauge was quite involved, and it's intended to operate automatically. Conceding that design point, the measured battery off current came to about 60uA. At 1000mAh, that's almost two years of off time before the battery goes dead. I'll expect to charge this every couple months.

Screen Icons

  • The screen must display a little battery in the corner and a symbol to show whether it's charging or not.

alt text

A bitmap image is used to mock up what the icons will look like

To make the graphics of the battery (and the screen in general), I used a bitmap editor extensively. Ok, you got me; I used mspaint with the zoom all the way in and the grid enabled. Then, I converted the pixels into HEX, knowing that the MSb is on top. For instance, the plug starts with 0x28, 0x28, 0x7C... The graphics are encoded into functions like drawPlug and batteryStyle1(x, y, %) so they can be easily used.

To detect charge state, it's easy to look for a positive current flow into the battery. If the condition is met, the plug is drawn. To prevent constant drawing on the screen, though, I check the current and percent remaining by the Babysitter's SOC (state of charge) function and only update if there is a new value to display.

Minimize Number of Buttons

  • Reuse a function button for both the power supply enabler and the intended function. To test, the button must not interfere with the operation of the power supply while operating, and the digital input pin must still be able to detect changes in voltage while the power system is enabled.

The idea of the SYSOFF pin is that it floats high (through a 5meg resistor) and needs to be pulled low in order to get the Babysitter to come online. By connecting two sink paths to the pin, essentially a NOR gate is created.

alt text

The first path is when the button is pressed, SYSOFF is pulled low through the diode. The second path occurs when the GPIO line is driven high, turning on the BJT to pull SYSOFF low.

The theory of operation is that when users want to use the system, they hold the power button until the processor boots. The first thing the processor does is configure its power control pin and pull SYSOFF low. Now the user can let go of the button, and the system remains on. When the system wants to shut itself down, it can release the power control line. The SYSOFF line goes high, and everyone goes to sleep.

The diode is included to allow the button to function normally on its input pin while the SYSOFF line is being held low by the processor.

Sleep After Some Length of Time

  • The system must be able to turn itself off from firmware.

This can be done by bailing from the menu state machine if an mstick count has expired. Not yet implemented. For now, power off occurs when the soft key is hit in the system menu.

The Firmware

To make the system 'catch' as soon as possible, the power pin is configured and asserted as the first thing within begin().

void setup()
    //Assert power on pin
    pinMode(PIN_POWER_ON, OUTPUT);
    digitalWrite(PIN_POWER_ON, HIGH);


Then, when I want to turn the whole thing off, I simply drive the pin low in response to a button operation. There's a bit more here to show the user what the system is doing, and to provide an out if the system fails to shut down.

if( encButton.serviceRisingEdge() )
        oled.setCursor(6, 6);
        oled.print("Power down.");
        digitalWrite(PIN_POWER_ON, LOW);
        oled.setCursor(6, 6);
        nextState = pSystemInit;

As an example of graphics drawing, here's what the battery widget function does. First, it writes pixels to the screen memory with a bytewise draw command, and then it fills in the battery area based on the input percent.

void OLEDFunctions::batteryStyle1( uint8_t xIn, uint8_t yIn, float percent )
    drawByte(xIn + 0,yIn + 0,0xFE);
    drawByte(xIn + 1,yIn + 0,0x82);
    drawByte(xIn + 2,yIn + 0,0x82);
    drawByte(xIn + 3,yIn + 0,0x82);
    drawByte(xIn + 4,yIn + 0,0x82);
    drawByte(xIn + 5,yIn + 0,0x82);
    drawByte(xIn + 6,yIn + 0,0x82);
    drawByte(xIn + 7,yIn + 0,0x82);
    drawByte(xIn + 8,yIn + 0,0x82);
    drawByte(xIn + 9,yIn + 0,0xEE);
    drawByte(xIn + 10,yIn + 0,0x38);

    line(xIn + 2, yIn + 2, xIn + 2 + (percent * 6), yIn + 2);
    line(xIn + 2, yIn + 3, xIn + 2 + (percent * 6), yIn + 3);
    line(xIn + 2, yIn + 4, xIn + 2 + (percent * 6), yIn + 4);


All graphic functions in this project exist in a class that inherits the TeensyView object from the library. This separates the complicated drawing commands from the complicated state machine. The decoupling of these two things really helps to allow the firmware to be expanded --- for example, when a new menu screen needs to be created.

Project Files

Take a look at this schematic to see how everything is wired together. If you're interested in actually making this project, or just seeing how it works, the code, schematic and 3D printer models can be found in a GitHub repository.

alt text

You can see that the Babysitter's output voltage drives the Teensy's bulk input (Vusb), which is regulated down to 3.3V for the Teensy and attached systems. Also, the USB communication lines have been extended to the convenient exposed PTH pads of the Babysitter, so the Teensy can be reprogrammed with the case closed.

alt text

The mechanical build is designed so the battery slides between a couple of snappable proto boards, and the whole assembly slides into the enclosure. No case screws!

Parts used in this build:

And again, the repository can be found here:


Please share your thoughts and ideas in the comments below.

Happy making!


Comments 12 comments

  • The Battery Babysitter must be able to go into SYSOFF mode. We’ll test this by measuring the off current through the battery terminal.

    maybe you can give a picture on this

  • Nice. You remembered to put in the requisite coffee mug ring on your hand drawn schematic. Very classy. :-D

    • Thanks! But this is 2017 so it's actually a digital coffee ring that has white sent to transparency, which was overlaid on the original. ;)

  • " or the GIPO output can pull the line low to turn the system on." I see an NPN open collector driver, shouldn't the gate be driven high (via GPIO) to enable the transistor to drive the SYSOFF signal low? Or maybe that's what you meant and it's just the wording that threw me off.

    • Your analysis is correct! I was a bit high-level with that sentence though, and left out words! I'll go in and see if I want to reword the section a bit.

      Maybe it should read: "The (processor) can pull the (SYSOFF) line low (by driving its GPIO high) to turn the system on."

      Also, because we're talking about words and meaning, BJTs have a base, mosfets have a gate! ;)

      Thanks for the comment!

      • Also, "When the system wants to shut itself down, it can release the power control line. The SYSOFF line goes low, and everyone goes to sleep." Methinks you mean that the SYSOFF line goes HIGH, and everyone goes to sleep. (PIN_POWER_ON goes low, and since the transistor is an inverter, this allows it's output to go high.)

        One other nit-pick: The symbols for the push buttons that you've used are for normally CLOSED ("NC") ones (that is, ones that open the circuit when the button is pushed). The symbol for a normally OPEN ("NO") have the "moving" part all on the same side. (I don't really think you want the user to have to hold the switch down to keep the device in the "sleep" mode, with it waking up as soon as the button is released.)

        • Low was indeed intended to be high, I have fixed it. Thanks!

          The button thing is an interesting point. I've been drawing them that way for years and no one has said anything, but sure enough the T is supposed to go the other way, or, I should have just drawn it as a line.

          • It isn't well known, but the symbol(s) for switches is(are) actually quite extensive with different bits meaning different things. Kind of like letters in languages that heavily use diacritics (unlike english).

            If you take a critical look at the symbols on this page you should start to see variations of the basic symbol along with modifiers that specify things like what causes the switch to change state. If you really want to see all sorts of modifiers and how they can be applied, dig up a copy of IEEE Std 315 (also ANSI Y32.2) and look at Section 4. (I have a pdf of the 1975 version (reaffirmed in 1993), but I don't remember where I found it other as a result of a google search. I don't know the legality of it since I never paid for it, but as a hobbyist I really can't justify the cost of the standards from any of the standards organizations.)

            • The ANSI Y32.2 is easy to find, thanks! I actually prefer the 1975 version, as the symbols are not space over pages and pages. I'll keep this one around!

              I'm not sure of the legality either, but it floods the google results. I wish these standards were made with the intent to be open source to aid humanity!

      • LOL yes a base, you got me there!

        • To be honest, that one gets me too sometimes.

          OK, I think I got it a little clearer in the post now.

          • While we are being pedantic, it isn't just MOSFETs that use the term "gate" for the controlling pin. AFAIK it's both MOSFETs and JFETs (though I haven't seen a JFET outside of class many solar orbits ago.) Also, don't most thyristors use "gate"?

            Hmmm... I don't want to spend too much time here at work researching this, but do any of the other simple solid state devices other than the BJT use "base"?

Related Posts

Recent Posts

As Teensy As Pie


All Tags