Advertisement
gersonfer

pid_match_motors

Aug 29th, 2019
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.04 KB | None | 0 0
  1. /*
  2.  * https://forum.arduino.cc/index.php?topic=100522.0
  3. The right way to do this is to measure the speed of each wheel and use a PID library (http://arduino.cc/playground/Code/PIDLibrary)
  4. to set the PWM output to each motor in order to obtain a commanded motor speed.
  5. This is a nice way to do it because you can change the setpoints at will to change the speed or to steer (use different commands).
  6. The trick is not to think of it as synchronizing the motors so much as it is setting them both to a commanded speed.
  7. That means each motor is its own separate unit, with its own PID loop.
  8. You then synchronize the motors by sending them the same command.
  9. This gives you the option to send them different commands, for things like steering or compensating for mismatched wheels.
  10. For each motor, the first thing to do is measure the speed.
  11. You can do this by measuring the time between encoder counts and dividing the amount of distance covered in a single count by the time difference.
  12. Now, you have the actual speed and you have the desired speed.
  13. Subtract that actual speed from the desired speed; this gives you the error.
  14. The error value is the input to the PID loop.
  15. The output from the PID loop, once it's correctly tuned, is the PWM value to write to the output for that motor.
  16. The link I provided has a lot more information on how to set up and tune PID loops. It's pretty good; you should read it.
  17.  
  18. As already mentioned, PID is what you want.
  19. In addition, you want to command a position, not a speed.
  20. As a loose PID will normally suffer from some velocity following error.
  21. If you find it difficult to tune and/or are going slowly, drop the D and just do PI.
  22. */
  23. int E1 = 5;     //Right Motor Power
  24. int E2 = 6;     //Left Motor Power
  25. int M1 = 4;    //Right Motor Direction
  26. int M2 = 7;    //Left Motor Direction
  27. const byte encoder0pinA = 2; //Interrupt 0
  28. const byte encoder0pinB = 12;
  29. const byte encoder1pinA = 3; //Interrupt 1
  30. const byte encoder1pinB = 13;
  31. byte overflow;
  32. byte encoder0PinALast;
  33. byte encoder1PinALast;
  34. int duration0;//Encoder0 number of pulses
  35. int duration00;
  36. int duration1;//Encoder1 number of pulses
  37. int duration11;
  38. boolean Direction0;
  39. boolean Direction1;
  40.  
  41. int SetPoint = 0; // 0 would be straight ahead
  42. double Kp = 25; // needs tunning
  43. int error = 0;
  44. int speed = 100; // set the speed of which the vechicle should move
  45. int output = 0;
  46.  
  47. void setup()
  48. {  
  49.   pinMode(4, OUTPUT);
  50.   pinMode(5, OUTPUT);
  51.   pinMode(6, OUTPUT);
  52.   pinMode(7, OUTPUT);
  53.   Serial.begin(9600);//Initialize the serial port
  54.   EncoderInit();//Initialize the module
  55.   timer_init();
  56.  
  57. }
  58.  
  59. void loop()
  60. {
  61. //  Serial.print("Left Pulse:");
  62. //  Serial.println(duration00);
  63. //  Serial.print("Right Pulse:");
  64. //  Serial.println(duration11);
  65.   Preg(duration0, duration1); //Go Forward
  66.   digitalWrite(M1,LOW);
  67.   digitalWrite(M2,LOW);
  68.   delay(2500);
  69.   Preg(duration0, duration1); //Go Backward
  70.   digitalWrite(M1,HIGH);
  71.   digitalWrite(M2,HIGH);
  72.   delay(2500);
  73.   digitalWrite(E1,LOW); //STOP!!!!!!
  74.   digitalWrite(E2,LOW);
  75.   delay(2500);
  76. }
  77. ISR(TIMER1_OVF_vect)
  78. {
  79.   overflow++;
  80.   if(overflow>=10)
  81.   {
  82.   duration00=duration0;
  83.   duration0=0;
  84.   duration11=duration1;
  85.   duration1=0;
  86.   overflow=0;
  87.   }
  88. }
  89. void Preg(int SpeedL, int SpeedR)
  90. {
  91.   noInterrupts(); // Disable interrupts, no need to slow down the P regulator
  92.   error = ((SpeedL-SpeedR)-SetPoint);
  93.   output = (Kp*error);
  94.   if(error >= 0) // its turning left of the setpoint, reduce E1 (right motor)
  95.   {
  96.     analogWrite(E2, speed);
  97.     analogWrite(E1, (speed-output)); // Subtract the error value multiplied by Kp from E1
  98.   }
  99.   if(error < 0) // turning right of our setpoint, reduce E0
  100.   {
  101.     analogWrite(E2, (speed+output)); // This time we add the error since its negative
  102.     analogWrite(E1, speed);
  103.   }
  104.   interrupts(); //Enable interrupts again
  105. }
  106.  
  107. void timer_init(void)
  108. {
  109.   TIMSK1 |= (1<<TOIE1); // Enable Timer1 overflow interrupt at 16MHz = 16 000 000 / 2^16 = 244Hz
  110. }
  111. void EncoderInit()
  112. {
  113.   Direction0 = true;
  114.   Direction1 = true;  
  115.   pinMode(encoder0pinB,INPUT);
  116.   attachInterrupt(0, wheelSpeed0, CHANGE);
  117.   pinMode(encoder1pinB,INPUT);  
  118.   attachInterrupt(1, wheelSpeed1, CHANGE);
  119. }
  120.  
  121.  
  122. void wheelSpeed0()
  123. {
  124.   //Encoder 0 Code
  125.   int Lstate = digitalRead(encoder0pinA);
  126.   if((encoder0PinALast == LOW) && Lstate==HIGH)
  127.   {
  128.     int val0 = digitalRead(encoder0pinB);
  129.     if(val0 == LOW && Direction0)
  130.     {
  131.       Direction0 = false; //Reverse
  132.     }
  133.     else if(val0 == HIGH && !Direction0)
  134.     {
  135.       Direction0 = true;  //Forward
  136.     }
  137.   }
  138.   encoder0PinALast = Lstate;
  139.  
  140.   if(!Direction0)  duration0++;
  141.   else  duration0++;
  142. }
  143.  
  144. void wheelSpeed1()
  145. {
  146.   //Encoder 1 Code
  147.   int Lstate1 = digitalRead(encoder1pinA);
  148.   if((encoder1PinALast == LOW) && Lstate1==HIGH)
  149.   {
  150.     int val1 = digitalRead(encoder1pinB);
  151.     if(val1 == LOW && Direction1)
  152.     {
  153.       Direction1 = false; //Reverse
  154.     }
  155.     else if(val1 == HIGH && !Direction1)
  156.     {
  157.       Direction1 = true;  //Forward
  158.     }
  159.   }
  160.   encoder1PinALast = Lstate1;
  161.  
  162.   if(!Direction1)  duration1++;
  163.   else  duration1++;
  164. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement