Toggling LEDs in a respond to a counter at different scenarios

I am trying to toggle LEDs on and off based on two scenarios.

  1. a counter.(input from two buttons - one for counting up and the other for counting down)
  2. a specific time for led to be ON

if counter is equal to 1: turn ON led 1 for x amount of time (specify at index 0 of the Time array) - all other leds are off;

if counter is equal to 2: turn off the previous led that was ON (even if the specify time of ON for that led was not elapsed) then turn ON led 2 for x amount of time.

the above should be same for all 5 indexes.

here is the code I have got so far for counting the button presses:

//Buttons//

const uint8_t MINBTNCOUNT = 0;
const uint8_t MAXBTNCOUNT = 4;


//Button1// count up
uint8_t buttonPin = 2;
uint8_t buttonPressCount = 0;
uint8_t lstbuttonPressCount = 0;
uint8_t PUSHED = 0;
unsigned long timePushed = 0;
uint8_t currentButtonState = HIGH;
uint8_t lastButtonState = HIGH;
uint32_t millisTimePress = 0;


//Button2// count down///

uint8_t buttonPin2 = 3;
uint8_t buttonPressCount2 = 0;
uint8_t lstbuttonPressCount2 = 0;
uint8_t PUSHED2 = 0;
unsigned long timePushed2 = 0;
uint8_t currentButtonState2 = HIGH;
uint8_t lastButtonState2 = HIGH;
uint32_t millisTimePress2 = 0;


////Leds/////
const int ledPins[] = {4, 5, 6, 7, 8}; // array of leds pins
const int numOfLeds =  (sizeof(ledPins) / sizeof(ledPins[0])); // size of Leds


//time translating//
#define sec * 1000
#define min * 60000
#define ms * 1

// LEDS ON Time Lengths //
const unsigned long ledOnTime[] = {19 sec, 44 sec, 9 sec, 7 sec, 33 sec};


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

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);

  // setting up the digital pins for the leds to be an output //
  for (int j = 0; j < numOfLeds; j++)
  {
    pinMode(ledPins[j], OUTPUT);
  }
}


void loop() {
  buttonPress1 ();
  buttonPress2 ();
}



void buttonPress1 ()
{
  byte currentButtonState = digitalRead (buttonPin);

  if (lastButtonState != currentButtonState)  {
    lastButtonState = currentButtonState;
    delay (35);             // debounce


    //******************
    //has the switch been pushed ?
    if (currentButtonState == PUSHED)
    {
      //record the time the switch closed
      timePushed = millis();

    }
    //******************
    //switch has been released
    else
    {
      //calculate the time the switch was closed
      timePushed = millis() - timePushed;

      if (timePushed < 500)
      {
        buttonPressCount++;
        if ( buttonPressCount == MINBTNCOUNT)
        {
          buttonPressCount = MAXBTNCOUNT;
        }
        if ( buttonPressCount > MAXBTNCOUNT)
        {
          buttonPressCount = 1;
        }
        Serial.print("button count: ");
        Serial.println(buttonPressCount);
      }


    }
  }
}

void buttonPress2 ()
{
  byte currentButtonState2 = digitalRead (buttonPin2);

  if (lastButtonState2 != currentButtonState2)  {
    lastButtonState2 = currentButtonState2;
    delay (35);             // debounce


    //******************
    //has the switch been pushed ?
    if (currentButtonState2 == PUSHED2)
    {
      //record the time the switch closed
      timePushed2 = millis();

    }
    //******************
    //switch has been released
    else
    {
      //calculate the time the switch was closed
      timePushed2 = millis() - timePushed2;

      if (timePushed2 < 500)
      {
        buttonPressCount--;
        if ( buttonPressCount == MINBTNCOUNT)
        {
          buttonPressCount = MAXBTNCOUNT;
        }

        if ( buttonPressCount > MAXBTNCOUNT)
        {
          buttonPressCount = 1;
        }
        if ( buttonPressCount == 255)
        {
          buttonPressCount = 1;
        }
        Serial.print("button count: ");
        Serial.println(buttonPressCount);
      }


    }
  }
}

the above code is working for counting up and down within a range.

I have tried to add another function for toggling the LEDS based on a counter and based on the ledOnTimearray[]

Here is my failed attempting:

