i know what is a pid controller but i dont know how to code and use those pid values to balance something (especially model rocket thrust vectorinng) any help is encouraged
something to read
https://playground.arduino.cc/Code/PIDLibrary/
https://www.csimn.com/CSI_pages/PIDforDummies.html
or to watch
not sure what you background is or level of understanding. you may find this plot of PID variables helpful.
if your application really is thrust vectoring, i suggest simulating your code (possibly learning how to simulate) to gain a understanding. part of that will be a model for you system response
i have seen lots of pid tutorial but not like this one, this is best thanks a lot
at least that one explained why you might want an integral term to overcome sticky movement. but it didn't see the explanation for how the integral sum is zeroed (i.e. "unwound")
Perhaps it's a different way of saying the same thing, but my way of viewing the integral term is that it allows your controller to have a non-zero control output if necessary to hold a zero error value.
Meaning ..... where you really want to be is at zero and unchanging error. Under that condition neither the P or D terms provide any control output. Only the I-term can be non-zero with zero error and hold the required control output value.
EDIT:
Actually not the same thing. "Sticky" is a non-linear condition. So, not covered by linear control theory.
it's the oscillation around 0 that creates positive and negative values for the error which, once summed, cancel each-other
that's possible but unlikely if you start far from the target.
the integral sum is the accumulation of error until the target is reached. this make sense if some residual voltage is needed to maintain the target when the error is zero such as a speed.
but in the case of a position, there should be no need for any residual output (e.g. stepper-motor, DC motor)
(perhaps the teter-toter using a servo is more similar to a speed system where there is a non-zero output at the target)
years ago someone argued with me that even in positioning systems, a residual may be needed if additional force is needed to drive the position to the target. at the time i didn't understand, but seeing the video helped me finally understand.
i guess your point is that if the ball is stuck on one side and an integral term is needed increase the height to make it move, the system will essential "hold" the ball on the opposite side of the teter-toter until the residual integral is "nulled-out"
it may make sense to have an integral term to deal with "sticky" situations. but it may also make sense in a positioning system to non-linearly adjust it, possibly reset it's value at the target position.
i hope you see that oscillations +/- 0 will not necessarily reduce a integral sum. the position must be held with the opposite sign of the sum to reduce it to zero.
i hope i've explained this well enough.
that's what I tried to say
understanding PID Control, Part 1 discusses the integral term and how some non-linear processing may be needed.
this is the 1st of 6 very good videos describing PID
I'd say the stepper-motor is an additional (discrete) integrator. It can hold a non-zero output (any position) with a zero-value input. So, if the PID's I-term is non-zero, then you have a P(I^2)D. I think that makes it a 3rd-order system.
So, maybe (perhaps you were saying this), make the I-term zero if you have a stepper.
hey can u suggest some free simulating software, thanks for the reply
i wrote the following code to gain an understanding. i believe the tricky part is the model for your device
// pid simulation
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <math.h>
char *progname;
unsigned int debug = 0;
unsigned int flag = 0;
// -----------------------------------------------------------------------------
#define MAX_BUF 500
struct File_s {
const char *desc;
float scale;
int idx;
float buf [MAX_BUF];
} file [] {
{ "err", 1.0}, // white
{ "out", 1.0}, // red
{ "acc", 1.0}, // blue
{ "spd", 1.0}, // green
{ "pos", 1.0}, // violet
{ "dErr", 1.0}, // orange
{ "errSum", 1.0}, // yellow
};
#define N_FILES (sizeof(file)/sizeof(File_s))
// -------------------------------------
void
append (
int id,
float val )
{
File_s *f = & file [id];
if (MAX_BUF <= f->idx)
return;
f->buf [f->idx++] = val;
}
// -------------------------------------
void
dump (
int id,
float dt )
{
File_s *f = & file [id];
printf ("# %s: %s [%d]\n", __func__, f->desc, f->idx);
printf ("color = %d\nnext\n", id+1);
unsigned nMax = 0;
unsigned nMin = 0;
unsigned n;
for (n = 0; n < f->idx; n++) {
printf (" %8.4f %8.4f\n", n * dt, f->buf [n] * f->scale);
if (f->buf [nMin] > f->buf [n])
nMin = n;
if (f->buf [nMax] < f->buf [n])
nMax = n;
}
if (f->buf [nMax] < fabs(f->buf [nMin]))
nMax = nMin;
if (0 == nMax)
nMax += 1;
printf ("anno %8.4f %8.4f %s\n",
nMax * dt, f->buf [nMax] * f->scale, f->desc);
}
// -----------------------------------------------------------------------------
float Mass = 2.0;
float Kp = 1.0;
float Kd = 0.45; // dErr < 0
float Ki = 0.0;
float
pid (
float target,
float current,
float dt,
float Kp,
float Kd,
float Ki )
{
static float errLst = 0;
static float sum = 0;
float err = target - current;
float dErr = errLst ? err - errLst : 0;
errLst = err;
sum += err * dt;
float out = (Kp * err) + (Ki * sum) + (Kd * dErr / dt);
append (0, err);
append (1, out);
append (5, dErr);
append (6, sum);
return out;
}
// ---------------------------------------------------------
float
step (
float target,
float dt )
{
static float pos = 0;
static float spd = 0;
float out = pid (target, pos, dt, Kp, Kd, Ki);
float acc = out / Mass;
spd += acc * dt;
pos += spd;
append (2, acc);
append (3, spd);
append (4, pos);
return pos;
}
// ---------------------------------------------------------
void
steps (
int seconds,
float target,
float dt )
{
float time = 0;
for ( ; time <= seconds; time += dt) {
#if 0
printf (" %8.1f %8.3f\n", time, step (target, dt));
#else
step (target, dt);
#endif
}
printf ("thickness = 1.5\n");
for (unsigned i = 0; i < N_FILES; i++)
dump (i, dt);
printf ("title PID simulation (Kp %.2f, Kd %.2f, Ki %.2f)\n", Kp, Kd, Ki);
printf ("title_x %s\n", "Time (sec)");
}
// -----------------------------------------------------------------------------
void
application (char *filename) {
FILE *fp;
char s[BUFSIZ];
printf ("%s: %s\n", progname, filename);
if ( (fp = fopen (filename, "rb")) == NULL) {
perror ("app - fopen input");
exit (1);
}
while (fgets (s, BUFSIZ, fp) != NULL) {
printf ("%s", s);
}
}
// --------------------------------------------------------------------
void help (void) {
printf (" Usage: %s \n", progname);
}
// --------------------------------------------------------------------
int main (int argc, char **argv) {
int c;
unsigned time = 2;
progname = *argv;
while ((c = getopt(argc, argv, "D:d:p:t:")) != -1) {
switch (c) {
case 'D':
debug = atoi (optarg);
break;
case 'd':
Kd = atof (optarg);
break;
case 'p':
Kp = atof (optarg);
break;
case 't':
time = atoi (optarg);
break;
default:
printf ("Error: unknown option '%c'\n", optopt);
help();
break;
};
}
steps (time, 50, 0.1);
return 0;
}
First you have to define what you mean by 'balance' and how you measure it. Once you can measure it, the setpoint is the measurement you get when it is 'balanced'. The output of the PID is then an arbitrary control value that can be applied to the system. Perhaps it is a servo position.
This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.