Help DC motor with limit switches

Hello,

I am new to Arduino. I am using Arduino Uno with H bridge to get forward and reverse rotation of the motor. I am also using encoder to get position of the motor. I would also like add 2 limit switches to get the end points of the particular path. For now I am able to get the forward and reverse rotation of the motor also adjusting the speed with PID. So my question is how can I add code for limit switches in the code that I already have.

Here is my code. I am using PID controller library which I found online.

#include <PIDController.h>


int distance = 30000;
int MotorSpeedLeft = 50;
int MotorSpeedRight = 70;

volatile int temp, counter = 0; //This variable will increase or decrease depending on the rotation of encoder

PIDController pos_pid;  

int motor_value = 255;     

int difference = 100;

void setup() {

   Serial.begin (9600);
   
   pinMode(2, INPUT_PULLUP); // encoder white to arduino 2 
   pinMode(3, INPUT_PULLUP); // encoder green to arduino 3
   pinMode(9, OUTPUT); // motor driver LPWM to arduino 9
   pinMode(10, OUTPUT); // motor driver RPWM to arduino 10
   

  attachInterrupt(0, ai0, RISING);

  attachInterrupt(1, ai1, RISING);


   pos_pid.begin();     
   pos_pid.tune(0.1,20, 0); //P,I,D    
   pos_pid.limit(-MotorSpeedLeft, MotorSpeedRight); //Motor speed 
   pos_pid.setpoint(distance); 
   TCCR1B = TCCR1B & B11111000 | B00000011; // for PWM frequency of 490.20 Hz (The DEFAULT)
   
  }

   

  void loop() {

  Serial.print (counter);
  
  Serial.println (motor_value);

  temp = counter;
if (counter > distance-difference){
  pos_pid.setpoint(-distance);
  }
  else if (counter < -(distance-difference))
  { pos_pid.setpoint(distance);
    }
  

 motor_value = pos_pid.compute(counter); 


  if(motor_value > 0){ 
  MotorCounterClockwise(motor_value); 
}else{ 
  MotorClockwise(abs(motor_value)); 
} 
  Serial.print(counter); 
 // delay(1); 
 //     digitalWrite(9, LOW); 
 //   digitalWrite(10, LOW); 
    
 

 }

  
  void ai0() {

  if(digitalRead(3)==LOW) {

  counter++;

  }else{

  counter--;

  }

  }

  void ai1() {

 if(digitalRead(2)==LOW) {

  counter--;

  }else{

  counter++;

  }
  }

  void MotorClockwise(int power){ 
  if(power > 10){
Serial.print("CW");
  analogWrite(9, power); 
  digitalWrite(10, LOW); 
  }else{ 
    digitalWrite(9, LOW); 
    digitalWrite(10, LOW); 
  } 
} 

void MotorCounterClockwise(int power){ 
  if(power > 10){ 
    Serial.print("CCW");
  analogWrite(10, power); 
  digitalWrite(9, LOW); 
  }else{ 
    digitalWrite(9, LOW); 
    digitalWrite(10, LOW); 
  } 

  }

To make it easy for people to help you please modify your post and use the code button </>
codeButton.png

so your code 
looks like this

and is easy to copy to a text editor. See How to use the Forum

Your code is too long for me to study quickly without copying to my text editor.

...R

Thanks for presenting your program properly. I should also have mentioned that if you use the AutoFormat tool it will indent your code consistently and make it much easier to read - something like this

#include <PIDController.h>

int distance = 30000;
int MotorSpeedLeft = 50;
int MotorSpeedRight = 70;

volatile int temp, counter = 0; //This variable will increase or decrease depending on the rotation of encoder

PIDController pos_pid;  

int motor_value = 255;     

int difference = 100;

void setup() {

    Serial.begin (9600);
    
    pinMode(2, INPUT_PULLUP); // encoder white to arduino 2 
    pinMode(3, INPUT_PULLUP); // encoder green to arduino 3
    pinMode(9, OUTPUT); // motor driver LPWM to arduino 9
    pinMode(10, OUTPUT); // motor driver RPWM to arduino 10
    
    attachInterrupt(0, ai0, RISING);
    attachInterrupt(1, ai1, RISING);

    pos_pid.begin();     
    pos_pid.tune(0.1,20, 0); //P,I,D    
    pos_pid.limit(-MotorSpeedLeft, MotorSpeedRight); //Motor speed 
    pos_pid.setpoint(distance); 
    TCCR1B = TCCR1B & B11111000 | B00000011; // for PWM frequency of 490.20 Hz (The DEFAULT)
    
}

    

void loop() {
    Serial.print (counter);
    Serial.println (motor_value);

    temp = counter;
    if (counter > distance-difference){
        pos_pid.setpoint(-distance);
    }
    else if (counter < -(distance-difference)) {
        pos_pid.setpoint(distance);
    }
    
    motor_value = pos_pid.compute(counter); 

    if(motor_value > 0){ 
        MotorCounterClockwise(motor_value); 
    }
    else{ 
        MotorClockwise(abs(motor_value)); 
    } 
    Serial.print(counter); 
    // delay(1); 
    //     digitalWrite(9, LOW); 
    //   digitalWrite(10, LOW); 

}

void ai0() {
    if(digitalRead(3)==LOW) {
        counter++;
    }else{
        counter--;
    }

}

