Problem with Motor DC and limit switch

Hi All,
I am trying to drive 12V dc motor forward and backward. Both side there are limit switch’s on interrupts to stop the motor. The problem is when motor is stopped by any limit switch it doesn’t rotate in reverse direction. Any help can solve my problem. Below is my code attached

Thank You

motor_limit_switch.c (1.93 KB)

thalangeajit: Hi All, I am trying to drive 12V dc motor forward and backward. Both side there are limit switch's on interrupts to stop the motor. The problem is when motor is stopped by any limit switch it doesn't rotate in reverse direction. Any help can solve my problem. Below is my code attached

Thank You

If you want to use interrupts, after motor has stopped try to detach interrupt from that end where your system is until motor start to move again and limit switch reach HIGH, then you can enable interrupt again.. It shouldn't interrupt while you are in the end but it's possible..

edit: Your schematics would help more.. Also, try to debug your interrupts and you'll see if they appear while end has reached.

TommiP

No!!! Don’t even think about doing it like that! Detaching and re-attaching an interrupt is a recipe for
confusion and late pending interrupts.

Your logic for stopping the motor should take into account the current direction and which switch was
triggered, leave the ISR running and doing its job.

MarkT: No!!! Don't even think about doing it like that! Detaching and re-attaching an interrupt is a recipe for confusion and late pending interrupts.

Why ?

Because the semantics of detach/reattach is not what people expect - you can get an interrupt indefinitely late when reattaching. It just causes bugs and problems for people regularly here.

There's a perfectly simple way to dynamically guard an ISR from running:

volatile boolean enable = true ;

void my_isr ()
{
  if (!enable) return ;
  .....
}

And this works exactly as expected.

MarkT: Because the semantics of detach/reattach is not what people expect - you can get an interrupt indefinitely late when reattaching. It just causes bugs and problems for people regularly here.

There's a perfectly simple way to dynamically guard an ISR from running:

volatile boolean enable = true ;

void my_isr () {   if (!enable) return ;   ..... }



And this works exactly as expected.

All right, then I've misunderstood the purpose of command detachInterrupt() :o

It has no use AFAICT. The issue with it is that it disables the individual interrupt, but (on ATmegas) each individual interrupt channel has a one-bit count of pending interrupts, which is not disabled. This means you can disable a particular interrupt for a while and not loose an interrupt. However if you disabled interrupts for too long and get two or more events, you do lose interrupts, and there is no way to tell. On re-enabling an interrupt the ISR runs immediately if there is a pending event for it.

Normally if you want to temporarily disable interrupts (for a critical section say), you'd just use noInterrupts ()/interrupts().

It's never too late to learn something new :)

I already tried the detachInterrupt() & enabling particular limit switch interrupt() according to motor drive direction, it work for first time only. i.e - I am not able to drive the motor back.

With my attached code above after applying break in ISR, Break pin is not releasing in main function. Why it is happening so...?

Hi,
Welcome to the forum.

Have you tried writing code WITHOUT INTERRUPTS?
The Arduino should be running fast enough to catch a motor on a limit switch.

Can you please post a copy of your sketch, using code tags?
They are made with the </> icon in the reply Menu.
See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html

Thanks… Tom… :slight_smile:

This is my code: -

/*  
     1. 12v DC Motor Test 1
    2. Use's PWM pulse to drive Motors
    3. Use 2 Limit Switches
*/

int PWM_L = 8;          // PWM pin
int DIRECTION_L = 4;    // Direction Pin
int BREAK_L = 6;        // Break Pin

int LIMIT_L_UP = 2;     // Input From Left Limit Switch 1
int LIMIT_L_DOWN = 3;   // Input From Left Limit Switch 2

#define DUTY_CYCLE 50

String inputString = "";
boolean stringComplete = false;

void setup() {
  Serial.begin(9600);
  inputString.reserve(200);      // Reserve 200 bytes for the inputString
  
  pinMode(PWM_L, OUTPUT);
  pinMode(DIRECTION_L, OUTPUT);
  pinMode(BREAK_L, OUTPUT);

  pinMode(LIMIT_L_UP, INPUT_PULLUP);    // Pin 2
  pinMode(LIMIT_L_DOWN, INPUT_PULLUP);  // Pin 3

  attachInterrupt(digitalPinToInterrupt(LIMIT_L_UP), Left_Up, FALLING);
  attachInterrupt(digitalPinToInterrupt(LIMIT_L_DOWN), Left_Down, FALLING);
}

void loop() {
  int Motor_Pos = 0, str_len, i = 0;
  
  if (stringComplete) {
    str_len = inputString.length() + 1;
    char server_arr[str_len];                       // Create char Array
    inputString.toCharArray(server_arr, str_len);   // convert String to char array
    Motor_Pos = atoi(server_arr);

    if (Motor_Pos == 1) {
      Serial.println("Open");
      digitalWrite(DIRECTION_L, HIGH);
      analogWrite(PWM_L, DUTY_CYCLE);
      digitalWrite(BREAK_L, LOW);
    }

    if (Motor_Pos == 2) {
      Serial.println("Close");
      digitalWrite(DIRECTION_L, LOW);
      analogWrite(PWM_L, DUTY_CYCLE);
      digitalWrite(BREAK_L, LOW);
    }
    inputString = ""; // Clear the main string
    stringComplete = false;
  }
}

void Left_Up() {      // Pin 2
  digitalWrite(BREAK_L, HIGH);
}

void Left_Down() {    // Pin 3
  digitalWrite(BREAK_L, HIGH);
}

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();  // Get the new byte:
    inputString += inChar;              // Add it to the inputString
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
}

checked with multi meter i am unable to release bread ones i return from ISR. :(

Hi, Did you write this code in stages? Have you got code that is purely making the motor move for and rev between the limit switches?

Tom... :)

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

How you power the project and how you have the limit switches wired is very important.

Thanks.. Tom... :)

Hi all, The limit switches are connected in the way that by default it gives high (Without Pressing) and after pressing it gives a low signal (With Pressing).

Hi, Do you have pull low resistors to pull the limit input to low, or do you have the limit wired as SPDT between +5 and 0V.

PLEASE..Can you please post a copy of your circuit, in CAD or a [u]picture of a hand drawn circuit in jpg, png[/u]?

It is very important that we know how your switches are wired to make sure you are providing a HIGH or LOW when you think you are.

Tom.... :)

Below is the image of how my limit switch's are connected with internal pull-ups ON.

Sorry for last post,
Below is the image of how my limit switch’s are connected with internal pull-ups ON.

In picture above the “Up s/w” and “Down s/w” are the names of two limit switches not the names given to NC terminal of limit switch. So when switch is pressed they give 0V to GPIO which are already Pulled Up and waiting for FALLING EDGE signal so that interrupts will trigger and motor can be stopped.

This works as aspect only for the first time but once the motor is stopped in particular ISR i am unable to reverse the motor. i.e :- I checked break pins they are not getting LOW in main loop after coming from ISR which is make break pin HIGH in ISR