Arduino Forum

Using Arduino => Programming Questions => Topic started by: rhaan on Sep 16, 2020, 07:20 pm

Title: Turn on outputs in a sequence while input is on.
Post by: rhaan on Sep 16, 2020, 07:20 pm
So I'm completely new to coding and I am struggling with a simple project. I have tried working this out myself  because I really want to understand what is going on in the project and the fact that i enjoy learning new things but I am under a bit of a time constraint.

It has to be really simple but I just wonder if I am making this more complicated than I need to.

I want the outputs to sequence through when the input turns on and only while the input is on (ie. output 1 turn on for 3 seconds then input 2 turn on a few milliseconds before output 1 turns off, output 2 will be on for 3 seconds then output 3 turn on a few milliseconds before output 2 turns off, output 3 will be on for 3 seconds and if the input is still on turn on output 1 a few milliseconds before output 3 turns off and cycle through again and again until the input is off.

I have attached a file of the project.

 Thanks in advance for the help and advice.
Title: Re: Turn on outputs in a sequence while input is on.
Post by: UKHeliBob on Sep 16, 2020, 07:22 pm
Please follow the advice on posting code in Read this before posting a programming question (https://forum.arduino.cc/index.php?topic=97455.0)

In particular note the advice to Auto format code in the IDE and using code tags when posting code here
Title: Re: Turn on outputs in a sequence while input is on.
Post by: dougp on Sep 16, 2020, 07:35 pm
I suspect you'll need to know how to do several things at the same time (https://forum.arduino.cc/index.php?topic=223286.0).

Also check out Using millis() for timing beginner's guide (http://forum.arduino.cc/index.php?topic=503368.0)
Title: Re: Turn on outputs in a sequence while input is on.
Post by: rhaan on Sep 16, 2020, 07:47 pm
Sorry, here is the code that I have so far. I have tried the several things at the same time code, I'm just having trouble understanding how to turn the outputs off as soon as the input button is released.



Code: [Select]
// --------CONSTANTS---------------

// the pin numbers for the LEDs
const int led_1_Pin = 4;
const int led_2_Pin = 7;
const int led_3_Pin = 8;

// the pin number for the button
const int inputSignal = 2;

// number of millisecs the Led's are off
const int led_1_OffDuration = 3000;
const int led_2_OffDuration = 3000;
const int led_3_OffDuration = 3000;

// number of millisecs that Led's are on
const int OnDuration_Led1 = 3000;
const int OnDuration_Led2 = 3000;
const int OnDuration_Led3 = 3000;



//------------ VARIABLES---------------------

// used to record whether the LEDs are on or off
byte led_1_State = LOW;           
byte led_2_State = LOW;
byte led_3_State = LOW;


unsigned long currentMillis = 0;   
unsigned long previousOnBoardLedMillis = 0;   // will store last time the LED was updated
unsigned long previousLed_1_Millis = 0;
unsigned long previousLed_2_Millis = 0;
unsigned long previousLed_3_Millis = 0;


//========================================

void setup() {

  Serial.begin(9600);
 
 
  // set the Led pins as output:
  pinMode(led_1_Pin, OUTPUT);
  pinMode(led_2_Pin, OUTPUT);
  pinMode(led_3_Pin, OUTPUT);
 
 
  // set the button pin as input with a pullup resistor to ensure it defaults to HIGH
  pinMode(inputSignal, INPUT);
 
 
 
}

//========================================

void loop() {

  currentMillis = millis();   
  int buttonState = digitalRead(inputSignal);


if (buttonState == HIGH) {
  if (led_1_State == LOW) {
    if (currentMillis - previousLed_1_Millis >= led_1_OffDuration) {
       led_1_State = HIGH;
       previousLed_1_Millis += led_1_OffDuration;
   
     Serial.print(previousLed_1_Millis);
    }
  }
    else {
      if (currentMillis - previousLed_1_Millis >= OnDuration_Led1) {
        led_1_State = LOW;
        previousLed_1_Millis += OnDuration_Led1;
       
        if (led_2_State == LOW) {
          if (currentMillis - previousLed_1_Millis >= led_2_OffDuration) {
            led_2_State = HIGH;
            previousLed_1_Millis += led_2_OffDuration;
          }
        }
        else {
          if (currentMillis - previousLed_1_Millis >= OnDuration_Led2) {
            led_2_State = LOW;
            previousLed_1_Millis += OnDuration_Led2;
       
            if (led_3_State == LOW) {
              if (currentMillis - previousLed_1_Millis >= led_3_OffDuration) {
                led_3_State = HIGH;
                previousLed_1_Millis += led_3_OffDuration;
              }
            }
            else {
              if (currentMillis - previousLed_1_Millis >= OnDuration_Led3) {
                led_3_State = LOW;
                previousLed_1_Millis += OnDuration_Led3;
              }
            }   
          }
        }   
      }
    }
 
  } 

  digitalWrite(led_1_Pin, led_1_State);
  digitalWrite(led_2_Pin, led_2_State);
  digitalWrite(led_3_Pin, led_3_State);
 
}

//========================================END
Title: Re: Turn on outputs in a sequence while input is on.
Post by: UKHeliBob on Sep 16, 2020, 07:53 pm
Quote
I'm just having trouble understanding how to turn the outputs off as soon as the input button is released.
If you use millis() for timing properly then the loop() function will repeat thousands of times per second.  On each iteration you can check the state of an input and compare it with the state last time it was checked.  If it has changed and is now in an off state then act as required
Title: Re: Turn on outputs in a sequence while input is on.
Post by: ToddL1962 on Sep 16, 2020, 09:21 pm
Your code is way too complicated for sequencing 3 LEDs on for 3 seconds a piece.  Here is one way to do it:

Code: [Select]

// --------CONSTANTS---------------

// the pin number for the button
const int inputSignal = 2;

// the pin numbers for the LEDs
const int ledPins[] = {4, 7, 8};

// number of millisecs that Led's are on
const int ledOnDuration[] = {3000, 3000, 3000};

const int numLeds = sizeof(ledPins)/sizeof(ledPins[0]);

//------------ VARIABLES---------------------

unsigned long previousMillis = 0;
int ledIndex = 0;

void setup()
{
  Serial.begin(9600);

  // set the Led pins as output:
  for (int i = 0; i < numLeds; i++) pinMode(ledPins[i], OUTPUT);

  // set the button pin as input with a pullup resistor to ensure it defaults to HIGH
  pinMode(inputSignal, INPUT);
}

void loop()
{
  int buttonState = digitalRead(inputSignal);
  static int prevButtonState = LOW;
  unsigned long currentMillis = millis();
 
  if (buttonState != prevButtonState)
  {
    if (buttonState == HIGH)
    {
      // Button has been pressed.  Begin sequence.
      ledIndex = 0;
      digitalWrite(ledPins[0], HIGH);
      previousMillis = currentMillis;
    }
    else
    {
      // Button has been release.  Turn all LEDs off.
      for (int i = 0; i < numLeds; i++) digitalWrite(ledPins[i], LOW);
    }
    prevButtonState = buttonState;
    delay(50); // debounce
  }
 
  if (buttonState == HIGH)
  {
    // Button is pressed check to see if current LED duration has expired
    if (currentMillis - previousMillis >= ledOnDuration[ledIndex])
    {
      // Turn current LED off
      digitalWrite(ledPins[ledIndex], LOW);
      ledIndex++;
      ledIndex %= numLeds;
      // Turn next LED on and reset the timer
      digitalWrite(ledPins[ledIndex], HIGH);
      previousMillis = currentMillis;
    }
  }
}
Title: Re: Turn on outputs in a sequence while input is on.
Post by: rhaan on Sep 16, 2020, 10:02 pm
That's what I figured.
I've tried using a separate function for each LED and I get the same result which is while I have the input button on the LED's stay on, the timers that I have set to turn the LED's off don't switch them off. The only way I can get the LED's to turn off is by releasing the input button.
I've tried putting the button state code in the main loop and also in each function loop.

Code: [Select]


void Led_1_State() {
  if (digitalRead(buttonPin) == HIGH)  {
     if (currentMillis - previousLed_1_Millis >= led_1_Interval) {
       led_1_State = HIGH;
       previousLed_1_Millis += led_1_Interval;
    }
  }
  else {
    if (currentMillis - previousLed_1_Millis >= blinkDuration) {
       led_1_State = LOW;
       previousLed_1_Millis += blinkDuration;
    }
  }   
}
Title: Re: Turn on outputs in a sequence while input is on.
Post by: ToddL1962 on Sep 16, 2020, 10:15 pm
That's what I figured.
I've tried using a separate function for each LED and I get the same result which is while I have the input button on the LED's stay on, the timers that I have set to turn the LED's off don't switch them off. The only way I can get the LED's to turn off is by releasing the input button.
I've tried putting the button state code in the main loop and also in each function loop.
One problem is you are evaluating the button's state and not looking for the state transition.  Look at the code I posted.  It starts the sequence when the button goes from LOW to HIGH and turns off all of the LEDs when the button goes from HIGH to LOW.  It continues executing the sequence as long as the button is HIGH.  Also, I used arrays which greatly shortened the length of the code.

I tested this code and it works.
Title: Re: Turn on outputs in a sequence while input is on.
Post by: rhaan on Sep 17, 2020, 04:38 pm
Thanks so much for the help. After studying the code i understand what it is doing.
I can program ladder logic all day long and enjoy it but I can see that coding is way different. I have a lot to learn.

Thanks again for the help.
Title: Re: Turn on outputs in a sequence while input is on.
Post by: ToddL1962 on Sep 17, 2020, 06:23 pm
Thanks so much for the help. After studying the code i understand what it is doing.
I can program ladder logic all day long and enjoy it but I can see that coding is way different. I have a lot to learn.

Thanks again for the help.
No problem.  Glad it helped!