2 or 3 LED colors on a single digital pin

I'd like to use a single 5V digital pin to control both colors of a 2 color common cathode LED. When the pin is high and on output I want the green LED lit. When it's on input the red should be lit.

Have I achieved that with this design?

And can I delete D1?

This is based on the digital pin providing a ground for Q1. I've never tried to use a pin like that before and I'm not sure it it will work.

Is it not necessary to both turn it off?

No, this is an indicator for the push button power switch. Green means the unit is operating normally.
When you hold down the power switch it triggers the program saves then lowers the pin to switch to red.
Then the user knows to release the switch which turns everything off.

Yep, you can delete D1. Risk of red LED staying partially on due to emitter being at 7.4V while base being controlled by 5V D-PIN ... I guess that's why you have R3 at a high value (1MΩ). Might need to put the emitter at 5V (VCC) and lower R3 to 10K-100K.

Isn't this okay if you don't need to turn both off? (All of this sentence is a simulator link.)

EDIT:
You can click to change digitalWrite state at simulator.

1 Like

Clamping the leak was my reasoning, the value was a guess.
Now that I think about it I can switch that to a 5V supply that's also available.

That's so much simpler :exploding_head:
Would a BS170 do the trick?

Yes it can.
Let's go breadboard.

1 Like

Ok, got it working, but the green is much brighter than the red.
If I swap the LED anodes the balance is much better, so I swapped the resistors to keep the colors in their correct spots. Is it safe to operate with the resistors swapped?

The resistance can be set as desired according to the required brightness of the LED.

Furthermore, the one LED that lights up when digitalWrite is set to LOW always consumes current.
It only goes off when digitalWrite is set to HIGH, but the current is only changed to flow through the MOSFET instead of the LED.
In addition, the other lit LED draws current from the port, which increases consumption.

In other words, it is best to set the less frequently used LED (red in your case) to the side that lights up when digialWrite is HIGH.

After that, you can freely change the resistance value according to the brightness.


By the way, it is possible to provide the four states of
both OFF , red ON / green OFF , green ON / red OFF and both ON(orange light?)
with a common cathode LED at single Arduino output pin.

But the Arduino output pin must be a PWM capable pin, and use one hardware timer...

The issue with that is that the signal pin is the same signal pin that holds the power supply high, so whatever color I want to show when the machine is running must be on the high side, which I'd prefer be green.
The red one should only ever be lit for a second or two as the machine shuts down.
How important is that?

If it is an indicator lamp, the current of the LED is enough at less than 1mA, so there is almost no need to worry about it.
People who use batteries (like coin cells) that are sensitive to the remaining amount may be important.

However, when the machine is turned off, the 5V power supply is lost at the same time, so the red LED doesn't light up?

Correct, the red only lights for a short moment, then the user releases the button and all power is cut until the button is pressed again.

The red light is the Arduino version of this Windows 95 classic:
image
Which you do by releasing the button.

image

That’s exactly what my 95 computer does on power down. :blush:

1 Like

Is it time for the necessary operations such as actually saving the variables to EEPROM?
Or is it just a funny effects?

Thought I had a code problem but it works great.

Yes, for this project I only have a couple things to save but they are on the ESP32-Cam module so I have to trigger the save and wait for a response. Should be a blink for the user but better to be sure and it's nice to have that control.

The code is pretty simple too:

// Pin Assignments
byte pwr_btn = 10;
byte main_pwr = 11;               // Must remain high to keep main power

// Power button variables
bool pwr_btn_pressed;             // Power button state
uint32_t pwr_btn_prev_time = 0;   // Last time power button was checked
uint16_t pwr_btn_timer = 100;     // Delay between checking
uint16_t shutdown_count = 0;      // Shutdown counter for power button hold
uint16_t shutdown_window = 1000;  // Hold time necessary to shutdown

// Timed event variables
uint32_t time_now = 0;            // Current time
bool new_state;                   // Current state reuse for each timed event

// Forward declarations
void power_off();

void setup() {
  // Hold main power on
  pinMode(main_pwr, OUTPUT);
  digitalWrite(main_pwr, HIGH);
  
  // Set up power button and check state
  pinMode(pwr_btn, INPUT_PULLUP);
  pwr_btn_pressed = digitalRead(pwr_btn) == LOW;
  while (pwr_btn_pressed) {
    // One time start up code if the button is held
    pwr_btn_pressed = digitalRead(pwr_btn) == LOW;
  }
}

void loop() {
  // Check power button
  time_now = millis();
  if (time_now - pwr_btn_prev_time >= pwr_btn_timer) { 
    new_state = digitalRead(pwr_btn) == LOW;
    shutdown_count = pwr_btn_pressed && new_state ? shutdown_count += pwr_btn_timer : 0;
    if (shutdown_count >= shutdown_window) {
      // Saves
      power_off();
    }
    pwr_btn_pressed = new_state;
    pwr_btn_prev_time = time_now; // Advance timer
  } 
  
  // next timed event
}

void power_off() {
  digitalWrite(main_pwr, LOW);
}
Sketch uses 1122 bytes (3%) of program storage space. Maximum is 32256 bytes.
Global variables use 21 bytes (1%) of dynamic memory, leaving 2027 bytes for local variables. Maximum is 2048 bytes.

Is it something like this?
Follow the steps below to operate this simulator.

Shutdown sequence

  1. Press the button switch (digitalRead of the button pin becomes 0)
  2. Arduino saving the register and variable to EEPROM
  3. Arduino changes digitalWrite to LOW and turns off the power (LED turns red)
  4. Release the button switch (LED goes out)

Startup sequence

  1. Press the button switch
  2. Arduino starts up, sets digitalWrite to HIGH and keeps power
    (red LED flash a moment, but humans can't see it)

Yes, but humans can see it.

Shutdown sequence

  1. Press the button switch (digitalRead of the button pin becomes 0)
  2. Program waits for 1 second to pass to ensure the button was not just bumped
  3. Arduino saving the register and variable to SD
  4. Arduino changes digitalWrite to LOW and turns off the power (LED turns red), but you holding the button keeps the power on until
  5. Release the button switch (LED goes out) and everything is off

The cool part about this design is that the Arduino can shut itself down for any other reason too, like sitting idle too long, or battery too low.

I wrote that as a startup sequence description.

If this button switch is used in combination with a power control circuit, I think it has already been achieved.

I got what you meant about the red flash at startup :smiley:
Made a video to show you:

There is a momentarily visible flash of red at the startup
Can't complain though. I feel like it works perfectly.

1 Like