I used this code and connection illustrate below for PID speed controller of Encoder DC motor is it correct?
because of this code the motor rotates at speed range 20 to 170 with volt 0 and 6 volt which is not as the code tells to rotate at desired rpm which is 50 rpm!
float kp = 0.05;
float ki = .0005 ;
float kd = 0;
unsigned long t;
unsigned long t_prev = 0;
const byte interruptPinA = 2;
const byte interruptPinB = 3;
volatile long EncoderCount = 0;
const byte PWMPin = 5;
const byte DirPin1 = 9;
const byte DirPin2 = 10;
volatile unsigned long count = 0;
unsigned long count_prev = 0;
float Theta, RPM, RPM_d;
float Theta_prev = 0;
int dt;
float RPM_max = 105;
#define pi 3.1416
float Vmax = 6;
float Vmin = -6;
float V = 0.1;
float e, e_prev = 0, inte, inte_prev = 0;
//**********FUNCTIONS******************
// Void ISR_EncoderA
// Void ISR_EncoderB
// Void Motor Driver Write
// Timer Interrupt
//*************************************
void ISR_EncoderA() {
bool PinB = digitalRead(interruptPinB);
bool PinA = digitalRead(interruptPinA);
if (PinB == LOW) {
if (PinA == HIGH) {
EncoderCount++;
}
else {
EncoderCount--;
}
}
else {
if (PinA == HIGH) {
EncoderCount--;
}
else {
EncoderCount++;
}
}
}
void ISR_EncoderB() {
bool PinB = digitalRead(interruptPinA);
bool PinA = digitalRead(interruptPinB);
if (PinA == LOW) {
if (PinB == HIGH) {
EncoderCount--;
}
else {
EncoderCount++;
}
}
else {
if (PinB == HIGH) {
EncoderCount++;
}
else {
EncoderCount--;
}
}
}
float sign(float x) {
if (x > 0) {
return 1;
} else if (x < 0) {
return -1;
} else {
return 0;
}
}
//***Motor Driver Functions*****
void WriteDriverVoltage(float V, float Vmax) {
int PWMval = int(255 * abs(V) / Vmax);
if (PWMval > 255) {
PWMval = 255;
}
if (V > 0) {
digitalWrite(DirPin1, HIGH);
digitalWrite(DirPin2, LOW);
}
else if (V < 0) {
digitalWrite(DirPin1, LOW);
digitalWrite(DirPin2, HIGH);
}
else {
digitalWrite(DirPin1, LOW);
digitalWrite(DirPin2, LOW);
}
analogWrite(PWMPin, PWMval);
}
void setup() {
Serial.begin(9600);
pinMode(interruptPinA, INPUT_PULLUP);
pinMode(interruptPinB, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPinA), ISR_EncoderA, CHANGE);
attachInterrupt(digitalPinToInterrupt(interruptPinB), ISR_EncoderB, CHANGE);
pinMode(DirPin1, OUTPUT);
pinMode(DirPin2, OUTPUT);
cli();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 3124; //Prescaler = 64
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS11 | 1 << CS10);
TIMSK1 |= (1 << OCIE1A);
sei();
}
void loop() {
if (count > count_prev) {
t = millis();
Theta = EncoderCount / 1050.0;
dt = (t - t_prev);
RPM_d = RPM_max * (sin(2 * pi * 0.005 * t / 1000.0))
* sign(sin(2 * pi * 0.05 * t / 1000.0));
if (t / 1000.0 > 100) {
RPM_d = 0;
}
RPM = (Theta - Theta_prev) / (dt / 1000.0) * 60;
e = RPM_d - RPM;
inte = inte_prev + (dt * (e + e_prev) / 2);
V = kp * e + ki * inte + (kd * (e - e_prev) / dt) ;
if (V > Vmax) {
V = Vmax;
inte = inte_prev;
}
if (V < Vmin) {
V = Vmin;
inte = inte_prev;
}
WriteDriverVoltage(V, Vmax);
Serial.print(RPM_d); Serial.print(" \t");
Serial.print(RPM); Serial.print(" \t ");
Serial.print(V); Serial.print("\t ");
Serial.print(e); Serial.println(" ");
Theta_prev = Theta;
count_prev = count;
t_prev = t;
inte_prev = inte;
e_prev = e;
}
}
ISR(TIMER1_COMPA_vect) {
count++;
Serial.print(count * 0.05); Serial.print(" \t");
}