Hi I'm subin Kim.
I want to simulate my 6-pole pairs BLDC motor by using AN5201SW.
But in application SW there are just 2 or 4-pole pairs motor SCALING factors(HIGH_SPEED_SCALING / LOW_SPEED_SCALING).
How can I moderate these codes for my motor and Can you explain how are these factors are made?
Thank you.
Hello SuBin Kim,
I'm not the author of the code, but let's walk through the calculation:
The motor speed is calculated based on the zero-cross detection of BEMF voltage on a non-active phase. These zero-cross events times are measured by capturing the TIM0CNT register at the time the ADC routine detects a zero-cross.
That means, the time is scaled by the TIM0 settings.
In the application, the zero-cross periods are captured with periodZC_F_PhA, periodZC_R_PhA, etc., which are defined as tU16 (16 bit unsigned). To calculate one "electric" revolution of a motor = 6 commutations (or 6 zero-crosses), 6 periods are summed. For that case, the "period6ZC" is defined, formated as tU32 (or unsigned long) to prevent an overflow if all 6 zero-cross periods are summed.
If you sum all the 6 zero-cross periods, you'll get the time per single "electric" revolution. That means, if the motor is 2-pole motor (1 pole-pair motor), it would be the time per single "mechanical" revolution of the rotor. You can easily get the time per mechanical revolution for higher-pole motor simply by multipling it by number of pole-pairs.
Let's get back to the code: the period per 6 zero-crosses "period6ZC" is calculated on the line 813, within the 1 ms timer interrupt routine. Since the speed (rotor frequency) is just an inverted time period, it is calculated using line 814:
actualSpeed = SPEED_CALC_NUMERATOR / period6ZC;
Now, how to read it's scale? Let's assume the "actualSpeed" is tFrac32 (1.31 formated signed 32bit number). It would mean the maximal fraction number is 1.0, which is 2^31 = 2,147,483,648.
The task is to find the SPEED_CALC_NUMERATOR for which the period6ZC gives the number above.
Considering the timer TIM0 prescaler is set to 16 (TIM0TSCR2_PR = 4) and the bus clock is 12.5MHz, the timer tick is 12.5MHz / 16 = 781.25 kHz, which is 1.28us.
Let's assume the maximum mechanical speed of the motor is 10,000 RPM and the motor is 6-pole-pair. That would give us 10000/(60 seconds) = 166.67 revolutions per second, 166.67*(6 pole-pairs) = 1000 electrical revolutions per second, so 1000 * (6 commutations) = 6000 commutations/zero-crosses per second. That would make 1/6000 = 167.67us per one commutation. With our 1.28us timer, we can catch upto 130.28 periods at maximal speed.
For maximal speed, we can simply rearrange the "actualSpeed" calulation, assuming that:
actualSpeed = FRAC32(1.0) = 2,147,483,648
period6ZC = 6 periods * 130 = 780 (rounded down, since the value is still an integer)
Well, the important information is hidden in the casting of the actualSpeed from Frac32 to Frac16 at line 816:
speedErr = requiredSpeed - (tFrac16) actualSpeed;
That means, only the lower 16 bits are considered the speed. Therefore, for maximum speed, the "actualSpeed" = 32767.
32767 = SPEED_CALC_NUMERATOR / 780
SPEED_CALC_NUMERATOR = 780 * 32767 = 25558260
Thus
#define SPEED_CALC_NUMERATOR 25558260
Using the equation from the line 814, the speed would be:
actualSpeed = SPEED_CALC_NUMERATOR / period6ZC = 25558260 / 780 = 32,767;
Masking that value by lower 15 bits and casting it as tFrac16 would make it fit the max speed range of 10,000 RPM.
RealScaleSpeedRPM = actualSpeed / 32,767 * MAX_SPEED = actualSpeed / 32,767 * 10,000.
If the speed scale is calculated like this, it should be reflected in the command constants as well:
#define SPEED_SCALE 10000.0 // Used for correct calculation of the following:
#define REQUIRED_RUN_SPEED FRAC16(2000.0/SPEED_SCALE) // 2000 rpm
#define MIN_SPEED FRAC16(500.0/SPEED_SCALE) // 500 rpm minimal speed for Down button control (should be min 10% of nominal motor speed)
#define MAX_SPEED FRAC16(5000.0/SPEED_SCALE) // 5 krpm maximum speed for Up button control
#define SPEED_STEP FRAC16(100.0/SPEED_SCALE) // 100 rpm, Up/Down step for button controls
These scales shall be updated in the FreeMASTER project as well. The FM scales are:
requiredSpeed .... Real type transformation: Linear: a = SPEED_SCALE = 10,000; b = 0
actualSpeed ....... Signed int, Size = 4, Show as: REAL, Bit fields maks with: word (0xffff)
.............................Real type transformation: Linear: a = SPEED_SCALE / 32767.0 = 0.3051851; b = 0
Now, let's have a look on the resolution:
At the full speed, if one period changes by 1 tick, then you'll get the period6ZC from 780 to 781, which makes 12.8041 RPM difference. The higher the SPEED_SCALE is, the higher the error is. If the assumption would be a change in all of the 6 periods (thus the period6ZC would change from 780 to 786), the resulting change to the speed would be 76.336 RPM. That makes the speed error 10,000 RPM +- 76, which is 0.76%
I believe this would make it clear. Please adjust the steps according to your case.
Best regards,
Matej
I have realized that it would be better to keep this in a single document rather than letting it fade in the history of questions. So I did one, based on this answer and the link is this: https://community.nxp.com/docs/DOC-340132