liba 0.1.15

An algorithm library based on C/C++
Documentation
/*!
 @file pid.h
 @brief proportional integral derivative controller
 @details
 A proportional integral derivative controller (PID controller or three-term controller) is
 a control loop mechanism employing feedback that is widely used in industrial control systems
 and a variety of other applications requiring continuously modulated control.
 \f[
  u(t) = K_p\left[e(t)+\frac{1}{T_i}\int{e(t)}\text{dt}+T_d\frac{\text{d}e(t)}{\text{d}t}\right]
 \f]
 \f[
  u(k) = K_p\left[e(k)+\frac{T}{T_i}\sum^k_{i=0}e(i)+\frac{T_d}{T}[e(k)-e(k-1)]\right]
 \f]
 - positional PID controller
 \f{aligned}{
  u(k) &= K_p e(k) + q\sum^k_{i=0} K_i e(i) + K_d [e(k)-e(k-1)] \\
       &= (K_p+K_d) e(k) + q\sum^k_{i=0}K_i e(i) + (-K_d) e(k-1) \\
       &\begin{cases}q=0&|\sum\limits^{k-1}_{i=0}K_ie(i)|>E \bigvee
       [\sum\limits^{k-1}_{i=0}K_ie(i)]K_ke(k)>0 \\ q=1\end{cases}
 \f}
 - incremental PID controller
 \f{aligned}{
  \Delta u(k) &= K_p [e(k)-e(k-1)] + K_i e(k) + K_d [e(k)+e(k-2)-2e(k-1)] \\
              &= (K_p+K_i+K_d) e(k) + (-K_p-2K_i) e(k-1) + K_d e(k-2)
 \f}
 https://en.wikipedia.org/wiki/PID_controller
*/

#ifndef LIBA_PID_H
#define LIBA_PID_H

#include "a.h"

/*!
 @ingroup liba
 @addtogroup a_pid proportional integral derivative controller
 @{
*/

typedef struct a_pid a_pid;

#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */

/*!
 @brief initialize for PID controller
 @param[in,out] ctx points to an instance of PID controller
*/
#define a_pid_init(ctx) a_pid_zero(ctx)

/*!
 @brief set proportional integral derivative constant for PID controller
 @param[in,out] ctx points to an instance of PID controller
 @param[in] kp proportional constant
 @param[in] ki integral constant
 @param[in] kd derivative constant
*/
A_EXTERN void a_pid_set_kpid(a_pid *ctx, a_float kp, a_float ki, a_float kd);

/*!
 @brief calculate for PID controller
 @param[in,out] ctx points to an instance of PID controller
 @param[in] set setpoint value
 @param[in] fdb feedback value
 @return setpoint value
*/
A_EXTERN a_float a_pid_run(a_pid *ctx, a_float set, a_float fdb);

/*!
 @brief calculate for positional PID controller
 @param[in,out] ctx points to an instance of PID controller
 @param[in] set setpoint value
 @param[in] fdb feedback value
 @return output value
*/
A_EXTERN a_float a_pid_pos(a_pid *ctx, a_float set, a_float fdb);

/*!
 @brief calculate for incremental PID controller
 @param[in,out] ctx points to an instance of PID controller
 @param[in] set setpoint value
 @param[in] fdb feedback value
 @return output value
*/
A_EXTERN a_float a_pid_inc(a_pid *ctx, a_float set, a_float fdb);

/*!
 @brief zeroing for PID controller
 @param[in,out] ctx points to an instance of PID controller
*/
A_EXTERN void a_pid_zero(a_pid *ctx);

#if defined(__cplusplus)
} /* extern "C" */
namespace a
{
typedef struct a_pid pid;
} /* namespace a */
#endif /* __cplusplus */

/*!
 @brief instance structure for PID controller
*/
struct a_pid
{
    a_float kp; //!< proportional constant
    a_float ki; //!< integral constant
    a_float kd; //!< derivative constant
    a_float summax; //!< maximum integral output
    a_float summin; //!< minimum integral output
    a_float sum; //!< controller integral output
    a_float outmax; //!< maximum final output
    a_float outmin; //!< minimum final output
    a_float out; //!< controller final output
    a_float var; //!< cache variable
    a_float fdb; //!< cache feedback
    a_float err; //!< cache error
#if defined(__cplusplus)
    A_INLINE void init() { a_pid_init(this); }
    A_INLINE void set_kpid(a_float kp_, a_float ki_, a_float kd_)
    {
        a_pid_set_kpid(this, kp_, ki_, kd_);
    }
    A_INLINE a_float run(a_float set, a_float fdb_)
    {
        return a_pid_run(this, set, fdb_);
    }
    A_INLINE a_float pos(a_float set, a_float fdb_)
    {
        return a_pid_pos(this, set, fdb_);
    }
    A_INLINE a_float inc(a_float set, a_float fdb_)
    {
        return a_pid_inc(this, set, fdb_);
    }
    A_INLINE void zero() { a_pid_zero(this); }
#endif /* __cplusplus */
};

/*! @} a_pid */

#endif /* a/pid.h */