2

enter image description here

I am new to Arduino and I have written code that makes 3 LEDs blink while the push button is off, so the lights are blinking from left to right (1,0,0)(0,1,0)(0,0,1) and then repeat from left to right.

Now I am trying to modify this code so that whenever the system receives a High from the switch it reverses the order, so it should start blinking from right to left and keep blinking that way until I press the push button and then return to left to right.

I hope my issue is clear. I only know how to use the if & else.

Here is my code:

int switchState;
int switchst = LOW;
int d=LOW;

void setup() {
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(2,INPUT);
}

void loop() {
  switchState = digitalRead(2);
  if (switchState == HIGH) {
    d= ~d;
    if(d==LOW) {
    digitalWrite(3,~switchst);
    digitalWrite(4,switchst);
    digitalWrite(5,switchst);
    delay(200);
    digitalWrite(3,switchst);
    digitalWrite(4,~switchst);
    digitalWrite(5,switchst);
    delay(200);
    digitalWrite(3,switchst);
    digitalWrite(4,switchst);
    digitalWrite(5,~switchst);
    delay(200);
  }  else {
    digitalWrite(3,switchst);
    digitalWrite(4,switchst);
    digitalWrite(5,~switchst);
    delay(200);
    digitalWrite(3,switchst);
    digitalWrite(4,~switchst);
    digitalWrite(5,switchst);
    delay(200);
    digitalWrite(3,~switchst);
    digitalWrite(4,switchst);
    digitalWrite(5,switchst);
    delay(200);
  }
}

The problem with this code is that it doesn't keep blinking if I release the push button.

This is the old code. It only goes from left to right and keeps repeating.

int switchState = 0;
int switchst = LOW;

void setup() {
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(2,INPUT);
}

void loop() {
  switchState = digitalRead(2);
  if (switchState == switchst) {
    digitalWrite(3,~switchst);
    digitalWrite(4,switchst);
    digitalWrite(5,switchst);
    delay(200);
    digitalWrite(3,switchst);
    digitalWrite(4,~switchst);
    digitalWrite(5,switchst);
    delay(200);
    digitalWrite(3,switchst);
    digitalWrite(4,switchst);
    digitalWrite(5,~switchst);
    delay(200);
  } else {
    digitalWrite(3,switchst);
    digitalWrite(4,switchst);
    digitalWrite(5,switchst);
  }
}

migrated from electronics.stackexchange.com Oct 1 '17 at 23:31

This question came from our site for electronics and electrical engineering professionals, students, and enthusiasts.

  • You need to learn more constructs than if and else. Learn to use a loop, you can then blink the LEDs in an infinite loop, with less and cleaner code too. – Oskar Skog Oct 1 '17 at 18:57
  • hi thanks for your comment I have done it in the class with only if & else but I forgot how and I am only allowed to use if and else. – Bro JJ Oct 1 '17 at 19:02
  • You also need to present code properly indented for legibility. Use blank lines only to separate logical sections. I've edited the first few lines for you ... and you've just overwritten the changes with a simulataneous edit. Oh well! – Transistor Oct 1 '17 at 19:08
  • The first thing I saw was a cartoon where apparently a schematic should have been. Not gonna look at the rest, so closing as unclear. – Olin Lathrop Oct 1 '17 at 20:14
  • 1
    What on earth are you studying if you're not allowed to use loops? – Oskar Skog Oct 1 '17 at 20:15
3

The easiest is to use a 'mode', which is a boolean that keeps the state if it is blinking right, let's call it blinkToRight. Initially this is true.

An if statement will be used to change the order.

So the program will be something like (not tested):

global:

bool blinkToRight = true;

in Setup:

pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
pinMode(2,INPUT);

In Loop:

// Check if loop is reversed
blinkToRight = checkReverse(); 

if (blinkToRight)
{
   show(true, false, false);
   show(false, true, false);
   show(false, false, true);
}
else
{
   show(false, false, true);
   show(false, true, false);
   show(true, false, false);
}


void show(bool led1, bool led2, bool led3)
{
   digitalWrite(2, led1);
   digitalWrite(3, led2);
   digitalWrite(4, led3);
   delay(200);
}

checkReverse will check the input button and returns true if the mode should be reversed.

However, you cannot simply check for the button state. The problem is bouncing. But check in the Arduino examples to a debounce example for this problem and the program should work as expected.

See example: Debounce example

Since only one led will be on, you can also use the following functions for Loop and show:

In Loop:

// Check if loop is reversed
blinkToRight = checkReverse(); 

if (blinkToRight)
{
   show(3);
   show(4);
   show(5);
}
else
{
   show(5);
   show(4);
   show(3);
}

Show:

void show(int ledOn)
{
   digitalWrite(ledOn == 3);
   digitalWrite(ledOn == 4);
   digitalWrite(ledOn == 5);
   delay(200);
}

And it's even better to use constants:

const int LED1   = 3
const int LED2   = 4
const int LED3   = 5
const int BUTTON = 2

Setup:

pinMode(LED1  , OUTPUT);
pinMode(LED2  , OUTPUT);
pinMode(LED3  , OUTPUT);
pinMode(BUTTON, INPUT);

Loop

// Check if loop is reversed
blinkToRight = checkReverse(); 

if (blinkToRight)
{
   show(LED1);
   show(LED2);
   show(LED3);
}
else
{
   show(LED3);
   show(LED2);
   show(LED1);
}

Show:

void show(int ledOn)
{
   digitalWrite(ledOn == LED1);
   digitalWrite(ledOn == LED2);
   digitalWrite(ledOn == LED3);
   delay(200);
}
  • 1
    you should add some delays between the "show()" functions, or have some kind of timing, othewise all the LED will appear as ON... – next-hack Oct 2 '17 at 8:14
  • @next-hack Thanks for the comment, you are absolutely true, and I updated my answer (part of the show function). – Michel Keijzers Oct 2 '17 at 8:40
1

In my opinion, there are two things I'd change. The first one is that delay functions should be avoided whenever possible, the other is that the switch bounces.

In order to solve the bounces, you will have to wait some time to stabilize the signal:

if (debouncedValueOfButton != (digitalRead(button_pin) == HIGH))
{ // Is there a change?
    if (((byte)currMillis) - lastMillisForButton) >= millisButtonDebounce)
    { // Yes, without bounces
        debouncedValueOfButton = !debouncedValueOfButton;
        if (debouncedValueOfButton)
        { // Rising edge
            if (increment > 1)
                increment = 1; // Go in one direction
            else
                increment = 2; // Go in the other direction
        }
    }
}
else
    lastMillisForButton = (byte)currMillis;

