millis() question

Hello,

I’m trying to have a keypad do the following when pressed:

If the 5 is pressed I want LED 1 to blink twice then stay on
If either the 4 or the 6 is pressed I want LED 2 to blink forever
If the # key is pressed I want it to cancel whatever’s going on with the other LEDs

I learned that I could not use delay() for button 4 or 6 being pressed so I tried using millis(). I tried using the millis() for just when button 4 is being pressed in the code below and nothing happens when 4 is pressed. I am just wondering if someone could maybe tell me what I am doing wrong?

Thanks,

#include <Keypad.h>

const byte ROWS = 4; // Four rows
const byte COLS = 3; // Three columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 12, 11, 10, 9 };
// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = { 8, 7, 6 }; 

// Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

#define ledone 2
//#define ledtwo 3

const int ledtwo =  3;
int ledState = LOW;
unsigned long previousMillis = 0;
const long interval = 1000;

void setup()
{
  pinMode(ledone,OUTPUT);
  digitalWrite(ledone, LOW);
  pinMode(ledtwo,OUTPUT);
  digitalWrite(ledtwo, LOW);
  Serial.begin(9600);
}

void loop()
{
    char key = kpd.getKey();  
    if (key == '5') {
      digitalWrite(ledone, HIGH);
      delay(1000);
      digitalWrite(ledone, LOW);
      delay(1000);
      digitalWrite(ledone, HIGH);
      delay(1000);
      digitalWrite(ledone, LOW);
      delay(1000);
      digitalWrite(ledone, HIGH); 
    }
     if (key == '*'){
      digitalWrite(ledone, LOW);
      digitalWrite(ledtwo, LOW);
    }

    unsigned long currentMillis = millis();

    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      
      if (ledState == LOW) {
      ledState = HIGH;
        } else {
          ledState = LOW;
    }
       if(key == '4'){
      digitalWrite(ledtwo, ledState);
      }
    }
}

You need variables to remember what state you are (or check the LEDs). in the code if I press twice on 5, I'll get the blinking again.

for the key 4, what you should declare and set a boolean variable as well key4or6HasBeenPressed = true; when you detect the press (and reset it to false when you press # + initialize to false in setup()) and then you were not very far:

if (key4or6HasBeenPressed) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;

      if (ledState == LOW) {
        ledState = HIGH;
      } else {
        ledState = LOW;
      }
      if (key == '4') {
        digitalWrite(ledtwo, ledState);
      }
    }
  }

if you press CTRL-T in the IDE, that will indent correctly the text

plshelp:
If the 5 is pressed I want LED 1 to blink twice then stay on
If either the 4 or the 6 is pressed I want LED 2 to blink forever
If the # key is pressed I want it to cancel whatever’s going on with the other LEDs

So at any given moment, your LED setup can be in the following states:

OFF - not blinking at all
BLINKING_TWICE
STAYING_ON
BLINKING

When the led is blinking, it can be on or off, and there is a time at which it started the “current” blink
When the led is blinking twice, it also needs to count the blinks.

So, to manage this led you will need the following four variables:

enum State {
  OFF = 0,
  ON = 1,
  BLINKING = 2,
  BLINKING_TWICE = 3
} state;

boolean isOn;
uint32_t blinkStartMs;
int blinkCount;

You then want some functions to control the blinking:

void cancelBlinking() {
  state = OFF;
  isOn = false; // dont realy need this
  digitalWrite(ledPin, LOW);
}

void startContinuousBlinking() {
  state = BLINKING;
  isOn = true;
  blinkCount = 0; // don't really need this
  blinkStartMs = millis();
  digitalWrite(ledPin, HIGH);
}

void startTwoBlinks() {
  state = BLINKING_TWICE;
  isOn = true;
  blinkCount = 0
  blinkStartMs = millis();
  digitalWrite(ledPin, HIGH);
}

Ok! Finally, you need a function that is called inside the loop - that is just that part of the loop that handles blinking.

void loop_blinker() {
  if(state == OFF || state == ON) return; // dont need to do anything

  if(millis() - blinkStartMs < 500) return; // dont do anything

  // ok! It's time to blink the led!

  isOn = !isOn;
  digitalWrite(ledPin, isOn ? HIGH : LOW);
  blinkStartMillis = millis(); 
  blinkCount ++;

  if(state == BLINKING_TWICE && blinkCount == 6) {
    // blink count will be 6 when the third "off" is complete
    // the led will now be on
    state = ON;
  }
}

Jam a call to loop_blinker() inside your loop() near the top, and it should all work for you. If you want multiple blinker, then you’ll want to learn about classes.

Thanks for the help guys.

So if I call the loop_blinker() in my loop() would this work?

if(key == '4'){
      loop_blinker();
    }