All the circuits work, with two final details to sort out.
Here is the schematic of the circuits I have been working on: [UPDATE] There is an error in the diagram. The input to Q2 should be VCC, not VDD, and R6 is connected to VDD and not VCC.
One thing I still need to solve is the right selection of the PowerFET that switches the 5V supply to the Pi. I ordered the Si3443DV based on the parameters, but I still loose too much voltage over the FET at 500mA.
The voltage drops from just over 5V to just about 4.75.
[update] Even at a Drain-Source On-Resistance of a mere 0.054 Ohm (typical @ 4.5V and 4A) the voltage drop should be only 0.027V, but I'm getting a total drop of 0.3V at 500mA and that is a problem. With a smaller load, the voltage is fine. Am I missing something? I'm certainly no expert on these devices, but if this is about the best you can get, that is not really good enough. I need to study this a bit more, to find out why I seem to get this deviation from the specifications. Can somebody please enlighten me? Otherwise it's back to the drawing board to soup-up the input to compensate for the loss, or use a relay. (The LT1302-5 is fixed, so I would need to change that to the variable version (LT1302) and set the output to 5.3V with two resistors - but I have that chip only in a very tiny SMD version) Stay tuned.
Working with parts that are so small has its challenges when you are testing. I resorted to the following contraption for the Si4334DV, which worked quite well (next to it a "normal" BS170): I have some more parts on order to see if I can improve on the voltage drop. [update] No real improvement
I'm still waiting for my new NiMH's so that part of the circuit is not really complete, although it works.
I had to change some of my thinking regarding the pull-up or pull-down resistors for the GPIO pins. I tried to be smart and use the special function pins of the i2C or the UART, because they are pulled high "automatically". Well, yes and no. During the shutdown period, the PI changes all that, including, but that was to be expected the GPIO pins that you can program to be pulled-high or low.
Can't use that in this case.
In short, the circuit works as follows: When the power is applied, the Pi is halted by the circuit around IC2, a 555 timer, for about 10 seconds. The idea behind that is that when there has been a power glitch, the power may stutter a bit before it gets stable. The circuit I use strangles the Halt pin of the processor. I also use that together with a button and a circuit to halt/shutdown/reset the Pi. I described that in another post.
The circuit around the LT1302-5 has been explained in the posts above, there is basically no change.
The circuit around IC1, the other 555 timer is used to create a delay after a loss of power has been detected, and after the timer is done, the power to the Pi is cut, to preserve the energy in the NiMH cells. The parts that sense a loss of power from the 5.3V supply is not shown, but that is just a voltage divider to get to a nice 3.3V that is used to create a falling edge trigger in the software.
Q4 is used to "gate" the timer signal and avoid false triggering.
In the meantime, I wrote the code that looks for a loss of power, starts the timer and controls the gate that switches off the supply to the Pi.:
Code: Select all
#!/usr/bin/python2.7 from time import sleep import subprocess import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) PWR_GATE = 15 # GPIO-15 : P1-10 PWR_TIMER = 14 # GPIO-14 : P1-8 PWR_SENSE = 22 # GPIO-22 : P1-15 GPIO.setup(PWR_GATE, GPIO.OUT) # Turn power on regardless of timer GPIO.setup(PWR_TIMER, GPIO.OUT) # kill power in 35 seconds after trigger GPIO.setup(PWR_SENSE, GPIO.IN) # Senses the loss of the main 5V supply # Init GPIO.output(PWR_GATE, GPIO.HIGH) # Power on GPIO.output(PWR_TIMER, GPIO.HIGH) # Trigger off def system_action(PWR_SENSE): print ('Negative edge detected on channel %s'%PWR_SENSE) print ('Loss of power detected') GPIO.output(PWR_TIMER, GPIO.LOW) # Toggle timer with a negative edge print ("start timer") sleep(0.1) GPIO.output(PWR_TIMER, GPIO.HIGH) # When the timer starts, it changes the output of the 555. # Wait a moment, then release the power gate to let the 555 timer # switch off the power. sleep (0.1) print ("release power gate") GPIO.output(PWR_GATE, GPIO.LOW) # release power gate # Start the shutdown process print ("shutdown sequence started") subprocess.call(['shutdown -hP now "System shutdown due to power failure" &'], shell=True) GPIO.add_event_detect(PWR_SENSE, GPIO.FALLING, callback=system_action, bouncetime=1000) # setup the thread, detect a falling edge on channel 22 and debounce it with 1 Sec # assume this is the main code... try: while True: # do whatever # while "waiting" for power failure sleep (2) except KeyboardInterrupt: GPIO.cleanup() # clean up GPIO on CTRL+C exit GPIO.cleanup() # clean up GPIO on normal exit
In the process of testing, I found that the power down sequence is such that I changed the timer delay from 45 seconds to about 35 seconds. The power down sequence between the sudo shutdown command and the last R/W activity and dropping of the current from 400-500 mA to about 120 mA is about 20-25 seconds so we have about 10 seconds to spare. The quicker we turn off the Pi, the more we preserve the capacity of the Ni-MH's, so we're ready for more power glitches if needed.
If you want to be more precise, you can also monitor the drop-off of the current by using a shunt in the power line and use a comparator to measure the drop and use it to kill the power.
Because my thermostat application is not time critical, I don't care if the power comes back up while the Pi has started the power down sequence. It will finish that before it restarts again.
Because I used a bread board for everything but the circuit around the LT1302, I may end up changing some R's and C's in the final built, but this should be very close.