Nano freezes intermittently

Hi,
Pretty new to using microcontrollers but really enjoying it so far. For my first real application i'm using a knockoff nano as a simple gate operator and it seems to keep getting hung up.

First it froze after about 12 hours which I thought was because of all the serial data I was printing to debug. So after I commented it out things were fine for over a week. Then today it needed to be reset again.

The nano is soldered to a breadboard and installed with a 4 channel relay inside an enclosure separate from the motor being controlled.

The motor being controlled uses 2 contactors powered by 24VAC for forward and reverse.

Also near the motor are two limit switches that push ground to the Arduino depending on whether the gate is currently open or closed.

To activate we have a keypad with a relay that's NO and closes for three seconds when the code is entered. Also using ground for that with internal pullup resistors for everything.

The signal that activates the relays for motor contactors are digital write High because I didn't think to move the jumpers around on the relay module. And the modules themselves are NO with the 24VAC coming off the secondary on a transformer near the motor.

The relay module is powered by the 5v pin on the nano.

The nano is powered by a 9v power supply

I thought the code was simple enough to run indefinitely without requiring intervention but that doesn't seem to be the case. I'll post it once I get to a laptop and figure out how.

I'm using two activation timers, one to count the length of the trigger pulse and one to prevent the motor from running more than 30 seconds, if for some reason the gate doesn't make it to the limit switches..

I wondered if the activation timers are causing the issue. I've read that millis() should turn over without causing issues. But maybe calling it over multiple instances for multiple timers is filling up memory?

What's more likely is I don't fully understand what I'm doing so any pointers in the right direction would be appreciated.

Here's a picture of the nano and relay module in the enclosure.

I don't see any snubber circuits on the nano relays for that.

I don't see any 100n capacitors to ground near the Arduino pins, to kill noise.
Sensor wires near contactor wires is a recipe for resets.

The Nano can barely provide the current for one relay without overheating the 5volt regulator.
Two relays 'on' at the same time will overheat the regulator and reset the Nano (if lucky).
Why didn't you use a 5volt supply, connected to the 5volt pin.

I assume your code doesn't use (dangerous) Strings.
Leo..

Thanks Leo, I'll have to look more into snubber circuits would that be for limiting voltage spikes across the relays when activated?
Only one relay is ever "supposed" to be activated at one time so it didn't occur to me that might take more than 300mA.
Also, admittedly still learning how to incorporate capacitors into circuits.. just got my first kit with some voltage regulators so I'm looking Forward to it.
For the power supply I only had the 9v DC adapter on hand. But using aforementioned kit I'm sure I can cobble something else together.
For what it's worth I used separate shielded cables for the power and switching wires, hoping that's not causing interference, unless you think the portion of wire not covered by the shield is susceptible? no strings tho.

anyway here's the code.

const int input1 = 2;  // Motor open relay 
const int input2 = 4;  // Motor close relay 
const int limit1 = 6;   // Limit switch for gate open 
const int trigger1 = 3;  // NO keypad relay
const int limit2 = 8;    // Limit switch for gate closed 

const int TLED = 10;     // Trigger status LED (blue)
const int L2LED = 11;     // Limit 2 status LED (red)
const int L1LED = 12;    // Limit 1 status LED (green)

unsigned long triggerStartTime = 0;  // Time when trigger1 became active 
const unsigned long triggerDuration = 2500;  // Minimum duration for trigger1 to be active 

unsigned long trigger2StartTime = 0; // Time when trigger became active
const unsigned long trigger2Duration = 2500; // Minimum duration for trigger2 to be active 

unsigned long activationStartTime = 0; // Time motor relay is active
const unsigned long activationDuration = 30000; // Max motor relay activation time

unsigned long activation2StartTime = 0; // Time motor relay2 is active
const unsigned long activation2Duration = 30000; // Max motor relay2 activation time

void setup() {
 // Serial.begin(9600); 

  pinMode(limit1, INPUT_PULLUP);
  pinMode(trigger1, INPUT_PULLUP);
  pinMode(limit2, INPUT_PULLUP);

  pinMode(input1, OUTPUT);// named for the termination location on relay module..
  pinMode(input2, OUTPUT);

  pinMode(TLED, OUTPUT);
  pinMode(L2LED, OUTPUT);
  pinMode(L1LED, OUTPUT);
}

