Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PID controller questions #1

Open
graza opened this issue Nov 9, 2019 · 3 comments
Open

PID controller questions #1

graza opened this issue Nov 9, 2019 · 3 comments

Comments

@graza
Copy link

graza commented Nov 9, 2019

Hey Der,

So I was looking at the PID code to understand how I might use it for the robot. My understanding is that I would create the data structure with the initial values and then starting feeding errors to pidcalc() to get the output value.

But I don't see e_sigma being updated in the struct - is that a bug or am I meant to update it outside the function?

And what sort of scaling values do you use for the e_mul/e_div and u_mul/u_div? Presumably you're doing this to avoid floating point and want to scale the integer arithmetic to get the most accuracy from it?

Cheers,
Gra

@dtynan
Copy link
Member

dtynan commented Nov 14, 2019

Hi Gra, e_sigma is updated within the anti-windup block.

	if (awu < 5000 && awu > -5000) {
		/*
		 * Anti-windup mechanism
		 */
		pp->e_sigma += bige;
	}

The idea is to prevent the sigma getting too large in the case of a non-linear actuator. Ideally the windup limits would also be defined in the struct rather than being hard-coded.

You're right that the mul/div stuff is to do some basic, basic scaling and avoid floating point. You can set the div to 1 until you get a better handle on the accuracy and you have reasonable Kp, Ki and Kd values.

@graza
Copy link
Author

graza commented Nov 14, 2019

Thanks Der, I must be going blind.

Expanding on mul/div: The code will scale the error so that the PID coefficients can all be positive integer values with useful relations to each other. So if the desired coefficients are for example 4/0.25/0.5, then use:

kp=16, ki=1, kd=2, 
e_mul=4, e_div=1, 
u_mul=1, u_div=4

But then need to be mindful of overflowing the short integers, right? If e=255, then first time through pidcalc will initially have:

big_e=1020, 
big_u=16*1020+1*1020+2*1020=19380
u=19380/4=4845

All OK, but have to be careful not to let big_u go above 32K. In an Arduino context, analogWrite(4845) makes no sense, so need to clamp that too... I think I need to play with this in a simple loop to visualise it better. :)

Cheers,
Gra

@dtynan
Copy link
Member

dtynan commented Nov 15, 2019

You could always set u_div to 19 instead of 4. That would mean your value would end up as 1020. I had intended that u_mul/u_div also be used to re-align 'u' around the particular actuator. In your case, a value between 0 & 1023. It definitely needs some clamping values somewhere in the process, though.

I wrote the code for a sailboat rudder with a range of +/- 45 degrees. However, the rudder is driven by a stepper motor (with, if memory serves, a 4:1 gear ratio) and has a zero-sense at one full extent so hard to port would be 0 and hard to starboard would be 200 with 100 being straight down the centre line. I think I may have limited it to a maximum of 40 degrees too, for efficiency sake. I also allowed for the fact that the rudder/stepper alignment may not be perfect so that "dead ahead" might actually work out at 102. In theory, the PID controller should be able to do this itself without me telling it where the "zero position" is. In fact, it's a good way of determining what the centre line actually is, but I haven't gotten to the point where I can test that aspect in the real world...

Feel free to ping me a Pull Request when you've debugged it for me! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants