EM Noise affecting linear actuator

So I did a DIY linear actuator, it consists of a NEMA 17 motor which drives a ball screw and has two steel rods acting as reinforcements alongside some custom 3D printed parts. Mechanically I think it works great, but electronically it's another story. To drive the whole thing I am using an arduino pro mini (3.3V) powered from a 12VDC power supply and LM317 regulator. The stepper motor is driven via a pololu a4988 motor driver and two push buttons to send the carrier to the top or bottom. In order to stop the motor when it reaches a certain limit, the linear actuator has two limit switches and two LEDs indicating which position it is at (top or bottom). Hopefully the diagrams and pictures will make it easier to understand how the system works.

The problem is that the top and bottom limit switches are doing false triggers. Inside the shop where I built it, the false triggers are not very frequent but are noticeable. However in the place where it's supposed to be installed has more EM noise and it's nearly impossible to use the thing because there are lots of false trigger. What happens is I press one of the push buttons and the routine starts but I see random flashes from the LED's which eventually stops the routine. This is because the program only stops the routine if the limit switch at the position it's going to is activated. For example it stops if it's going to the top and the top limit switch is activated, so I might see the bottom LED flashing and the carrier is still moving but when the top LED flashes the linear actuator stops.

All digital inputs are configured as INPUT_PULLUP and the wire that goes to the limit switches is 22 awg stranded and has no shield. I have some CAT5E FTP cable I could use, but I am not sure if that would fix the problem.




The schematic is actually for a pcb board I'd like to make, the current implementation is the same except it's on a breadboard so no JST or Screw terminal connectors are used and things are just connected directly

Code:

// Define pin connections
#define dirPin 2
#define stepPin 3
#define upButton 4
#define bottomButton 5
#define upLimitSwitch 6
#define bottomLimitSwitch 7
#define IsAtTopLED 8
#define IsAtBottomLED 9
#define ESPsignal 10
#define enable 11

boolean upPressed = false;
boolean bottomPressed = false;
boolean IsAtTop = false;
boolean IsAtBottom = false;

