Run different parts of the code by different buttons

Guys, I saw similar threads on the forum, but they didn't help me, so I'm asking for help. I have average knowledge, but I can study if necessary. I don't know how to program, but I can edit, copy, paste, etc.
Objective: I work on several projects, but I have to execute them one at a time. I wanted to know if it's possible to make a single sketch with three buttons so that each button does a different thing. (I don't need them all to be executed at the same time, just one at a time.)
Example: Button 1 - make an LED blink every 5 seconds
Button 2 - control a motor with a potentiometer
Button 3 - display the time on an OLED display
I have the separate codes, but I don't know how to combine them and insert the buttons.
Thanks to anyone who can help.

Hi @baltazarvieira!

The things you want to be done don't sound very difficult.

Posting your separate working code would be very helpful (if not required) to avoid unnecessary effort for you and us ...

You posted already in the past so no need to tell you basics about the forum :wink:

ec2021

And add also sufficient information about your (planned) hardware and wiring please ...!

Yes, it is

  • Write a function for each set of code that you want to run
  • In loop() call a function to read the button inputs and call the corresponding function
  • Ideally you would use code in each function that does not block the free running of the loop() function. That would allow you to switch functions

Note that if your code is complicated and uses a lot of resources then you may have problems running out of memory because the code for all functions needs to be in memory all of the time

I suggest that you start by putting the code for Blink in a function and calling it from loop() while a single button is pressed. This NOT a good way to do it but will give you a start

I’d suggest you check the examples for one of the numerous button library such as Button in easyRun or OneButton or Toggle or EasyButton or Bounce2, ...

They will show you how to detect the button press and react to it.

Otherwise if you don’t want to learn, chatGPT will likely be able to generate such a code.

do you have code that can recognize when a button has been pressed and do something simple like print something or flash an LED on and then off?

could you then change that code to execute your different projects as separate functions: blinkLed(), runMotor() and dispTime()

I'll try to put together a diagram of the scenario I want and then post it here for you to help me. Thanks for now.

no need, i think what you're trying to do is pretty obvious

i'm also assuming that pressing a different buttons causes a change in behavior whicn means buttons much constantly be monitored

Colleagues, I imagine it's simple for your level, but it's not so easy for me. Do you have any examples? It could be just with LEDs. Then I'll try to adapt it.
Ex.
Button 1 makes the green LED blink every 5 seconds.
Button 2 makes the red LED blink every 10 seconds.
Button 3 makes the blue LED blink every 15 seconds.

  • Show us the code you have written.
  • Show us your schematic and actual wiring.

Here is a sketch generated by chatGPT using the OneButton library.


#include <OneButton.h>

const byte pinButton1 = 2;
const byte pinButton2 = 3;
const byte pinButton3 = 4;

const byte pinLed1 = 8;
const byte pinLed2 = 9;
const byte pinLed3 = 10;

enum Activity {
  NONE,
  ACT1,
  ACT2,
  ACT3
};

Activity currentActivity = NONE;

OneButton btn1(pinButton1, true);
OneButton btn2(pinButton2, true);
OneButton btn3(pinButton3, true);

void stopCurrentActivity() {
  switch (currentActivity) {
    case ACT1: digitalWrite(pinLed1, LOW); break;
    case ACT2: digitalWrite(pinLed2, LOW); break;
    case ACT3: digitalWrite(pinLed3, LOW); break;
    default: break;
  }
  currentActivity = NONE;
}

void setup1() {
  pinMode(pinLed1, OUTPUT);
  // any other runtime setup for activity 1
}

void setup2() {
  pinMode(pinLed2, OUTPUT);
  // any other runtime setup for activity 2
}

void setup3() {
  pinMode(pinLed3, OUTPUT);
  // any other runtime setup for activity 3
}

void activate1() {
  stopCurrentActivity();
  // do activity-specific runtime setup here if needed
  currentActivity = ACT1;
}

void activate2() {
  stopCurrentActivity();
  // do activity-specific runtime setup here if needed
  currentActivity = ACT2;
}

void activate3() {
  stopCurrentActivity();
  // do activity-specific runtime setup here if needed
  currentActivity = ACT3;
}

void loop1() {
  static unsigned long last = 0;
  if (millis() - last >= 500) {
    last = millis();
    digitalWrite(pinLed1, digitalRead(pinLed1) == HIGH ? LOW : HIGH);
  }
}

void loop2() {
  static unsigned long last = 0;
  if (millis() - last >= 1000) {
    last = millis();
    digitalWrite(pinLed2, digitalRead(pinLed2) == HIGH ? LOW : HIGH);
  }
}

void loop3() {
  static unsigned long last = 0;
  if (millis() - last >= 2000) {
    last = millis();
    digitalWrite(pinLed3, digitalRead(pinLed3) == HIGH ? LOW : HIGH);
  }
}

void setup() {
  setup1();
  setup2();
  setup3();

  btn1.attachClick(activate1);
  btn2.attachClick(activate2);
  btn3.attachClick(activate3);
}

void loop() {
  btn1.tick();
  btn2.tick();
  btn3.tick();

  switch (currentActivity) {
    case ACT1: loop1(); break;
    case ACT2: loop2(); break;
    case ACT3: loop3(); break;
    default: break;
  }
}

