Hi,
I have been trying to generate a PWM 5khz frequency whose duty cycle varies.
I my project I'm trying to control my motor using Arduino. Where I sense the angle, 3-phase current using sensors and get them as inputs.
Now, with the help of angle I found the speed then using PI- controller in Arduino I compared ref speed to the actual speed and give the output error to the PI controller. The output of this controller is the reference current which I then compare with all three current inputs and the error would be fed to another PI controller.
Now, these 3 PI controllers gives 3 different PWM duty cycle values( from 0 to 1 ).
Now, I need these duty cycle to work as a PWM signal with 5khz frequency) or in other words I need to compare these values with a 5khz repeating sequence.
I have attached my code below for the reference.
#include <PID_v2.h>
#define COUNT_PER_REV 600
#define ENCODER_A 2
#define ENCODER_B 3
boolean Dir = true;
volatile long pulse_count = 0;
int a = 90;
int b = 30;
int c = 60;
int val = 0;
int num = 0;
int count = 1;
int potPin = 0;
int Position = 0;
int interval = 1000;
int refcurrent = 0;
int sensitivity = 100;
int offsetVoltage = 1650;
int rotationalAngle = 0;
const int Ia = A0;
const int Ib = A2;
const int Ic = A3;
const int IS = A4;
long currentMillis = 0;
long previousMillis = 0;
float rpm = 0;
float erroRS = 0;
float erroR1 = 0;
float erroR2 = 0;
float erroR3 = 0;
float refrpm = 0;
float avgcurrent1 = 0;
float avgcurrent2 = 0;
float avgcurrent3 = 0;
float avgcurrentS = 0;
float prevcurrent1 = 0;
float prevcurrent2 = 0;
float prevcurrent3 = 0;
float prevcurrentS = 0;
double adcValue1 = 0.0;
double adcValue2 = 0.0;
double adcValue3 = 0.0;
double adcValueS = 0.0;
double duty_cycle1 = 0.0;
double duty_cycle2 = 0.0;
double duty_cycle3 = 0.0;
double adcvoltage1 = 0.0;
double adcvoltage2 = 0.0;
double adcvoltage3 = 0.0;
double adcvoltageS = 0.0;
double currentValue1 = 0.0;
double currentValue2 = 0.0;
double currentValue3 = 0.0;
double currentValueS = 0.0;
double Kp = 0.000541, Ki = 0.042301, Kd = 0;
double kp = 0.001221, ki = 0.034444, kd = 0;
PID_v2 mySDPID(Kp, Ki, Kd, PID::Direct);
PID_v2 myI1PID(kp, ki, kd, PID::Direct);
PID_v2 myI2PID(kp, ki, kd, PID::Direct);
PID_v2 myI3PID(kp, ki, kd, PID::Direct);
void setup()
{
Serial.begin(9600);
pinMode(5, OUTPUT);
pinMode(ENCODER_A , INPUT_PULLUP);
pinMode(ENCODER_B , INPUT_PULLUP);
pinMode(Ia,INPUT);
pinMode(Ib,INPUT);
pinMode(Ic,INPUT);
pinMode(IS,INPUT);
pinMode(9, OUTPUT);
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);
attachInterrupt(digitalPinToInterrupt(ENCODER_A), pulse, RISING);
attachInterrupt(digitalPinToInterrupt(ENCODER_A), encoderA, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENCODER_B), encoderB, CHANGE);
}
void loop()
{
mySDPID.Start(erroRS,0,0);
myI1PID.Start(erroR1,0,0);
myI2PID.Start(erroR2,0,0);
myI3PID.Start(erroR3,0,0);
currentMillis = millis();
refrpm = (analogRead(potPin)*500)/1023;
previousMillis = currentMillis;
rpm = float(pulse_count * 60 / COUNT_PER_REV);
rotationalAngle = (360 * Position) / (600 * 4);
num = rotationalAngle % 90;
adcValue1 = analogRead(Ia);
adcValue2 = analogRead(Ib);
adcValue3 = analogRead(Ic);
adcValueS = analogRead(IS);
adcvoltage1 = ((adcValue1/1023)*3300);
adcvoltage2 = ((adcValue2/1023)*3300);
adcvoltage3 = ((adcValue3/1023)*3300);
adcvoltageS = ((adcValueS/1023)*3300);
currentValue1 = ((adcvoltage1 - offsetVoltage)/ sensitivity);
currentValue2 = ((adcvoltage2 - offsetVoltage)/ sensitivity);
currentValue3 = ((adcvoltage3 - offsetVoltage)/ sensitivity);
currentValueS = ((adcvoltageS - offsetVoltage)/ sensitivity);
erroR1 = (refcurrent - currentValue1);
erroR2 = (refcurrent - currentValue2);
erroR3 = (refcurrent - currentValue3);
if (num == 90 || num == 0)
{
count = 1;
}
else
{
count++;
}
avgcurrent1 = (prevcurrent1 + currentValue1)/count;
avgcurrent2 = (prevcurrent2 + currentValue2)/count;
avgcurrent3 = (prevcurrent3 + currentValue3)/count;
avgcurrentS = (prevcurrentS + currentValueS)/count;
if (num == (a))
{
prevcurrent1 = 0;
prevcurrent2 = 0;
prevcurrent3 = 0;
prevcurrentS = 0;
}
else
{
prevcurrent1 = avgcurrent1*count;
prevcurrent2 = avgcurrent2*count;
prevcurrent3 = avgcurrent3*count;
prevcurrentS = avgcurrentS*count;
}
pulse_count = 0;
if(refrpm > rpm)
{
if((refrpm - rpm)>10)
{
erroRS = 10;
}
else
{
erroRS = (refrpm - rpm);
}
}
else
{
if((rpm - refrpm) > 10)
{
erroRS = -10;
}
else
{
erroRS = rpm - refrpm;
}
}
if(erroR1>(0.02*refcurrent))
{
erroR1=0.02*refcurrent;
}
if(erroR2>(0.02*refcurrent))
{
erroR2=0.02*refcurrent;
}
if(erroR3>(0.02*refcurrent))
{
erroR3=0.02*refcurrent;
}
mySDPID.SetMode(AUTOMATIC);
myI1PID.SetMode(AUTOMATIC);
myI2PID.SetMode(AUTOMATIC);
myI3PID.SetMode(AUTOMATIC);
mySDPID.SetOutputLimits(0,1);
myI1PID.SetOutputLimits(0,1);
myI2PID.SetOutputLimits(0,1);
myI3PID.SetOutputLimits(0,1);
refcurrent = mySDPID.Run(erroRS);
duty_cycle1 = myI1PID.Run(erroR1);
duty_cycle2 = myI2PID.Run(erroR2);
duty_cycle3 = myI3PID.Run(erroR3);
}
void encoderA()
{
if(digitalRead(ENCODER_A) != digitalRead(ENCODER_B))
{
Position++;
}
else
{
Position--;
}
}
void encoderB()
{
if (digitalRead(ENCODER_A) == digitalRead(ENCODER_B))
{
Position++;
}
else
{
Position--;
}
}
void pulse()
{
val = digitalRead(ENCODER_B);
if(val == LOW)
{
Dir = false;
}
else
{
Dir = true;
}
if (Dir)
{
pulse_count++;
}
else
{
pulse_count--;
}
}