Synchronizing Motor Position with Encoders, PID Control and Arduino

Sdílet
Vložit
  • čas přidán 15. 06. 2024
  • In this video, I demonstrate how to use PID Control to synch the positions of two motors with encoders by only using two interrupt pins on the Arduino.
    Check out this Reference Desk Mat for Arduino:
    amzn.to/3vO6QBl
    Video Timestamps:
    0:00 - Introduction
    0:33 - PID Control for a single motor
    0:40 - Parts needed
    0:46 - Pin out for the motor and encoder
    0:58 - Wiring the circuit
    1:16 - Arduino code for one motor
    4:40 - Selecting the gains
    5:27 - Beginning of two motor example
    5:32 - Updating the wiring for two motors
    5:58 - Arduino code for two motors
    7:29 - Selecting the gains for the two motor example
    7:58 - Conclusion
    The code for the section with PID control for a single motor was adapted from what was presented in this video below. I have no incentive to reference this video, but it's a great resource for other projects:
    • How to control a DC mo...
    👉Subscribe for more robotics and engineering tips:
    / @theboredrobotllc
    Share this video with a friend:
    • Synchronizing Motor Po...
    Website:
    www.theboredrobot.com/
    Parts needed for this example:
    Arduino Uno - amzn.to/3pGK6Am
    Gear Motors with Encoder - amzn.to/3Fszeuj
    Power Supply - amzn.to/3DKs2sF
    Motor Shield - amzn.to/3Qtbeh6
    (Note: This shield is a different one from the example. Make sure the pin assignments line up with the the documentation for the shield.)
    Connect:
    Instagram - /theboredrobot
    Twitter - @theboredrobot
    Facebook - / theboredrobot
    Pinterest - /TheBoredRobot
    Disclaimer: This video contains affiliate links, meaning that if you make a purchase from one of the product links, I'll receive a small commission.
  • Věda a technologie

