cancel
Showing results for 
Search instead for 
Did you mean: 

How do I go from an integer value to a q31_t? Do I need to normalize the in32_t to a value between -1 and 1 and then pass to arm_pid_q31 to complete the calculation?

AIsma
Associate II

I am using the arm pid library and I do not know how to use the arm_pid_q31 call. I need to give it an error as a q31_t, however, I am not entirely sure how to go from an int32_t to a q31_t. Do I need to normalize the in32_t to a value between -1 and 1 and then pass to arm_pid_q31 to complete the calculation?

1 ACCEPTED SOLUTION

Accepted Solutions

You're expect to pass an array with numbers in your selected fixed point format.

Review the "data representation" expectations and diagrams.

Values are going to need to be less than 1

If you have a 12-bit signed ADC value

q31 = adc12i << 20;

q31 = (q31_t)(fltvalue * ((float)(1 << 31)));

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

6 REPLIES 6

You're expect to pass an array with numbers in your selected fixed point format.

Review the "data representation" expectations and diagrams.

Values are going to need to be less than 1

If you have a 12-bit signed ADC value

q31 = adc12i << 20;

q31 = (q31_t)(fltvalue * ((float)(1 << 31)));

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I don't understand entirely, so I wanted to clarify a few things:

  1. You said the expectation is to pass an array with numbers, however, arm_pid_q31 accepts a q31_t, not a q31_t*. Are you saying arm_pid_q31 needs to be called multiple times.
  2. You mentioned reviewing expectations and diagrams, could you point me to them?
  3. Thanks for the help :)

It is passed an array of q31 values https://www.keil.com/pack/doc/CMSIS/DSP/html/structarm__pid__instance__q31.html

You understand how bits are held in bytes and word, and how floating point and fixed point values are held, and data in memory?

https://www.tutorialspoint.com/fixed-point-and-floating-point-number-representations

With q31 you've got 1 sign bit, and 31 fractional bits. Given this is entirely fractional bits holding the value, it will need to always be less than ONE (positive or negative), it could arguably represent -1 but unhelpfully.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

That is what is causing confusion for me. I want to control the speed of a motor that say can be driven from 0 to 15 RPM. Say my target is 10 RPM and I need to be at 14 RPM. I have an error of 4 RPM. The arm_pid_instance_q31 is based on q31. My input into arm_pid_q31 must be q31 and my output is in q31. I apologize if this question is silly, but how to I translate my integer of 4 into q31, so that the arm pid library will give me a meaningful output that I can translate from q31 back into an RPM (Integer)? Since there are 31 fractional bits and only number -1 to 1 can be represented, how do I represent 4? After giving it some more thought, is it just dependent on the maximum value of my input?

>>Since there are 31 fractional bits and only number -1 to 1 can be represented, how do I represent 4? 

Clearly it cannot.

It could represent 0.25 ? Or 0.4 or 0.04

int32_t x = 400; // say you hold a value in milli-volts as an integer

q31_t foo = (q31_t)((double)x * 0.001* (double)(1 << 31)); // Converting that to a voltage in fixed-point

or

q31_t bar = (q31_t)(x * ((1 << 31)/1000)); // precision here probably really poor

How it is applicable in your application, not really my domain, but 4 rpm is 0.0666666 revolutions a second, so perhaps it is a question of units.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I think I am following now. I just had one last question. How do the Kp or Ki get set? In the example you provided, would they have to follow the same scaling scheme?

If I wanted Kp = 100

It would be PID.Kp = 100*0.001*(1 << 31);