One of my designs needs a soft power button with sense output. I'm posting my design here to be reviewed and improved.
To make the experience fit your profile, pick a username and tell us what interests you.
We found and based on your interests.
It works!
The initial goal was to have a simple push button to
My breadboard is populated with:
The basic routing is battery -> power button -> reg -> teensy, and the teensy keeps an eye on the power button's sense output and controls the keep_alive signal (active high):
And here's the sketch:
#define SENSE_PIN 34
#define KEEP_ALIVE_PIN 33
#define LED_PIN LED_BUILTIN
bool power_button_pressed()
{
return !digitalRead(SENSE_PIN);
}
void setup() {
// put your setup code here, to run once:
pinMode(SENSE_PIN, INPUT_PULLUP);
pinMode(KEEP_ALIVE_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, 1);
digitalWrite(KEEP_ALIVE_PIN, 1);
while(power_button_pressed());
Serial.println("Starting up");
}
void loop() {
static bool power_wait_off = false;
static const uint16_t power_off_time = 2000;
static elapsedMillis power_off_timer;
if((!power_wait_off) && power_button_pressed())
{
Serial.println("Starting power button timeout");
power_wait_off = true;
power_off_timer = 0;
}
else if(power_wait_off && (!power_button_pressed()))
{
Serial.println("Aborting power button timeout");
power_wait_off = false;
}
else if(power_wait_off && (power_off_timer > power_off_time))
{
digitalWrite(LED_PIN, 0);
Serial.print("powering down, let go of that button.");
while(power_button_pressed());
delay(500);
digitalWrite(KEEP_ALIVE_PIN, 0);
while(1); // loop until power is gone
}
}
The sketch not only implements the "sense and keep_alive thing", but also takes care of two caveats:
This was in the mail two days ago:
There were a second sticker and a third board but I just wanted to show top and bottom here.
The board cuts aren't really clean:
The result after soldering (the Aisler stencil did a good job!) and adding a teensy:
In that circuit, I just use the teensy to
Here's the sketch, which
#define SENSE_PIN 0
#define POWER_PIN 1
#define KEEP_ALIVE_PIN 2
void setup() {
pinMode(SENSE_PIN, INPUT_PULLUP);
pinMode(POWER_PIN, INPUT_PULLDOWN);
pinMode(KEEP_ALIVE_PIN, OUTPUT);
digitalWrite(KEEP_ALIVE_PIN, 0);
}
void loop() {
static const uint16_t on_time = 2000;
static elapsedMillis on_timer;
static bool on = false;
static const uint16_t print_time = 250;
static elapsedMillis print_timer = print_time;
if(!digitalRead(SENSE_PIN))
{
on_timer = 0;
on = true;
digitalWrite(KEEP_ALIVE_PIN, 1);
}
else if(on && (on_timer == on_time))
{
digitalWrite(KEEP_ALIVE_PIN, 0);
on = false;
}
if(print_timer >= print_time)
{
Serial.printf("sense: %01d | power: %01d | on: %01d\n", digitalRead(SENSE_PIN), digitalRead(POWER_PIN), on);
print_timer = 0;
}
}
This worked as expected.
I also tried to modify the circuit to make it latch by itself. It just needed a strong enough pullup resistor (I had 2k7 at hand) from Q2's base to Vbat_out and once the button was pressed, power stayed on by itself.
Next: Test with a Teensy that can shut itself off with this circuit, because that's waht I had in mind when I started this project.
So this is what I'll try:
There's only one modification compared to the schematic in the previous log: A cap between Q1's gate and Vbat_in. When the button is pressed, this cap will be charged and keep the mosfet open should the switch bounce.
One of the headers has the same pinout as standard TO-220 MOSFET (G-D-S) so Q1 can be replaced by an external larger transistor, even on a breadboard.
The PCB:
The switch is centered so the board won't lean over when pressing the switch while breadboarded.
A pack of these is ordered from both oshpark and aisler, I'll compare, solder and test them when they're here.
I'll start with this one and write about how I (partially) understand it. It's basically the third schematic from the previous log plus a pull-down resistor for Q2's gate:
As soon as SW1 is pressed and the MCU is supplied with power, the MCU has to pull up Q2's gate to keep power enabled. The application can use the sense signal to get input from the push button. If, for example, the button is pressed for more than 1 second, the MCU can run some cleanup code and let go of the keep alive signal.
So much for the theory as I understand it. If you spot any serious flaws in this (especially component choice, since the basic circuit seems to be one that has been proven to work) please leave a comment.
I might remove R4. If this is built as a breadboardable pcb, the user can then choose to either pull Q2's base up or down depending on the application's needs.
Since there are many circuits which do something very similar to what this circuit should do, I'll have a look at some of those first.
From https://electronics.stackexchange.com/a/140416/18496
This one seems to be a bit minimalistic, but doesn't have anything I don't need. There's no "press and hold button to switch off again" for example. OTOH, it doesn't feature a sense output to be read by an MCU.
Next one is again from stack exchange:
There was a lot to find in the eevblog forums. This thread for example. From that one:
That looks simple enough and it might do what I need. Some things to consider:
Create an account to leave a comment. Already have an account? Log In.
Become a member to follow this project and never miss any updates
Great project! I like the idea of using only standard components which makes the design more adaptable. For the people looking for the most compact (and expansive) solution, the MAX16054 may be a good option (this is just for inspiration, not as replacement for your project). Thx again!