void loop() {
  int triggerState = digitalRead(trigger1);
  int limit1State = digitalRead(limit1);
  int limit2State = digitalRead(limit2);

  // LED STATUS GREEN=OPEN, RED=CLOSE, BLUE=TRIGGER
  digitalWrite(TLED, triggerState == LOW ? HIGH : LOW);
  digitalWrite(L2LED, limit2State == LOW ? HIGH : LOW);
  digitalWrite(L1LED, limit1State == LOW ? HIGH : LOW);

  // Check if the trigger1 is active and limit1 is LOW
  if (triggerState == LOW && limit1State == LOW) {
    if (triggerStartTime == 0) {
       triggerStartTime = millis();
 //     Serial.println("Trigger1 count active");
 //     Serial.println("Start Time Trigger1: " + String(triggerStartTime));
     }

    // Check if the trigger1 has been active for the required duration
    if (millis() - triggerStartTime >= triggerDuration) {
      // Trigger1 has been active for the required duration
      // Serial.println("Trigger1 active for 3 seconds! Activate motor open relay.");
      digitalWrite(input1, HIGH);
      triggerStartTime = 0;
    }
  } else {
   triggerStartTime = 0;
  }

  // Check if the motor relay1 is active
 if (digitalRead(input1) == HIGH) {
    if (activationStartTime == 0) {
      activationStartTime = millis();
    }

 //   // Check if the motor relay1 has been active for the required duration or limit2 is LOW
    if (millis() - activationStartTime > activationDuration || limit2State == LOW) {
      // Motor relay1 has been active for the maximum duration or limit2 is LOW
      // Serial.println("Motor close relay active for 30 seconds or limit2 is LOW. Deactivate.");
      digitalWrite(input1, LOW);
     activationStartTime = 0; 
    }
  } else {
    activationStartTime = 0;
  }

  // Check if the trigger is active and limit2 is LOW
  if (triggerState == LOW && limit2State == LOW) {
    if (trigger2StartTime == 0) {
      trigger2StartTime = millis();
//      Serial.println("Trigger2 count active");
//      Serial.println("Start Time Trigger2: " + String(trigger2StartTime));
    }

    // Check if the trigger2 has been active for the required duration
    if (millis() - trigger2StartTime >= trigger2Duration) {
//     Serial.println("Trigger2 active for 3 seconds! Activate motor open relay.");
      digitalWrite(input2, HIGH);
      trigger2StartTime = 0; // Reset trigger2 start time
    }
  } else {
    trigger2StartTime = 0;
  }

  // Check if the motor relay2 is active
  if (digitalRead(input2) == HIGH) {
    if (activation2StartTime == 0) {
      activation2StartTime = millis();
    }

 
    if (millis() - activation2StartTime > activation2Duration || limit1State == LOW) {
//      Serial.println("Motor open relay active for 30 seconds or limit1 is LOW. Deactivate.");
      digitalWrite(input2, LOW);
    activation2StartTime = 0;
     }
     } else {
        activation2StartTime = 0;
     }

// relevant state information for debugging
 // Serial.print("triggerState = ");
//  Serial.println(triggerState);
 // Serial.print("limit1State = ");
 // Serial.println(limit1State);
 // Serial.print("limit2State = ");
 // Serial.println(limit2State);
 // Serial.print("triggerStartTime is ");
 // Serial.println(triggerStartTime);
//  Serial.print("trigger2StartTime is ");
 // Serial.println(trigger2StartTime);

  // Serial.print("activationStartTime is ");
 // Serial.println(activationStartTime);
 // Serial.print("activation2StartTime is ");
 // Serial.println(activation2StartTime);

  delay(350);
}

Spikes occur when an inductor is turned off.
For a contactor powered with DC you would use a diode "the wrong way round" across the coil, but for contactors driven with AC you use a varistor, bi-directional TVS diode, or cap/resistor circuit. What is best depends on the contactor. No real experience with contactors, but maybe others here do. The relay coils of the blue relays already have them fitted.

A 5volt cellphone charger connected to the USB socket of the Nano is an easy way to power it.
Leo..

Spikes occur when an inductor is turned off .

ahh, yes thanks for spelling it out. the motor being controlled is 3/4H.P, 3 phase 120/208V so I can understand that having an induced current but once the relay opens followed by the contactor there shouldnt really be any physical path back to the relay module or uno, right? if you say the blue relays are fitted with varistor protection I won't worry too much about it.

