Close

PCB and firmware update

A project log for LiFePO4wered/Pi+

Next Gen LiFePO4 battery / UPS / power manager for Raspberry Pi, ideal for headless and IoT use

patrick-van-oosterwijckPatrick Van Oosterwijck 12/15/2017 at 19:210 Comments

I got my new proto PCBs from OSH Park, 0.8mm 2oz copper this time:

It has the improvements described in the previous project log, you can see the new DFN power MOSFET footprint for instance.  I was getting ready to populate some prototypes by updating the BOM, until I noticed I had the wrong power MOSFET!

That AON7408 I talked about last time?  Well turns out it's an N-channel MOSFET, and I need P-channel.  How I ever missed that while tearing apart the datasheet, I don't know.  So, I decided to use an Infineon BSZ120P03NS3 instead.  It's more expensive, but the safe operating area looks even better:

Since I'm ordering production quantities to save time, I think this MOSFET should definitely have enough margin to work at high input voltages.

On the firmware front, a LOT of work has been done.  I mean a TON.  Unfortunately most time has been spent chasing an elusive bug.  I think I finally got to the bottom of it.  Although it's more a patch than a root cause solution, it's as good as it will get, since the bug seems to be related to a hardware limitation.

I really don't like the I2C peripheral in the small MSP430G micros I'm using.  Calling it a hardware I2C peripheral is an overstatement, it's more like a glorified shift register.  At every I2C related event, it requires software assistance.  8 bits are received: interrupt, set up for sending ACK.  1 bit sent: interrupt, set up for receiving 8.  Start condition, stop condition: all handled in software.  It stinks.

So when I needed to add shadow buffering to ensure the 4-byte RTC would be written atomically, I seem to have upset a delicate timing balance.  Something in the timing was screwed up so sporadically the end of one packet and beginning of another would not be detected, causing the 8-bit I2C address with r/w bit and some other bytes (usually 0xFF because of reading) to be written over registers.  Registers such as the LED state (not good) or the I2C address (very bad) would be overwritten, with symptoms ranging from a flashing LED to killing communication.

I tried for weeks, even months to track this down and fix it, but I think I just can't make it 100% reliable with this hardware.  With the shadow buffering added, there's just too much code running and based on when different other interrupts (timers, ADC) end up running, I can't guarantee the I2C baby sitting code will always run on time.  This is of course compounded by the fact that the Raspberry Pi has a retarded I2C peripheral as well that pays no attention whatsoever to I2C clock stretching, but just barges on even if the peripheral can't keep up.

So I did the next best thing: I implemented a patch to prevent stray writes to I2C registers.  After the register to be written is received, the LiFePO4wered/Pi+ now expects an "unlock code" that is a combination of the I2C address, a magic value and the register to be written.  Once this is received correctly, the other bytes are written.  It just requires a small update to the host driver code.

Other firmware updates: boot and shutdown timeouts, 32kHz crystal timers, RTC code, higher resolution oversampled ADC values, touch timing fixes, 10-second button hold to force off.  Many of these improvements will also carry over to the #LiFePO4wered/Pi as well, except those requiring a 32kHz crystal.

Discussions