Switches to control LEDs and can be read by Arduino

Hello everyone,

It's been quite some time since I did electronics so I'm trying to re-learn everything, and I have big doubts over what I'm prototyping and if my ideas will work.

What I'm attempting to do is have switches which will be manually set before running the Arduino's program, with the switches relating to setting an RBG LED's colour. Rather than have this read by 3 Arduino pins, then use 3 more to power the LED, I want to have the switches allow the Arduino to read the states whilst also enabling the colours of the LED directly.

I've worked up the attached schematic:

Hopefully it shows switches which will be low at the LED and Arduino pins when open, due to the pull-down resistors, and high when closed, enough to power the LED well enough (I have not looked into resistor values much yet, but the LED resistor is about 400 Ohms while the pull-down is 10 kOhms). The cathode of the LED is wired up to the Arduino as an output pin, as I want to be able to control when the LED is lit from the code, so by setting the pin high, the LED won't light, and when low, current will flow.

Can anyone see any problems before I start putting this together and frying it?!

edit: I've just noticed my wiring from the switch to the LED has two of the colours tied... Stupid mistake there! I've been suffering with a headache for a week and can't think straight... But barring this mistake, does the principle work?

TIA,
Mike

OP’s image.

Here is a circuit that shows LEDs and switches being used on the same pins.

/*
  Demonstration how to use a pin as an output to a LED
  and at the same time, as an input from a switch.
 
  Note:
  The LED(s) 'must' be connected to +5V (CA) through a series resistor.
  The switch is connected to GND through a 240 ohm resistor.
 
  Typical setup for SMD LEDs:
  +5V White  LED - 4.7K - I/O PIN - 240R - Switch GND
  +5V Red    LED - 2.2K - I/O PIN - 240R - Switch GND
  +5V Green  LED - 1.2K - I/O PIN - 240R - Switch GND
  +5V Blue   LED - 4.7K - I/O PIN - 240R - Switch GND
  +5V Yellow LED - 2.2K - I/O PIN - 240R - Switch GND
 
  Version YY/MM/DD
  1.00    17/06/01   Running code
*/
 
//Assume 6 LED/Switch combinations are connected to pins as below
const byte HeartBeatLED  = 41; //Heart beat LED, toggles on and off showing if there is blocking code
const byte YellowLED     = 40; //This LED will be toggled when the switch on this pin is pressed
const byte BlueLED       = 37; //This LED will be toggled when the switch on this pin is pressed
const byte GreenLED      = 36; //This LED will be toggled when the switch on this pin is pressed
const byte RedLED        = 35; //This LED will be toggled when the switch on this pin is pressed
const byte WhiteLED      = 34; //This LED will be toggled when the switch on this pin is pressed
 
byte lastYellowSwitchState; //The state this switch was in
byte lastBlueSwitchState;
byte lastGreenSwitchState;
byte lastRedSwitchState;
byte lastWhiteSwitchState;
 
//======================================================================
//An example of Timer 'structure' coding
struct timer
{
  //lastMillis = the time this "timer" was (re)started
  //waitMillis = delay time (mS) we are looking for
  //restart    = do we start "this timer" again and again
  //enableFlag = is "this timer" enabled/allowed to be accessed
  //timeType   = true = millis(), false = micros()
  //**********************
  //For each timer object you need:
  //Example:
  //   timer myTimer = //give the timer a name "myTimer"
  //   {
  //     0, 200UL, true, true, true  //lastMillis, waitMillis, restart, enableFlag, timeType
  //   };
  // You have access to:
  // myTimer.lastMillis, myTimer.waitMillis, myTimer.restart, myTimer.enableFlag, myTimer.timeType, myTimer.CheckTime()
  //**********************
 
  unsigned long lastMillis;
  unsigned long waitMillis;
  bool          restart;
  bool          enableFlag;
  bool          timeType;
 
  unsigned long currentTime;
 
  bool CheckTime() //Delay time expired function "CheckTime()"
  {
    if (timeType == true)
    {
      currentTime = millis();
    }
    else
    {
      currentTime = micros();
    }
 
    //is the time up for this task?
    if (enableFlag == true && currentTime - lastMillis >= waitMillis)
    {
      //should this start again?
      if (restart)
      {
        //get ready for the next iteration
        lastMillis = currentTime;
      }
      //time was reached
      return true;
    }
    //time was not reached
    return false;
 
  } //END of CheckTime()
 
}; //END of structure timer
//======================================================================
 
//**********************************************************************
//                Create and initialize timer objects
//**********************************************************************
timer heartBeatLED =          //create timer for the heartBeatLED
{
  0, 100UL, true, true, true            //lastMillis, waitMillis, restart, enableFlag, true=millis/false=micros
};
 
timer checkSwitches =         //create a timer to check the switches
{
  0, 50UL, true, true, true   //lastMillis, waitMillis, restart, enableFlag, true=millis/false=micros
};
 
 
 
//                            s e t u p ( )
//**********************************************************************
void setup()
{
  //**************************************
  digitalWrite(HeartBeatLED, HIGH);  //LED  LOW = ON
  pinMode(HeartBeatLED, OUTPUT);
 
  digitalWrite(YellowLED, HIGH); //LED  LOW = ON
  pinMode(YellowLED, OUTPUT);
 
  digitalWrite(BlueLED, HIGH);   //LED  LOW = ON
  pinMode(BlueLED, OUTPUT);
 
  digitalWrite(GreenLED, HIGH);  //LED  LOW = ON
  pinMode(GreenLED, OUTPUT);
 
  digitalWrite(RedLED, HIGH);    //LED  LOW = ON
  pinMode(RedLED, OUTPUT);
 
  digitalWrite(WhiteLED, HIGH);  //LED  LOW = ON
  pinMode(WhiteLED, OUTPUT);
 
} //                    E N D  O F  s e t u p ( )
 
 
//                             l o o p ( )
//**********************************************************************
void loop()
{
  //***************************
  //HeartBeat LED
  if (heartBeatLED.CheckTime())
  {
    //Toggle HeartBeatLED
    digitalWrite(HeartBeatLED, !digitalRead(HeartBeatLED));
  }
 
  //***************************
  // Non blocking code goes here
  //***************************
 
  //Is it time to check the Switch(s)?
  if (checkSwitches.CheckTime())
  {
    handleSwitchPresses();
  }
 
} //                     E N D  O F  l o o p ( )
 
 
//======================================================================
//                         F U N C T I O N S
//======================================================================
 
//**********************************************************************
//               h a n d l e S w i t c h P r e s s e s ( )
//**********************************************************************
void handleSwitchPresses()
{
  //Read our five switches
 
  byte CurrentSwitchState;
 
  //***************************
  //Has the switch changed position for this pin?
  CurrentSwitchState = ReadSwitchLED(YellowLED);
  if (lastYellowSwitchState != CurrentSwitchState)
  {
    //update to the new switch state
    lastYellowSwitchState = CurrentSwitchState;
   
    //when the switch goes from not pushed (HIGH) to pushed (LOW) then do something
    if (CurrentSwitchState == LOW)
    {
      //example: toggle the LED on this pin
      digitalWrite(YellowLED, !digitalRead(YellowLED));
    }
  }
 
  //***************************
  CurrentSwitchState = ReadSwitchLED(BlueLED);
  if (lastBlueSwitchState != CurrentSwitchState)
  {
    lastBlueSwitchState = CurrentSwitchState;
    if (CurrentSwitchState == LOW)
    {
      digitalWrite(BlueLED, !digitalRead(BlueLED));
    }
  }
 
  //***************************
  CurrentSwitchState = ReadSwitchLED(GreenLED);
  if (lastGreenSwitchState != CurrentSwitchState)
  {
    lastGreenSwitchState = CurrentSwitchState;
    if (CurrentSwitchState == LOW)
    {
      digitalWrite(GreenLED, !digitalRead(GreenLED));
    }
  }
 
  //***************************
  CurrentSwitchState = ReadSwitchLED(RedLED);
  if (lastRedSwitchState != CurrentSwitchState)
  {
    lastRedSwitchState = CurrentSwitchState;
    if (CurrentSwitchState == LOW)
    {
      digitalWrite(RedLED, !digitalRead(RedLED));
    }
  }
 
  //***************************
  CurrentSwitchState = ReadSwitchLED(WhiteLED);
  if (lastWhiteSwitchState != CurrentSwitchState)
  {
    lastWhiteSwitchState = CurrentSwitchState;
    if (CurrentSwitchState == LOW)
    {
      digitalWrite(WhiteLED, !digitalRead(WhiteLED));
    }
  }
 
} //      E N D   O F   h a n d l e S w i t c h P r e s s e s ( )
 
 
//**********************************************************************
//                    R e a d S w i t c h L E D ( )
//**********************************************************************
byte ReadSwitchLED(byte thisPin)
{
  //Save the current state of this output pin
  byte PinState = digitalRead(thisPin);
  //read the switch connected to this pin
  pinMode(thisPin, INPUT_PULLUP);
  byte SwitchState = digitalRead(thisPin);
  //return the pin to OUTPUT
  pinMode(thisPin, OUTPUT);
  //restore the pin state
  digitalWrite(thisPin, PinState);
 
  return SwitchState;
 
} //            E N D   O F  R e a d S w i t c h L E D ( )
 
 
//======================================================================
//                         E N D  O F  C O D E
//======================================================================

Aah I see, so rather than just using the current flow with hardware (which I thought it would be simple to do), you're momentarily switching the pin from a digital output to input pull-up just to read the switch. :slight_smile:

Ok I'll try to incorporate this into my design, looks pretty simple in terms of components, I'll just have to spend a lot more time in the code.

Thanks larryd!

Mike

Can this be implemented in reverse?

The RBG LED is common cathode, so I'd need to have the branch off to the Arduino before the current flow to the LED, so in my case the switches would have to be by the 5V rail and LED by ground. It'll just need the corresponding inverting of the switch state detection, right?

Cheers,
Mike

“ RBG LED is common cathode”

Buy a “Common Anode”. :wink:

Haha fair enough :stuck_out_tongue:

“I'll just have to spend a lot more time in the code.”

There is a sketch below the image that you can scavenge.

Oh totally, I've looked through it and thanks for sharing that. It'll certainly speed up me putting something together to make it work. It's just a much more flexible and robust script than I'd probably have put together by myself so that's why I said it would take longer for me to get going!

2017-07-09_9-48-23.jpg
Not sure what the IC block is on the right, but for an Arduino, the lower resistors are unnecessary unless the intention is to allow the LED to be OFF despite the switch being closed - which as I understand, is not the OP's expectation..

A common anode LED arrangement is more practical as to sense the switches, you use INPUT_PULLUP, when you are not either sensing or driving the LEDs, you use INPUT and to illuminate the LED, you write LOW and then set to OUTPUT.

Note of course, that you need to avoid writing an OUTPUT as HIGH, so to actuate INPUT_PULLUP, you first set to INPUT and then write HIGH. To illuminate the LED, you first write LOW and only then set to OUTPUT. :astonished:

“ Not sure what the IC block is on the right,”

That is just a connector/header, A, B, C . . . go straight to Arduino output/inputs.


“ the lower resistors are unnecessary ”

They are needed as an Arduino output/input pin can be 0v or 5v; if the output was at 5v and a switch
(with no lower resistor) was closed we would have a short :(.


Scope readings for different conditions.

larryd:
They are needed as an Arduino output/input pin can be 0v or 5v; if the output was at 5v and a switch
(with no lower resistor) was closed we would have a short :(.

Which is precisely why I carefully explained how to program it.

It is perfectly common practice to connect switches directly to Arduino inputs - in fact the recommended practice to connect them between an Arduino input and ground. No series resistor. :roll_eyes:

“It is perfectly common practice to connect switches directly to Arduino inputs - in fact the recommended practice to connect them between an Arduino input and ground. No series resistor. ”

Agreed.

I am a bit dense. :confused:

Referring to the schematic in post#2.

The resistor is there for two reasons:

  • As mention, to prevent possible damage to the Arduino pin when the pin is set to output and then it is set HIGH.

A HIGH would be needed when driving external I/O.

Yes, for this cct. turning the LED OFF can also be done by making the pin an INPUT.
Setting the pin to input with pull-ups 'might be' valid as there would be some current the could drive I/O.
20-50k is high though and the PCB LED might also be on dim.

  • When the Arduino wants to toggle a LED ‘or send levels to I/O’, the pin is set to output and HIGH and LOW levels are sent.

If the resistor ‘was zero’ ohms, pushing and holding the switch would keep the LED on all the time.

With the resistor, a HIGH on the pin, when set to output, would place 5V across the 240R resistor with ~20mA flow.

“Note of course, that you need to avoid writing an OUTPUT as HIGH, so to actuate INPUT_PULLUP, you first set to INPUT and then write HIGH. To illuminate the LED, you first write LOW and only then set to OUTPUT. ”

Doing this you never get a 5V level on the pin that can be used to drive I/O.

Anyway, a 240R resistor is 1 cent. :wink:

Hey guys, thanks a lot for your careful explanations. It looks like there are a lot of subtleties to pick up, with the order of setting pin modes and values, etc, so I'll stick to your suggestions until I learn a lot more about potential pitfalls!

larryd:
With the resistor, a HIGH on the pin, when set to output, would place 5V across the 240R resistor with ~20mA flow.

Yes. The only reason for the resistor, is to allow you to drive the output HIGH in order to prevent the LED showing despite the button being pressed. But then it will briefly illuminate - which may be quite noticeable - when you wish to read the button by setting INPUT_PULLUP. :roll_eyes:

larryd:
Setting the pin to input with pull-ups 'might be' valid as there would be some current the could drive I/O.
20-50k is high though and the PCB LED might also be on dim.

I have no idea what you are saying there, as the LEDs are connected to the 5 V and in parallel with the INPUT_PULLUP. :astonished:

“But then it will briefly illuminate - which may be quite noticeable”

For ~8.6us, you see only if you turn off the surrounding lights.


The PCB LED (schematic in post #2) might also be on dim.
“ I have no idea what you are saying there, as the LEDs are connected to the 5 V and in parallel with the INPUT_PULLUP.”

When A-F are connected to a load: i.e. base resistor, the base of a BJT, the BJT emitter to GND.

If we were to turned OFF the LED by setting the Arduino pin to input/inputpullup then:
current flow would be: +5v, LED anode/cathode, LED resistor, A-F lead, load’s base resistor, BJT’s base, BJT base emitter GND.

Hence, the LED could come on dimly as of this base current.

Using the pin set to output, then set to HIGH keeps the LED OFF.

Edit, added image:

So, nothing to do with the original application then; you are introducing something else entirely. :astonished:

Whatever! :roll_eyes:

No, I am explaining how adding the switch/led combination to the real world is filled with complexities.

I am tired.

Guys,

It took me a while to digest this, due to my inexperience and recent illness, but now I've had some time to go through your points I wanted to thank you both for your help and information.

To go back to my initial problem, I restructed things to do more in the sketch rather than by switches, but it's came back around as very useful for a follow-up piece. So I'd like to check I'm following what you've both said.

Working from larryd's post #2, I see how one pin can sense a switch and control an LED (so thanks again larryd!). The LEDs are actived with an Output pin and switches read with an Input pullup pin. I had originally just thought that the LED would be controlled with a toggle between high and low ouputs, but see that this could be dangerous for the Arduino, so rather than turning the LED off with high output you would recommend setting the pin to input? I hadn't considered what state this would create at the pin and how it would affect current flow.

In terms of the switch resistors in there, they are to stop any High Outputs from pulling a huge current if the switch is closed, allowing an high output as a safe and valid option to switch the LED off (correct?), but this can also be achieved with no switch resistor and careful output settings as Paul__B suggested. BTW I wasn't aware you would have to set as input_pullup then write high, I assumed setting this mode would automatically write the pin to high.

The other difference you have mentioned between having switch resistors and not is that closing the switches may light the LEDs no matter the pin state/mode. I'm not sure I follow the reason behind this, as the resistor values are relatively small compared to the LED resistors so I'm not sure why this would make a large enough difference to prevent LEDs from activating.

Sorry for the questions but basic knowledge doesn't seem to cut it when it comes down to small subtlties like this!

Thanks again,
Mike

“In terms of the switch resistors in there, they are to stop any High Outputs from pulling a huge current if the switch is closed, allowing an high output as a safe and valid option to switch the LED off (correct?)“

Yes, you just graduated. :slight_smile: