Need help adding Limit Switch for DC Motor Control

So Having scrapped an earlier idea of using latching buttons to control my system I change to a joystick input. The code as is works fine. However for the purposes I need to use it for I cant seem to get a limit switch working. How best could I insert the code for a limit switch so that it works. The goal is for the DC motor to operate as normal while the analog stick is pressed forwards or backwards and if it hits a limit switch for just the DC motor to stop. How can I achieve this?

#include <SPI.h>      //the communication interface with the modem
#include "RF24.h"     //the library which helps us to control the radio modem (nRF24L)

//Motor A DC Motors
const int RightMotorForward = 4;    // IN1 Linear Actuator
const int RightMotorBackward = 5;   // IN2 Linear Actuator

//Motor B Linear Motors
const int LeftMotorForward = 7;     // IN3 DC Motor
const int LeftMotorBackward = 8;    // IN4 DC Motor

int limit_switch= 3;

int data[2];

RF24 radio(10, 9); //10 and 9 are a digital pin numbers to which signals CE and CSN are connected

const uint64_t pipe = 0xE8E8F0F0E1LL; //the address of the modem,that will receive data from the Arduino


void setup() {
  Serial.begin(9600);
  pinMode(RightMotorForward, OUTPUT);
  pinMode(LeftMotorForward, OUTPUT);
  pinMode(RightMotorBackward, OUTPUT);
  pinMode(LeftMotorBackward, OUTPUT);
  pinMode (limit_switch, INPUT);
  radio.begin();                    //it activates the modem
  radio.openReadingPipe(1, pipe);   //determines the address of our modem which receive data
  radio.startListening();           //enable receiving data via modem
}

void loop() {
  if (radio.available()) {
    radio.read(data, sizeof(data));

    //data X
    if (data[0] > 550) {
      digitalWrite(LeftMotorForward, HIGH);
      digitalWrite(LeftMotorBackward, LOW);
      digitalWrite(RightMotorForward, HIGH);
      digitalWrite(RightMotorBackward, LOW);
      Serial.println("FORWARD");
    }

    //data X
    if (data[0] < 400) {
      digitalWrite(LeftMotorForward, LOW);
      digitalWrite(LeftMotorBackward, HIGH);
      digitalWrite(RightMotorForward, LOW);
      digitalWrite(RightMotorBackward, HIGH);
      Serial.println("BACKWARD");
    }

    //data Y
    if (data[1] > 550 ) {
      digitalWrite(LeftMotorForward, HIGH);
      digitalWrite(LeftMotorBackward, LOW);
      digitalWrite(RightMotorForward, LOW);
      digitalWrite(RightMotorBackward, HIGH);
      Serial.println("TURN RIGHT");
    }

    //data Y
    if (data[1] < 400 ) {
      digitalWrite(LeftMotorForward, LOW);
      digitalWrite(LeftMotorBackward, HIGH);
      digitalWrite(RightMotorForward, HIGH);
      digitalWrite(RightMotorBackward, LOW);
      Serial.println("TURN LEFT");
    }

    if (data[0] < 550 && data[0] > 400 && data[1] < 550 && data[1] > 400) {
      digitalWrite(LeftMotorForward, LOW);
      digitalWrite(LeftMotorBackward, LOW);
      digitalWrite(RightMotorForward, LOW);
      digitalWrite(RightMotorBackward, LOW);
      Serial.println("STOP");
    }

  }
}

Wire the NC side of the switch inline with the drive motor. Do NOT run "safety" circuits in software. use a DPDT switch and feed the other half back to the Arduino to let it know about the crash. Stopping the motor needs to be built into the hardware to be failsafe.

2 Likes

a conventional way to wire any SPST switch is to connect it between the pin and ground with the pin configured as INPUT_PULLUP using the internal pull-up resistor. the pin is LOW when pressed

loop() should have a piece of code that reads the pin and checks if it is LOW. that condition should stop the motor an defeat any other processing that might re-enable the motor, at least in the direction of the switch

So I can’t use this category of limit switch?

Also in specific application how would I write the IF statement such that it reads the state of the switch and sets the DC Motor LOW. In a previous attempt I tried to nest

if (data [0] > 550 && digitalRead(limit_switch ==High)
`
between the Linear Motor code and Dc Motor code and when the analog stick was used the DC motor didn’t move at all for that conidition

Maybe wire the limit switch in series with the enable pin of the motor controller. So if the limit switch opens up it disables the motor. Code it such that the program tells you what limit switch has been reached.

void setup() {
    pinMode (limit_switch, INPUT_PULLUP);
    ...
}


void loop() {
    if (LOW == digitalRead (limit_switch)  {
        digitalWrite(LeftMotorForward, LOW);
        digitalWrite(LeftMotorBackward, LOW);
        digitalWrite(RightMotorForward, LOW);
        digitalWrite(RightMotorBackward, LOW);
        Serial.println("STOP - limit");
        return;
    }

    if (radio.available()) {
        radio.read(data, sizeof(data));

        ...
}

Wire your power regulation into a terminal block with all your devices in parallel using little scraps of wire to make jumpers on one side of the block (they aren't typically all connected together by default, at least not on the ones I use).

On the other side, I see at least two wires coming out in parallel: positive voltage for the Arduino/joystick and positive voltage for the motor. Wire the NC side of the limit switch referenced before the motor positive voltage like so

+V-----/NC--C--/+V-----motor + (this will kill power to the motor dead. Ideally you'd have a fuse inline as well protecting the switch from the motor drawing too much current through the switch because of an incorrectly sized motor)

Wire the NO pin of the switch to an Arduino pin, as madmark2150 suggests, if you want the Arduino to poll for the state of the limit switch (do this first in your void loop(), then assuming the switch safety limit is in safe operating state, everything else about what your motors are doing nested in a while loop). Then if the safety limit switch has been activated, you could serial.println(F("Motor Breaker Tripped!")); or something like that. You don't NEED to let the Arduino know using the other switch pin, but it's better to for sure. You could even toggle green and red leds depending on the state of the switch NO pin to have feedback independent of the serial monitor.

100% though, safety limit switches need to run independently of software to stop the machinery involved. Imagine a deadman pedal on a forklift or something: if anything happens to the operator, the machine needs to just stop.

Thanks for the help guys. It worked exactly how I wanted.

1 Like

Right so I doubled checked they system and it doesn't quite achieved what I wanted. The point for the limit switch (of which I planned to have 2) was to set as a hard travel limit for the DC Motor. What I wanted was essential a way to start rotating the motor, hit a limit switch, and stop. Then when another condition is met (moving the analog stick down) the system would reverse until it hit the other limit switch, stopped, and when the analog stick went up it would start over again. I thought I could just use a limit switch as is but cant seem to get it to reverse. I dont know if that is possible or not with the above code

The board im using to control the motors is the L298N motor driver

The crash switch disables the motor so you can't reverse it. The question is, is this a Zero swich or a crash switch? if its a crash switch, do it in hardware and the no automatic recovery ensures operator interaction needed to recover. If its a Zero switch, then you CAN do it in software.
Best is dual switches slightly offset. First sw is ZERO, 2nd is CRASH. 1st sw tells software to STOP and software can revese. If software misses, 2nd switch STOPS MOTOR and requires operator intervention to recover.

1 Like

How would I determine the type of switch I have?

Or rather what would the code look like for that

You have MICRO switches. Its what you want to USE them for. Zero switch for repeating position, or CRASH switch for detecting you're smashing into something and need to STOP NOW!

I'm sorry. I'm kinda dumb when it comes to this stuff. The switch I have is the one up above. How would I write the code for that? I'm great at physical things but code I'm incredibly weak at.

a switch is normally connected between the I/O pin and ground. the pin is configured with an internal pullup resistor as INPUT_PULLUP. the pin is normally pulled HIGH by the resistor. when the switch is pressed or "closed", it pulls the pin to ground.

    if (LOW == digitalRead (pin))
        someAction();

the switches above are single-pole double-throw (SPDT) meaning they make electrical contact in both positions. there is a common pin, a normally open and normally closed pins. use the normally open pins for what i describe above

1 Like

You have to think of what and how you want it to behave before you start wiring and coding. Is someone going to get hurt if it malfunctions? Yes - Hardware safety required. Is the equipment going to get damaged? Yes - Hardware safety needed. Is it just a location mark? Yes - software is fine.

So yeah I’m just making a pair of animatronic wings. Nothing too serious but definitely complicated. Linear actuators extend the feathers Dc motor rotates the wing from open to closed. So yeah

So no safety issues. just wire the switch's C terminal to ground the NO terminal to any (mostly) D line on the cpu, define that line as INPUT_PULLUP in the SETUP() portion, and use the code examples given already, remembering that the switch reads HIGH normally and only reads LOW when tripped.

if ( !digitalRead(yourPin) )
  {
  // do it to it.
  }