void ledToggle()
{
  for (int i = 0; i < MAXBTNCOUNT; i++)
  {
    if (counter != lstcounter)
    {
      Serial.print("counter:");
      Serial.println(counter);
      lstcounter = counter;

      if (millis() - timeButtonPressed <= ledOnTime[i])
      {
        Serial.print(ledOnTime[i]);
        digitalWrite(ledPins[i], HIGH);
      }

    }
    if (millis() > timeButtonPressed +  ledOnTime[i] || counter != lstcounter)
    {
      digitalWrite(ledPins[i], LOW);
    }
  }
}

What do you need such a sketch for?

It is for representing when a specific action is happening ( a track that is playing)

if led 1 is on I know track 1 is playing
if led 2 is on I know track 2 is playing.

counter is for iterate between tracks.

if counter == 1 track 1 is playing and led 1 should be on for the length of the track or until the button is pressed again and in that case the led will be off and a new led will be on indicate the new track .

Does it make sense?

You have a button.
If button becomes pressed the led lits until eiter the button becomes pressed again or a time out occurs?

exactly!
This what I want to happen without success.

edit: the button press is a counter so when button press again a new led (correspond to counter) should be on

this function working with 1 led and when counter == 1

When I try to copy the function to work for led 2 it is not working:

void ledToggle()
{
    if (counter != lstcounter)
    {
      Serial.print("counter:");
      Serial.println(counter);
      lstcounter = counter;

      if (millis() - timeButtonPressed <= ledOnTime[0])
      {
        Serial.print(ledOnTime[0]);
        digitalWrite(ledPins[0], HIGH);
      }

    }
    if (millis() > timeButtonPressed +  ledOnTime[0] || counter != 1)
    {
      digitalWrite(ledPins[0], LOW);
    }
  }
}

Have you already gained programming experience in C++?

some experience. Not enough to make what I wanted to work :slight_smile:

My recommendation is to build some objects, like for the button, timing and Leds.
Some tasks take care about these objects and generates the needed output.
Classes aren´t needed, some structured arrays only.

What do you mean?

I have already have the function for the button that made the counting as I need.

I also manage to turn on led based on counter for the length of the track.
When I tried to make it work with more then 1 variable (counter == 2) it was not working.

#include <wavTrigger.h>
#include <AltSoftSerial.h>    // Arduino build environment requires this


// WAV Trigger object //
wavTrigger wTrig;

//time translating//
#define sec * 1000
#define min * 60000
#define ms * 1

// Track Lengths //
const unsigned long trackLength[] = {19 sec, 44 sec, 9 sec, 7 sec, 33 sec};


//Button//
uint8_t buttonPin = 2;       // uint8_t is an unsigned (positive) 8-bit integer.  Giving the compiler this detail rather than a generic 'byte' helps it treat it as you would expect, resulting in Serial.print not needing that 'DEC' argument.
uint8_t counter = 0;// Note an uint8_t stores a number from 0-255, so after 255 the counter will go back to 0 again.  If you want to store a larger integer, use uint16_t (0-65535), uint32_t (0-4294967295), or even uint64_t (0-18446744073709551615).
uint8_t lstcounter = 0;
uint8_t PUSHED = 0;
const uint8_t MINBTNCOUNT = 0;
const uint8_t MAXBTNCOUNT = 4; //num of tracks
unsigned long timePushed = 0;
uint8_t currentButtonState = HIGH;
uint8_t lastButtonState = HIGH;
uint32_t millisTimePress = 0; // unsigned longs are uint32_t, an unsigned 32 bit integer.


////Leds/////

const int ledPins[] = {4, 5, 6, 7, 8}; // array of leds pins
const int numOfLeds =  (sizeof(ledPins) / sizeof(ledPins[0])); // size of Leds

unsigned long timeButtonPressed = 0;

uint32_t currentMillis;

int  gNumTracks;              // Number of tracks on SD card

char gWTrigVersion[VERSION_STRING_LEN];    // WAV Trigger version string

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

  pinMode(buttonPin, INPUT_PULLUP);

  // setting up the digital pins for the leds to be an output //
  for (int j = 0; j < numOfLeds; j++)
  {
    pinMode(ledPins[j], OUTPUT);
  }

  delay(1000);

  // WAV Trigger startup at 57600
  wTrig.start();
  delay(10);

  // Send a stop-all command and reset the sample-rate offset, in case we have
  //  reset while the WAV Trigger was already playing.
  wTrig.stopAllTracks();
  wTrig.samplerateOffset(0);
  wTrig.masterGain(-6);                  // Reset the master gain to 0dB


  // Enable track reporting from the WAV Trigger
  wTrig.setReporting(true);

  // Allow time for the WAV Trigger to respond with the version string and
  //  number of tracks.
  delay(100);

  // If bi-directional communication is wired up, then we should by now be able
  //  to fetch the version string and number of tracks on the SD card.
  if (wTrig.getVersion(gWTrigVersion, VERSION_STRING_LEN)) {
    Serial.print(gWTrigVersion);
    Serial.print("\n");
    delay(1000);
    gNumTracks = wTrig.getNumTracks();
    Serial.print("Number of tracks = ");
    Serial.print(gNumTracks);
    Serial.print("\n");
  }
  else
    Serial.print("WAV Trigger response not available");
}


