Hi everyone, I'm trying to use PI (Proportional-Integral) control in order to control the velocity of a DC motor. I'm using an Arduino UNO with the Arduino motor shield connected to the DC motor. The motor has a quadrature encoder which emits 64 pulses per revolution. The user can change the speed (RPM) of the motor via the serial port.
The problem I'm facing is that the system ignores the speed commands I send to it and continues to alter the speed of the DC motor itself randomly. The code I've written is below. Could you take a look at it and help me in finding the problem?
#include "TimerOne.h"
int pwm = 0;
const int motorBrake = 8;
const int motorDirection = 13;
const int pwmPin = 11;
const int encA = 2;
const int encB = 3;
volatile double count = 0;
volatile double Setpoint = 0;
unsigned long lastTime;
double Input, Output = 0;
double errSum, lastErr = 0;
double kp, ki;
void setup()
{
//Setup Serial port
Serial.begin(9600);
//Setup Motor
pinMode(motorBrake, OUTPUT);
pinMode(motorDirection, OUTPUT);
//Setup Encoder
pinMode(encA, INPUT);
pinMode(encB, INPUT);
attachInterrupt(0, encoderInt, CHANGE);
attachInterrupt(1, encoderInt, CHANGE);
//Timer1 setup
Timer1.initialize(10000);
Timer1.attachInterrupt(rpmCalculate);
digitalWrite(motorDirection, HIGH);
digitalWrite(motorBrake, LOW);
SetTunings(0.6, 0.8);//Kp and ki values.
}
void loop()
{
if(Serial.available())
{
Input = Serial.parseInt();
}
Compute();
if(Output < 5000)
{
pwm = map(Output, 100, 5000, 1, 255);//The Max RPM is 5000, measured before.
}
else
{
pwm = 255;
}
analogWrite(pwmPin, pwm);
Serial.println(Setpoint);
//delay(3000);
}
void Compute()
{
/*How long since we last calculated*/
unsigned long now = millis();
double timeChange = (double)(now - lastTime);
/*Compute all the working error variables*/
double error = Input - Setpoint;
errSum += (error * timeChange);
/*Compute PID Output*/
Output = (kp * error) + (ki * errSum);
/*Remember some variables for next time*/
lastErr = error;
lastTime = now;
}
void SetTunings(double Kp, double Ki)
{
kp = Kp;
ki = Ki;
}
void encoderInt()
{
count++;
}
void rpmCalculate()
{
Setpoint = ((count/64)*60)/0.01;
count = 0;
}
The problem I'm facing is that the system ignores the speed commands I send to it and continues to alter the speed of the DC motor itself randomly. The code I've written is below. Could you take a look at it and help me in finding the problem?
#include "TimerOne.h"
int pwm = 0;
const int motorBrake = 8;
const int motorDirection = 13;
const int pwmPin = 11;
const int encA = 2;
const int encB = 3;
volatile double count = 0;
volatile double Setpoint = 0;
unsigned long lastTime;
double Input, Output = 0;
double errSum, lastErr = 0;
double kp, ki;
void setup()
{
//Setup Serial port
Serial.begin(9600);
//Setup Motor
pinMode(motorBrake, OUTPUT);
pinMode(motorDirection, OUTPUT);
//Setup Encoder
pinMode(encA, INPUT);
pinMode(encB, INPUT);
attachInterrupt(0, encoderInt, CHANGE);
attachInterrupt(1, encoderInt, CHANGE);
//Timer1 setup
Timer1.initialize(10000);
Timer1.attachInterrupt(rpmCalculate);
digitalWrite(motorDirection, HIGH);
digitalWrite(motorBrake, LOW);
SetTunings(0.6, 0.8);//Kp and ki values.
}
void loop()
{
if(Serial.available())
{
Input = Serial.parseInt();
}
Compute();
if(Output < 5000)
{
pwm = map(Output, 100, 5000, 1, 255);//The Max RPM is 5000, measured before.
}
else
{
pwm = 255;
}
analogWrite(pwmPin, pwm);
Serial.println(Setpoint);
//delay(3000);
}
void Compute()
{
/*How long since we last calculated*/
unsigned long now = millis();
double timeChange = (double)(now - lastTime);
/*Compute all the working error variables*/
double error = Input - Setpoint;
errSum += (error * timeChange);
/*Compute PID Output*/
Output = (kp * error) + (ki * errSum);
/*Remember some variables for next time*/
lastErr = error;
lastTime = now;
}
void SetTunings(double Kp, double Ki)
{
kp = Kp;
ki = Ki;
}
void encoderInt()
{
count++;
}
void rpmCalculate()
{
Setpoint = ((count/64)*60)/0.01;
count = 0;
}