1 #include "pid_expert.h"
2 #if A_PREREQ_GNUC(3, 0) || __has_warning("-Wfloat-equal")
3 #pragma GCC diagnostic ignored "-Wfloat-equal"
4 #endif /* -Wfloat-equal */
6 void a_pid_expert_kpid(a_pid_expert
*ctx
, a_float kp
, a_float ki
, a_float kd
)
8 a_pid_kpid(&ctx
->pid
, kp
, ki
, kd
);
11 a_float
a_pid_expert_iter(a_pid_expert
*ctx
, a_float set
, a_float fdb
)
14 a_float
const err
= set
- fdb
;
15 a_float
const abs
= A_ABS(err
);
16 a_float
const var
= ctx
->pid
.fdb
- fdb
;
17 a_float
const ec
= err
- ctx
->pid
.err
;
24 else if (err
> ctx
->max1
)
30 if (err
* ec
> 0 || ec
== 0)
32 out
= ctx
->pid
.kp
* ec
+ ctx
->pid
.ki
* err
+ ctx
->pid
.kd
* (var
- ctx
->pid
.var
);
33 if (abs
> ctx
->max2
) { out
*= ctx
->gain
; }
35 else if (ec
* ctx
->ec
< 0 && err
!= 0)
37 out
= ctx
->pid
.kp
* ctx
->pid
.err
;
38 if (abs
> ctx
->max2
) { out
*= ctx
->gain
; }
39 else { out
*= ctx
->loss
; }
42 if (abs
< ctx
->epsilon
) { out
= ctx
->pid
.kp
* ec
+ ctx
->pid
.ki
* err
; }
45 ctx
->pid
.out
= A_SAT(out
, ctx
->pid
.outmin
, ctx
->pid
.outmax
);
53 void a_pid_expert_zero(a_pid_expert
*ctx
)
55 a_pid_zero(&ctx
->pid
);