I changed the blinking periods to make them shorter this way you don’t have to wait 15s to see a blink.

It’s very verbose but each task is clearly outlined .

There one global setup and a specific one for whatever needs to be done once regardless of the task that will. E running.

Then when you press a button a run time activation function is called to clean up the previous state if needed and setup the new environment and then a specific loop is run in the loop()

Should be self explanatory but if you can’t program…

you'e not answering questions

here

const byte PinBut  [] = { A1, A2, A3 };
const int  Nbut       = sizeof(PinBut);
      byte butState [Nbut];

const byte PinLed  [] = { 13, 12, 11, 10 };
const int  Nled       = sizeof(PinLed);

enum { Off = HIGH, On = LOW };

int mode = -1;      // none

unsigned long msec;
unsigned long msec0;

char s [90];

// -----------------------------------------------------------------------------
void
pot ()
{
    if (msec - msec0 >= 500)  {
        msec0  = msec;
        sprintf (s, " pot %4d", analogRead (A0));
        Serial.println (s);
    }
}

// -----------------------------------------------------------------------------
int idx;

void
flasher ()
{
    if (msec - msec0 >= 200)  {
        msec0 = msec;
        digitalWrite (PinLed [idx], ! digitalRead (PinLed [idx]));
        if (Nled <= ++idx)
            idx = 0;
    }
}

// -----------------------------------------------------------------------------
unsigned sec;

void
timer ()
{
    if (msec - msec0 >= 1000)  {
        msec0 = msec;
        sec++;
        sprintf (s, "%2d:%02d", sec /60, sec %60);
        Serial.println (s);
    }
}

// -----------------------------------------------------------------------------
void loop ()
{
    msec = millis ();

    switch (mode) {
    case 0:
        pot ();
        break;

    case 1:
        flasher ();
        break;

    case 2:
        timer ();
        break;
    }

    for (int n = 0; n < Nbut; n++)  {
        byte but = digitalRead (PinBut [n]);
        if (butState [n] != but)  {
            butState [n]  = but;
            delay (20);                     // debounce

            if (LOW == but)  {
                mode = n;
                sprintf (s, "loop: mode %d", mode);
                Serial.println (s);
            }
        }
    }
}

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

    for (int n = 0; n < Nbut; n++)  {
        pinMode (PinBut [n] ,INPUT_PULLUP);
        butState [n] = digitalRead (PinBut [n]);
    }

    for (int n = 0; n < Nled; n++) {
        pinMode      (PinLed [n], OUTPUT);
        digitalWrite (PinLed [n], Off);
    }
}

Dear colleagues, I was about to prepare the experiment when I noticed that I didn't have the buttons in my parts cabinet. I ordered them and they will arrive tomorrow 09/15. Once again, thank you for your kindness.

Guys, I managed to do roughly what I wanted with LEDs. At first, just being able to control each LED with a button got me excited. I'll try to extrapolate the project to other sensors, OLEDs, etc. I'll post a very simple project here, and if I make progress, I'll post it here. Thank you all very much. I use a 30-pin ESP32.

void setup() {
  pinMode(15, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(16, INPUT_PULLUP);
  pinMode(17, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
}

// the loop function runs over and over again forever
void loop() {
  if(digitalRead(16)){
    digitalWrite(15, LOW);
  }else{
    digitalWrite(15, HIGH);
  }

  if(digitalRead(17)){
    digitalWrite(2, LOW);
  }else{
    digitalWrite(2, HIGH);
  }

  if(digitalRead(5)){
    digitalWrite(4, LOW);
  }else{
    digitalWrite(4, HIGH);
  }

}

This sketch also worked perfectly

It has a better structure than your simpler code as it takes actions only when the press is detected (and not a bounce or if not needed)

Good news that it works. Now you can move on to take other actions when the buttons are pressed

One suggestion that I would make is to give the pins named so that the code becomes easier to read and understand. Something like this

const byte butPin1 = 16;
const byte butPin2 = 17;
const byte butPin3 = 5;
const byte ledPin1 = 15;
const byte ledPin2 = 2;
const byte ledPin3 = 4;

void setup()
{
    pinMode(ledPin1, OUTPUT);
    pinMode(ledPin2, OUTPUT);
    pinMode(ledPin3, OUTPUT);
    pinMode(buttonPin1, INPUT_PULLUP);
    pinMode(buttonPin2, INPUT_PULLUP);
    pinMode(buttonPin3, INPUT_PULLUP);
}

// the loop function runs over and over again forever
void loop()
{
    if (digitalRead(buttonPin1))
    {
        digitalWrite(ledPin1, LOW);
    }
    else
    {
        digitalWrite(ledPin1, HIGH);
    }

    if (digitalRead(buttonPin2))
    {
        digitalWrite(ledPin2, LOW);
    }
    else
    {
        digitalWrite(ledPin2, HIGH);
    }

    if (digitalRead(butPin3))
    {
        digitalWrite(ledPin3, LOW);
    }
    else
    {
        digitalWrite(ledPin3, HIGH);
    }
}

You can, and should, give the pins meaningful names if possible