void loop() {
  buttonPress ();
  isPlaying1(); // for track 1
  isPlaying2(); // for track 2
  wTrig.update();
}


void buttonPress ()
{
  byte currentButtonState = digitalRead (buttonPin);

  if (lastButtonState != currentButtonState)  {
    lastButtonState = currentButtonState;
    delay (35);             // debounce


    //******************
    //has the switch been pushed ?
    if (currentButtonState == PUSHED)
    {
      //record the time the switch closed
      timePushed = millis();

    }
    //******************
    //switch has been released
    else
    {
      //calculate the time the switch was closed
      timePushed = millis() - timePushed;
      timeButtonPressed = millis();
      Serial.print("timeButtonPressed:");
      Serial.println(timeButtonPressed);

      if (timePushed < 500)
      {
        counter++;

        if ( counter == MINBTNCOUNT)
        {
          counter = MAXBTNCOUNT;
        }
        if ( counter == 5)
        {
          counter = 1;
        }
        //        Serial.print("button count: ");
        //        Serial.println(counter);
      }

      else if (timePushed > 600)
      {
        counter--;
        //        Serial.println(timeButtonPressed );
        if ( counter == MINBTNCOUNT)
        {
          counter = MAXBTNCOUNT;
        }
        if ( counter > MAXBTNCOUNT )
        {
          counter = MINBTNCOUNT;
        }

      }

    }
  }
}



void isPlaying1()
{
  if (counter != lstcounter)
  {
    Serial.print("counter:");
    Serial.println(counter);
    lstcounter = counter;
    //    Serial.print("millis: ");
    //    Serial.print(millis());

    if (millis() - timeButtonPressed <= trackLength[0])
    {
      Serial.println(trackLength[0]);
      digitalWrite(ledPins[0], HIGH);
      wTrig.trackGain(1, -40);
      wTrig.trackPlaySolo(1);
      wTrig.trackFade(1, -6, 3000, false);
    }
  }


  if (millis() > timeButtonPressed +  trackLength[0] || counter != 1 )
  {
    digitalWrite(ledPins[0], LOW);
  }
}


void isPlaying2()
{
  if (counter != lstcounter)
  {
    Serial.print("counter:");
    Serial.println(counter);
    lstcounter = counter;
    //    Serial.print("millis: ");
    //    Serial.print(millis());

    if (millis() - timeButtonPressed <= trackLength[1])
    {
      Serial.println(trackLength[1]);
      digitalWrite(ledPins[1], HIGH);
      wTrig.trackGain(2, -40);
      wTrig.trackPlaySolo(2);
      wTrig.trackFade(2, -6, 3000, false);
    }
  }


  if (millis() > timeButtonPressed +  trackLength[1] || counter != 2 )
  {
    digitalWrite(ledPins[1], LOW);
  }
}




when counter == 2 I'm expecting it to print the time of track 2 but it printing the time of the first track (19,000 ms) I am thinking that this where the mistake is but can't fixed it

I´m not familar with the wavTrigger.h libary.

Have a nice day and enjoy coding in C++.

I have managned to make it work!
The code is full of repeating which I know is bad way.

perhaps you could comment on that part of code ? how can I make it work without all those duplications?

void loop() {
  buttonPress ();
  if(counter ==1) // for track 1
  {
    digitalWrite(ledPins[1], LOW);
    digitalWrite(ledPins[2], LOW);
    digitalWrite(ledPins[3], LOW);
  isPlaying1(); 
  }
  if(counter == 2) //for track 2
  {
    digitalWrite(ledPins[0], LOW);
    digitalWrite(ledPins[2], LOW);
    digitalWrite(ledPins[3], LOW);
  isPlaying2(); // for track 2
  }

   if(counter == 3) //for track 2
  {
    digitalWrite(ledPins[0], LOW);
    digitalWrite(ledPins[1], LOW);
    digitalWrite(ledPins[3], LOW);
  isPlaying3(); // 
  }
  
   if(counter == 4) //for track 4
  {
    digitalWrite(ledPins[0], LOW);
    digitalWrite(ledPins[1], LOW);
    digitalWrite(ledPins[2], LOW);
  isPlaying4(); // 
  }
  wTrig.update();
}


