Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: TextLCD mbed PID
main.cpp
- Committer:
- nicovv44
- Date:
- 2018-10-24
- Revision:
- 15:e1a76426fb6a
- Parent:
- 14:3f7e54ee1211
File content as of revision 15:e1a76426fb6a:
#include "mbed.h"
#include "TextLCD.h"
#include "PID.h"
#define PIDRATE 0.2
//Kc, Ti, Td, interval
PID PIDcontroller1(2.9, 1.0, 0.0, PIDRATE);//frequency PID
PID PIDcontroller2(0.4, 1.0, 0.0, PIDRATE);//amplitude PID
TextLCD lcd(D2, D3, D4, D5, D6, D7); // rs, e, d4-d7
Serial pc(USBTX, USBRX); // tx, rx
PwmOut pwmDC(D9);
PwmOut pwmSY(D13);
DigitalOut relay1(D8);
DigitalOut relay2(D14);
DigitalOut relay3(D11);
DigitalOut relay4(D12);
DigitalIn userButton(USER_BUTTON);
AnalogIn syncPin(A0);
AnalogIn gridPin(A1);
AnalogIn differentialPin(A2);
AnalogIn potarDC(A3);
AnalogIn potarSY(A4);
AnalogIn currentPin(A5);
const float sqrt2 = 1.414213562;
Timeout timeout;
Ticker tickerPWMDC;
Ticker tickerPID;
volatile bool looping = false;
volatile bool synchronized = false;
volatile bool mainLoop = true;
volatile float PID1Output;
volatile float PID2Output;
// ##############################################
// ########## PROTOTYPES ########################
// #############################################################################
void stopLooping(void);
float getVolageRMS(AnalogIn ana_pin);
float getVolageReadedMax(AnalogIn ana_pin);
float getFrequency(AnalogIn ana_pin);
void displayLCD(float syncRMS, float gridRMS, float syncFreq, float gridFreq);
void tickerPWMDCfunction();
void initPID1();
void initPID2();
void tickerPIDfunction();
float getPhaseAngle(AnalogIn voltage_pin, AnalogIn current_pin);
// ##############################################
// ########## MAIN ##############################
// #############################################################################
int main() {
float syncRMS, gridRMS, syncFreq, gridFreq;
relay1 = 1;//Relay off=1, on=0
relay2 = 1;//Relay off=1, on=0
relay3 = 1;//Relay off=1, on=0
relay4 = 0;//Relay off=1, on=0
//initialise PIDcontrollers
initPID1();
initPID2();
while(mainLoop){
pwmDC.period(0.0002f);
pwmDC.write(1-0.00f); //(1-duty)
pwmSY.period(0.0002f);
pwmSY.write(1-0.00f); //(1-duty)
while(userButton==1){;}
pwmDC.write(1-0.900f); //(1-duty)
pwmSY.write(1-0.80f); //(1-duty)
//tickerPWMDC.attach(&tickerPWMDCfunction, 0.1);
//pc.printf("\n\nAccelerating\r\n");
lcd.printf("ACCELERATING");
wait(5);//wait so the motor get steady state
//pwmDC.write(1-0.00f); //(1-duty)
//manual synchronisation
while(!synchronized){
//measure and calculate desired value
syncRMS = getVolageRMS(syncPin);
gridRMS = getVolageRMS(gridPin);
syncFreq = getFrequency(syncPin);
gridFreq = getFrequency(gridPin);
//Update the PID process variable.
PIDcontroller1.setProcessValue(syncFreq);
PIDcontroller2.setProcessValue(syncRMS);
//Interrupt for a correct PID rate
//tickerPID.attach(&tickerPIDfunction, PIDRATE);
//display values on LCD
displayLCD(syncRMS, gridRMS, syncFreq, gridFreq);
//update PID values
PID1Output = PIDcontroller1.compute();
PID2Output = PIDcontroller2.compute();
//drive PWMs with PID values
pwmDC.write(1-PID1Output); //(1-duty)
pwmSY.write(1-PID2Output); //(1-duty)
pc.printf("PID1:%f \t syncFreq:%f \r\n", PID1Output, syncFreq);
pc.printf("PID2:%f \t syncRMS:%f \r\n\n", PID2Output, syncRMS);
wait(PIDRATE);
//voltage and frequency matching
if(abs(syncRMS-gridRMS)<0.5 && abs(syncFreq-gridFreq)<0.1){
//pc.printf("voltage and freqency OK\r\n");
lcd.locate(11,0);//(col,row)
lcd.printf("V&fOK");
while(!synchronized){//phase matching loop
//measure and calculate desired value
syncRMS = getVolageRMS(syncPin);
gridRMS = getVolageRMS(gridPin);
syncFreq = getFrequency(syncPin);
gridFreq = getFrequency(gridPin);
//display values on LCD
displayLCD(syncRMS, gridRMS, syncFreq, gridFreq);
//phase matching
if(getVolageReadedMax(differentialPin) < 0.050){
//pc.printf("SYNCHONIZATION OK\r\n\n");
lcd.locate(12,1);//(col,row)
lcd.printf("SYNC");
relay1 = 0;//Relay off=1, on=0 // to hear the noise
relay2 = 0;//Relay off=1, on=0 // to hear the noise
relay3 = 0;//Relay off=1, on=0 // to hear the noise
relay4 = 1;//Relay off=1, on=0 // to hear the noise
pwmDC.write(1-0.00f); //(1-duty)
pwmSY.write(1-0.00f); //(1-duty)
synchronized = true;
mainLoop = false;
}
}
}
}
while(true)
getPhaseAngle(currentPin, gridPin);
}
}
// ##############################################
// ########## FUNCTIONS #########################
// #############################################################################
// ISR to stop loping
void stopLooping(void) {
looping = false;//looping is volatile bool
}
// #############################################################################
// ISR to update pwmDC with potarDC
void tickerPWMDCfunction(){
float valuePotar1;
float valuePotar2;
valuePotar1 = potarDC.read();
pwmDC.write(1-valuePotar1);
valuePotar2 = potarSY.read();
pwmSY.write(1-valuePotar2);
//lcd.locate(12,0);//(col,row)
//lcd.printf("%f",valuePotar);
}
// #############################################################################
// ISR to update PID
void tickerPIDfunction(){
PID1Output = PIDcontroller1.compute();
pwmDC.write(1-PID1Output); //(1-duty)
pc.printf("PID1:%f\r\n\n", PID1Output);
}
// #############################################################################
void initPID1(){
//Input
PIDcontroller1.setInputLimits(0.0, 100.0);
//Pwm output from 0.0 to 1.0
PIDcontroller1.setOutputLimits(0.0, 1.0);
//If there's a bias.
PIDcontroller1.setBias(0.70);
PIDcontroller1.setMode(true);
//We want the process variable to be 50Hz
PIDcontroller1.setSetPoint(50);//50Hz
}
// #############################################################################
void initPID2(){
//Input
PIDcontroller2.setInputLimits(0.0, 25.0);
//Pwm output from 0.0 to 1.0
PIDcontroller2.setOutputLimits(0.0, 1.0);
//If there's a bias.
PIDcontroller2.setBias(0.70);
PIDcontroller2.setMode(true);
//We want the process variable to be 50Hz
PIDcontroller2.setSetPoint(getVolageRMS(gridPin));
}
// #############################################################################
float getVolageRMS(AnalogIn ana_pin){
float v1;//readed voltage
float v1Max = 0;//max readed voltage
float VRMS; //RMS voltage
looping = true;
timeout.attach(callback(&stopLooping), 0.020);//T=20ms because f=50Hz
while(looping){
v1 = ana_pin.read()*3.3;
if(v1 > v1Max){
v1Max = v1;
}
}
VRMS = (v1Max+0.685)*9.32/sqrt2;
//pc.printf("VRMS: %f\r\n",VRMS);
return VRMS;
}
// #############################################################################
float getVolageReadedMax(AnalogIn ana_pin){
float v1;//readed voltage
float v1Max = 0;//max readed voltage
looping = true;
timeout.attach(callback(&stopLooping), 0.025);//T=25>20ms because f=50Hz
while(looping){
v1 = ana_pin.read()*3.3;
if(v1 > v1Max){
v1Max = v1;
}
}
return v1Max;
}
// #############################################################################
float getFrequency(AnalogIn ana_pin){
float freq; //frequency
float maxReadedVoltage;//maximum voltage readed by the ADC
float readedVoltage;//readed voltage
int nbrRisingEdge=0;// number of rising edge detected
float T;//Periode
Timer timer;
maxReadedVoltage = getVolageReadedMax(ana_pin);
//pc.printf("maxReadedVoltage: %f\r\n",maxReadedVoltage);
bool aboveLine = true;
bool allowedClicTimer = false;
looping = true;
timeout.attach(callback(&stopLooping), 1);//try to find rising edges during 1sec max
while(nbrRisingEdge<2 and looping){
readedVoltage = ana_pin.read()*3.3;
if(readedVoltage<(maxReadedVoltage/2)){//rising edge detection ready
aboveLine = false;
}
if((maxReadedVoltage/2)<readedVoltage && aboveLine==false){//rising edge detected
allowedClicTimer = true;
aboveLine = true;
}
if((maxReadedVoltage*2/3)<readedVoltage && allowedClicTimer==true){//rising edge detected
allowedClicTimer = false;
if(nbrRisingEdge==0)
timer.start();
if(nbrRisingEdge==1)
timer.stop();
nbrRisingEdge++;
}
}
if(nbrRisingEdge!=2){
lcd.locate(13,1);
lcd.printf("f!%d",nbrRisingEdge);
}
T = timer.read();
freq = 1/T;
//pc.printf("T: %f\r\n",T);
//pc.printf("freq: %f\r\n\n",freq);
if(looping==false)
freq = 0;
return freq;
}
// #############################################################################
void displayLCD(float syncRMS, float gridRMS, float syncFreq, float gridFreq){
lcd.locate(0,0);//(col,row)
lcd.printf(" ");
lcd.locate(0,1);//(col,row)
lcd.printf(" ");
lcd.locate(0,0);//(col,row)
lcd.printf("G:%3.1f@%3.1f", gridRMS, gridFreq);
lcd.locate(0,1);//(col,row)
lcd.printf("S:%3.1f@%3.1f", syncRMS, syncFreq);
}
// #############################################################################
float getPhaseAngle(AnalogIn voltage_pin, AnalogIn current_pin){
bool searchingInstant = true;
Timer timer1;
float voltageValue;
//float maxReadedVoltageVoltage, maxReadedVoltageCurrent;//maximum voltage readed by the ADC
//maxReadedVoltageVoltage = getVolageReadedMax(voltage_pin);
//maxReadedVoltageCurrent= getVolageReadedMax(current_pin);
//pc.printf("maxReadedVoltageVoltage: %f \t maxReadedVoltageCurrent: %f\r\n", maxReadedVoltageVoltage, maxReadedVoltageCurrent);
while(searchingInstant){
voltageValue = voltage_pin.read();
//pc.printf("voltageValue voltage:%f\n\r",voltageValue);
if(voltageValue < 0.50){
timer1.start();
searchingInstant = false;
}
}
searchingInstant = true;
while(searchingInstant){
voltageValue = current_pin.read();
//pc.printf("voltageValue current:%f\n\r",voltageValue);
if(voltageValue < 0.050){
timer1.stop();
searchingInstant = false;
}
}
pc.printf("phaseAngle:%f\n\r",timer1.read()*180/0.020);
return 0;
}