Using millis and Press/Release in one code

Hi, I am new with Arduino. I need some advice or help. I am currently busy with a management project, using a 4x4 Keypad and a 8 Channel Relay module. For now I am only starting with 2 relays and later duplicate it when I get the issue sorted. When it is just the Press and Release part of the code the relays activate, but when I add the Millis part of the code the relays does not want to activate and only the LED on that channel flashes, but when pressing key 'A' the relay activates.

#include <Keypad.h>

const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

byte rowPins[ROWS] = {22, 23, 24, 25}; // Connect to the row pinouts of the keypad
byte colPins[COLS] = {26, 27, 28, 29}; // Connect to the column pinouts of the keypad

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

byte relayPin1 = 9;
byte relayPin2 = 8;



unsigned long relayOffTime = 0; // variable to store the time when the relays were turned off

void setup() {

  Serial.begin(9600); // Initialize serial communication
  pinMode(relayPin1, OUTPUT);
  pinMode(relayPin2, OUTPUT);
    // Initialize relays to OFF state
  digitalWrite(relayPin1, HIGH);
  digitalWrite(relayPin2, HIGH);

      keypad.addEventListener(keypadEvent);
}

unsigned long startTime = 0; // variable to store the start time when a key is pressed
unsigned long duration = 200; // duration for which relays stay on (in milliseconds)

void loop() {
    unsigned long currentMillis = millis(); // get the current time
    char key = keypad.getKey(); // get the key
    
    if (key) {
        Serial.println(key); // print the key to Serial monitor
        switch (key) {
            case 'A':
                digitalWrite(relayPin1, LOW); // turn on relay 1
                digitalWrite(relayPin2, LOW);
                startTime = currentMillis; // store the current time
                break;
            // add cases for other keys as needed
            default:
                break;
        }
    }
    
    // check if it's time to turn off the relays
    if (currentMillis - startTime >= duration) {
        // turn off all relays
        digitalWrite(relayPin1, HIGH);
        digitalWrite(relayPin2, HIGH);
    }
}

void keypadEvent(KeypadEvent key){
  //char key = keypad.getKey(); // Get the pressed key
    switch (keypad.getState()){
    case PRESSED:
        if (key == '1') {
            digitalWrite(relayPin1,LOW);
        }
        break;

    case RELEASED:
        if (key == '1') {
            digitalWrite(relayPin1,HIGH);
            
        }
        break;
    }
      /* FRONT UP */  
    switch (keypad.getState()){    
    case PRESSED:
        if (key == '2') {
          
            digitalWrite(relayPin1,LOW);
            digitalWrite(relayPin2,LOW);
        }
        break;

    case RELEASED:
        if (key == '2') {
            digitalWrite(relayPin1,HIGH);
            digitalWrite(relayPin2,HIGH);
            
        }
        break;
    }

}

I see your code aiming for some kind of functionality but it isn't clear what. To me. Yet.

Confirm or correct:

A key should energize a relay. After a certain time elapses the relay should be turned off.

If the key is pressed when the relay is energized, the relay should be turned off. The timer for it is irrelevant.

a7

If you have more than one relay going at a time, each will need its own

unsigned long startTime = 0; // variable to store the start time when a key is pressed

Use an array of unsigned long variables.

a7

Hi, When I press key '1' relay1 must be energized and off when released. When key 'A' is pressed, multiple relays (relay1 and relay2) needs to be energized for the set amount of time and then go off.

OK, this

    if (currentMillis - startTime >= duration) {
        // turn off all relays
Serial.println("turning off!");
        digitalWrite(relayPin1, HIGH);
        digitalWrite(relayPin2, HIGH);
    }

is getting execute alla time. So even if your other logic turns on the relays, this turns them off.

Look at this small change:

    // if we are timing the relays
    // check if it's time to turn off the relays
    if (startTime && currentMillis - startTime >= duration) {
        // turn off all relays
Serial.println("turning off!");
        digitalWrite(relayPin1, HIGH);
        digitalWrite(relayPin2, HIGH);
        startTime = 0;
    }

It uses startTime being non-zero to even bother checking the timer.

HTH

a7

Thank you @alto777 it is working perfectly. Appreciate the help.

You may have noticed the serial print statement right where the relays were getting turned off.

Any time you can't understand what's happening, inserting print statements to check the values of key variables or to see the flow of the code can help.

I had several theories, but placing that print statement was definitive.

BTW welcome to the fora.

a7