On-Off-On Toggle Switch Problems

For testing a method of switching between "modes," I connected an RGB LED to a toggle switch. My goal was to have one color on if toggle switch was up, LED off if switch is middle, and a different color on if switch is down.

Here's my code:

int redPin = 8;
int bluePin = 9;
int toggle1 = 6;
int toggle2 = 7;

void setup() {
  pinMode(redPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  pinMode(toggle1, INPUT);
  pinMode(toggle2, INPUT);
}

void loop() {
  
  if (digitalRead(toggle1) == HIGH && digitalRead(toggle2) == LOW)
  {
    digitalWrite(redPin, LOW);
    digitalWrite(bluePin, HIGH);
  }

  else if (digitalRead(toggle1) == LOW && digitalRead(toggle2) == HIGH)
  {
    digitalWrite(redPin, HIGH);
    digitalWrite(bluePin, LOW);
  }
  else if (digitalRead(toggle1) == HIGH && digitalRead(toggle2) == HIGH)
  {
    digitalWrite(redPin, HIGH);
    digitalWrite(bluePin, HIGH);
  }
  
  else (digitalRead(toggle1) == LOW && digitalRead(toggle2) == LOW);
  {
    digitalWrite(redPin, HIGH);
    digitalWrite(bluePin, HIGH);
  }
}

My circuitry: Toggle Switch connected to 5v in middle and pins 6 and 7 on outer terminals. RGB LED (common cathode) connected to 5v and blue/red connections are on pins 8 and 9. Arduino powered via USB.

The program works as expected, except for one thing. When in the middle position, which should be OFF, the LED is sort of flickering with a tiny bit of red and a tiny bit of blue. It never turns fully off. You can see what I mean in this video:

https://www.youtube.com/watch?v=U-ACD1m4ejE

Is this a common issue with 3 way toggle switches? Or is there something wrong with my switch and/or code?

Thank you for all help in advance! Adam

Try connecting 6 and 7 to 10K resistors to GND. Your inputs were floating and should be referenced to ground in this particular example.

If you connect the middle pin of the switch to GND you can use the internal pullup resistors with pinMode(toggle1, INPUT_PULLUP) etc. Then the pin will read LOW when the switch is "on".

Using the internal resistors means there is no requirement for 5v wires running around with the possibility of a short circuit.

...R

Robin2: If you connect the middle pin of the switch to GND you can use the internal pullup resistors with pinMode(toggle1, INPUT_PULLUP) etc. Then the pin will read LOW when the switch is "on".

Using the internal resistors means there is no requirement for 5v wires running around with the possibility of a short circuit.

...R

Thank you, that worked!

Now I tried doing something different; one position will turn a solid color on, and the other will allow the color to be controlled via potentiometer. Here's what I have for that:

const int redPin = 9;
const int greenPin = 10;
const int bluePin = 11;

int toggle1 = 6;
int toggle2 = 7;

const int redPot = 2;
const int bluePot = 1;
const int greenPot = 3;

int currentRed;
int currentGreen;
int currentBlue;

void setup() {
  pinMode(redPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(toggle1, INPUT_PULLUP);
  pinMode(toggle2, INPUT_PULLUP);
}

void loop() {
  
  if (digitalRead(toggle1) == HIGH && digitalRead(toggle2) == LOW)
  {
    analogWrite(redPin, 255); //this mode works
    analogWrite(bluePin, 0);
  }

  else if (digitalRead(toggle1) == LOW && digitalRead(toggle2) == HIGH)
  {
    currentRed = map(analogRead(redPot), 0, 1024, 0, 255); //this mode does NOT work
    currentGreen = map(analogRead(greenPot), 0, 1024, 0, 255);
    currentBlue = map(analogRead(bluePot), 0, 1024, 0, 255);
  
    analogWrite(redPin, 255 - currentRed);
    analogWrite(greenPin, 255 - currentGreen);
    analogWrite(bluePin, 255 - currentBlue);
  }
  else if (digitalRead(toggle1) == HIGH && digitalRead(toggle2) == HIGH)
  {
    analogWrite(redPin, 255);
    analogWrite(bluePin, 255);
  }
  
  else (digitalRead(toggle1) == LOW && digitalRead(toggle2) == LOW);
  {
    analogWrite(redPin, 255);
    analogWrite(bluePin, 255);
  }
}

But it's not working! All I did was pop some potentiometer control code into one of the else if statements. The mode where I write bluePin = 0 and redPin = 255 works perfectly, but the other mode does not. I just get a random flicker of red and blue. Originally I thought it was because I was combining digitalWrite and analogWrite in the same sketch, but as you can see I changed all those and it still does not work. Any suggestions?

Temporarily put a long delay() - maybe 5000 - after the third analogWrite(). If the problem is that the values are being overwritten that will allow time to see them., and you will know whether the analogRead()s are working as you want.

...R

I got it working for now. Since I only have one pot on hand, I commented out the unused analogWrite() and potPin's. Here's the code I'm using:

const int redPin = 9;
const int greenPin = 11;
const int bluePin = 10;

int toggle1 = 6;
int toggle2 = 7;

const int redPot = 2;
//const int bluePot = 1;
//const int greenPot = 3;

int currentRed;
int currentGreen;
int currentBlue;

void setup() {
  pinMode(redPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(toggle1, INPUT_PULLUP);
  pinMode(toggle2, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {
  
  if (digitalRead(toggle1) == HIGH && digitalRead(toggle2) == LOW)
  {
    analogWrite(redPin, 255);
    analogWrite(bluePin, 0);
  }

  else if (digitalRead(toggle1) == LOW && digitalRead(toggle2) == HIGH)
  {
    currentRed = analogRead(redPot)/4;
    currentGreen = 255; //map(analogRead(greenPot), 0, 1024, 0, 255);
    currentBlue = 255; //map(analogRead(bluePot), 0, 1024, 0, 255);
      
    analogWrite(redPin, 255 - currentRed);
    //analogWrite(greenPin, currentGreen);
    //analogWrite(bluePin, currentBlue);
    
    Serial.println(currentRed, DEC);
  }
  else if (digitalRead(toggle1) == HIGH && digitalRead(toggle2) == HIGH)
  {
    analogWrite(redPin, 255);
    analogWrite(bluePin, 255);
  }
  
  else (digitalRead(toggle1) == LOW && digitalRead(toggle2) == LOW);
  {
    analogWrite(redPin, 255);
    analogWrite(bluePin, 255);
  }
}

But... you guessed it. There's a problem :P For values up to about 135-140 going to the LED, it flickers pretty noticeably. Almost like it's ready two commands at once (something telling to turn off and then turn right back on again). Any ideas here?

Give this a go:

// INPUT: Potentiometer should be connected to 5V and GND
int potPin = 3; // Potentiometer output connected to analog pin 3
int potVal = 0; // Variable to store the input from the potentiometer

// OUTPUT: Use digital pins 9-11, the Pulse-width Modulation (PWM) pins
// LED's cathodes should be connected to digital GND
int redPin = 9;   // Red LED,   connected to digital pin 9
int grnPin = 10;  // Green LED, connected to digital pin 10
int bluPin = 11;  // Blue LED,  connected to digital pin 11

// Program variables
int redVal = 0;   // Variables to store the values to send to the pins
int grnVal = 0;
int bluVal = 0;

void setup()
{
  pinMode(redPin, OUTPUT);   // sets the pins as output
  pinMode(grnPin, OUTPUT);   
  pinMode(bluPin, OUTPUT); 
}

// Main program
void loop()
{
  potVal = analogRead(potPin);   // read the potentiometer value at the input pin

  if (potVal < 341)  // Lowest third of the potentiometer's range (0-340)
  {                  
    potVal = (potVal * 3) / 4; // Normalize to 0-255

    redVal = 256 - potVal;  // Red from full to off
    grnVal = potVal;        // Green from off to full
    bluVal = 1;             // Blue off
  }
  else if (potVal < 682) // Middle third of potentiometer's range (341-681)
  {
    potVal = ( (potVal-341) * 3) / 4; // Normalize to 0-255

    redVal = 1;            // Red off
    grnVal = 256 - potVal; // Green from full to off
    bluVal = potVal;       // Blue from off to full
  }
  else  // Upper third of potentiometer"s range (682-1023)
  {
    potVal = ( (potVal-683) * 3) / 4; // Normalize to 0-255

    redVal = potVal;       // Red from off to full
    grnVal = 1;            // Green off
    bluVal = 256 - potVal; // Blue from full to off
  }
  analogWrite(redPin, redVal);   // Write values to LED pins
  analogWrite(grnPin, grnVal); 
  analogWrite(bluPin, bluVal);  
}
else (digitalRead(toggle1) == LOW && digitalRead(toggle2) == LOW);

I think this line is the problem.

If you just mean it to be an else there should be no code in brackets In any case, the semi-colon concludes the else and allows the following two lines to operate in every case

I think it should be

else 
  {
    analogWrite(redPin, 255);
    analogWrite(bluePin, 255);
  }

...R