#include "../cfunctions.h"
#define DigOutPin p[0]
#define AnaInPin p[1]
#define dtAddress p[2]
#define ticks p[3]
#define measured_value p[4]
#define setpointAddress p[5]
#define KpAddress p[6]
#define KiAddress p[7]
#define KdAddress p[8]
#define error p[9]
#define previous_error p[10]
#define derivative p[11]
#define integral p[12]
#define output p[13]
#define display_previous_error p[14]
#define biasAddress p[15]
#define useintegral p[16]
#define directcomponent p[17]
#define integralcomponent p[18]
#define derivativecomponent p[19]
#define lastsetpoint p[20]
void msec(void){
union ftype{
unsigned long a;
float b;
}f_error, f_previous_error, f_derivative, f_integral, f_measured_value, f_output, f_directcomponent, f_integralcomponent, f_derivativecomponent, f_lastsetpoint;
unsigned int * p;
float * kp;
float * ki;
float * kd;
float * bias;
float * setpoint;
float dtsecs,abserror;
unsigned int l,j,t,b[14];
unsigned int * dt;
p=(void *)(unsigned int)StartOfCFuncRam; //get a pointer to the permanent memory area
kp=(float *)(unsigned int)KpAddress; //Get a pointer to the Basic variable Kp
ki=(float *)(unsigned int)KiAddress; //Get a pointer to the Basic variable Ki
kd=(float *)(unsigned int)KdAddress; //Get a pointer to the Basic variable Kd
setpoint=(void *)(unsigned int)setpointAddress; //Get a pointer to the Basic variable setpoint
dt=(void *)(unsigned int)dtAddress; //Get a pointer to the Basic variable dt
bias=(float *)(unsigned int)biasAddress; //Get a pointer to the Basic variable bias
ticks++; //increment p[1]
f_output.a=output; //restore the saved value of the output
if(ticks>=FloatToInt(f_output.b)){ //has the required output time expired?
PinSetBit(DigOutPin, LATCLR); //Turn off the output
}
if(ticks>=*dt){ //check whether it is time to execute main PID loop
dtsecs=FDiv(IntToFloat(*dt),LoadFloat(0x447A0000)); //divide by 1000 to get dt in seconds
f_integral.a=integral;
f_previous_error.a=previous_error;
f_lastsetpoint.a=lastsetpoint;
if(FCmp(f_lastsetpoint.b,*setpoint)!=0)useintegral=0; //disable integral after change of setpoint
display_previous_error=previous_error; // just used to see error and previous error in Basic
ticks=0;
for(l = 0; l < 14; l++) { //read in the ADC, take 14 samples and use middle 10, code copied from MM firmware
b
= ExtInp(AnaInPin); // get the value
for(j = l; j > 0; j--) { // and sort into position
if(b[j - 1] < b[j]) {
t = b[j - 1];
b[j - 1] = b[j];
b[j] = t;
}
else
break;
}
}
// we then discard the top 2 samples and the bottom 2 samples and add up the remainder
for(j = 0, l = 2; l < 12; l++) j += b
;
f_measured_value.b=FDiv(IntToFloat(j),LoadFloat(0x41200000)); //Get the new input value by dividing by 10
measured_value=f_measured_value.a; //save it for inspection in Basic
// error = setpoint - measured_value
f_error.b=FSub(*setpoint,f_measured_value.b); //calculate the error from the setpoint
error=f_error.a; //save it for inspection in Basic
abserror=f_error.b;
if(FCmp(f_error.b,LoadFloat(0))==-1){ //error is -ve
abserror=FSub(LoadFloat(0),f_error.b);
}
if(FCmp(abserror,FDiv(*setpoint,LoadFloat(0x42480000)))==-1)useintegral=1; //within 2% of target
// integral = integral + error*dt
f_integral.b=FAdd(f_integral.b,FMul(f_error.b,dtsecs)); //Calculate the integral of the error
if(useintegral)integral=f_integral.a; //save it for inspection in Basic
else { //not yet in controlled region so zero
integral=0;
f_integral.a=0;
}
// derivative = (error - previous_error)/dt
f_derivative.b=FDiv(FSub(f_error.b,f_previous_error.b),dtsecs); //Calculate the derivative of the error
derivative=f_derivative.a;
// output = Kp*error + Ki*integral + Kd*derivative
f_directcomponent.b=FMul(*kp,f_error.b);
f_integralcomponent.b=FMul(*ki,f_integral.b);
f_derivativecomponent.b=FMul(*kd,f_derivative.b);
f_output.b=FAdd(*bias,FAdd(f_directcomponent.b, FAdd(f_integralcomponent.b, f_derivativecomponent.b)));
directcomponent = f_directcomponent.a;
integralcomponent = f_integralcomponent.a;
derivativecomponent = f_derivativecomponent.a;
// Scale output 0-dt
if(FCmp(f_output.b,IntToFloat(*dt)) >= 0) {
f_output.b=IntToFloat(*dt);
}
if(FCmp(LoadFloat(0),f_output.b)>=0){
f_output.a=0;
}
output=f_output.a;
if(output)PinSetBit(DigOutPin, LATSET);
// previous_error = error
previous_error=f_error.a;
}
}
long long main(long long *func, long long *MyAddress, long long *digoutpin, long long *anainpin,long long *rate, float *setpoint, float *Kp, float *Kd, float *Ki, float *bias ){
int Offset;
unsigned int * p; //Set up a pointer which will be used to access the allocated memory
unsigned int * getsetpoint;
//If already Open just use the memory
if (StartOfCFuncRam){
p=(void *)(unsigned int)StartOfCFuncRam;
}else{
//Get some persistent memory
p = GetMemory(256);
//Save the address for other functions
StartOfCFuncRam=(unsigned int)p;
}
//Clean up if Close Request
if (*func==1){
CFuncmSec=0;
FreeMemory(p);
StartOfCFuncRam=0;
ExtCfg(DigOutPin,EXT_NOT_CONFIG,0);
ExtCfg(AnaInPin,EXT_NOT_CONFIG,0);
return 0;
}
if ((unsigned int)&msec < (unsigned int)&main){ //calculate the address of the msec routine
Offset=*MyAddress - ((unsigned int)&main - (unsigned int)&msec);
}else{
Offset=*MyAddress + ((unsigned int)&msec - (unsigned int)&main);
}
DigOutPin=*digoutpin; //Set up the I/O pins
AnaInPin=*anainpin;
ExtCfg(DigOutPin,EXT_DIG_OUT,0);
ExtCfg(AnaInPin,EXT_ANA_IN,0);
previous_error=0; //Initialise the PID variables
integral=0;
ticks=0;
output=0;
useintegral=0;
setpointAddress=(unsigned int)setpoint; //store the addresses of the input variables
getsetpoint=(void *)(unsigned int)setpointAddress; //Get a pointer to the Basic variable setpoint
KpAddress = (unsigned int)Kp; //etc.
KiAddress = (unsigned int)Ki;
KdAddress = (unsigned int)Kd;
dtAddress=(unsigned int)rate;
biasAddress=(unsigned int)bias;
lastsetpoint = *getsetpoint;
//Set the CFuncmSec vector to point to our msec function
CFuncmSec=Offset;
msec(); //run this once to avoid the compiler "optimising" it away completely
return (unsigned int)p;
}