flexPTP 1.0
An IEEE 1588 PTP implementation designed for microcontrollers
Loading...
Searching...
No Matches
pid_controller.c
Go to the documentation of this file.
1/* (C) AndrĂ¡s Wiesner, 2021 */
2
3#include "pid_controller.h"
4
5#include <math.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include <flexptp_options.h>
10
11// ----------------------------------
12
13#ifndef K_P
14#define K_P (0.5 * 0.476)
15#endif
16
17#ifndef K_I
18#define K_I (0)
19#endif
20
21#ifndef K_D
22#define K_D (3.0)
23#endif
24
25// ----------------------------------
26
27static bool logInternals = false;
28static bool firstRun = true;
29
30// ----------------------------------
31
32// static float P_FACTOR = 0.5 * 0.476;
33// static float D_FACTOR = 2.0 * 0.476;
34
35// PID servo coefficients
36static float Kp = K_P;
37static float Ki = K_I;
38static float Kd = K_D;
39
40// ----------------------------------
41
42static double rd_prev_ppb;
43static double integrator_value;
44
45// ----------------------------------
46
47#ifdef CLI_REG_CMD
48
49#ifndef CMD_FUNCTION
50#error "No CMD_FUNCTION macro has been defined, cannot register CLI functions!"
51#endif
52
53static CMD_FUNCTION(CB_params) {
54 // set if parameters passed after command
55 if (argc >= 3) {
56 Kp = atof(ppArgs[0]);
57 Ki = atof(ppArgs[1]);
58 Kd = atof(ppArgs[2]);
59 }
60
61 MSG("> PTP params: K_p = %.3f, K_i = %.3f, K_d = %.3f\n", Kp, Ki, Kd);
62
63 return 0;
64}
65
66static CMD_FUNCTION(CB_logInternals) {
67 if (argc >= 1) {
68 int en = ONOFF(ppArgs[0]);
69 if (en >= 0) {
70 if (en && !logInternals) {
71 MSG("\nSyncIntv. [ns] | dt [ns] | gamma [ppb]\n\n");
72 }
73 logInternals = en;
74 return 0;
75 } else {
76 return -1;
77 }
78 } else {
79 return -1;
80 }
81}
82
83static struct {
84 int params;
85 int internals;
86} sCliCmdIdx = {0};
87
88#ifdef CLI_REG_CMD
89static void pid_ctrl_register_cli_commands() {
90 sCliCmdIdx.params = CLI_REG_CMD("ptp servo params [Kp Ki Kd] \t\t\tSet or query Kp, Ki, and Kd servo parameters", 3, 0, CB_params);
91 sCliCmdIdx.internals = CLI_REG_CMD("ptp servo log internals {on|off} \t\t\tEnable or disable logging of servo internals", 4, 1, CB_logInternals);
92}
93#endif
94
95#ifdef CLI_REMOVE_CMD
96static void pid_ctrl_remove_cli_commands() {
97 CLI_REMOVE_CMD(sCliCmdIdx.params);
98 CLI_REMOVE_CMD(sCliCmdIdx.internals);
99}
100#endif
101
102#endif // CLI_REG_CMD
103
106
107#ifdef CLI_REG_CMD
108 pid_ctrl_register_cli_commands();
109#endif // CLI_REG_CMD
110}
111
113#ifdef CLI_REMOVE_CMD
114 pid_ctrl_remove_cli_commands();
115#endif // CLI_REMOVE_CMD
116}
117
119 firstRun = true;
121}
122
123float pid_ctrl_run(int32_t dt, PtpServoAuxInput *pAux) {
124 if (firstRun) {
125 firstRun = false;
126 rd_prev_ppb = dt;
128 return 0;
129 }
130
131 // calculate relative time error
132 double rd_ppb = ((double)dt) / (pAux->measSyncPeriodNs) * 1E+09;
133
134 // calculate difference
135 double rd_D_ppb = Kd * (rd_ppb - rd_prev_ppb);
136
137 // calculate output (run the PD controller)
138 double corr_ppb = -(Kp * (rd_ppb + rd_D_ppb) + integrator_value) * exp((pAux->measSyncPeriodNs * 1E-09) - 1.0);
139
140 // update integrator
141 integrator_value += Ki * rd_ppb;
142
143 // store error value (time difference) for use in next iteration
144 rd_prev_ppb = rd_ppb;
145
146 CLILOG(logInternals, "%d %f\n", dt, rd_ppb);
147
148 return corr_ppb;
149}
150
151// ----------------------------------
#define CLI_REG_CMD(cmd_hintline, n_cmd, n_min_arg, cb)
#define CLILOG(en,...)
#define ONOFF(str)
static float Kp
Proportional factor.
#define K_D
Default Kd parameter value.
static double rd_prev_ppb
relative frequency error measured in previous iteration
static bool logInternals
Decides if servo's internal operation shoud be reported or not.
void pid_ctrl_deinit()
void pid_ctrl_init()
static float Ki
Integrating factor.
#define K_I
Default Ki parameters value.
static bool firstRun
Indicates if first run did not occur yet.
static double integrator_value
value stored in the integrator
static float Kd
Differentiating factor.
void pid_ctrl_reset()
float pid_ctrl_run(int32_t dt, PtpServoAuxInput *pAux)
#define K_P
Default Kp parameter value.
Data to perform a full synchronization.
int64_t measSyncPeriodNs
Measured synchronization period (t1->t1)