void isPlaying1()
{
  if (counter != lstcounter)
  {
    Serial.print("counter:");
    Serial.println(counter);
    lstcounter = counter;
    //    Serial.print("millis: ");
    //    Serial.print(millis());

    if (millis() - timeButtonPressed <= trackLength[0])
    {
      Serial.println(trackLength[0]);
      digitalWrite(ledPins[0], HIGH);
      wTrig.trackGain(1, -40);
      wTrig.trackPlaySolo(1);
      wTrig.trackFade(1, -6, 3000, false);
    }
  }


  if (millis() > timeButtonPressed +  trackLength[0] || counter != 1 )
  {
    digitalWrite(ledPins[0], LOW);
  }
}


void isPlaying2()
{
  if (counter != lstcounter)
  {
    Serial.print("counter:");
    Serial.println(counter);
    lstcounter = counter;
    //    Serial.print("millis: ");
    //    Serial.print(millis());

    if (millis() - timeButtonPressed <= trackLength[1])
    {
      Serial.println(trackLength[1]);
      digitalWrite(ledPins[1], HIGH);
      wTrig.trackGain(2, -40);
      wTrig.trackPlaySolo(2);
      wTrig.trackFade(2, -6, 3000, false);
    }
  }


  if (millis() > timeButtonPressed +  trackLength[1] || counter != 2 )
  {
    digitalWrite(ledPins[1], LOW);
  }
}


void isPlaying3()
{
  if (counter != lstcounter)
  {
    Serial.print("counter:");
    Serial.println(counter);
    lstcounter = counter;
    //    Serial.print("millis: ");
    //    Serial.print(millis());

    if (millis() - timeButtonPressed <= trackLength[2])
    {
      Serial.println(trackLength[2]);
      digitalWrite(ledPins[2], HIGH);
      wTrig.trackGain(3, -40);
      wTrig.trackPlaySolo(3);
      wTrig.trackFade(3, -6, 3000, false);
    }
  }


  if (millis() > timeButtonPressed +  trackLength[2] || counter != 3 )
  {
    digitalWrite(ledPins[2], LOW);
  }
}



void isPlaying4()
{
  if (counter != lstcounter)
  {
    Serial.print("counter:");
    Serial.println(counter);
    lstcounter = counter;
    //    Serial.print("millis: ");
    //    Serial.print(millis());

    if (millis() - timeButtonPressed <= trackLength[3])
    {
      Serial.println(trackLength[3]);
      digitalWrite(ledPins[3], HIGH);
      wTrig.trackGain(4, -40);
      wTrig.trackPlaySolo(4);
      wTrig.trackFade(4, -6, 3000, false);
    }
  }


  if (millis() > timeButtonPressed +  trackLength[3] || counter != 4 )
  {
    digitalWrite(ledPins[3], LOW);
  }
}

Using 'if else' instead of just 'if', for one thing. 'counter' can only have one value at a time, if it equals 1 for example, you don't need to test it to see if it's 2.

Or follow the advice of reply #9 and put the LED states in an array, and index the array with the counter.

Just as a comment on style, identifiers beginning with 'is..' like 'isPlaying' are usually advertising that they refer to a logical value (true/false) because it 'is' or 'isn't'. Functions with names like that usually don't affect anything, they only test the state of something.

@hk_jh it might be better to keep all this on one thread.

From your other thread, I had been writing but sorta gave up, I had this, never posted

Tuning in late…

You write

if (counter == 1) { led 1 is on for 10 seconds, all other led are off }
if (counter == 2) {led 2 is on for 20 seconds, all other led are off }
if (counter == 3) {led 3 is on for 30 seconds, all other led are off }

but that leaves many questions. Maybe you have answered them.

Would this be closer?

if the button gets pressed
    stop any song that is playing and extinguish his LED
    advance counter, if it gets to 3 set it back to 0
    start playing track number counter
    light up his LED
    set up a timer

if the track playing finishes (timer runs out)
    extinguish his LED

You were slogging it out with @Railroader over there.

HTH

a7

Yes!

Because English is not my first language I have hard time to find the words to explain exactly what I have in mind...

edit: the final code I have managed too write is working but very much not efficient . It got multiple repetition of code and is for playing only 4 tracks. If I would like to add more track the code will continue to increase in size.
I'll be happy to se more efficant code

Your English is better than my <insert any language here>.

But words are always going to come in second or worse when describing a system like this. @Railroader didn't, but often calls it word salad. It is hard to read a block of text and come away with a good idea of what you need.

Flowcharts can be useful.

Pseudocode, as I wrote, can be useful. It is more than words, less than real code. It forces you to think like it is coding, but relieves you of pesky details.

So you are saying that my pseudocode does what you want? From what I have seen so far here, you should be able to use the pseudocode to write the actual C/C++.

a7

I'll try again without thewavTrigger library as at the end is only another line of code to play the track. The idea of the code could be without it for the sake of writing:

#define NUMTRACKS 4;


//time translating//
#define sec * 1000
#define min * 60000
#define ms * 1

// Track Lengths //
const unsigned long trackLength[] = {19 sec, 44.1 sec, 20 sec, 8 sec , 33 sec};

////Leds/////

const int ledPins[] = {4, 5, 6, 7, 8}; // array of leds pins
const int numOfLeds =  (sizeof(ledPins) / sizeof(ledPins[0])); // size of Leds

//Button//
uint8_t buttonPin = 2;
uint8_t counter = 0;
uint8_t lstcounter = 0;
uint8_t PUSHED = 0;
const uint8_t MINBTNCOUNT = 0;
const uint8_t MAXBTNCOUNT = NUMTRACKS;
unsigned long timePushed = 0;
uint8_t currentButtonState = HIGH;
uint8_t lastButtonState = HIGH;
uint32_t millisTimePress = 0; //

unsigned long timeButtonPressed = 0;


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

  pinMode(buttonPin, INPUT_PULLUP);

  // setting up the digital pins for the leds to be an output //
  for (int i = 0; i < numOfLeds; i++)
  {
    pinMode(ledPins[i], OUTPUT);
  }
}


void loop()
{
  buttonPress ();
  runSequence();

}



void buttonPress ()
{
  byte currentButtonState = digitalRead (buttonPin);

  if (lastButtonState != currentButtonState)  {
    lastButtonState = currentButtonState;
    delay (35);             // debounce
    //******************
    //has the switch been pushed ?
    if (currentButtonState == PUSHED)
    {
      //record the time the switch closed
      timePushed = millis();

    }
    //******************
    //switch has been released
    else
    {
      //calculate the time the switch was closed
      timePushed = millis() - timePushed;
      timeButtonPressed = millis();
      Serial.println();
      Serial.print("timeButtonPressed:");
      Serial.println(timeButtonPressed);

      if (timePushed < 500)
      {
        counter++;

        if ( counter == MINBTNCOUNT)
        {
          counter = MAXBTNCOUNT;
        }
        if ( counter == 5)
        {
          counter = 1;
        }
      }

      else if (timePushed > 500)
      {
        counter--;
        //        Serial.println(timeButtonPressed );
        if ( counter == MINBTNCOUNT)
        {
          counter = MAXBTNCOUNT;
        }
        if ( counter > MAXBTNCOUNT )
        {
          counter = MINBTNCOUNT;
        }

      }

    }
  }
}

//track playing/ LED indications //

void runSequence()
{
  for (int i = 0; i < MAXBTNCOUNT; i++)
  {
    if (counter != lstcounter) //check if there is a new value of counter(button state was changed)

    {
      Serial.print("counter:");
      Serial.println(counter);
      lstcounter = counter;

      if (millis() - timeButtonPressed <= trackLength[i])
      {
        Serial.print("track ");
        Serial.print(counter);
        Serial.print("length: ");
        Serial.println(trackLength[i]);
        digitalWrite(ledPins[i], HIGH);
      }
    }


    if (millis() > timeButtonPressed +  trackLength[i])
    {
      digitalWrite(ledPins[i], LOW);
    }
  }
}

When I first press the button the serial is printing:

Screen Shot 2022-12-17 at 17.19.57

Which is exactly what I am expecting and indeed the LED os turned off after 19 seconds.

When I press the button again it print (marked in green):

track length should be 44100 but it printed 19000. I think I have found the first mistake.

I did not manage to fix that.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.