Hello everyone,
I am working on a project where I need to control the motor speed of a DC motor with an encoder. I am using this motor, an Arduino UNO, an L298N motor driver, and a 12V power supply. The circuit diagram is attached below.
My goal is to input a goal speed in RPM and use the PID control formula to correct the error between the goal speed and the actual speed measured by an accelerometer. I accomplished doing that for all integer speeds, but am struggling to write my code in a way to achieve float speeds. For example, if I want my motor to run at 5.5rpm, the output speed is 6rpm every time.
From my understanding, a float will occur if you set all values run through calculations to have the same number of values after the decimal, but when I do that, I still get an integer. I've attached my code below. If there is any way I can modify my code to achieve float speeds, please let me know. Any and all help is greatly appreciated! Thank you!!
#define ENCA 2 // ORANGE
#define ENCB 3 // YELLOW
#define IN2 8 // GREY
#define IN1 9 // PINK
#define PWM 10 // BLUE
float ipos = 0.0;
float prevT = 0.0;
float eprev = 0.0;
float eintegral = 0.0;
float actualRPM = 0.0;
void setup() {
Serial.begin(9600);
pinMode(ENCA,INPUT);
pinMode(ENCB,INPUT);
attachInterrupt(digitalPinToInterrupt(ENCA),readEncoder,RISING);
pinMode(PWM,OUTPUT);
pinMode(IN1,OUTPUT);
pinMode(IN2,OUTPUT);
}
void loop() {
// set target position
float desiredRPM = 0.00; //CHANGE THIS LINE ONLY
float target = 20.9124*desiredRPM *(prevT/1.0e3); // Calculated based on accelerometer output
// PID constants (set before running device -different for each motor)
float kp = 15.0;
float kd = 0.75;
float ki = 0.75;
// time difference
float currT = millis();
float deltaT = ((currT - prevT))/(1.0e3);
prevT = currT;
float pos = 0.0;
{
pos = ipos;
}
// error
float e = pos - target;
// derivative
float dedt = (e-eprev)/(deltaT);
// integral
eintegral = eintegral + e*deltaT;
// control signal
float u = kp*e + kd*dedt + ki*eintegral;
// motor power
float pwr = fabs(u);
if( pwr > 255){
pwr = 255;
}
// motor direction
float dir = 1;
if(u<0){
dir = -1;
}
// actual RPM
float actualRPM = (ipos*1.0e3)/(20.9124*prevT);
// signal the motor
setMotor(dir,pwr,PWM,IN1,IN2);
// store previous error
eprev = e;
Serial.print(" Speed: ");
Serial.print(actualRPM);
Serial.print(" RPM");
Serial.println();
}
void setMotor(int dir, int pwmVal, int pwm, int in1, int in2){
analogWrite(pwm,pwmVal);
if(dir == 1){
digitalWrite(in1,HIGH);
digitalWrite(in2,LOW);
}
else if(dir == -1){
digitalWrite(in1,LOW);
digitalWrite(in2,HIGH);
}
else{
digitalWrite(in1,LOW);
digitalWrite(in2,LOW);
}
}
void readEncoder(){
int b = digitalRead(ENCB);
if(b > 0){
ipos++;
}
else{
ipos--;
}
}