Arduino digital pin not going low only when a motor is running (through a L293D)

Hello to everyone!

I'm trying to modify a model train with an Arduino Nano and I'm having some problems with a digital pin set as INPUT_PULLUP not going to LOW when I connect it to GND.

I attach the code and a schematic below, the basic idea is that the Arduino Nano has to receive commands to start / stop / change speed via Bluetooth from the HC-05, and drive the motor in the model train through the L293D chip. The power supply consists of a 18650 battery holder with two cells connected in series. Also, the model train has to detect magnets along the tracks with a reed switch, and send a message over Bluetooth when is does. To do this, I set the pin D2 as INPUT_PULLUP, connected D2 to one of the sides of the switch, and the other to ground.

The problem is that when I turn on the motor, there is no way to make the pin D2 (connected to the reed switch) to get LOW, even connecting it directly (or through a resistor) to GND doesn't make it LOW, and so it doesn't trigger the interrupt (I also tried checking if it’s LOW in the loop function, but no use). However, if I stop the motor, the this problem goes away and the interrupt and reed switch work every time.

So far I’ve tried to use a 5.2KOhm resistor between the output of the switch and GND (works when the motor is stopped, otherwise also no), I’ve tried putting a 5.2KOhm resistor between D6 and the L293D, and D7 and the L293D, and a 10Ohm resistor between D5 (PWM) and the PWM input of the L293D (which also slowed down the motor), but the problem on D2 persists.

What am I missing?

//
// Pinout description: (ARDUINO UNO / NANO)
// DIGITAL:
// 2 } - Reed switch
// 3
// 4
// 5   } - L293D - { Enable
// 6   }           { DIR_B
// 7   }           { DIR_A
// 8
// 9
// 10
// 11
// 12
// 13
// TX -> HC-05 RX
// RX -> HC-05 TX



// Constants
const unsigned long ACCESS_KEY = 2107106630;
const byte MOTOR_MAX_POWER = 100;
const byte MOTOR_MIN_POWER = 85;
const float MAX_SPEED_LIMIT = 255;
const unsigned short SOFTWARE_DEBOUNCING_WAIT = 250; // ms

// Define pinout
const byte REED_SWITCH_PIN = 2;

const byte MOTOR_ENABLE_PIN = 5;
const byte MOTOR_DIR_A_PIN = 6;
const byte MOTOR_DIR_B_PIN = 7;

const unsigned short SERIAL_BAUD_RATE = 57600;

// Variables
volatile bool reedSwitchClosed = false;
volatile long lastReedSwitchClosedTime = 0;



enum CommunicationMessageServerToClient {
  FORWARD = 1,
  BACKWARD = 2,
  FAST_STOP = 3
};

enum CommunicationMessageClientToServer {
  REED_TRIGGERED = 1,
};

void setup()
{
  // Initialize the pin and interrupt for the reed switch
  pinMode(REED_SWITCH_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(REED_SWITCH_PIN), onReedSwitchClosed, FALLING);

  // Initialize the pins for the L293D motor controller
  pinMode(MOTOR_ENABLE_PIN, OUTPUT);
  pinMode(MOTOR_DIR_A_PIN, OUTPUT);
  pinMode(MOTOR_DIR_B_PIN, OUTPUT);

  // Open a (hardware) serial connection with the HC-05 BlueTooth module
  Serial.begin(SERIAL_BAUD_RATE);
  // Log in the the ground control software through BlueTooth
  blueToothLogin();
}

void blueToothLogin()
{
  // When the ground control server is ready, it sends a byte of all ones (255) and awaits for the token
  // Wait for the "ready" byte to come
  while (Serial.available() == 0) {}
  Serial.read();
  // Send the authentication token
  Serial.write((byte*)&ACCESS_KEY, sizeof(unsigned long));
}

void onReedSwitchClosed()
{
  if (millis() - lastReedSwitchClosedTime < SOFTWARE_DEBOUNCING_WAIT)
  {
    lastReedSwitchClosedTime = millis();
    return;
  }
  lastReedSwitchClosedTime = millis();
  reedSwitchClosed = true;
}

void loop()
{
  if (reedSwitchClosed)
  {
    Serial.write(1);
    Serial.write(CommunicationMessageClientToServer::REED_TRIGGERED);
    reedSwitchClosed = false;
  }

  while (Serial.available())
  {
    receiveIncomingCommunicationMessage();
  }
}

void receiveIncomingCommunicationMessage()
{
  byte size = Serial.read();
  byte message[size];

  for (byte i = 0; i < size; i++) {
    int b = Serial.read();
    if (b == -1)
    {
      i--;
    }
    else
    {
      message[i] = b;
    }
  }

  processIncomingMessage(message);
}

void processIncomingMessage(byte message[])
{
  switch (message[0])
  {
    case CommunicationMessageServerToClient::FORWARD:
      {
        goForward(message[1]);
        break;
      }
    case CommunicationMessageServerToClient::BACKWARD:
      {
        goBackwards(message[1]);
        break;
      }
    case CommunicationMessageServerToClient::FAST_STOP:
      {
        fastStop();
        break;
      }
  }
}

void goForward(byte speedLimit)
{
  lastReedSwitchClosedTime = millis();
  byte motorSpeed = convertSpeedLimitToMotorSpeed(speedLimit);
  analogWrite(MOTOR_ENABLE_PIN, motorSpeed);
  digitalWrite(MOTOR_DIR_A_PIN, HIGH);
  digitalWrite(MOTOR_DIR_B_PIN, LOW);
}

void goBackwards(byte speedLimit)
{
  lastReedSwitchClosedTime = millis();
  byte motorSpeed = convertSpeedLimitToMotorSpeed(speedLimit);
  analogWrite(MOTOR_ENABLE_PIN, motorSpeed);
  digitalWrite(MOTOR_DIR_A_PIN, LOW);
  digitalWrite(MOTOR_DIR_B_PIN, HIGH);
}

void fastStop()
{
  analogWrite(MOTOR_ENABLE_PIN, 255);
  digitalWrite(MOTOR_DIR_A_PIN, LOW);
  digitalWrite(MOTOR_DIR_B_PIN, LOW);
}

byte convertSpeedLimitToMotorSpeed(byte speedLimit)
{
  float relativeSpeed = float(speedLimit) / MAX_SPEED_LIMIT;
  return MOTOR_MIN_POWER + (relativeSpeed * (MOTOR_MAX_POWER - MOTOR_MIN_POWER));
}

I don't have time to look right now but thank you for posting code, schematic, and description!

Nice start on the schematic. I cannot see where the power comes in so I am assuming the top left corner. Close the reed switch and start from ground of the power supply to where the switch connects to the Arduino. When you find a non zero value you have a bad connection from that point back to the last good connection.

1 Like

Measure the voltage on the reed switch. A switch with a non-zero voltage in closed state is defective.

Then measure the voltage between the lower switch pin and Arduino GND and follow the cable to find out where the discontinuity sits.

1 Like

Thank you very much for your replies! :smiley:

I've been measuring different points with my multimeter, and writing them down.

  • When D2 is left not connected, it reads 5.046V above battery GND, no matter if the motor is on or off (this is OK because it is set as INPUT_PULLUP).
  • When I connect D2 to GND with the motor off, it reads 0.194V above the Arduino's GND, and the interrupt gets triggered as normal.
  • When I connect D2 to GND with the motor on, it reads 0.060V above the Arduino's GND, but despite this, the interrupt is not triggered.

But then I noticed that there is a difference between the measurements from the Arduino's GND and from the battery's GND.

  • When I connect D2 to GND with the motor off, it reads 0.435V above battery's GND.
  • When I connect D2 to GND with the motor on, it reads 0.377V above battery's GND.

I think this is a result of my flimsy wiring. I am using dupont cables and a little breadboard. Just between the battery's GND and the little breadboard's contact I read a ~0.1V difference, and between the battery's GND and the Arduino's GND pin I get around ~0.4V (with the motor off)!

Now I've tried removing the cable that connect the Arduino from the Vin pin to the battery, and feeding the Arduino from a USB powerbank, and it seems the interrupt seems to trigger fine (although a couple of times it triggered with no reason).

Does this make it more likely that this problem is a result of my poor and ill-prepared wiring?

1 Like

Sounds like poor build quality.
The L293 has no logic power.
The BT module should not be used on the TX/RX pins, which are already used by the USB chip.
You should use different pins with SoftwareSerial. And a voltage divider on the BT RX pin.
Leo..

2 Likes

Thank you for your reply!

I'll add logic power to the L293D.
I was using the Arduino's UART pins because I've had issues with data loss with SoftwareSerial at the speeds that I'm currently working at (normally 57.600baud, sometimes 115.200baud).
Which resistor values do you recommend in the voltage divider for the BT TX pin? 2 KOhm to the BT and 5.2 KOhm to GND is OK?

I've tried connecting D2 through the switch directly to the battery's GND (but not using the already connected cable to the breadboard, just another cable directly from one side of the reed switch to the battery) and it seems to work every time. Everything points to it simply being a problem with my crappy and flimsy wiring.

I'll try to improve it. Thanks to everyone!

Hi, @itzanh
Welcome to the forum.
It sounds like the Nano and the motor driver chips are sharing the same power wires, so motor current noise is being injected into the Nano and other circuits.

You could try connecting the motor power and Nano power to the power source/input at the same point, like a star connection of positive and a star connection of negative.

Also 0.1uF caps across the motor terminals and across the power input pins to gnd at the 293.
Also one in parallel with C1 as close to C1 as possible.

Tom.. :smiley: :+1: :coffee: :australia:

2 Likes

Hi Tom,

Thank you very much for your reply. I added a ceramic capacitor in between the L293D and the motor, another one betwen the L293D and the star, another between the star and the Nano, and two more close to C1. The noise seems to have lowered (now it don't get random interrupts for no reason, like it used to).

However, connecting D2 to the arduino GND still doesn't trigger the interrupt, but as I said earlier, connecting it to the battery's GND seems to work (and also I need to improve the wiring).

Hi

I hope you mean between the motor terminals on the motor.
Between the Vcc pin and gnd at the 293.

Good to hear and improvement.

Sounds like you need to check your gnd wiring.

Tom.. :smiley: :+1: :coffee: :australia:

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