What sterretje said.
delay() is like putting on the egg, and then sitting there watching the minute hand until it has moved the proper amount.
Using millis() is like putting on the egg, looking at the clock, calculating what time the egg will be done, and then periodically check the clock to see whether the "end time" has been reached.
The "periodically" is important - you must come back from some kind of loop to check the end-times. I'd guess that your problem - you have a subroutine buried far down in your logic, to turn on the relay for a particular time, and there is no way for THAT FUNCTION to do a non-delay based shut off of the relay, because it isn't even called periodically.
Instead, you have to implement a new function that IS called periodically to turn off the relay.
boolean relayActivated = false; // has the relay been turned on?
unsigned long relayOffTime; // when does the relay get turned off?
void execute (int m) {
digitalWrite (relay, HIGH); // Turn on the relay
relayActivated = true; // Notice that it's been turned on
relayOffTime = millis() * (1000UL * m); // calculate when it needs to go off, and save that time.
}
void loop() {
:
//
// Complicated logic that eventually calls execute(), sometimes, perhaps.
//
:
checkRelayOff(); // Now check whether the relay needs turned off.
:
// More code, perhaps.
}
// function to check if relay needs to be turned off.
void checkRelayOff() {
if (relayActivated) { // Is the relay on?
if (millis() >= relayOffTime) { // Is it time (or past time) to turn it off?
relayActivated = false;
digitalWrite(relay, LOW); // turn it off
}
}
}
(You'll want to notice that the above code doesn't handle the fact that millis() will wrap around after 50 days or so, in the interest of clarity. How to fix that is described elsewhere.)
(also notice that once you use this sort of non-delay() timing, you have to use it EVERYWHERE that is called from loop(); if you have any actual delay() calls, they'll interfere with the promptness of the millis() based checking.)