Triggering different loops when buttons are pushed.

Hi,

I've been ripping my hair out for the last 8 hours trying to figure out how to use 5 momentary switches to trigger different lines of code.

What I have is a lighting system that I want to perform different task depending on what button that was pressed.

Can anyone guide me in the right direction?

Thank you,
Jacob

It would help if you post the code you are struggling with.

The way I would do it is to read and save the state of all the buttons and then depending on the saved values call the appropriate function. The demo Several Things at a Time might give you some ideas.

...R

Yeah, sorry. Below is the code. I've added where I want the buttons to react (in the void loop). I looked at your guide for how to run several tasks at once and I am using it in the code. Can't really see how it solves my problem though. Worth mentioning again is that I am using momentary switches.

#define DRUM1 0 //Define port A0
#define DRUM2 1 //Define port A1
#define THRESHOLD 200 //Threshold for trigger to react
#include <DmxMaster.h> //Go get DMX lib


byte val1 = 0; 
byte val2 = 0;
int brightness=255;
int time=100; 


void setup() {
  DmxMaster.usePin(3);
  DmxMaster.maxChannel(6);
}

void loop() {

  //If button 1 is pressed, run this:
  Blink1(time); //virvel
  Blink2(time); //kagge

  //If button 2 is pressed run this:
  Blink3();

  //etc.
}
void Blink1 (int interval){
   static long prevMill = 0;
    val1 = analogRead(DRUM1);
   if ( (((long)millis() - prevMill) >= interval) && (val1 > THRESHOLD)){ 
    prevMill = millis(); 
     for (brightness = 255; brightness >= 0; brightness--) {
    
    /* Update DMX channel 1 to new brightness */
    DmxMaster.write(1, brightness);
    
    /* Small delay to slow down the ramping */
    delay(1);
  }//digitalWrite(blueLed, !digitalRead(blueLed));
    
  }
 if ( (((long)millis() - prevMill) >= interval) && (val1 < THRESHOLD)){
    DmxMaster.write(1, 0);
  }
 
 }
  void Blink2 (int interval){
   static long prevMill = 0;
   val2 = analogRead(DRUM2);
   if (((millis() - prevMill) >= interval) && (val2 > THRESHOLD+20)){ 
    prevMill = millis(); 
    for (brightness = 255; brightness >= 0; brightness--) {
    
    /* Update DMX channel 1 to new brightness */
    DmxMaster.write(17, brightness);
    
    /* Small delay to slow down the ramping */
    delay(1);
  }
 } 
  if (((millis() - prevMill) >= interval) && (val2 < THRESHOLD)){ 
    DmxMaster.write(17, 0);
  }
}

void Blink3(){
  
    for (brightness = 0; brightness >= 255; brightness++) {
    
    /* Update DMX channel 1 to new brightness */
    DmxMaster.write(17, brightness);
    
    /* Small delay to slow down the ramping */
    delay(1);
 }
 }

The following code got me somewhere but it seems overly complicated. I also only got it to react to one of the buttons (4) and not the other.

#define DRUM1 0 //Definierar port A0
#define DRUM2 1 //Definierar port A1
#define THRESHOLD 200 //Gränsvärde för när tiggern skall reagera
#include <DmxMaster.h> //Hämtar in DMX-bibliotek

// One side of the button is attached to pin 2, the other to ground.
#define PIN_BUTTON 2
#include "MomentaryButton.h"

MomentaryButton button(PIN_BUTTON);

//0-ar värdet på analogport
byte val1 = 0; 
byte val2 = 0;
int ljusstyrka=255;
int tid=100;



int inPin1 = 4;  // the pin number for input (for me a push button)
int inPin2 = 5;
int current1;         // Current state of the button
int current2;
                     // (LOW is pressed b/c i'm using the pullup resistors)
long millis_held;    // How long the button was held (milliseconds)
long secs_held;      // How long the button was held (seconds)
long prev_secs_held; // How long the button was held in the previous check
byte previous1 = HIGH;
byte previous2 = HIGH;
unsigned long firstTime; // how long since the button was first pressed 




void setup() {
  DmxMaster.usePin(3);
  DmxMaster.maxChannel(6);
  Serial.begin(9600);         // Use serial for debugging
  digitalWrite(inPin1, HIGH);  // Turn on 20k pullup resistors to simplify switch input
  digitalWrite(inPin2, HIGH);  // Turn on 20k pullup resistors to simplify switch input
  
  
}

void loop() {

  

  
   current1 = digitalRead(inPin1);
   current2 = digitalRead(inPin2);
   //Serial.println(current2);

  // if the button state changes to pressed, remember the start time 
  if (   (current1 == LOW && previous1 == HIGH)  && (millis() - firstTime) > 200) {
    firstTime = millis();
  }

  if (   (current2 == LOW && previous2 == HIGH) && (millis() - firstTime) > 200) {
    firstTime = millis();
  }

  

  millis_held = (millis() - firstTime);
  secs_held = millis_held / 1000;

  // This if statement is a basic debouncing tool, the button must be pushed for at least
  // 100 milliseconds in a row for it to be considered as a push.
  if (millis_held > 50) {
    // check if the butt{on was released since we last checked
    if  (  current1 == HIGH && previous1 == LOW ) {
      // HERE YOU WOULD ADD VARIOUS ACTIONS AND TIMES FOR YOUR OWN CODE
      // ===============================================================================

     while(previous1==LOW && digitalRead(inPin1)==HIGH && millis_held >100){
        Serial.println("In the loop");
           Blink1(tid); //virvel
           Blink2(tid); //kagge
        if(previous1==LOW && digitalRead(inPin1)==LOW && millis_held >200){

         
        break;
        } }
        
        }
        
       
  }
      
    if(digitalRead(inPin1)==LOW){
          delay(200);
        }
  

  previous1 = current1;
   previous2 = current2;
  
  prev_secs_held = secs_held;
 Serial.println("Out of the loop");


}


/*=======================================================================
 * Trigger 1 activates this 
 */
void Blink1 (int interval){
   static long prevMill = 0;
    val1 = analogRead(DRUM1) ;
   if ( (((long)millis() - prevMill) >= interval) && (val1 > THRESHOLD+20)){ 
    prevMill = millis(); 
     for (ljusstyrka = 255; ljusstyrka >= 0; ljusstyrka--) {
    
    /* Update DMX channel 1 to new brightness */
    DmxMaster.write(1, ljusstyrka);
    
    /* Small delay to slow down the ramping */
 delay(1);
}
    
  }
 if ( (((long)millis() - prevMill) >= interval) && (val1 < THRESHOLD)){
    DmxMaster.write(1, 0);
  }
  
}
 
/*=====================================================================
 * Trigger 2 activates this
 */
 void Blink2 (int interval){
   static long prevMill = 0;
   val2 = analogRead(DRUM2);
   if (((millis() - prevMill) >= interval) && (val2 > THRESHOLD)){ 
    prevMill = millis(); 
    for (ljusstyrka = 255; ljusstyrka >= 0; ljusstyrka--) {
    
    /* Update DMX channel 1 to new brightness */
   DmxMaster.write(17, ljusstyrka);
    
    /* Small delay to slow down the ramping */
    delay(1);
  }
 } 
  if (((millis() - prevMill) >= interval) && (val2 < THRESHOLD)){ 
    DmxMaster.write(17, 0);
  }
}


void Blink3(){
  
    for (ljusstyrka = 0; ljusstyrka >= 255; ljusstyrka++) {
    
    /* Update DMX channel 1 to new brightness */
    DmxMaster.write(17, ljusstyrka);
    
    /* Small delay to slow down the ramping */
    delay(1);
 }
 }

jacobthebluesman:
I am using it in the code. Can't really see how it solves my problem though

I don't see the point of using anyone's code if you can't see a reason for it.

You have posted two programs. Which one do you want me to look at?

...R

I'm sorry, I think I explained that wrong. I used your code for the purpose of running loop simultaneously, which worked and is great, BUT now the question lies in turning these loops on and off using momentary buttons, which I can't figure out.

If you should look at one code the first one is probably the best. It only contains the program to run the loops which turn on the lights. No code for buttons added.

The second one is the same code but I added some lines of code for controlling using switches. I just got it working for one switch though, and not two (or more) for some reason. It just wont react. I posted it in hope that it would maybe make things clearer of what I'm trying to accomplish.

There did not seem much point looking at the code without buttons when buttons are the problem.

What would be wrong with something like this pseudo code

void loop() {
  readAndSaveButtons();
  if (button1val == HIGH) {
     callFunction1();
  }
  if (button2val == HIGH) {
    callFunction2();
  }
}

Your 2nd example seems a lot more complicated than that and you have not explained why that complexity might be needed.

If you are concerned about switch bounce a short interval (say 50 millisecs) between subsequent reads of the switches is usually sufficient.

...R

Well, thing is is that I would like to be able to exit the loop once the a button is pressed once more. In your code above, entering the loop works, but there is now way to get out of it.

This is what i want from the code:
Imagine that you have 5 lamp buttons on the wall. If i press #1, the lights in the sealing will turn on with a steady light. If i press button #1 again they will turn off.

If i press #2, the lights in the sealing will start blinking. If i press button #2 again they will turn off.

