Now's probably a good time to show you the whole schematic:
The battery and charging terminals aren't actually components; I just drew them out of the traces on the PCB itself.
The LEDs on the left are Charlieplexed which allowed me to connect a large number of LEDs with a small number of wires going to the front PCB. This means that I can only light one at a time. I used some multiplexing with PWM to give the appearance of one brighter LED surrounded by two dimmer ones. This triplet is what travels around the display. The feathering of brightnesses smooths out the rotation animation a bit.
R1 and R2 bring the battery voltage to the microcontroller. The ATTiny24 has an internal 1.1V band gap reference which it can use to perform ADC measurements where 1.1V is equal to 0xFF. This means that the LSB is worth around 0.0043V. With this configuration, when the ADC reads a value of 125, the divider's output is 0.54V and the battery voltage is 3.078.
That is assuming that the band gap and resistors are perfectly accurate. In reality I got closer to 2.9V which I figured was close enough.
Hall Effect and Power Switch
With no buttons or switches accessible, I wanted some way to switch the circuit off. This would be a convenience to the user trying to save the battery as well as a necessity during battery charging (more on that later). U3 is a low-power magnetic or "Hall Effect" sensor. I originally purchased a hand full of them when I was trying to find a replacement for the optical sensor on my longboard wheel displays, but I was disappointed to find that the low power draw of this model came at the cost of sample rate.
The MLX90248 only measures the magnetic field once every 40ms, but it also only draws an average of 6.5A. It's a bi-directional sensor too, so a sufficiently strong magnetic field in the north or south direction along its sensor axis will cause it to pull its output low. What this means in practice is that if you put a strong enough neodymium magnet within a centimeter of it, it'll trigger the output.
So what does the microcontroller do when the the hall-effect pin goes low? The idea is to shut off and draw as little power as possible while still being able to keep the battery connected to the circuit and allow the circuit to recover out of the sleep state when the magnet is removed.
There are a number of shutdown modes available to the ATTiny24. The lowest power option is "power-down mode" where all operations on the processor are halted and the part requires a transition on an interrupt pin to wake up. In this state, it draws just 3-4A which is tiny.
My original plan was to finagle a sort of hardware clock similar to poor man's capsense using C3. The idea was to charge C3 and then switch the pin to a high-impedance input before going into power-down mode. The tiny leakage current on the input pin would slowly drain the capacitor until its voltage dropped low enough to trigger a falling edge interrupt and wake back up again.
This was a great solution for the menorah where the circuit could stay in power-down indefinitely with no problems, but I was concerned with my earrings that the board could get stuck in power-down for an extended period of time and neglect the critical battery monitoring functions. It was also generally flakey and not the kind of thing I wanted to implement in a place where I couldn't easily access the circuit.
Of course, my real reason for ditching it was a short that developed somewhere in my prototype preventing it from working. Now it's just an extra capacitor that does nothing.
The next lowest power mode is "standby" which still draws less than 10A. This mode keeps an oscillator running which can pull the chip out of standby after a certain number of clock cycles has passed. This is super useful in things like wristwatches and soil moisture sensors.
Sadly, this solution requires an external crystal oscillator which is A) large and B) not already implemented on the PCBs that I had already made. For these reasons, I had to fall back to "idle" mode.
In idle mode, the microcontroller is more or less still totally awake. It can be woken by pin change interrupts as well as software timers. While this is super convenient, it also draws substantially more power. Even using the system clock prescaler fuse to drop the clock frequency down to 1MHz and using the Power Reduction Register to disable the ADC, USI, and one of the timers, I was still orders of magnitude above the other modes.
Page 197 of the data sheet says I should be able to drop down to somewhere between 0.15mA and 0.25mA. I measured closer to .45mA:
(note, this was before I added the pull up/pull down to the FETs. The actual current draw should be higher.)
I'm not sure why this is so high. I think it might have something to do with the need to keep the gate of my PFET pulled low. Regardless, it's still much lower than the 6mA I measured when the circuit was active, so I moved on.
Update: Multiple readers have brought it to my attention that I could have used the watchdog timer of the ATTiny24 to reset the device every 8 seconds or so. This can run while the system is in power-down or standby mode and does not require an external oscillator.
When a magnet is brought close to the circuit, the microcontroller switches off the LEDs, starts a timer, and goes into idle mode. Then when the timer expires, it wakes up for a moment, takes a brief measurement of the battery, checks to see the magnet is still there and goes to sleep. If the battery is too low, it disconnects it from the circuit, and if the magnet is removed, it wakes up.
The only downside of this method is that lengthening the timer interval to decrease power draw also makes the earrings very slow to respond to being turned on. Depending on the user's timing, it can take anywhere from 0 to 16 seconds for the device to light up after they remove the magnet. While this may be inconvenient, I consider it to be well within my use case.
Charging lithium polymer batteries is a strange process that's usually split into two stages: the constant current stage and the constant voltage stage.
Unlike the capacitors used in a typical circuit, lithium polymer batteries have a maximum rate at which they can be charged. Your typical battery can be modeled as a resistor and a voltage source:
When you begin charging a dead battery, the voltage is all the way down at 3V. The goal of charging is to force current backwards through the voltage source. This is done by attaching the battery to a larger voltage source. The battery will have a rated charging voltage which in the case of my battery is 4.2V.
The current traveling backwards through the battery will be the voltage across the resistor divided by its resistance. Let's say the resistor starts out at 50 (it will change depending on a number of conditions, but I'm going to stick with 50 to keep things simple):
The only problem is that the datasheet for this battery lists its maximum charge current as 9mA. We're almost tripling that! With this amount of current flowing across the battery's internal resistance, it will start to heat up more than the battery can handle. It could eventually cause the battery to balloon up and even start a fire (probably an exaggeration for such a small cell, but it will still damage the battery).
This phase of charging is known as the "constant current phase". This is where the charger needs to carefully limit its current to make sure that it doesn't overdrive the battery. This will involve using a voltage smaller than 4.2V starting out. In this case, you could use:
As you pump current into this battery, its internal voltage will slowly rise. Soon you'll be able to drive it at a higher voltage than 3.45V. Eventually, you'll get to the point that you can safely charge it at 4.2V, but then you've got another problem. In order to maintain 9mA of charging, you would need to drive the battery above the rated 4.2V charging voltage. What do you do?
This is called the "constant voltage" stage of battery charging. This means that you maintain the voltage at 4.2V and allow the current to slowly drop. As the internal voltage rises closer to 4.2V, the voltage across the internal resistance will drop lowering the current.
Eventually, this current will drop below some cut off threshold (in my case, 1mA), and it will be okay to stop charging. The battery is fully charged!
You might find that a number of cheap chargers for things like those little RC helicopters don't even have a constant voltage mode. This is because once you exit the constant current mode, you can be as high as 80% full. The last 20% isn't considered worth it especially since it takes so much longer to complete due to the lower charge current.
So the question is, how do you implement this charging scheme? I came up with this solution (click to enlarge):
This probably isn't the cheapest or most effective way to charge a battery, but it could be done with parts that I happened to have lying around. The charger is designed to run off of either microUSB or two AAA batteries (for portable use). D4 and D5 act as ORing diodes. Whichever voltage is higher (USB if it's connected) will be used to power the circuit. These are Schottky diodes, so the voltage drops about 0.3V across them.
That's where U4 steps in. U4 is the boost converter from my bullet counter circuit. When configured correctly, this thing will take a voltage from as low as 2V and output a good 5V at up to 200mA. This is enough to boost the AAA's 3V output up to 5V or to overcome the Schottky diode voltage drop in the case of USB power.
The power switch originally controlled the enable pin on the boost converter until I realized that with the boost converter disabled, there is still a current path through L1 and D3, so switching it off won't prevent the circuit from drawing power.
Now for the part that actually charges the batteries. There are two independent chargers here (one for each earring). Here's one of them:
This circuit only controls the negative terminal of the battery. The positive terminal is connected directly to +5V.
Voltage limiting is handled by Q2 and its op amp. R1, R2, and R9 make up a voltage divider that outputs 0.8V (this could have been done with 2 resistors, but I wanted to make it work with values I had handy). This 0.8V is fed into the inverting input of the op amp which is configured in a negative feedback mode through Q2. The end result is that the drain of Q2 is kept at 0.8V which means that the maximum voltage possible across the battery is 4.2V
R28 was added after I tested the circuit due to a problem I discovered with this setup when the currents get very small. In order for Q2 to maintain the 0.8V drop, it needs some amount of current traveling through its R. When this current drops too low, the voltage drop decreases, and the battery sees a voltage higher than 4.2V. R28 acts to maintain at least 4.2mA of current flowing across Q2 at all times. This energy is wasted of course, but I figured it was okay to sacrifice energy for stability considering this charger is going to be plugged into USB most of the time.
Q1 and its op amp are responsible for current limiting. R3 and R4 combine to make a 31 current sense resistor. When the charge current reaches 9mA, the voltage across this 31 resistor should be:
When this is added to the 0.8V of the voltage limiting section below, it comes out to 1.079V. The voltage divider comprised of R6, R7, and R8 creates a 1.071V reference and the Q1 op amp combo try to keep both of those outputs at the same level. The op amp is only monitoring the voltage, but the addition of the current sense resistors turn this into a current limiting supply.
When the battery's voltage increases high enough to exit constant current mode, this portion of the circuit will continue to try to raise the current, but because it only has 4.2V maximum to work with, it won't be able to damage the battery and the circuit will effectively be in constant voltage mode.
The two lines leading off the right side of the page go to an onboard ATTiny24 micro controller. This device monitors the charge current by looking at the voltage at the top of R3 and R4. When this voltage drops below 0.843V, it means that the current has dropped below 1.4mA.
At this point, the micro controller pulls the top line down. This overrides the output of the op amp which is weakened by R5 and shuts Q1 off effectively killing the output and disconnecting the battery from the charger.
The 1.4V represents the 1mA shutoff current of the battery added to the 0.4mA idle current of the micro controller.