now that I've gone and made a post about it the forum search function seems to be revealing this is a common issue with arduinos, relays and motors with the most likely cause being interference... and since i cant see EMF and if no one thinks my "timer issue theory" has any merit it makes more sense to try and reduce noise than add a watchdog timer I guess.

I don't see any 100n capacitors to ground near the Arduino pins, to kill noise.
Sensor wires near contactor wires is a recipe for resets.

can you tell me more about the caps? would it just need one between + and - at the Vin? also should my shielded cable be grounded to the UNO or would an earth on the AC side be better? right now its not terminated anywhere.

You likely will only need 100n ceramic caps on the limit switches.
Between Arduino pin and Arduino ground, shortest path, close to the Nano pins.
That kills RF picked up by the limit switch wires (aerials).

If that doesn't help, then try a 25volt AC (24-30) varistor across the relay contacts of the blue relays.
If... you can get them.

Shielding of a cable should (in theory) be connected only at one end (to Arduino ground).
Try to twist the wires going to the blue relays (twist two wires that belong to one relay).
And try to keep them separated from the (also twisted) pairs that go to the limit switches.
If you strip a Cat-5 wire, then you see how.
Leo..

Hi, @donneer
Welcome to the forum.

Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.
No Fritzy copy and paste images.

As a bit of advice, add the "blink without delay" code to your code and have it blink the onboard LED, if the LED stops blinking, then the code has locked up.
If your project appears to lock up and the LED is still flashing then you have still got code running and a possible software problem.

Keep the 24V motor wiring well away from the signal wiring, including going into the box in separate holes.

Thanks.. Tom.. :grinning: :+1: :coffee: :australia:

The first thing I would do is replace the relays with solid state relays with zero cross, that will eliminate a lot of the EMI (ElectroMagnetic Radiation). Keep the AC wires away from the DC and they should cross at right angles and not be in the same cable. What are you using for Pull up resistors, I cannot see them. If you are using the internal pull up of the Arduino that is a plan for problems with something like this. I can take a lot more guesses but having an annotated schematic would make it much easier to figure out.

Hi @TomGeorge Thanks for the tips. I've attached my attempt at drawing a schematic hopefully that will help.
The blink without delay might be a good idea. The reason I know it's locked up now is because the led that goes on with its limit switch will stay on after the limit switch opens and closing the other switch doesn't light the opposing LED.

I want to reiterate that the problem is intermittent, the last streak was 10 days with multiple operations per day. I should also mention that its possible the nano is getting stuck waiting for the trigger. I don't think it has frozen while the motor is running.

So far my plan of action is to clean up the wires that can be twisted up until they terminate. Add the cap for decoupling and ground the drain from the shielded cables. After that it will be at least a week to see if there's any improvement. But I will post an update.

Some other ideas I've had are putting the nano to sleep until it sees the trigger? Deleting the motor run time condition or wrapping the plastic enclosure with tin foil and binding that to earth..

@gilshultz Never heard of zero cross relays before but they are super cool. Though it might be overkill as I'm not switching the motor directly with the blue relays. At most it's switching 24VAC at 1A and only one relay is ever closed and not for more than 10 seconds.
I am using the internal pull up resistors in the nano, haven't had any apparent issues with that yet but In the future I will include external pull ups. If you have anymore guesses I'm open to more suggestions. Thank you

1 Like

They can be gotten from many sources, I have seen them less then $2 from china suppliers. Following is an image of one. I have not used this particular one but it will give you an idea.
image

Thanks @gulshultz they seem cheap enough, can't hurt to try that too. They probably require less current than a coil would. Do they just open or close depending on whether there's a DC voltage or not?
Edit. Looked more into ssr, a lot of zero cross modules are expensive makes me think a cheap one is probably fake, is still worth it if I cant get zero cross? And do the blue relays leak current? Is current leakage an actual problem?

I have never had problems with the inexpensive ones, however they are rated at least 350V and I use them on a 120V system. They also work great on 24V ac. They are designed to be driven from a processor or other logic device. The most inexpensive way to build them is with an optocoupler, that gives you at least 1500V but they will tell you that in the specification. Once you get to about half of there current rating you need to consider mounting on a heat sinking material.

not sure how to mark this resolved but its been at least a month since I added the decoupling cap and SSR's and the nano hasn't frozen despite daily usage. Thanks for the help!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.