Using a 1x4 Keypad to switch between loops

Hi Community,

I have a project that I am creating with a ardunio uno microcontroller. I am using to to examples on the ardunio website: one sketch uses a potentiometer to vary a LED, the second sketch uses sin function to vary the LED. I combined both of these sketches with the use keypad to switch between the loops. The main sketch works; however when I press the button to switch to the sin function, I can't get it out of the loop to go back to the other loop. Could I get some advice on my sketch.

#include <Key.h>
#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 1; //one columns
char keys[ROWS][COLS] = {
	{'1'},
	{'2'},
	{'3'},
	{'4'}
	};
byte rowPins[ROWS] = {7, 6, 5, 4}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {8}; //connect to the column pinouts of the keypad
	
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
//byte ledPin = 3; 
const int Poten = A0;  // Analog input pin that the potentiometer is attached to
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  3;      // the number of the LED pin

void setup(){
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
  digitalWrite(ledPin, HIGH);   // sets the LED on
  keypad.addEventListener(keypadEvent); //add an event listener for this keypad
}
  
void loop(){
  char key = keypad.getKey();
  if (key) {
    Serial.print("Pressed: ");
    Serial.println(key);
}
}

//take care of some special events
void keypadEvent(KeypadEvent key){
  
    Serial.print("Pressed: ");
    Serial.println(key);
      
  switch (keypad.getState()){
    case PRESSED:
      switch (key){
        case '1': loop2(); break;
        case '2': loop1(); break;
} 
}
}
  void loop1(){
     int key1 = keypad.getKey ();
    while(1){
       key1 = keypad.getKey ();
        if (key1)
        {break;} // leave the loop
        int value = analogRead(Poten);
        int led_speed = value/4;
        analogWrite(ledPin, led_speed);
        Serial.println(led_speed);
        delay(1);
}
}
void loop2(){
   int key1 = keypad.getKey ();
   while(1){
     key1 = keypad.getKey ();
      if (key1)
      {break;}  // leave the loop
        
   for(int i = 0; i<360; i++){
    //convert 0-360 angle to radian (needed for sin function)
    float rad = DEG_TO_RAD * i;
   //calculate sin of angle as number between 0 and 255
    int sinOut = constrain((sin(rad) * 128) + 128, 0, 255); 
    analogWrite(ledPin, sinOut);
    delay(15);
    Serial.println(sinOut);
}
}
}

(code tags added by moderator)

Quick reply off the top of my head on lunch:

The loop() function will always be called, and without writing your own code from scratch cannot be stopped - short of stopping the whole program.

What you want is a basic state machine - there's a few examples around on how to implement one, but the basic idea would be something like this (along with your setup stuff):

enum Tasks
{
    Task1
    Task2
    Task3
} currentTask;

void doTask1()
{
    Serial.println("Doing Task 1");
}

void doTask2()
{
    Serial.println("Doing Task 1");
}

void doTask3()
{
    Serial.println("Doing Task 1");
}
//take care of some special events
void keypadEvent(KeypadEvent key)
{  
	Serial.print("Pressed: ");
	Serial.println(key);

	switch (keypad.getState())
	{
		case PRESSED:
		switch (key)
		{
			case '1': currentTask = Task1; break;
			case '2': currentTask = Task2; break;
			case '3': currentTask = Task3; break;
		} 
	}
}

void loop()
{
  if(currentTask == Task1)
	doTask1();
  else if(currentTask == Task2)
	doTask2();
  else if(currentTask == Task3)
	doTask3();
}

That's the basic idea - the code might not work as a drop in but I hope it helps.

Also you might want to place your code into code tags (the # button) :wink: