Unwanted Relay activation glitch [RESOLVED]

Hi,

I've been working on trying to find this glitch in my code, but after days of reviewing my code, I am hoping another set of eyes will catch what I am missing.

I am trying to use my UNO to operate two relays in different ways based on the position of a potentiometer.

The problem is that when I turn the potentiometer, the relays flicker on and then off, which is not good for the motors that I'll eventually be switching with these relays. I expect that in the future, this will be running more than the two relays I am testing with.

Attached is a very basic diagram of what I've put together. And now for the code:

void loop() {
//  Make sure LEDs are off 
  WriteLED(10); // Clear LED

// Initialize Relays after unknown start condition
  digitalWrite(Relay1, RelayOff); // set the relay 1 off
  digitalWrite(Relay2, RelayOff); // set the relay 2 off  

// */
    Mode = ReadMode();  // Check operating mode
    switch (Mode){
    case 1:
      WriteLED(1); // Normal
      delay (sec);
      ControlRelay(Relay1,OnTimeRelay1,RelayOn);
      ControlRelay(Relay2,OnTimeRelay2,RelayOn);
      ControlRelay(Relay2,OffTimeRelay2,RelayOff);
      ControlRelay(Relay1,OffTimeRelay1,RelayOff);
      break;
    case 2:
      WriteLED(2); // Relay 1 only
      delay (sec);
      ControlRelay(Relay1,OnTimeRelay1,RelayOn);
      ControlRelay(Relay1,OffTimeRelay1,RelayOff);
      break;
    case 3:
      WriteLED(3); // Relay 2 only
      delay (sec);
      ControlRelay(Relay2,OnTimeRelay2,RelayOn);
      ControlRelay(Relay2,OffTimeRelay2,RelayOff);
      break;
    default:
      WriteLED(0); // OFF
    } // end switch
// */
}  // End Loop

ReadMode() takes a reading of the potentiometer and then based on that reading, writes to the global variable "Mode"
WriteLED() lights up a series of LEDs to indicate either the mode it is in or the time that the relay is operating until
ControlRelay() takes which relay I want to turn on or off and the time to run for either.

void ControlRelay(int Relay, int RunTime, int ControlState) {
  int countTime;
  switch (ControlState) {
    case LOW:
      digitalWrite(Relay, RelayOn); // set the relay to on
      break;
    case HIGH:
      digitalWrite(Relay, RelayOff); // set the relay to off
      break;
    default:  // Turn relay Off in any unknown conditions
        digitalWrite(Relay, RelayOff); // set the relay to off
  } // end switch
  for (countTime = 0; countTime < RunTime; countTime++){ 
    WriteLED(countTime);
    CountDelay();
  }  // end for
} // end ControlRelay

CountDelay() is where I suspect my glitch is. All it does is count off the time, but I have it check to see if the input mode has changed. If it has, to break out of the for loop.

void CountDelay(){ // 
  int minutes, seconds, chkMode, chkTstate;

  for (minutes = 0; minutes < DelayTime; minutes ++) {
    for (seconds = 0; seconds < 60; seconds++){
      chkMode = ReadMode();  // Check if Mode has changed
      if (chkMode != Mode) {  // Immediately stop if Mode has changed
        break;  // Break will have a slight delay as minutes count off
      } // end if
      delay(sec);  
      OnIndicator(); // flashes LED to indicate seconds
    } // end for seconds
  } // end for minutes
} // end CountDelay()

int ReadMode() {  // Reads ADC input value 0-1023
  int newMode=0;
  int PotValue = analogRead(analogPin);
  if (PotValue < 31) { newMode = 0; }
    else if (PotValue < 325) { newMode = 1; }
    else if (PotValue < 720) { newMode = 2; }
    else if (PotValue < 980) { newMode = 3; }
          else { newMode = 4; }  // Not implemented, default to OFF
  return newMode;
}

TIA!

I'd suggest that you read, understand, and embrace the blink without delay example. There is no need to use delay() in your code.

PaulS:
I'd suggest that you read, understand, and embrace the blink without delay example. There is no need to use delay() in your code.

With the number of times I use delay in my code, I have always considered that implementation of time handling as inelegant and unwieldy. That's aside from making my code more confusing.

It seems to me that someone must have written something better than that by now. I just don't know where to look, especially since I'm not sure I want to, in essence, re-invent the wheel by spending my time to code, test, then re-code my own version of the delay() function. Which I know that I'm no expert on.

However, I think that my use of the delay() function doesn't have much bearing on why I am getting glitches, unless you're inferring that it is.

You said that you thought the glitches (not a very technical term) were a result of the delay(). I suggested eliminating it. You vetoed that idea, unless there was proof that it is the issue. I can't provide that proof.

What kind of relays are they? Perhaps the current change as the potentiometer is turned is the issue. Normally, the Arduino would be triggering the gate of a transistor that controls the flow of current from another power source to the relay.

Ok. I am curious to know why you consider glitch to be a non-technical term, as it describes the situation accurately.
From the Merriam-Webster dictionary:

glitch
noun ?glich\

: an unexpected and usually minor problem; especially : a minor problem with a machine or device (such as a computer)

In this case, the glitch is appearing when I change the mode via turning the potentiometer, it causes both relays to flicker from off state to on state and then back to off before resuming the intended process I programmed.

While I suspect that my CountDelay() function is the source of my glitch, I wasn't clear enough. I suspect that my checking the Mode in a double For loop and using the Break command is the source of my issue, not the delay() function, which only stalls the program for 1000 milliseconds. I don't understand completely how the arduinio handles my calling a break while in a nested For loop and I am hypothesizing that this is causing a previously never observed glitch. I have not attempted to comment out the Mode check, but I had not observed the glitch prior to adding that check. Admittedly, I didn't test it much prior to adding those few lines of code. I'll see what happens after I comment out those few lines of code.

The relays are SSRs similar to the ones I put in the fritzing diagram. I understand that it uses a TRIAC to switch the other half of the circuit on and off. I'm not using coil driven relays (which I irreverently call thumpers) if that is what you're thinking. I don't want additional vibration induced into the unit.

For the record, I also made a second circuit using a pair of LEDs to simulate the relays and I am seeing the same behavior.

I just want to note that waiting an entire 20 minute cycle while staring at a blinking LED is very hypnotic. Waiting several cycles to make sure you didn't blink during the mode changeover at the end of the cycle was far worse. :sleeping:

I've confirmed that the glitch is no longer present after commenting out the IF statement that called a Break in mid-cycle.

Back to the drawing board for my delay algorithm to handle these mode changes.

Made the changes to the code and the glitch came back! :stuck_out_tongue_closed_eyes:

void CountDelay(int countMin){ // countMin is not yet implemented
  int minutes, seconds, chkMode, chkTstate;

  for (minutes = 0; minutes < DelayTime; minutes ++) {
    chkMode = ReadMode();  // Check if Mode has changed
    if  (chkMode != Mode) {  // Immediately stop if Mode has changed
      minutes = DelayTime; // Exit outer for loop
    } else {
      for (seconds = 0; seconds < 60; seconds++){
        chkMode = ReadMode();  // Check if Mode has changed
        if (chkMode != Mode) {  // Immediately stop if Mode has changed
          seconds = 61;  // Exit inner for loop
        } else {
          chkTstate = ChkThermostat();  // Check if Thermostat has triggered
          if (chkTstate != Thermostat && TStatEnable == LOW) {  // Thermostat not triggered
            seconds = 61;  // Exit inner for loop
          } else {
            delay(sec);  
            OnIndicator(); // flashes seconds
          } // end if chkTstate
        } // end if chkMode
      } // end for seconds
    } // end if minutes
  } // end for minutes
} // end CountDelay()

Started making changes to ControlRelay() to make similar checks when I realized that I was already turning the relay on or off before I ever made a check in the code! $)

I am curious to know why you consider glitch to be a non-technical term, as it describes the situation accurately.

I don't think that it does. It simply describes that there IS a problem, without explaining the symptoms in any way.

Anyway, I'm happy that you solved your problem. Or, did you?

Take another look at the third paragraph of my OP. Thereafter, I began referring to it as a glitch. :stuck_out_tongue:

I am happy to say that once I realized that the relays were being activated prior to checking the mode had changed, everything came together very quickly. I haven't reverted the code back to breaking out of the nested For loop as a precautionary measure.

Now, I have the problem where it's responding too quickly to changing the mode with the potentiometer, but that's a new problem that's easy to address. XD