You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This PR fixes the bug #73 + It fixes the bug of the hard-coded number of samples per motor (5 * motor.pole_pairs) - see more info in the community.
Automatic number of samples given a LUT size
Now the code will automatically choose the number of samples to run in one motor rotation based on the LUT size.
It will always do the closest posible number of samples to the LUT size that is multiple of the motor's pole_pairs number.
That way we guarantee that the sampling is equal for each electrical angle.
Then at the final stage the the samples will be remapped to the user's requested LUT size.
For example if we have a BLDC motor with 7 pole pairs and he wants a LUT size of 200
The calibration will be done with ceil(200/7) * 7 = 203 positins
And then at the end of the calibration process the 203 values will be mapped to the 200.
This mapping at the moment does not implement any interpolation, it only extrapolates. It should work for most use cases.
uint16 LUT rather than float
The main reason is the memory footprint. The LUT now requires half the memory.
The float to uint16 scaling is done with the encodeOffsetU16 and decodeOffsetU16 functions that basically just scale float angle of [-pi, pi] to [0, 65535].
For the moment the resolution is ~0.000096 rad (~0.0055 deg) , which is probably fine for most of applications.
For example if we take a stepper motor with 50pp, in one electrical rotation is discretized in 360/50/0.0055=1309 elements which amounts the resolution of the electrical angle of around ~0.275 deg.
The resolution can be greatly improved if we consider that the LUT will have a smaller range than [-pi,pi] (which is probably always the case). In that case we can increase the scaling factor LUT_SCALE in the CalibratedSensor.h and increase the overall resolution of the LUT.
Board,examples/drivers/drv8316/drv8316_3pwm<br>flash,%,examples/drivers/drv8316/drv8316_3pwm<br>RAM for global variables,%,examples/drivers/drv8316/drv8316_6pwm<br>flash,%,examples/drivers/drv8316/drv8316_6pwm<br>RAM for global variables,%,examples/encoders/calibrated_sensor/calibration_save<br>flash,%,examples/encoders/calibrated_sensor/calibration_save<br>RAM for global variables,%,examples/encoders/linearhall<br>flash,%,examples/encoders/linearhall<br>RAM for global variables,%,examples/encoders/mt6816/mt6816_spi<br>flash,%,examples/encoders/mt6816/mt6816_spi<br>RAM for global variables,%,examples/encoders/calibrated_sensor/calibrated<br>flash,%,examples/encoders/calibrated_sensor/calibrated<br>RAM for global variables,%
adafruit:samd:adafruit_metro_m4,0,0.0,N/A,N/A,0,0.0,N/A,N/A,528,0.1,N/A,N/A,0,0.0,N/A,N/A,0,0.0,N/A,N/A
rp2040:rp2040:rpipico,0,0.0,0,0.0,0,0.0,0,0.0,512,0.02,112,0.04,0,0.0,0,0.0,0,0.0,0,0.0
arduino:sam:arduino_due_x,0,0.0,N/A,N/A,0,0.0,N/A,N/A,144,0.03,N/A,N/A,0,0.0,N/A,N/A,0,0.0,N/A,N/A
arduino:samd:nano_33_iot,0,0.0,0,0.0,0,0.0,0,0.0,552,0.21,116,0.35,0,0.0,0,0.0,0,0.0,0,0.0
esp32:esp32:esp32,2548,0.19,0,0.0,2548,0.19,0,0.0,3148,0.24,112,0.03,,,,,2548,0.19,0,0.0
esp32:esp32:esp32s2,2544,0.19,0,0.0,2544,0.19,0,0.0,3160,0.24,120,0.04,2544,0.19,0,0.0,2544,0.19,0,0.0
STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8,0,0.0,0,0.0,0,0.0,0,0.0,520,0.79,116,0.57,0,0.0,0,0.0,,,,
STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_F411RE,0,0.0,0,0.0,0,0.0,0,0.0,556,0.11,116,0.09,0,0.0,0,0.0,0,0.0,0,0.0,436,0.08,8,0.01
I don't think downsampling the LUT is a good idea. I don't think it should be up to the user to set LUT size in this way. User configurable LUT per electrical angle would make more sense I think, that way you never run into the issue of up/downsampling.
Alternatively, the user could specify a max lut size (to prevent memory overflows) and the code determines a lut that can fit into that max size without having to interpolate. In this case a user would request a max N_LUT 200 and get back a LUT of size 196. This would have to then also change the output print for the LUT after calibration, as well as possibly include the N_LUT variable in the output print.
It just feels backwards to me to create a calibration function and sacrifice accuracy of said calibration to fit some arbitrary number constraint that is entirely self-imposed.
I'd like to merge this but there are some conflicts?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR fixes the bug #73 + It fixes the bug of the hard-coded number of samples per motor (
5 * motor.pole_pairs) - see more info in the community.Automatic number of samples given a LUT size
Now the code will automatically choose the number of samples to run in one motor rotation based on the LUT size.
It will always do the closest posible number of samples to the LUT size that is multiple of the motor's pole_pairs number.
That way we guarantee that the sampling is equal for each electrical angle.
Then at the final stage the the samples will be remapped to the user's requested LUT size.
For example if we have a BLDC motor with 7 pole pairs and he wants a LUT size of 200
The calibration will be done with
ceil(200/7) * 7 = 203 positinsAnd then at the end of the calibration process the
203values will be mapped to the200.This mapping at the moment does not implement any interpolation, it only extrapolates. It should work for most use cases.
uint16 LUT rather than float
The main reason is the memory footprint. The LUT now requires half the memory.
The float to uint16 scaling is done with the
encodeOffsetU16anddecodeOffsetU16functions that basically just scale float angle of [-pi, pi] to [0, 65535].For the moment the resolution is ~0.000096 rad (~0.0055 deg) , which is probably fine for most of applications.
For example if we take a stepper motor with 50pp, in one electrical rotation is discretized in
360/50/0.0055=1309elements which amounts the resolution of the electrical angle of around~0.275 deg.The resolution can be greatly improved if we consider that the LUT will have a smaller range than [-pi,pi] (which is probably always the case). In that case we can increase the scaling factor LUT_SCALE in the
CalibratedSensor.hand increase the overall resolution of the LUT.