2018-02-07 12:08 AM
I have a control algorithm which operates within a Timer Interrupt of 200 us. Basically my code generates an output and compares it to a look up table. When I have a single array defined:
const float Adm_Re_array[720] = {...values...}
And search for a match in the LUT which has the minimum distance from the array using this code:
for (i=1;i<=8;i=i++)
{
k = act_element+i-4;
if (k < 0) k = k + 720;
if (k >(719)) k = k - 720;
dist_Re = Adm_Re-Adm_Re_array[k];
dist_T = (dist_Re*dist_Re);
if ((dist_T <= dist_T_min)||(dist_T_min == -1))
{
dist_T_min = dist_T;
act_element = k;
}
}
My control algorithm works well and I have used only 124 us of the 200 us.
When I change from a single dimension to a multi-dimensional array of form:
const float Adm_Re_array[7][720] = {...values...}
And search for a match in the LUT which has the minimum distance from the array using this code:
for (i=1;i<=8;i=i++)
{
k = act_element+i-4;
if (k < 0) k = k + 720;
if (k >(719)) k = k - 720
dist_Re = Adm_Re-Adm_Re_array[4][k];
dist_T = (dist_Re*dist_Re);
if ((dist_T <= dist_T_min)||(dist_T_min == -1))
{
dist_T_min = dist_T;
act_element = k;
}
}
My control code goes unstable while the loop time does not change significantly from the 124 us as I am only looking at one row of the multidimensional array in my search. Are there any known issues with the STM32 using multidimensional arrays similar to what I am observing.
Regards,
K
2018-02-07 12:18 AM
You are not on a PC here, with virtually unlimited ressources.
Can you tell where this array is located (stack or global) ?
My control code goes unstable ...
What exactly does this mean ?
Are there any known issues with the STM32 using multidimensional arrays similar to what I am observing.
One thing has nothing to do with the other.
Organizing memory for your variables is the sole responsibility of the compiler (toolchain).
BTW, I am pretty sure your algorithm could use integer types and scaled math instead of floating point.
2018-02-07 01:36 AM
I am generating a sinusoidal current (controlled by the microcontroller) and comparing it to the fixed LUT in memory. When I compare it to a single dimension array the LUT and real time current are exactly the same. When I introduce multi-dimensional arrays the generated sinusoidal current (real-time) is not controlled according to the reference (hence not stable).
Yes I can easily use integer and scale accordingly. The size of the array is constant hence i defined it const float. Could you direct me towards documentation on how to optimize my array definitions?
2018-02-07 02:16 AM
When I introduce multi-dimensional arrays the generated sinusoidal current (real-time) is not controlled according to the reference (hence not stable).
Still not sure what you mean with unstable.
Deviation too high, ringing, or does your code take too long ?
Yes I can easily use integer and scale accordingly. The size of the array is constant hence i defined it const float.
Do you use the FPU at all in your project ?
Adding floating point code does not mean the FPU is actually used.
And have you realized that single precision floating point has only 24 bit resolution ?
Algorithms designed with double in mind tend to become unstable with float.
if (k < 0) k = k + 720;
if (k >(719)) k = k - 720
I would replace that with something like
k = (uint32_t) (k%720);
Generally, the involved datatypes and some surrounding code would clarify things, too.
As a general advice, you can test your algorithms extensively with proper datatypes on a PC before.
Instrumentation, debugging and validation of results is much easier.
We use a (not so cheap) testing tool and a simulation environment for that purpose.
2018-02-07 02:45 AM
meyer.frank
'We use a (not so cheap) testing tool and a simulation environment for that purpose.'what is it called ?
do you have a tutorial link ?2018-02-07 02:58 AM
Tessy from Razorcat.
Price is a 5 digit figure, but our software needs to fulfill certain safety (SIL) requirements.
I am generating a sinusoidal current (controlled by the microcontroller) and comparing it to the fixed LUT in memory.
As I understand it, you have a sine lookup table.
What do you need multiple dimensions for ?
You can realize phase-shifted LUTs as simple offset to the table index.
In an older hobby project, I got away with a quarter period LUT of 16 bit values, and very slighty increased runtime for the index calculation.
The MCU had just 8kB of RAM.
2018-02-07 03:04 AM
The function is sinusoidal but it has distortions which are important to the application. The function is too complex to model accurately using modelling. I tried to use a signed char instead of float in the LUT; obviously the memory allocation size has decreased significantly but the problem still remains. Maybe there is something else which is messing up the timer loop. I will investigate further. Thank you for your help.
2018-02-07 03:21 AM
The function is sinusoidal but it has distortions which are important to the application. The function is too complex to model accurately using modelling.
That's fine, I was just guessing.
I tried to use a signed char instead of float in the LUT;
But that is a drastic step downward.
Short
(16 bit) would be better, andint
would have the same size, but better resolution (32 bits instead of 24).Maybe there is something else which is messing up the timer loop.
Are you sure it's a timing issue ?
If that is the case, you can try to reorganize your loop code, and turn on compiler optimization.
But I would check the runtimes first, either with toolchain support (cycle counter), or by toggling GPIOs and using a scope.