Switching between scripts with arduino

Hey guys,

I am working on a project where I have a circuit that can either run automatically or with manual input. I have two scripts, one for each mode (manual/auto) however I am unsure of how to implement a switch or a button to switch modes since the arduino runs almost linearly, an instruction after next.

Is there any way to add a switch or have a piece of code that will I guess continuously run simultaneously to the script and listen to a switch or button, see if it is being pressed to stop the running script and switch to the other mode? I mean something like eventlistener in javascript for example for a button or switch.

I appreciate any help or guidance and many thanks in advance!!!

How about a boolean variable? If true, run this code, if false, run that code?

Why not just have it run automatically until it detects manual input? Once it detects any manual input, it starts a timer, say 3 seconds. If in that 3 seconds, it gets another manual input, it resets the timer and repeats. After 3 seconds is up, it reverts back to automatic.

Assmue that you ave the following sketch with two tasks -- Task1 is to blink LED1 connected at DPin-2 for 3 sec at 1 sec interval, and Tasks is to blink LED2 connected at DPin-3 for 10 sec at 2 sec interval.

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

void loop()
{
     Task1();
     Task2();
}

void Tak1()
{
    //code here
}

void Task2()
{
     //code here
}

If you upload the above sketch, you will see that LED1 blinks for 3 times and then LED2 blinks for 5 times and the cycle repeaes.

Now you want to connect an On/Off (close/open) button such that when the button is On (closed) Task1() will be running and Task2() will be running when the button is Off (open).

Is this what you want?

You cannot have two seperate sketches running in Arduino. It is always true that you can upload only one sketch with many tasks.

Post both sketches, one manual, one automatic that each works to your plans.

Without seeing the two rhinos things you want to easily switch between, helping is difficult.

TIA

a7

+1 to @alto777 's post #5.

And I have implemented something just like @camsysca 's post #2 many times.

It could look like this: if (a toggle is switched) {do this code} else {do that code}

==>

if (a toggle is switched) 
{
   do this code
} 
else 
{
   do that code
}

It could be as simple as that.

void loop() {
  if (digitalRead(somePin) == LOW)
    sketchALoop();
  else
    sketchBLoop();
} 

Perhaps this would help: Google

arduino combone sketches

or do better than I did and spell "combine" right. You will get many hits, take a look at a few - they all have to address the fundamental issues when two things are expected to fit in one bag.

a7

You will want to use "interrupts" for that to "monitor" the button.

https://docs.arduino.cc/language-reference/en/functions/interrupts/interrupts/

const byte interruptPin = 2; // pushbutton
volatile byte state = LOW;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP); // wired PIN >> BUTTON..BUTTON >> GND
  attachInterrupt(digitalPinToInterrupt(interruptPin), globalthermonuclearwarfare, FALLING);
}

void loop() {
  digitalWrite(LED_BUILTIN, state);
  state = 0;
}

void globalthermonuclearwarfare() {
  state = 1;
}

Or, have "coin flip" decide which task to run...

void setup() {
  Serial.begin(115200);
  randomSeed(analogRead(A0));
}

void loop() {
  if (random(2))
    tictactoe();
  else
    globalthermonuclearwarfare();
}

void tictactoe() {
  Serial.println("No winnner.");
}

void globalthermonuclearwarfare() {
  Serial.println("NO WINNER!");
}

@xfpd I doubt our OP understands the nuance of "simultaneously" that you're addressing with the interrupt approach. There is no reason, if properly constructed, two alternative codes such as his previous two threads contained cannot monitor the 'button', 'switch', or what have you while performing their tasks. We've had no indication, as far as I can see, of what Arduino(Uno, Nano, ESP32, whatever), our OP is working with; hence, I suspect an Uno. One might argue that neither task is performed simultaneously anyway, in a single-threaded one-lung half-a-brain-cell processor such as the '328'.

