Pipad: Debugging the power button


View or comment on this project log on Hackaday.io

Hey, I'm back with a simple one today. Between the holidays and general life stuff, I haven't found time to work on this project for a while. Motivation on hobby projects seems to ebb and flow. Hopefully it's starting to flow again.

I saw a post on the Facebook group "Raspberry Pi and DIY Projects" where someone was using the MAX16150 IC to handle power on/off for their Pi, and it inspired me to try and get my MAX16150-based circuit working.

One of the typical application circuits from page 16 of the MAX16150 datasheet, showing it controlling the enable pin on a power supply for a power-hungry device.

The MAX16150 monitors a push button on its PB_IN pin. A short press of the button will either turn on the OUT pin, or if it's already on, send a brief low pulse on the INT pin. The MCU (the CM4 in my case) can detect this pulse and handle it gracefully, by e.g. starting a soft shutdown.

If you press the power button for 8 seconds, the MAX16150 will deassert the OUT pin (pull it low), cutting power to the downstream device. This is consistent with the power button behavior of most computers, tablets, and phones.

If the CLR pin goes low, the MAX16150 will deassert the OUT pin. This is used to give the MCU a way to shut off its own power, and also provides some power watchdog functionality -- if the power goes low for some reason, like a short circuit or a dead battery, the MAX16150 will shut off the power.

I more or less followed the typical application circuit above in my own design:

On my current revision of the PCB, the PWR_BUTTON_INT net connects to GPIO22 on the CM4, while PWR_CLR connects to the nEXTRST pin on the CM4.

nEXTRST is meant to indicate that power is good on the CM4, so it can be used for driving the RST pin on EXTernal devices that need to be powered when the Pi is powered. I assumed this would mean it would go low when the Linux kernel halts.

However, this approach has two problems:

  1. Turns out that nEXTRST is not pulled low when the kernel halts.
  2. nEXTRST stays low for around 200ms after 5V power is applied to the CM4.

The second problem is more severe. After asserting the OUT pin, the MAX16150 will ignore the CLR pin for 2x its interrupt period (32ms on my version. Different versions exist, but they're less "add to your Digikey cart" and more "call the factory to custom order".) When that 64ms has elapsed, if CLR is still low, the MAX16150 deasserts OUT again, which cuts power to the downstream device.

It turns out that this isn't an artificial delay on the nEXTRST pin - it actually just takes about 200ms for the CM4's 3.3V supply to start when 5V is applied.

I had originally worked around this by cutting the CLR<->nEXTRST trace on the PCB and then connecting CLR to 5V with a resistor. I then connected an extra push button between CLR and ground, to give me a way to cut power. However, this meant the Pi had no way to turn off its own power, and I had to manually click that second button any time I did a shutdown, or it would sit there, halted, drawing a nontrivial amount of power.

I've improved on this bodge in a way that I think is suitable to incorporate into my next PCB revision:

This causes the INT pin to come up as soon as the 5V supply is good, but also keeps the voltage at a safe enough level for the GPIO pin, which is only 3.3V-tolerant.

At bootup, the GPIO pin seems to have a weak pull-down resistor, so the INT pin ends up with around 3.0V on it instead of 3.3V, but this is high enough for the MAX16150 to treat it as high.

With the following configuration in /boot/config.txt, I now have startup and shutdown behavior that works exactly as I intended.


I should have a few more updates for you shortly - I'm working on a new revision of the PCB which incorporates these fixes, as well as some other modifications I've had to make, and I'd like to double-check some other functionality before I commit to another PCB spin, in case I need to make more changes.