I need to monitor my gadget’s battery.
It has a 4.2V LiPo battery with Adafruit’s USB charging circuit. The system can be charging and running at the same time. However, the circuit does not have a fuel gauge or other monitoring information. It has a couple LEDs to say when charging is finished and when it is charging, but nothing to say “battery is nearly dead” (what I need).
My Electric Imp can only take up to 3.3V as an input. If I try to plug by fully charged battery (4.2V) into my Imp’s ADC input, well, fire is fun but bad. (Ok, it probably won’t cause a fire but it may cause an early demise to my Imp.)
Level shifting a signal is a common thing to do. I know this because, in role as software engineer, I have said, “Can’t the hardware just level shift it to a better range for the software?” It is easy!
When someone else does it.
Faced with the problem, I went off to read a little bit. I asked my EE friends to recommend books (other than the physically heavy, mentally heavy, doesn’t-come-in-Kindle Art of Electronics). I read Make:Electronics awhile back and enjoyed it but it was too simple. I need something beyond “here’s how to read a schematic” and more on the order of “here’s how to solve the 25 most common problems a DIYer will have”. Though if they ever do a Headfirst Electrical Engineering book, I’d be all over that.
Anyway, I eventually found that I want a resistor divider. This is like page 3 of a good electronics book so it wasn’t like I spent more than an hour on it. I don’t remember which web page made me think, “This is what I need” since I found it in a few places, including Wikipedia. Here’s what I learned about a resistor divider:
So if Vin is my battery and Vout is going to go to the Imp’s ADC to be measured, I need to set the resistor values (Z1 and Z2) to be something that makes sense.
I’m too lazy to do real math when I’m just poking at this. Ideally, I’d look at the range I want to measure (4.2-2.8V) and the range I want it to shifted to (3.3-0V) and crank. But lazy. So let’s just set Z1=Z2 so my resistor divider divides everything in half. I can prototype that and not blow the Imp, work out the details later.
But wait! Resistors to ground are power vampires. Since this is a battery system, I want to minimize power. I typed “power calculator” into Google and came up with a reasonable webpage that would do the math for me, though the equations were there so I went ahead and thought about it. Here is the important equation, from Wikipedia:
So if I want to minimize power… then I need to maximize resistance (R).
I know I’ve used these equations before but I’ve always been answering a review or exam question, not my own need-to-know musings.
Next, I thought about looking through my bag of resistors. But I realized that the 4.2V already gets translated to 3.3V so why didn’t I use that? I don’t even need to dig through a pile of anything.
Use existing resources
I connected 3.3V to my ADC input and wrote the software to sample the pin. Well, really I just copied it from the Electric Imp Sampler API page and then got it working for my system.
The ADC measured 0xFFFF (maximum value). That made sense, it can measure 0-3.3V and I was putting in 3.3V. I sampled every second as my battery took forever to die, eventually it measured 0xFFEF. Since the ADC is only 12 bits (shifted over to 16), that actually means there was only one bit of difference.
One minute after it went from 0xFFFF to 0xFFEF, it died. So there is only one bit of difference between “great” and “dying”. Plus, only one minute of “dying”.
This method won’t work.
Resistor networks, Part 2
Well, I had estimated the resistor math so after my failure, I got my bag o’ resistors and fished out the highest value ones: 91MOhm, 33MOhm, 10MOhm, 1.5MOhm. I’ve got several of each, from buying a pack of 500 at RadioShack.
I was pulling over my solderless breadboard when I realized that this was too easy. I started hearing that “monsters ahead” music in my head. (Dear brain, can’t we find another way to communicate? And what does the Gilligan’s Island theme mean?)
Plus, it was about lunch so I shot off a quick email to Phil (of Weekend Engineering) and told him my plan. His reply was two paragraphs long. The first one made me wish we’d used a white board:
The voltage divider output is just R2 / (R2 + R1). So if you want your peak 4.2V input to be 3.3V at the output, you want a ratio of 3.3 / 4.2 = R2 / (R2 + R1), so you want resistors proportional to R2 = 3.3, R1 = 0.9. This makes sense intuitively if you think of a series stack of identical resistors with the voltage dropping across it. If you had a stack of 100 equal 1 ohm resistors, then 1% of the voltage drops as you go through each resistor. If you put 4.2V in the top, the voltage decreases by .042V every resistor you move down. 22 resistors down, the voltage has dropped by 22 x 0.042V = 0.924V to 3.276V. So R1=22 ohms (the 22 one ohm resistors in series), and R2 = 78 ohms (the remaining 78 one ohm resistors in series.) There’s your 0.9 : 3.3 ratio.
He probably did all that math. None of my “well, voltage squared is around ten” ballpark nonsense for him. So, cool, he did the math. I can just use his answer.
The second paragraph burst my bubble:
Now, the larger resistors you use, the less current you’re drawing through this stack of resistors. BUT, if you draw current out of the stack, into your ADC, then the you change the voltage, because the resistor divider assumes that there are no other current paths. So the max size resistor you can use depends upon the effective input impedance of your ADC. You want that impedance to be very large (10X or more, possibly much more) compared to the total resistance of your resistor divider. As the current through your resistor divider gets very small (because the resistors are huge), that signal will also be more and more subject to sources of noise. That’s the motivation for not maximizing. (Otherwise, you’d want to just use giga-ohm scale resistances.)
Yeah… I think that was the monster: why doesn’t everyone use giant resistors? And how am I to wade through Electric Imps documentation to find what the input impedance is. (I like my Imp but their Wiki is often a maze of twisty little passages, all alike.)
I looked at their forums (mental note: write a blog post about why I deeply dislike forums) and found an answer deep in a comment thread: around 50kOhm. Later in the thread, they report which processor the Imp uses (but I don’t think they want to bandy that about so I’ll let you look). I went to the processor’s datasheet (already on my harddrive as I used it in a client project recently) and 50k looks right.
So according to Phil, my resistance needs to be 1/10 of the input impedance: around 5k. But the power dissipation is huge! (3.528mW, Phil and I exchanged emails and, again, he did the math.) Essentially, it burns 0.8mA all the time.
This is a crime in a battery powered system.
To deter my continued questions, Phil suggested using a FET to control whether the battery monitor was on. But that requires an IO pin. I don’t have any extra, I’ve already made my tricolor LED a bicolor LED since I need to have a pin from the accelerometer to wake up the Imp.
Stomp stomp grrr. Electrical engineering is all about making difficult things more difficult. Hmph.
Buy my way out
Once I got over my post-lunch-need-a-nap-fussiness, I thought about some projects I’ve worked on and tried to remember how the problem was solved (without cheating and looking at client schematics). I remember someone swearing at a fuel gauge driver and an EE remarking at how stupidly expensive the part was. A little bit of searching led me to a SparkFun board with an I2C power monitor.
The first product comment is a plea to add this to a USB LiPo charger board. That was two years ago. Nothing. Not on AdaFruit or MakerShed either. Someone is missing a big opportunity here.
Anyway, this bumps my materials cost up by $10 but solves the problem very neatly. Plus, since it is I2C, I actually get an IO pin back so I can have a tricolor LED again.
Tempting, so tempting.
If this was a startup, I would be strongly in favor of buy instead of make. You can always make (and make cheaply) later but you can’t get the startup rolling if you take on too much at the start.
I think I’ll sleep on it and see if I can find a better solution. One that doesn’t involve much soldering.
Sadly, one of the negatives is that I need to buy a few other pieces of gear and right now I’ve got carts on SparkFun, AdaFruit, and Digikey but I don’t want to have three orders of stuff. I don’t know why. I’m just that way.