@atmnsm678413 Would you care to participate in this thread, please, and provide some responses?

I agree... but it will be something to read and look forward to trying... or are you referring to tictactoe? ( :

I tried this, here is the code for it however it only runs the manual code (else if) no matter what value is read from the potentioemter (acts as my temporal switch), is there something I am doing wrong?

int redLED = 3;
int blueLED = 4;
int button = 6;
int buzzer = 5;

long starttime = 0;
long endtime = 0;



void setup() {
Serial.begin(9600); //remove when end
 pinMode(A0, INPUT); //potentiometer
 pinMode(buzzer, OUTPUT);
 pinMode(redLED, OUTPUT);
 pinMode(blueLED, OUTPUT);
 pinMode(button, INPUT_PULLUP);

 
 digitalWrite(redLED, LOW); //initialize all these as off, LEDs as well as we need to see in the void loop which one will be turne on
 digitalWrite(blueLED, LOW);
 digitalWrite(buzzer, LOW);
}

void loop() {

  Serial.println(analogRead(A0));
  if (analogRead(A0) >= 512) {
    auto2();
    }
  else if (analogRead(A0) < 512){
    manual();
    }
}


void auto2(){
   //depending on if manual or auto, have either one or the other LED on
  
  while (digitalRead(button) == HIGH){ //while loop that stops everything until user presses the button to start
  
    
    }
 digitalWrite(buzzer, HIGH);
  delay(50); //delay required between while loops or the LOW state that breaks each loop will affect both and will not start the light flashing loop
  digitalWrite(buzzer, LOW);

  
  while (1==1){ //while loop that stops everything until user presses the button to start
  
    
    
  
  digitalWrite(buzzer, HIGH);
  delay(100);
  digitalWrite(buzzer, LOW);
  starttime = millis();
  endtime = starttime;
  while ((endtime - starttime) <=20000) // do this loop for up to 1000mS = 1S, 20x60x1000=1200
  {
    digitalWrite(redLED, LOW);
    delay(500);
    digitalWrite(redLED, HIGH);
    delay(500);
    endtime = millis();
  }

  digitalWrite(buzzer, HIGH);
  delay(100);
  digitalWrite(buzzer, LOW);

 starttime = millis();
  endtime = starttime;
  while ((endtime - starttime) <=5000) // do this loop for up to 1000mS = 1S
  {
    digitalWrite(redLED, HIGH);
    endtime = millis();
  }
 
  digitalWrite(buzzer, HIGH);
  delay(100);
  digitalWrite(buzzer, LOW);
  digitalWrite(redLED, LOW);
  delay(50);

  
  }

  }

void manual(){

//depending on if manual or auto, have either one or the other LED on
digitalWrite(blueLED, HIGH);
  
  while (digitalRead(button) == HIGH){ //while loop that stops everything until user presses the button to start
  
    
    }
  
  digitalWrite(buzzer, HIGH);
  delay(50); //delay required between while loops or the LOW state that breaks each loop will affect both and will not start the light flashing loop
  digitalWrite(buzzer, LOW);
  delay(50);
  digitalWrite(buzzer, HIGH);
  delay(50);
  digitalWrite(buzzer, LOW);
  
  
  starttime = millis();
  endtime = starttime;
  while ((endtime - starttime) <=1200000) // do this loop for up to 1000mS = 1S, 20x60x1000=1200
  {
    digitalWrite(blueLED, LOW);
    delay(500);
    digitalWrite(blueLED, HIGH);
    delay(500);
    endtime = millis();
  }

  digitalWrite(buzzer, HIGH);
  delay(50);
  digitalWrite(buzzer, LOW);

  while (digitalRead(button) == HIGH){ //while loop that stops everything until user presses the button to start
  
    
    }
  digitalWrite(buzzer, HIGH);
  delay(50);
  digitalWrite(buzzer, LOW);
  
 starttime = millis();
 endtime = starttime;
  
  while ((endtime - starttime) <=20000) // do this loop for up to 1000mS = 1S
  {
    digitalWrite(blueLED, HIGH);
    endtime = millis();
  }
 
  digitalWrite(buzzer, HIGH);
  digitalWrite(blueLED, LOW);
  delay(500);
  digitalWrite(buzzer, LOW);
  
  



  
  }
type or paste code here

Hey, it is an Arduino UNO and here is an approach I tried from one of the other comments, it doesn't work but I hope you can understand what I mean with like monitor simultaneously.

(basically the arduino is constantly checking the potentioemters value - which simulates a switch since I don't have one - and depending on the state one of two modes runs)

int redLED = 3;
int blueLED = 4;
int button = 6;
int buzzer = 5;

long starttime = 0;
long endtime = 0;



void setup() {
Serial.begin(9600); //remove when end
 pinMode(A0, INPUT); //potentiometer
 pinMode(buzzer, OUTPUT);
 pinMode(redLED, OUTPUT);
 pinMode(blueLED, OUTPUT);
 pinMode(button, INPUT_PULLUP);

 
 digitalWrite(redLED, LOW); //initialize all these as off, LEDs as well as we need to see in the void loop which one will be turne on
 digitalWrite(blueLED, LOW);
 digitalWrite(buzzer, LOW);
}

void loop() {

  Serial.println(analogRead(A0));
  if (analogRead(A0) >= 512) {
    auto2();
    }
  else if (analogRead(A0) < 512){
    manual();
    }
}


void auto2(){
   //depending on if manual or auto, have either one or the other LED on
  
  while (digitalRead(button) == HIGH){ //while loop that stops everything until user presses the button to start
  
    
    }
 digitalWrite(buzzer, HIGH);
  delay(50); //delay required between while loops or the LOW state that breaks each loop will affect both and will not start the light flashing loop
  digitalWrite(buzzer, LOW);

  
  while (1==1){ //while loop that stops everything until user presses the button to start
  
    
    
  
  digitalWrite(buzzer, HIGH);
  delay(100);
  digitalWrite(buzzer, LOW);
  starttime = millis();
  endtime = starttime;
  while ((endtime - starttime) <=20000) // do this loop for up to 1000mS = 1S, 20x60x1000=1200
  {
    digitalWrite(redLED, LOW);
    delay(500);
    digitalWrite(redLED, HIGH);
    delay(500);
    endtime = millis();
  }

  digitalWrite(buzzer, HIGH);
  delay(100);
  digitalWrite(buzzer, LOW);

 starttime = millis();
  endtime = starttime;
  while ((endtime - starttime) <=5000) // do this loop for up to 1000mS = 1S
  {
    digitalWrite(redLED, HIGH);
    endtime = millis();
  }
 
  digitalWrite(buzzer, HIGH);
  delay(100);
  digitalWrite(buzzer, LOW);
  digitalWrite(redLED, LOW);
  delay(50);

  
  }

  }

void manual(){

//depending on if manual or auto, have either one or the other LED on
digitalWrite(blueLED, HIGH);
  
  while (digitalRead(button) == HIGH){ //while loop that stops everything until user presses the button to start
  
    
    }
  
  digitalWrite(buzzer, HIGH);
  delay(50); //delay required between while loops or the LOW state that breaks each loop will affect both and will not start the light flashing loop
  digitalWrite(buzzer, LOW);
  delay(50);
  digitalWrite(buzzer, HIGH);
  delay(50);
  digitalWrite(buzzer, LOW);
  
  
  starttime = millis();
  endtime = starttime;
  while ((endtime - starttime) <=1200000) // do this loop for up to 1000mS = 1S, 20x60x1000=1200
  {
    digitalWrite(blueLED, LOW);
    delay(500);
    digitalWrite(blueLED, HIGH);
    delay(500);
    endtime = millis();
  }

  digitalWrite(buzzer, HIGH);
  delay(50);
  digitalWrite(buzzer, LOW);

  while (digitalRead(button) == HIGH){ //while loop that stops everything until user presses the button to start
  
    
    }
  digitalWrite(buzzer, HIGH);
  delay(50);
  digitalWrite(buzzer, LOW);
  
 starttime = millis();
 endtime = starttime;
  
  while ((endtime - starttime) <=20000) // do this loop for up to 1000mS = 1S
  {
    digitalWrite(blueLED, HIGH);
    endtime = millis();
  }
 
  digitalWrite(buzzer, HIGH);
  digitalWrite(blueLED, LOW);
  delay(500);
  digitalWrite(buzzer, LOW);
  
  



  
  }

The problem is that your code is not monitoring the potentiometer continuously.

loop() only checks A0 until either auto2() or manual() is entered. Once inside those functions, the many while loops and delays block the program. In particular, while (1==1) in auto2() is an endless loop, the code can never return to loop() and therefore can never check A0 again.

So the Arduino is not really running two modes simultaneously. The key issue is not having separate auto2() and manual() functions. The key issue is that the code is heavily blocked by while loops and delay() calls.

For example, this:

digitalWrite(redLED, HIGH);
delay(5000);
digitalWrite(redLED, LOW);

blocks the Arduino for 5 seconds.

A typical millis() approach would look more like:

unsigned long timer = millis();

void loop() {

  if (analogRead(A0) >= 512) {
    // auto mode
  } else {
    // manual mode
  }

  if (millis() - timer >= 5000) {
    digitalWrite(redLED, LOW);
  }
}

The important difference is that the Arduino keeps executing loop() thousands of times per second while waiting for the 5 seconds to expire, so it can still monitor the potentiometer, buttons, sensors, etc.

You need to rewrite this as a non-blocking state machine using millis() instead of delays and avoid blocking loops. That way loop() can keep checking the potentiometer, button and timing conditions continuously.

so basically what you mean is that once I replace all the while loops by millis() then the code will run infinitely and check the analog input cointinuously that way i will be able to change the functions with one value or another? and what would you suggest as a new approach, have a vairable of timer and then like for example, if timer is less than 20 blink the redLED and once it is bigger until timer <= 25 keep it HIGH constantly and then reset the timer once this is done? also how would I blink the LEDs without delay(), am I on the right track?

I am curious why you are using all of the while loops. Maybe you want something to be done WHILE a button is pressed?? But you don't have to do that. You can do something IF it is pressed. In fact you can use IF instead of while, and still run code while the button is pressed.

Yes, you are on the right track.

The important idea is that loop() keeps running continuously instead of getting stuck inside while loops or long delay() calls.

That way the Arduino can keep checking the potentiometer, button, timing conditions, etc., and can switch modes whenever required.

I think you are starting to think in terms of states and timing rather than blocking code, which is exactly the direction I was trying to point you towards.

Conceptually I think you are now heading the right way.

One method I use to "blink without delay()" is change states of the LED on alternate passes. That is to say, "ON" for even states and "OFF" for odd states.

unsigned long timer, timeout = 500; // used for 1/2 second timer
void setup() {
  pinMode(LED_BUILTIN, OUTPUT); // LED to blink
}
void loop() {
  if (millis() - timer >= timeout) { // compare elapsed time against "timeout"
    timer = millis(); // reset timer
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // change LED state
  }
}

By simply changing their state when it's time to do so. Requires that you write non-blocking code, so that one of the things your code does very frequently is a time check, to see if it is indeed time to change the state of the LED.

That is the essence of the mindset change you need to embrace. Don't "do something until it's done", but do many checks to see if it's time to do something; then expanding on that, check if it's time to do many things.

yeah you are right, I should change it to an IF now that I am thinking about it. I believe I used a while loop because my computer science teacher in highschool loved them and he would make us use them for literally everything