HI!!
I declared 3 global var, i call it inside diferent task and every execution this var should be updates but not to do it. I have a 8051 under evaluation board. Maybe can be a problem of my small micro? What do u think about this?
Thanks
Maybe can be a problem of my small micro?
Most likely not. I would guess it is a problem with the code, but lacking the code it is hard to verify that.
What do u think about this?
I think that given the scarcity of information, any statement about the nature of the problem can be classified as speculation.
What do u think about this? I have no idea what micro (u) think about this, what I think is that you are trying to run before you have even learned to crawl, that is a surefire way of breaking a leg. learn to crawl, THEN learn to walk, THEN learn to run. 1) read "the bible" and the datasheet for your device a couple of times to familiarize yourself with the contents. 2) work through (I did NOT say 'read') the Keil "getting started guide" 3) do some simple projects (start with 'blinky') gradually adding complexity 4) go back to whatever running it is you are trying to do way too early.
Erik
please post the body of
UpdatePID
not just the calls to it - the function itself.
OK, well!! I explain the code:
-I have a global var type struct. -I have 2 task: WRITE task: here create PID task PID task: here call to the funtion that update the those struct.
This is the piece of code:
PID.H typedef int real; typedef struct { real dState; /* Ultima posicion */ real iState; /* Estado del integrador */ real uMax,uMin; /* Saturacion del actuador */ real Kp; /* Ganancia proporcional */ real Ti,Td; /* Cte, tiempo integral y derivativo */ real Ts,Tt; /* Periodo muestreo, Cte. tiempo tracking */ real Kwindup; /* Cte. antireset windup */ } SPid; real UpdatePID (SPid *pid, real SP, real PV, unsigned int AUTO,real Uman) reentrant{ into PID.c .... pid->iState += error; return pid->iState; } MAIN.C //global var SPid iA void Write (void) _task_ WRITE _priority_ 1{ ..... os_create_task(A); os_wait(K_SIG, WAIT_FOREVER,0); os_clear_signal(WRITE); } void PIDa (void) _task_ A _priority_ 1 { ... Ua = UpdatePID (&iA, SPa, PVa, 1, 4); os_send_signal(WRITE); os_delete_task(B); } the iA var never update
real UpdatePID (SPid *pid, real SP, real PV, unsigned int AUTO,real Uman) reentrant { real P,I,D,v,u,Es,error; if (AUTO){ error = SP - PV; P = pid->Kp*error; if (pid->Ti){ I = pid->iState*(pid->Kp*(pid->Ts/pid->Ti)+ pid->Kwindup); pid->iState = pid->iState + error; }else I=0; if (pid->Td){ D = (pid->Kp*(pid->Td/pid->Ts)*(PV - pid->dState)); pid->dState = PV; }else D=0; v = P + I + D; if (v > pid->uMax) u=pid->uMax; /* Antireset windup */ else if (v < pid->uMin) u=pid->uMin; else u=v; Es = u-v; pid->Kwindup = Es/pid->Tt; }else{ /* Modo Manual */ u = Uman; pid->iState = Uman - (pid->Kp*error); /* Bumpless transfer */ } return u; }
are you sure your gains are not 0? if your
iA
is not updates, maybe
if (pid->Ti)
and
if (pid->Td)
are 0? did you try to debug this code?
it is OK because if i do it:
return pid->iState;
First the value is for example 10, after is 4, but should be 14.
but you said that your iA variable is not updated! so it is updated after all, and the problem seems to be a calculation bug of some kind. I suggest you start debugging.
Always Im debugging my code, i trying everythings and im seeing for webs and datasheet. And i dont know where is the problem. Im exasperate!!!
Thanks.
I see some serious problems with your implementation. I think your integrator is totally wrong - you do not even accumulate the error! it should be something like this:
double UpdatePID(SPid * pid, double error, double position) { double pTerm, dTerm, iTerm; pTerm = pid->pGain * error; // calculate the proportional term // calculate the integral state with limiting pid->iState += error; if (pid->iState > pid->iMax) pid->iState = pid->iMax; else if (pid->iState < pid->iMin) { pid->iState = pid->iMin; iTerm = pid->iGain * iState; } dTerm = pid->dGain * (position - pid->dState); pid->dState = position; return pTerm + iTerm - dTerm; }
If your "real" is "(signed) int" I'm in doubt if you thought about scaling, underflow and overflow of our variables.
sorry, you do accumulate the error but I still think your implementation is not correct.
Thanks for your reply. But i think that the problem is not the implementation because is a simple acumulate. I dont understand why this var not acumulate the old value.
The var values in my debugging are 10, 4 ,... im trying change the data type for unisgned int and is the same.
Let me give you simple example with signed int (-32768 to +32767). In mathematical notation:
SP=3000 (setpint) PV=0 (value read from ADC) Kp=12 P=KP*(SP-PV)=12*(3000-0)=36000
This causes an overflow. The result is treated as a negative number.
I understand your example. But in my code i have this:
First iteraction SP=10 (setpint) PV=0 (value read from ADC) Kp=1 P=KP*(SP-PV)=1*(10-0)=10 Second iteraction SP=10 (setpint) PV=6 (value read from ADC) Kp=1 P=KP*(SP-PV)=1*(10-6)=4 but my pid->iState should be 10+4=14, and it is 4
i dont know why dont save the old value in pid->iState
Are There Anybody that help me with my project?? Maybe i can send the code for see it!!!
It is very important for me!! Thanks
View all questions in Keil forum