If i press #3, the lights in the sealing will start fading, up and down. If i press button #3 again they will turn off.

And so on...

Btw, thank you for all you help so far @Robin2. Means a lot.

jacobthebluesman:
This is what i want from the code:
Imagine that you have 5 lamp buttons on the wall. If i press #1, the lights in the sealing will turn on with a steady light. If i press button #1 again they will turn off.

Then you need a variable for each button that keeps track of the state of the lights. Let's call the variable lightsON and initialize it to false. With the first press the variable changes to true. On the next press it changes to false etc.

To do that you also need to check that the button changed from HIGH to LOW (assuming LOW means pressed) so that it does not cycle through the sequence at 1000 times a second.

Then you could have a function called lightsFullOn() which checks the variable lightsON to know what to do. You can just call that function every time loop() repeats. The code in loop() could be as simple as

void loop() {
  readAndSaveButtons();
  lightsFullOn();
  lightsFlash();
  lightsFade();
}

You probably also need to deal with two things trying to happen at once.

Personally I would use 4 buttons with the extra one for OFF as that would make the process much simpler.

...R

Thank you @Robin2.

My more experienced friend gave me some support and now I have a working code. This code will turn on LED1 if button 1 is pressed, and turn it off if button one us pressed again. The same goes for LED2 and button 2. Here it is:

//Defining variables
boolean buttonIsPressed = false;
int pressedButton = 0;
int LED1=5;
int LED2=6;
int brightness = 0;
int pin1=2;
int pin2=4;

//======================================================
  
void setup(){
//Define LED-ports as outputs  
pinMode(LED1, OUTPUT); 
pinMode(LED2, OUTPUT);

//Initiate serialprint
Serial.begin(9600);

}

//===================================================
  
void loop() {


  while(!buttonIsPressed) {  // Idle mode: no lights are on
  
    if( readButtons() > 0 ) //Reads if any of the buttons where pressed
      buttonIsPressed = true;           // turns 'buttonIsPressed' to TRUE so that we can leave the idle-loop
      Serial.println("Nothing going on"); //Prints that we are not in a case
      digitalWrite(LED1,LOW);//Turns of LED1
      digitalWrite(LED2,LOW); //Turns of LED2

  }
  buttonIsPressed = false; // Resets the variable so that we return to the while-loop above after we passed through the 'loop'.
  pressedButton = readButtons(); //Stores value for button
  delay(50);            // Waits for the button to debounc
  while( readButtons() != 0); // Waits for the pressed button to be released
  delay(50); // Waits for the button to debounce
  
  //======================================================
  
  switch (pressedButton) {    // Switches between cases depending on which value 'pressedButton' has. If pressedButton == 1, switches to 'case 1:' and the to 'SWITCHEND'


    //====================================================
    case 1:           // When the first button is pressed
      
      while(readButtons() != 1) {   //As long as readButton() returns 1 (button 1 not pressed), this while-loop will run
        
        
        digitalWrite(LED1,HIGH); //Turns on LED1
        Serial.println("case1"); //Prints that we are in case 1

        /*To use later for DMX-control
         * DmxMaster.write(1, brightness);   // Dimming lights, vet inte vad för mönster du vill göra
         brightness = brightness + 1; //T
        
        
        if( brightness > 255)
          brightness = 0; // Återställ brightness
        
        delay(1);       // Godtycklig delay
        */
      }
      
      
    break;

     //======================================================
    
    case 2:           // When the second button is pressed
      
      while(readButtons() != 2) {   //As long as readButton() returns 2 (button 2 not pressed), this while-loop will run
        
        digitalWrite(LED2, HIGH); //Turns on LED1
        Serial.println("case2"); //Prints that we are in case 2

         /* To use later for DMX-control
          brightness = brightness + 1;
        if( brightness > 255)
          brightness = 0; // Återställ brightness
         
        
        delay(1);       // Slows down 
        */
        
      }
      
    break;


     //=====================================================
    default:
        // If non of the cases are TRUE, that is 'pressedButton' does not equal 1 or 2 (which is unlikley) the process ends up here.
    break;
    
    
  } // SWITCHNEND
  
  //brightness = 0;   //Resets brightness
  
while( readButtons() != 0); //One more debounce saftey
  delay(50);
}


  //=======================================================
int readButtons(void) {
  
  if(digitalRead(pin1)){
    return 1;   // 1 means that button one has been pressed
    delay(50); } //Debounce
  else if(digitalRead(pin2)){
    return 2;   // 2 means that button 2 has been pressed
    delay(50); //Debounce
    }
  else
    return 0;   // No button has been pressed, sends value 0
  
  
}