Advertisement
Guest User

Untitled

a guest
Sep 13th, 2019
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.    This program uses an Arduino for a closed-loop control of a DC-motor.
  3.    Motor motion is detected by a quadrature encoder.
  4.    Two inputs named STEP and DIR allow changing the target position.
  5.    Serial port prints current position and target position every second.
  6.    Serial input can be used to feed a new location for the servo (no CR LF).
  7.    
  8.    Pins used:
  9.    Digital inputs 2 & 8 are connected to the two encoder signals (AB).
  10.    Digital input 3 is the STEP input.
  11.    Analog input 0 is the DIR input.
  12.    Digital outputs 9 & 10 control the PWM outputs for the motor (I am using half L298 here).
  13.  
  14.  
  15.    Please note PID gains kp, ki, kd need to be tuned to each different setup.
  16. */
  17.  
  18. #include <PinChangeInt.h>
  19. #include <PinChangeIntConfig.h>
  20. #include <PID_v1.h>
  21. #define encoder0PinA  2 // PD2;
  22. #define encoder0PinB  8  // PC0;
  23. #define M1            9
  24. #define M2            10  // motor's PWM outputs
  25.  
  26.  
  27. double kp=3,ki=300,kd=0.02;
  28. double input=80, output=0, setpoint=180;
  29. PID myPID(&input, &output, &setpoint,kp,ki,kd, DIRECT);
  30. volatile long encoder0Pos = 0;
  31.  
  32. long previousMillis = 0;        // will store last time LED was updated
  33.  
  34. long target1=0;  // destination location at any moment
  35.  
  36. //for motor control ramps 1.4
  37. bool newStep = false;
  38. bool oldStep = false;
  39. bool dir = false;
  40.  
  41. void setup() {
  42.   pinMode(encoder0PinA, INPUT);
  43.   pinMode(encoder0PinB, INPUT);  
  44.   PCintPort::attachInterrupt(encoder0PinB, doEncoderMotor0,CHANGE); // now with 4x resolution as we use the two edges of A & B pins
  45.   attachInterrupt(0, doEncoderMotor0, CHANGE);  // encoder pin on interrupt 0 - pin 2
  46.   attachInterrupt(1, countStep      , RISING);  // step  input on interrupt 1 - pin 3
  47.   TCCR1B = TCCR1B & 0b11111000 | 1; // set  Hz PWM
  48.   Serial.begin (115200);
  49.   //Setup the pid
  50.   myPID.SetMode(AUTOMATIC);
  51.   myPID.SetSampleTime(1);
  52.   myPID.SetOutputLimits(-255,255);
  53. }
  54.  
  55. void loop(){
  56.     input = encoder0Pos;
  57.     setpoint=target1;
  58.     myPID.Compute();
  59.     // interpret received data as an integer (no CR LR): provision for manual testing over the serial port
  60.     if(Serial.available()) target1=Serial.parseInt();
  61.     pwmOut(output);
  62.   //  if(millis() % 3000 == 0) target1=random(2000); // that was for self test with no input from main controller
  63. }
  64.  
  65. void pwmOut(int out) {
  66.    if(out<0) { analogWrite(M1,0); analogWrite(M2,abs(out)); }
  67.    else { analogWrite(M2,0); analogWrite(M1,abs(out)); }
  68.   }
  69.  
  70. const int QEM [16] = {0,-1,1,2,1,0,2,-1,-1,2,0,1,2,1,-1,0};               // Quadrature Encoder Matrix
  71. static unsigned char New, Old;
  72. void doEncoderMotor0(){
  73.   Old = New;
  74.   New = (PINB & 1 )+ ((PIND & 4) >> 1); //
  75.   encoder0Pos+= QEM [Old * 4 + New];
  76. }
  77.  
  78. void countStep(){ if (PINC&B0000001) target1--;else target1++; } // pin A0 represents direction
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement