EMF from L298N triggering button?

Images first


Code:

const int buttonPin = 2;
const int rotorMotor1 = 7;
const int rotorMotor2 = 8;
const int rotorPwm = 9;
const int vibMotor1 = 10;
const int vibMotor2 = 11;
const int vibPwm = 12;

volatile int count = 0;
volatile int setPwm = 255;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(rotorMotor1, OUTPUT);
  pinMode(rotorMotor2, OUTPUT);
  pinMode(rotorPwm, OUTPUT);
  pinMode(vibMotor1, OUTPUT);
  pinMode(vibMotor2, OUTPUT);
  pinMode(vibPwm, OUTPUT);

  attachInterrupt(digitalPinToInterrupt(buttonPin), cycle, FALLING);

  Serial.begin(9600);
}

void loop() {
  if (count==0) {
    Serial.println("0");
    analogWrite(rotorPwm, 0);
    analogWrite(vibPwm, 0);
    delay(2000);
  }
  
  else if (count==1) {
    Serial.println("1");
    digitalWrite(rotorMotor1, HIGH);
    digitalWrite(rotorMotor2, LOW);
    analogWrite(rotorPwm, setPwm);
    digitalWrite(vibMotor1, HIGH);
    digitalWrite(vibMotor2, LOW);
    analogWrite(vibPwm, setPwm);
    delay(2000);
    digitalWrite(rotorMotor1, LOW);
    digitalWrite(rotorMotor2, HIGH);
    digitalWrite(vibMotor1, HIGH);
    digitalWrite(vibMotor2, LOW);
    delay(2000);
  }
  else if (count==2) {
    Serial.println("2");
    digitalWrite(rotorMotor1, HIGH);
    digitalWrite(rotorMotor2, LOW);
    analogWrite(rotorPwm, setPwm);
    digitalWrite(vibMotor1, HIGH);
    digitalWrite(vibMotor2, LOW);
    analogWrite(vibPwm, setPwm);
    delay(2000);
  }
  else if (count==3) {
    Serial.println("3");
    digitalWrite(rotorMotor1, LOW);
    digitalWrite(rotorMotor2, HIGH);
    analogWrite(rotorPwm, setPwm);
    digitalWrite(vibMotor1, LOW);
    digitalWrite(vibMotor2, HIGH);
    analogWrite(vibPwm, setPwm);
    delay(2000);
  }
  else if (count==4) {
    Serial.println("4");
    analogWrite(rotorPwm, 0);
    analogWrite(vibPwm, 0);
    delay(2000);
  }
  else {
    Serial.println("resetting count");
    count = 0;
  }
}

void cycle() {
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  if (interrupt_time - last_interrupt_time > 500)
   {
    Serial.println("incrementing cycle");
    count = count + 1;
   }
   last_interrupt_time = interrupt_time;
}

Alright so the project is just a motor controller with presets. You press the button to cycle through the presets, and this is accomplished simply by incrementing a count. The problem is that whenever the motors fire, my button gets triggered (advancing the count) and then the button becomes unresponsive while the motors are going, I'm assuming this is because of EMF interference.

I did some troubleshooting, here's what the serial messages should look like (done by disconnecting the L298N from arduino so no motors active):

0
0
incrementing cycle
1
1
incrementing cycle
2
2
incrementing cycle
3
3
incrementing cycle
4
4
incrementing cycle
resetting count
0

Here's what it does look like when everything is connected and the motors fire:

0
0
incrementing cycle   <- this is where I press the button
1
incrementing cycle   <- this is when the motors fire, triggering the button again
2                            <- I am unable to use the button here while the motors are spinning
2
2
2

Another troubleshooting step I did was disconnecting the connecting ground line between the arduino and the L298N. With this disconnected, the only connected wires between the two are now the 6 data lines controlling the power, ground, and pwm for each motor. The same EMF appeared to affect the button while the ground was disconnected, so that can be ruled out.

So I'm a bit lost here. Maybe my breadboard is crap? Not sure what to think

sketch_sep14a.ino (2.12 KB)

You're using delay; so only the next iteration of loop (e.g. after 2 seconds) will react on a changed count count.

No idea why the L298 causes an additional spike (electronics is not my strong point).

By the way, if you use a solution based on blink without delay you don't need interrupts. This is actually an example where they are not needed and don't give you the desired result.

sterretje:
You're using delay; so only the next iteration of loop (e.g. after 2 seconds) will react on a changed count count.

No idea why the L298 causes an additional spike (electronics is not my strong point).

By the way, if you use a solution based on blink without delay you don't need interrupts. This is actually an example where they are not needed and don't give you the desired result.

Right, yeah I figured there would be a better method to accomplish the functionality, unfortunately this current issue has to be resolved before any of that matters though.

Motors need to be powered separately from the Arduino. They create heavy electrical noise and can cause the Arduino to reset or malfunction.

jremington:
Motors need to be powered separately from the Arduino. They create heavy electrical noise and can cause the Arduino to reset or malfunction.

The L298N is powered by a separate 5v PSU, the arduino is powered by USB. The only common wires they have are the 6 data cables signalling the L298N, and a common ground cable, which I ruled out as the cause of the issue in the OP.