1

I have task which includes a 30s delay in the void loop. During this delay I want to be able to press a key on a keypad and have a message displayed on the serial monitor as an emergency stop. Since delays block code until they are done I thought I would be able to break them down into smaller sections so I could still press the emergency stop key in between them but of course that doesn't work. I've read through how to use the milis() function but from what I can gather it seems like it wouldn't work for my system as I need user input for it so the time from the start of the Arduino to me pressing the emergency stop button is different every time. Is there a way that isn't too complicated and would allow me to press the button during that 30s?

The delay is in if (key == '2') and the last part of the sketch is the emergency stop.

const int greenLED = 13;  //Declares greenLED as being connected to D13
const int redLED = 12;    //Declares redLED as being connected to D12 
//
const int ButtonT1 = 11;    //Declare pin number for ButtonT1 as D11
int ButtonT1State = 0;      //Variable for reading ButtonT1 state
const int ButtonT2 = 10;    //Declare pin number for ButtonT2 as D10
int ButtonT2State = 0;      //Variable for reading ButtonT2 state
//
int count_value1 = 0;       //Variable for storing counter value for turnstile 1
int count_value2 = 0;       //Variable for storing counter value for turnstile 2
//
const byte ROWS = 4;        //Four row matrix
const byte COLS = 4;        //Four columns matrix
char keys [ROWS] [COLS] = { //Defines symbols on buttons of keypad 
  {'1','2','3','A'},        //Defines ROW 1 
  {'4','5','6','B'},        //Defines ROW 2
  {'7','8','9','C'},        //Defines ROW 3 
  {'*','0','#','D'}};       //Defines ROW 4
  byte rowPins[ROWS] = {9, 8, 7, 6};  //Pin numbres of row pinouts of the keypad 
  byte colPins[COLS] = {5, 4, 3, 2};  //Pin numbers of column pinouts of the keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); 
//
void setup() { //Begin void setup, code runs once 
 Serial.begin(9600);      //Begin serial transmission 
 Wire.begin();            //Begin I2C wire communication protocol 
 lcd.begin(16,2);         //Begin LCD with 16 columns and 2 rows
//
 pinMode(greenLED, OUTPUT);  //Set greenLED as an OUTPUT
 pinMode(redLED, OUTPUT);    //Set redLED as an OUTPUT
 pinMode(ButtonT1, INPUT);   //Set ButtonT1 as an INPUT 
 pinMode(ButtonT2, INPUT);   //Set ButtonT2 as an INPUT 
}
//
void loop() {                               //Begin void loop 
   char key = keypad.getKey();              //Get a character key from the keypad 
//
   //counter 1
    ButtonT1State = digitalRead(ButtonT1);  //Read the state of ButtonT1 -  
    if (ButtonT1State == HIGH){             //Begin IF ButtonT1State is HIGH
      count_value1++;                       //IF buttonT1 pressed, increase count value 
      Serial.println(count_value1);         //Print count_value1 on serial monitor
      delay(200);                           //Delay for 200ms, 0.2s 
      digitalWrite(greenLED,HIGH);          //Set greenLED to HIGH,ON 
      digitalWrite(redLED,LOW);             //Set redLED to LOW, OFF
 //
     if (key == '1'){                         //Wait until key '1' is pressed
    }                                         //End IF key == '1'
    ButtonT2State = digitalRead(ButtonT2);   //Read ButtonT2 state
    if (ButtonT2State == HIGH){              //Check if ButtonT2State is == HIGH
      count_value2++;                        //IF buttonT1 pressed, increase count value 
      Serial.println(count_value2);          //Print count_value2 on serial monitor
      delay(500);                            //Delay for 500ms, 0.5s  
//
    if(key == '2'){                            //Wait untill key '2' is pressed - confirm ride is ready
      Serial.println("Ride starting - 30s");   //Print message in brackets on serial monitor
//30s delay, broken into smaller delays
      delay(10000); 
     Serial.println("20s left"); 
      delay(10000);
      Serial.println("10s left");
      delay(10000);
      Serial.println("Ride finished");        //Print message in brackets on serial monitor
      delay(100);                             //Delay for 1000ms, 1s 
    }                                         //End if key == '2'
//
    if (key == '4'){                        //Wait until key '4' is pressed - emergency stop 
      Serial.println("Emergency stop");     //Print message in brackets on serial monitor 
      digitalWrite(redLED,HIGH);            //Set redLED to HIGH,ON
      digitalWrite(greenLED,LOW);           //Set greenLED to LOW,OFF
      lcd.clear();                          //Clear i2c LCD
      lcd.setCursor(0,0);                   //Set cursor to column 0, row 0
      lcd.print("Emergency stop");          //Print message in brackets on i2c LCD
      count_value2 = 0;                     //Set count_value2 to 0
      delay(1000);                          //Delay for 1000ms, 1s 
    }                                       //End IF key == '4' 
}
3
  • 2
    Three words: "Finite State Machine". Don't have any delays. Instead use millis() to decide when to do different actions.
    – Majenko
    Mar 29 at 10:34
  • @Majenko How do I use millis() to create a 30s delay without making it in intevals? I want the delay to start once a key on the keypad is pressed. Can I set the value to 0 when i press the key and then do the 30s interval?
    – Izabela
    Mar 29 at 11:01
  • 2
    Record the time when the button is pressed. Then look at the difference between the current time and that time to find how much time has passed. Like you would when boiling an egg. You don't sit staring at the clock, you look at it once and then glance at it regularly while doing other things until the 5 minutes has passed.
    – Majenko
    Mar 29 at 11:07
1

Make a statemachine.

Take a piece of paper and draw out the order of operation and each time you are waiting you specify what each button will do.

So for example each time button 1 is pushed you increment the counter and change the display.

When waiting for a timeout you check if(startTimestamp - millis() > timeout) for the next step.

Then give each waiting state a number and put a big switch on a global at the start of the loop() and update the global each time the state needs to change.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.