Komentáře • 77

  • @noah7164
    @noah7164 Před 7 měsíci +4

    Just the video i needed for my project. Thank you!!!

  • @ffsscorpion6940
    @ffsscorpion6940 Před 7 měsíci +9

    Just a quick note, you don't need 2 interrupt pins for each encoder, you need to attach an interrupt to just 1 and check the level of the other, so you could use that to allow both direction catch-up, maybe even use in of the motor as a very expensive encoder input and move it with your hand, great vid though ❤

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 7 měsíci +4

      That's a great idea and I should try out. I don't know why I didn't think to check for the status outside of the function called by the interrupts. Thank you for this!

    • @drotalion620
      @drotalion620 Před 7 měsíci +1

      I kinda don't get it. What do you mean with "level of the other"? Do you mean like: Rotation you provided first decides in interrupt if stepsCounter++ or stepsCounter--?

    • @peterlingas
      @peterlingas Před 4 měsíci +1

      @@drotalion620 When the interrupt is triggered, you can check the voltage level of the other encoder pin. Depending on the state of it you can tell if it was triggered due to clockwise or counterclockwise rotation. So indeed, it will let you decide if you should do stepsCounter++ or stepsCounter--.

    • @khalmaxroboticsgh3176
      @khalmaxroboticsgh3176 Před 3 měsíci

      I'm working on a 4wd robot car using Arduino Mega. I am trying to synchronize the speed of all 4 wheels of the robot. I intend to read the motor speed from each motor using an AS5600 hall sensor. That means 4 hall sensors in all. I also realised the arduino mega has only one sda and scl pins so this tutorial is helpful. Can you also help me with more tips and advise on how to go about it?
      Thanks

  • @Rolandvanroy
    @Rolandvanroy Před 2 měsíci

    Thanks for this interesting video. Any reason why you did not use the Arduino PID library?

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 2 měsíci +1

      The PID library probably would have been less lines of code. This just happens to be more of an educational exercise.

  • @arduinomaquinas
    @arduinomaquinas Před 4 měsíci +1

    Very cool video ❤😉👍 👏👏👏

  • @MukeshPatel-tw5ge
    @MukeshPatel-tw5ge Před 5 měsíci +3

    Thanks for your video. It is great ! Which motor do you recommend for a robo vehicle project using 9v running by arduino ? The RPM requirement is 75-100 and goal is to have precision straight and angular move for a school competition. And if you can suggest best wheels/tires. Thanks for your help.

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 5 měsíci +1

      For a vehicle, I recommend using a brushed motor. There are some decent motor/wheel combos on Amazon. Otherwise, I often buy from Pololu or Servo City.

    • @MukeshPatel-tw5ge
      @MukeshPatel-tw5ge Před 3 měsíci

      @edRobotLLC Thanks. My son got motor synchronization working after learning from your video. As you said in video that Arduino Uno has pin limitation so you used only one encoder output from each motor. Arduino Giga has so many pins available, can you suggest how can we use both encoder pins of two motors for synchronization ? Will that work better ? Thanks a lot.

  • @MUHAMMAD-hl2tn
    @MUHAMMAD-hl2tn Před 5 měsíci +1

    The motor in video is different from one you mentioned in links. Could you tell what is the motor you have used in video?

  • @jameslin3841
    @jameslin3841 Před 4 měsíci

    Thank you so much for the content🙏 may I know which encoder did u use to control the motor?

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 4 měsíci +1

      I used these:
      www.pololu.com/category/116/37d-metal-gearmotors

    • @jameslin3841
      @jameslin3841 Před 4 měsíci

      @@TheBoredRobotLLC Thank you so much!!

  • @gutgutia
    @gutgutia Před 4 měsíci +1

    This is a life saver - thank you! Would you mind uploading the code please?

  • @roh5768
    @roh5768 Před 5 měsíci +2

    Are you able to code the motors to allow for turning to be possible given the shortcomings of the interrupters?

    • @srinathnarayanan2585
      @srinathnarayanan2585 Před 5 měsíci

      Brilliant question! Looking forward to an answer as well.

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 5 měsíci +1

      Are referring to the fact that Arduino Uno only has 2 interrupt pins? I haven't worked on this problem yet, but you certainly gave me a new idea for another tutorial video.

    • @brendanowen7563
      @brendanowen7563 Před 3 měsíci

      @@TheBoredRobotLLC You could solve this problem, but wiring the second encoder pin of each motor to another input on the board. You do not need to use the interrupts on these pins. You can just use the original logic of comparing the encoder outputs from each motor.

  • @omarsalem5832
    @omarsalem5832 Před 5 měsíci +2

    What's 'target' variable? how do you set the angle/position?

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 5 měsíci

      The 'target' is the desired value in the PID controller. This is the desired encoder count. You'll have what relationship the encoder count has with a specific angle or position in your system.

  • @sarinashahhosseini
    @sarinashahhosseini Před měsícem

    Does synchronizing also depend on the initial position of the two motors? Since from the beginning we are counting encoder counts, then synchronization only can happen if the motors started at the same position.

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před měsícem

      For this simple example, it's assumed that the motors start at the same position. The motor positions are relative to the positions that the motors started at when the Arduino was powered up.

  • @khalmaxroboticsgh3176
    @khalmaxroboticsgh3176 Před 3 měsíci +1

    I'm working on a 4wd robot car using Arduino Mega. I am trying to synchronize the speed of all 4 wheels of the robot. I intend to read the motor speed from each motor using an AS5600 hall sensor. That means 4 hall sensors in all. I also realised the arduino mega has only one sda and scl pins so this tutorial is helpful. Can you also help me with more tips and advise on how to go about it?
    Thanks

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 3 měsíci

      It's the same process, but you'll need the additional interrupt for the additional motors. For the mega, pins 2, 3, 18, 19, 20, and 21 will accomplish this for the sensors.

    • @khalmaxroboticsgh3176
      @khalmaxroboticsgh3176 Před 3 měsíci

      @@TheBoredRobotLLC that's the problem. Iam using four AS5600 hall sensors on each tire. Problem is I can only read from one hall sensor I.e sda and scl pins on arduino mega.
      How to I hall read sensor values from all tires on arduino

  • @joshuacain485
    @joshuacain485 Před 4 měsíci

    I'm trying to get my motor to work, and so far so good (new at this) - I don't understand something - you're showing controlling the direction with pin 4 - but nothing is plugged into pin 4 in your circuit?

  • @siddharthtata
    @siddharthtata Před 4 měsíci +1

    I have a small query, what did you connect to pin 4 and 5 ? I am unable to see any more wires connected @
    1:10

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 4 měsíci +1

      Pins 4 and 5 have are assigned to the direction and speed values, as defined by this specific motor shield.

    • @siddharthtata
      @siddharthtata Před 4 měsíci

      ​​@@TheBoredRobotLLCsorry for this silly question but how is the signal being given to the motor for speed and direction? I only see six wires and according to the pinout 2 are for encoder outputs, 2 for power and 2 for hall effect sensors. Wires for 4 and 5 are not visible in the video. Is there an internal connection which I am missing?

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 4 měsíci

      @@siddharthtata There are signals coming directly from the motor shield.

  • @sampamnl.8964
    @sampamnl.8964 Před 21 dnem

    ขอบคุณมากครับ

  • @blibberblabber756
    @blibberblabber756 Před 2 měsíci

    Both of my encoder counts go up by a lot, within just a second they are in the 1000s, is this supposed to be happening? I am asking this because I want to make my robot move the same distance no matter the speed of the motors, so I need to be able to count the motors rotations. Also, does this setup allow for the motors to be in sync going in reverse as they don't utilize the other encoder signal?

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 2 měsíci

      It's hard to say what would cause the count to jump so much. Take a look at what is causing the interrupt to be triggered. This method doesn't allow for reverse.

  • @memocool4279
    @memocool4279 Před 2 měsíci

    Can you please tell me how to control 2 dc motors with different targets rather than following each other. Like what changes to the code should i do.

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 2 měsíci

      Instead of the set point to the PID controller being the position of one of the motor encoders, set it to your desired set point. You'll need the PID output signal to then go to both motors.

  • @abekiri
    @abekiri Před 5 měsíci +1

    Thank you for this video, can you share the code

  • @GaBut-wo8nr
    @GaBut-wo8nr Před 4 měsíci +3

    #define DIR1 4
    #define PWM1 5
    #define encoderPinA 2
    #define encoderPinB 3
    volatile long encoderCount = 0;
    long previousTime = 0;
    float ePrevious = 0;
    float eIntegral = 0;
    void setup() {
    Serial.begin(9600);
    pinMode(DIR1, OUTPUT);
    pinMode(PWM1, OUTPUT);
    pinMode(encoderPinA, INPUT);
    pinMode(encoderPinB, INPUT);
    attachInterrupt(digitalPinToInterrupt(encoderPinA), handleEncoder. RISING);
    }
    void loop() {
    int target = 1000;
    float kp = 0,0;
    float kd = 0,0;
    float ki = 0,0;
    float u = pidController(target, kp, kd, ki);
    moveMotor(DIR1, PWM1, u);
    Serial.print(target);
    Serial.print(", ");
    Serial.print(encoderCount);
    }
    void handleEncoder() {
    if (digitalRad(encoderPinA) > digitalRead(encoderPinB)){
    encoderCount++;
    }
    else{
    encoderCount--;
    }
    }
    void moveMotor(int dirPin, int pwmPin, float u){
    float speed = fabs(u);
    if(speed > 255){
    speed = 255;
    }
    int direction = 1;
    if (u < 0){
    direction = 0;
    }
    digitalWrite(dirPin, direction);
    analogWrite(pwmPin, speed);
    }
    float pinController(int target, float kp, float kd, float ki) {
    long currentTime = micros();
    float deltaT = ((float)(currentTime - previousTime)) / 1.0e6;
    int e = encoderCount - target;
    float eDerivative = (e - ePrevious) / deltaT;
    eIntegral = eIntegral + e * deltaT;
    float u = (kp * e) + (kd * eDerivative) + (ki * eIntegral);
    previousTime = currentTime;
    ePrevious = e:
    return u;
    }

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 4 měsíci

      Feel free to contact me if you have a specific question on this.
      theboredrobot.com/pages/contact

  • @User-Tal1951
    @User-Tal1951 Před 2 měsíci

    Any advice for a motor that moves very fast 180 degrees?

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 2 měsíci

      That's a pretty broad question. You'll probably have to really tune the gains carefully. Start with a slow motor speed, and then work your way up to a faster speed.

  • @xanderyesilirmak956
    @xanderyesilirmak956 Před měsícem

    Out of interest, if one motor is moved by hand when stationary, does the other motor follow the other still?

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 29 dny

      Yes, it should still work. If you ever tried to take the back of one of these motors off to expose the encoder, you're count should still go up if you move the encoder by hand. However, the motor shafts in this video are pretty hard to move by hand because of the gear ratio.

  • @shivpat6522
    @shivpat6522 Před 3 měsíci

    Hi. I have a question regarding your code. I notice in my code, there isn't any identified osilations detected or at least what is shown on your serial plotter in 5:09 and my code is really generic to yours. Do you know what could be causing the issues. I think it has to do with my gains, speed, or encodercount.

    • @shivpat6522
      @shivpat6522 Před 3 měsíci

      Yea more likely encoder count because in serial plotter, my target looks fine at 1000, but my encoder count stays consistently at 0 even when the motor is running, leading to no change regardless of PID gains.

    • @shivpat6522
      @shivpat6522 Před 3 měsíci

      Another question. For the dual motor code, everything looks right except for PID controller. This is because for your "int e", your initial equation for 1 motor was "int e. = encoderCount - target;" but since there are 2 encoders coming into perspective right now, how are we supposed to write the code for this with 2 encoders, each from each motor.

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 3 měsíci

      If you're not seeing oscillations in your plot, your derivative gain may be high, or proportional gain might be low. It's hard to say without seeing all of the details.

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 3 měsíci

      In the code with 2 motors, one of the motors is just moving at a constant speed in one direction. This count is being tracked and being used as the target for the second motor. The PID controller is being implemented on the second motor. It's a simple example showing the limitations of only having two interrupt pins on the Arduino Uno.

  • @user-vl6nu2tn5j
    @user-vl6nu2tn5j Před měsícem

    Is it possible for the motor '1' to go around 10 times, and the motor '2' to go around 1 time?

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před měsícem

      Yes that is possible. You would have to know the number of counts per revolution and then set that to be your desired position in your code.

  • @deksis8519
    @deksis8519 Před 4 měsíci

    I used the code in github (just changed the pin #'s) and motor 1 moves but motor 2 does not. I am using a l298n sheild and arduino uno for my 2 motors. Do you know what the issue could be?

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 4 měsíci

      That's a pretty hard question to answer without knowing all the details of the project. My first steps would be to check the connections and the jumper selections on the shield. Then I would double check the pin assignments.

    • @deksis8519
      @deksis8519 Před 4 měsíci

      ​thx! I ended up adding a few lines of code under the moveMotor command and it works well enough for what I need. Great video, helped a ton!

  • @abdotsouri9432
    @abdotsouri9432 Před 8 dny +1

    link of the code !

  • @drotalion620
    @drotalion620 Před 7 měsíci +1

    What happens, when Motor 2 can't reach the speed of motor 1 because of unbalanced load for example? In this case, motor 1 will not get slower, I guess. Any idea, how to handle this problem?
    Else cool idea. Thank you

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 6 měsíci

      That is certainly a limitation of this approach under these constraints. If the second motor can't go faster than the first 1 one, then it won't work.

  • @shivpat6522
    @shivpat6522 Před 4 měsíci

    Can you send a file or a link of the code for me to easily replicate

  • @christiandelacruz6796
    @christiandelacruz6796 Před 3 měsíci

    Hello can i have a copy for the whole code? We are also conducting a robot sweeper for our capstone project, we will use 2 dc motor with encoder. Hope i can have Thanks!

  • @hichamgrinda7869
    @hichamgrinda7869 Před 2 měsíci

    where is the code?

  • @mbenj2023
    @mbenj2023 Před 22 dny

    Outputs were visibly not synchronised.

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před 21 dnem +1

      Arduino not synchronous in general, but this did approach did the job for the application of getting two walking legs to sync up for another project. I do agree there is still plenty of room for improvement with adjusting gains or even a completely different method.

  • @GeekDetour
    @GeekDetour Před měsícem

    Ok.... but... why? ha ha ha. I was expecting a particular practical reason for that.

    • @TheBoredRobotLLC
      @TheBoredRobotLLC  Před měsícem

      This video was made for a group of students who had built walking mechanisms that needed the linkages to be in sync. It was for a very specific project.