void ai1() {
    if(digitalRead(2)==LOW) {
        counter--;
    }
    else {
        counter++;
    }
}

void MotorClockwise(int power){ 
    if(power > 10){
        Serial.print("CW");
        analogWrite(9, power); 
        digitalWrite(10, LOW); 
    }
    else{ 
        digitalWrite(9, LOW); 
        digitalWrite(10, LOW); 
    } 
} 

void MotorCounterClockwise(int power){ 
    if(power > 10){ 
        Serial.print("CCW");
        analogWrite(10, power); 
        digitalWrite(9, LOW); 
    }
    else{ 
        digitalWrite(9, LOW); 
        digitalWrite(10, LOW); 
    } 
}

Now to deal with your question about adding code for limit switches ...

I would add a function that reads the two switches and saves their values. Then you could add some code to loop() like this

checkLimitSwitches();
if (limitSwitchAstate == LOW) { // assumes LOW when pressed
    // do something
}
if (limitSwitchBstate == LOW) {
   // do something else
}

And it would probably be neater to put the code to act on the switches in its own function to simplify the extra code in loop() to

checkLimitSwitches();
actOnLimitSwitchStates();

...R

Hi Robin,

Can you please explain it more clearly.

Pranav9861:
Can you please explain it more clearly.

It will be easier to help if you explain what part you are unsure of, or tell me how you think my suggested code works.

And you have not told us what you want to happen when a limit switch is triggered.

...R

Hi Robin,

I just want the Motor to stop and reverse its direction of Rotation as soon as Limit Switches at both Ends is triggered.

Here is the new code which i tried but was not able to get what i want.

#include <PIDController.h>
PIDController pos_pid;
volatile int temp, counter = 0; //This variable will increase or decrease depending on the rotation of encoder


int distance = 25000;
int MotorSpeedLeft = 70;
int MotorSpeedRight = 70;
int motor_value = 255;     
int difference = 100;
const int LS1 = 4;
const int LS2 = 6;
         
boolean limitswitch1 = 0;        
boolean limitswitch2 = 0;


void setup() {

   pinMode(2, INPUT_PULLUP); // encoder white to arduino 2 
   pinMode(3, INPUT_PULLUP); // encoder green to arduino 3
   pinMode(9, OUTPUT); // motor driver LPWM to arduino 9
   pinMode(10, OUTPUT); // motor driver RPWM to arduino 10
   pinMode(LS1, INPUT); // limit switch 1 to arduino 4
   pinMode(LS2, INPUT); // limit switch 2 to arduino 6

   Serial.begin (9600);
   

  attachInterrupt(0, ai0, RISING);

  attachInterrupt(1, ai1, RISING);


   pos_pid.begin();     
   pos_pid.tune(0.1,20, 0); //P,I,D    
   pos_pid.limit(-MotorSpeedLeft, MotorSpeedRight); //Motor speed 
   pos_pid.setpoint(distance); 
   TCCR1B = TCCR1B & B11111000 | B00000011; // for PWM frequency of 490.20 Hz (The DEFAULT)
   
  }

   
void loop()

  {

    limitswitch1 = digitalRead(LS1);
    limitswitch2 = digitalRead(LS2);
    
    //actonLimitSwitchStates();
    void checkLimitSwitches();
     if (limitswitch1 == LOW) {
       MotorClockwise (50);
   } 
   if (limitswitch2 == LOW) {
      MotorCounterClockwise (50);
  } 

  Serial.print (counter);
  
  Serial.println (motor_value);

  temp = counter;
if (counter > distance-difference){
  pos_pid.setpoint(-distance);
  }
  else if (counter < -(distance-difference))
  { pos_pid.setpoint(distance);
    }
  

 motor_value = pos_pid.compute(counter); 


  if(motor_value > 0){ 
  MotorCounterClockwise(motor_value); 
}else{ 
  MotorClockwise(abs(motor_value)); 
} 
  Serial.print(counter); 
 // delay(1); 
 //     digitalWrite(9, LOW); 
 //   digitalWrite(10, LOW); 
    
 

 }

  
  void ai0() {

  if(digitalRead(3)==LOW) {

  counter++;

  }else{

  counter--;

  }

  }

  void ai1() {

 if(digitalRead(2)==LOW) {

  counter--;

  }else{

  counter++;

  }
  }

  void MotorClockwise(int power){ 
  if(power > 10){
Serial.print("CW");
  analogWrite(9, power); 
  digitalWrite(10, LOW); 
  }else{ 
    digitalWrite(9, LOW); 
    digitalWrite(10, LOW); 
  } 
} 

void MotorCounterClockwise(int power){ 
  if(power > 10){ 
    Serial.print("CCW");
  analogWrite(10, power); 
  digitalWrite(9, LOW); 
  }else{ 
    digitalWrite(9, LOW); 
    digitalWrite(10, LOW); 
  } 

  }

Before you post code the next time be sure to use the AutoFormat tool - it will be big help for you as well as for us.

This line of code does not create a function - because it ends with a semi-colon.

    void checkLimitSwitches();

and you can't create a function inside another function - in this case it would be inside loop().

The function I had in mind is like this

void checkLimitSwitches() {
    limitswitch1 = digitalRead(LS1);
    limitswitch2 = digitalRead(LS2);
}

...R