void setup() { 
  pinMode(dirPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(IsAtTopLED, OUTPUT);
  pinMode(IsAtBottomLED, OUTPUT);
  
  pinMode(upButton, INPUT_PULLUP); // send carrier to top
  pinMode(bottomButton, INPUT_PULLUP); // sends carrier to bottom
  pinMode(upLimitSwitch, INPUT_PULLUP); // goes to limit switch at top
  pinMode(bottomLimitSwitch,INPUT_PULLUP); // goes to limit switch at the bottom
  pinMode(ESPsignal, INPUT_PULLUP); // ESP trigger signal to close chimney
}

void loop() { 
  digitalWrite(enable,HIGH); // stepper is OFF, only ON if it has to move
  readButtons();
  actOnButtons();
  readESPsignal();
}

void readButtons() { 
  bottomPressed = false;
  upPressed = false;
  if (digitalRead(upButton) == LOW) {
    upPressed = true;
  }
  if (digitalRead(bottomButton) == LOW) {
    bottomPressed = true;
  }
}

void actOnButtons() {
  readStates();
  if (upPressed == true) {
    digitalWrite(enable,LOW);
    digitalWrite(dirPin, LOW);
    GoTOP();
  }
  if (bottomPressed == true) {
    digitalWrite(enable,LOW);
    digitalWrite(dirPin, HIGH);
    GoBOTTOM();
  }
}

void GoBOTTOM() {
  while(IsAtBottom == false) {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(700);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(700);
    readStates();
    // Break if up/bottom buttons are pressed
    readButtons();
    if(upPressed == true || bottomPressed == true) {break;}
  }
}

void GoTOP(){
  while(IsAtTop == false) {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(700);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(700);
    readStates();
    // Break if up/bottom buttons are pressed
    readButtons();
    if(upPressed == true || bottomPressed == true) {break;}
  }
}

void readStates() { 
    if (digitalRead(upLimitSwitch) == LOW) {
        IsAtTop = true;
        digitalWrite(IsAtTopLED, HIGH);
        digitalWrite(IsAtBottomLED, LOW);
    }
    else if (digitalRead(bottomLimitSwitch) == LOW) {
        IsAtBottom = true;
        digitalWrite(IsAtBottomLED, HIGH);
        digitalWrite(IsAtTopLED, LOW);
    }
    else{
      IsAtTop = false;
      IsAtBottom = false;  
      digitalWrite(IsAtTopLED, LOW);
      digitalWrite(IsAtBottomLED, LOW);   
    }
}

void readESPsignal() {
  
}

Electrical noise on the switch leads can be dramatically reduced by doing the following:

  1. Use grounded, shielded wire for the switch leads. Route them away from motors and power connections.
  2. Use lower value pullup resistors for the switches (e.g. 2.2K or even lower), instead of the weak internal pullups.

I agree with @jremington regarding the pullup. You should also add a 0.01µF capacitor where the switch wires enter the Arduino.

I don't think shielded cable should be one of your first modifications but definitely use twisted wires for each switch.

You should mention the type of location and the wire lengths.

If I use lower value pullup resistors does that mean I should now only define them as inputs?

  pinMode(upLimitSwitch, INPUT); // goes to limit switch at top
  pinMode(bottomLimitSwitch,INPUT); // goes to limit switch at the bottom

The 0.01µF cap goes between the input signal and the ground for each switch?

Location is an industrial gas furnace, it's in a zone where there's not much heat but there are AC solenoid valves nearby, a three phase 3HP induction motor is about 10 meters away and three phase powerlines are about 5 meters away. Wire length from top limit switch to arduino is 5 feet and for the bottom limit switch is 3 feet.

For the button box I used twisted wire and it's 3 feet long, it's also configured as Input Pullup but it doesn't have any false triggers

No, you can use external and internal pullups in parallel.

Twisted pair wiring will certainly help, but shielded wire leads will be more effective, especially in environments where there might be arcing and/or radio frequency interference. Twisted and shielded combines the best of both approaches.

Does twisted pair only work if the pair is signal and ground? i.e in a CAT cable let's say the pair is blue/white-blue, the blue wire carries a digital signal and the white-blue wire the corresponding GND? What if the pair contained the two signals? i.e blue is the top limit switch signal and white-blue the bottom limit switch signal?

I have some shielded CAT5E, but I ask this because I'd like to be able to use the 8 wires as 7 signals and 1 gnd, instead of only 4 signals and 4 gnds

IMHO capacitors are more effective than stronger pull up.
Stronger pull up (without capacitors) is only needed if you need ultrafast reaction.

Try a 10-100n ceramic capacitor from Arduino switch pin to ground, close to the Arduino.
Leo..

Yes and as close to the Arduino as possible. The idea is to reduce any "noise" picked up on the wires so being close to the Arduino input is the most effective.

If you put a low resistance value as an external pullup it doesn't matter if the Arduino internal pullup is enabled as it is so little in comparison the difference is not noticeable.

Is the button box metal? If yes, is it grounded locally to the furnace? This could be a problem.

It works for all cases, including differential signalling. The idea is that changing magnetic fields, which cannot be electrically shielded, induce opposite voltages/currents in adjacent twists.

I opened up the control box and tried to add the pullup resistors. In doing so, I accidently connected the GND wire that goes to the limit switches to +12V. I didn't notice it, and since things were not working because I had rewired incorrectly the push buttons, I clicked the limit switches to see if the LEDs would light up...

I believe I fried up the pro mini, and possibly the A4988 driver too, since I can't even upload a code anymore

I've done similar....... I learned to kill power before doing such things. Also you might want to put the resistor near the (new) pro mini.

Got some new pro mini's and after changing the original cable to a foil shielded CAT5E the linear actuator no longer has false triggers :slight_smile: I connected the shield to the arduino ground on both ends and removed the shield as close as possible to the arduino. No need for filter capacitors or resistors, so I guess I made things right?

In theory the shield should only be connected at the Arduino side. Else you could get ground loops that could cause issues when some other device starts or stops or ???.

Filter capacitors are always a good idea. I understand you have found what appears to be a solution, however in my experience there will/may/could be random issues that the capacitor could help with.

I added filter capacitors to the inputs and finished the design of a PCB board on EasyEDA. Thoughts or suggestions?