So, if the value is different from the one I think it is I'll wait for some milliseconds; if it is stable then I change the value I think it is.

As for removing the delay, I think it is better to use an approach similar to the "blink without delay" sketch:

if ((((uint16_t)currMillis) - lastMillisForBlink) >= millisBetweenBlinks)
{
    lastMillisForBlink += millisBetweenBlinks;
    currentLed = (currentLed + increment) % 3;

    digitalWrite(led0_pin, currentLed == 0);
    digitalWrite(led1_pin, currentLed == 1);
    digitalWrite(led2_pin, currentLed == 2);
}

In this implementation, you use a variable increment to decide whether you have to go forward or backwards; when increment is 1 the led to be colored are 0 -> 1 -> 2 -> (3)0 -> 1 ...; when it is 2 the led are 0 -> 2 -> (4)1 -> (3)0 -> 2 ....

The complete code is (DISCLAIMER: NOT TESTED)

const byte led0_pin = 3;
const byte led1_pin = 4;
const byte led2_pin = 5;
const byte button_pin = 2;

int8_t currentLed, increment;
unsigned int lastMillisForBlink;
const unsigned int millisBetweenBlinks = 200;

bool debouncedValueOfButton;
byte lastMillisForButton;
const byte millisButtonDebounce = 50;

void setup() {
    pinMode(led0_pin,OUTPUT);
    pinMode(led1_pin,OUTPUT);
    pinMode(led2_pin,OUTPUT);
    pinMode(button_pin,INPUT);

    increment = 1;
    currentLed = 2; // At first run, currentLed will be increased by 1, so it starts at 0
    lastMillisForBlink = millis() - millisBetweenBlinks; // trigger a refresh at first loop

    debouncedValueOfButton = (digitalRead(button_pin);
}

void loop() {
    unsigned long currMillis = millis();

    if ((((uint16_t)currMillis) - lastMillisForBlink) >= millisBetweenBlinks)
    {
        lastMillisForBlink += millisBetweenBlinks;
        currentLed = (currentLed + increment) % 3;

        digitalWrite(led0_pin, currentLed == 0);
        digitalWrite(led1_pin, currentLed == 1);
        digitalWrite(led2_pin, currentLed == 2);
    }

    if (debouncedValueOfButton != (digitalRead(button_pin) == HIGH))
    { // Is there a change?
        if (((byte)currMillis) - lastMillisForButton) >= millisButtonDebounce)
        { // Yes, without bounces
            debouncedValueOfButton = !debouncedValueOfButton;
            if (debouncedValueOfButton)
            { // Rising edge
                if (increment > 1)
                    increment = 1; // Go in one direction
                else
                    increment = 2; // Go in the other direction
            }
        }
    }
    else
        lastMillisForButton = (byte)currMillis;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy