2019-08-13 09:55 AM
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?
Solved! Go to Solution.
2019-08-13 10:10 AM
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)));
2019-08-13 10:10 AM
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)));
2019-08-13 10:27 AM
I don't understand entirely, so I wanted to clarify a few things:
2019-08-13 10:47 AM
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.
2019-08-13 12:25 PM
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?
2019-08-13 01:44 PM
>>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.
2019-08-13 03:19 PM
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);