Advertisement
Guest User

Untitled

a guest
May 28th, 2024
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.99 KB | Source Code | 0 0
  1.  
  2. /*
  3.    This program uses an Arduino for a closed-loop control of TWO brushless DC-motors.
  4.    Motor motion is detected by a quadrature encoder.
  5.    Two inputs per motor named STEP and DIR allow changing the target position.
  6.    Serial port prints current position and target position every second.
  7.    Serial input can be used to feed a new location for the servo (no CR LF).
  8.    
  9.    Pins used: please read defines and code below
  10.  
  11.    Please note PID gains kp, ki, kd need to be tuned to each different setup.
  12.    
  13.  
  14.    */
  15. //#define DEBUG
  16.  
  17. #include <PID_v1.h>
  18. #define encoder0PinA  12
  19. #define encoder0PinB  8  
  20. #define encoder1PinA  7
  21. #define encoder1PinB  6
  22. #define PWM           9
  23. #define PWM1          10
  24. #define CWCCW         11  
  25. #define CWCCW1        5
  26.  
  27.  
  28. double kp=1,ki=0,kd=0.0;
  29. double input=0, output=0, setpoint=0;
  30. double input1=0, output1=0, setpoint1=0;
  31. PID myPID(&input, &output, &setpoint,kp,ki,kd, DIRECT);
  32. PID myPID1(&input1, &output1, &setpoint1,kp,ki,kd, DIRECT);
  33.  
  34. volatile long encoder0Pos = 0;
  35. volatile long encoder1Pos = 0;
  36.  
  37. long previousMillis = 0;        // will store last time LED was updated
  38.  
  39. long target0=0;  // destination location at any moment
  40. long target1=0;  // destination location at any moment
  41.  
  42. //for motor control ramps 1.4
  43. bool newStep = false;
  44. bool oldStep = false;
  45.  
  46. // Install Pin change interrupt for a pin, can be called multiple times
  47. void pciSetup(byte pin)
  48. {
  49.     *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // enable pin
  50.     PCIFR  |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
  51.     PCICR  |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
  52. }
  53.  
  54. void setup() {
  55.   pinMode(encoder0PinA, INPUT); digitalWrite(encoder0PinA, HIGH);
  56.   pinMode(encoder0PinB, INPUT); digitalWrite(encoder0PinB, HIGH);  
  57.   pciSetup(encoder0PinA);
  58.   pciSetup(encoder0PinB);
  59.  
  60.   pinMode(encoder1PinA, INPUT); digitalWrite(encoder1PinA, HIGH);
  61.   pinMode(encoder1PinB, INPUT); digitalWrite(encoder1PinB, HIGH);  
  62.   pciSetup(encoder1PinA);
  63.   pciSetup(encoder1PinB);
  64.  
  65.   TCCR1B = TCCR1B & 0b11111000 | 1; // set  Hz PWM
  66.   Serial.begin (115200);
  67.   //Setup the pid
  68.   myPID.SetMode(AUTOMATIC);
  69.   myPID.SetSampleTime(1);
  70.   myPID.SetOutputLimits(-150,150);
  71.   //pinMode(13,OUTPUT); digitalWrite(13,HIGH); // disable motor brake
  72.   pinMode(CWCCW,OUTPUT); analogWrite(PWM,255);
  73.  
  74.   myPID1.SetMode(AUTOMATIC);
  75.   myPID1.SetSampleTime(1);
  76.   myPID1.SetOutputLimits(-150,150);
  77.   //pinMode(13,OUTPUT); digitalWrite(13,HIGH); // disable motor brake
  78.   pinMode(CWCCW1,OUTPUT); analogWrite(PWM1,255);
  79.   // step pin interrupts on rising edge
  80.   attachInterrupt(0, countStep      , RISING);  // step0  input on interrupt 1 - pin 2
  81.   attachInterrupt(1, countStep1     , RISING);  // step1  input on interrupt 1 - pin 3
  82. }
  83.  
  84. void loop(){
  85.     input = encoder0Pos;
  86.     setpoint=target0;
  87.     input1 = encoder1Pos;
  88.     setpoint1=target1;
  89.     myPID.Compute();
  90.     myPID1.Compute();
  91.     // interpret received data as an integer (no CR LR): provision for manual testing over the serial port
  92.     if(Serial.available()) target1=Serial.parseInt();
  93.     pwmOut(output);
  94.     pwmOut1(output1);
  95. #ifdef DEBUG
  96.     if(millis() % 2000 == 0) target0=target1=random(1000); // that was for self test with no input from main controller
  97.  
  98.     if( millis() % 1000 ==0 )
  99.     {
  100.         Serial.print(target1);
  101.         Serial.print(":");
  102.         Serial.print(" P=");
  103.         Serial.print(output);
  104.         Serial.print(" P1=");
  105.         Serial.print(output1);
  106.         Serial.print(" 0: ");
  107.         Serial.print(encoder0Pos); // print out current location every second
  108.                 Serial.print(" 1: ");
  109.         Serial.println(encoder1Pos); // print out current location every second
  110.     }
  111. #endif
  112. }
  113.  
  114. void pwmOut(int out) {
  115.   // if(abs(out)<10) digitalWrite(13,LOW); else digitalWrite(13,HIGH); // brake, compensate dead-band
  116.    if(out<0) { digitalWrite(CWCCW,HIGH);}
  117.    else { digitalWrite(CWCCW, LOW); }
  118.    analogWrite(PWM, 255-abs(out) );
  119.   }
  120.  
  121.  
  122. void pwmOut1(int out) {
  123.   // if(abs(out)<10) digitalWrite(13,LOW); else digitalWrite(13,HIGH); // brake, compensate dead-band
  124.    if(out<0) { digitalWrite(CWCCW1,HIGH);}
  125.    else { digitalWrite(CWCCW1, LOW); }
  126.    analogWrite(PWM1, 255-abs(out) );
  127.   }
  128.  
  129.  
  130. const int QEM [16] = {0,-1,1,2,1,0,2,-1,-1,2,0,1,2,1,-1,0};               // Quadrature Encoder Matrix
  131. static unsigned char New, Old;
  132.  
  133.   ISR (PCINT0_vect) // handle pin change interrupt for D8 to D13 here
  134.  {
  135.   Old = New;
  136.   New = (PINB & 1 )+ ((PINB & 16)/8); //
  137.   encoder0Pos+= QEM [Old * 4 + New];
  138. }
  139.  
  140. static unsigned char New2, Old2;
  141. ISR (PCINT2_vect) // handle pin change interrupt for D0 to D7 here
  142.  {
  143.   Old2 = New2;
  144.   New2 =  (PIND & 192)/64; //(PIND & 128 )/128 + ((PIND & 64)/32); //
  145.   encoder1Pos+= QEM [Old2 * 4 + New2];
  146. }
  147.  
  148. void countStep(){ if (PINC&B0000001) target0++;else target0--; } // pin A0 represents direction0
  149.  
  150. void countStep1(){ if (PINC&B0000010) target1++;else target1--; } // pin A1 represents direction1
  151.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement