PWM center interval?

#1

For my project I need to control both motors using the PWM outputs of my RC reciever.
I set everything up and it works, except the motors don’t brake when I have the stick in the middle position.

Here is my setup code:

odrv0.config.gpio3_pwm_mapping.min = -350000
odrv0.config.gpio3_pwm_mapping.max = 350000
odrv0.config.gpio3_pwm_mapping.endpoint = odrv0.axis0.controller._remote_attributes['vel_setpoint']

odrv0.config.gpio4_pwm_mapping.min = -350000
odrv0.config.gpio4_pwm_mapping.max = 350000
odrv0.config.gpio4_pwm_mapping.endpoint = odrv0.axis0.controller._remote_attributes['vel_setpoint']

The promlem I encouter is that vel_setpoint never gets 0.0, it floats always around [-1000, 1000], because my reciever doesnt produce a perfect 1500ns in middle position!

Is it possible to have an interval e.g. 1450ns-1550ns, where vel_setpoint gets set to 0.0?
Or can I do something similar to get the motors to brake at 0-position?

#2

I don’t know if that is possible, but I think it’s possible to change the firmware to have this functionality if the current one doesn’t have it.

When I have time I will look into it and post some updates

#3

Sounds great, thank you!

#4

So I had time and I tried to program something. It’s untested, but I think it works. Here is what I did:

First of all, I added a new variable in the board_config that lets you set a limiter.

struct PWMMappingLimiter_t {
    float min = 0;
    float value = 0;
    float max = 0;
};
PWMMappingLimiter_t pwm_mappings_limiter[GPIO_COUNT];

Adding it to board_config has the effect that the values get saved by calling odrvX.save_configuration().

The pwm_mappings_limiter variable gives you the option to set a minimal and a maximal pwm boundary (in %) and a limiting value (also in %) where the received pwm value will be limited to when the original pwm value lies between the minimal and maximal boundary. The code for clarity:

 if (fraction > board_config.pwm_mappings_limiter[gpio_num - 1].min && fraction < board_config.pwm_mappings_limiter[gpio_num - 1].max)
        fraction = board_config.pwm_mappings_limiter[gpio_num - 1].value;

Where fraction is the original pwm value in percentage.
Those values are normally changed in the following commands:

odrvX.config.gpio1_pwm_mapping_limiter.min
odrvX.config.gpio1_pwm_mapping_limiter.max
odrvX.config.gpio1_pwm_mapping_limiter.value

odrvX.config.gpio2_pwm_mapping_limiter.min
odrvX.config.gpio2_pwm_mapping_limiter.max
odrvX.config.gpio2_pwm_mapping_limiter.value

odrvX.config.gpio3_pwm_mapping_limiter.min
odrvX.config.gpio3_pwm_mapping_limiter.max
odrvX.config.gpio3_pwm_mapping_limiter.value

odrvX.config.gpio4_pwm_mapping_limiter.min
odrvX.config.gpio4_pwm_mapping_limiter.max
odrvX.config.gpio4_pwm_mapping_limiter.value

So in your situation something that might work is the following:

odrvX.config.gpio3_pwm_mapping_limiter.min = 0.47
odrvX.config.gpio3_pwm_mapping_limiter.max = 0.53
odrvX.config.gpio3_pwm_mapping_limiter.value = 0.5

odrvX.config.gpio4_pwm_mapping_limiter.min = 0.47
odrvX.config.gpio4_pwm_mapping_limiter.max = 0.53
odrvX.config.gpio4_pwm_mapping_limiter.value = 0.5

If the pwm then changes in [0.47; 0.53], then the pwm value will be limited to 0.5 and as a result will set the vel_setpoint to 0.

You can see the source code here: https://github.com/LowiekVDS/ODrive.
In ODrive/Firmware you will find two precompiled pwminterval_xxV.hex files, one for the 48V version and one for the 24V version, both ODrive V3.5.

Hopefully it works!

2 Likes
#5

I finally found the time to test your code.
Thank you for the time you spent writing it!
The code works really well, its easy and fast, however I found some issues/improvements:

  1. If fraction jumps out of the limiter.min/limiter.max intervall, there is no smooth transition - the motor makes a jump to a certain speed. The effect is especially strong if you have a big limiter intervall.

  2. The limiter.value parameter schould not set the fraction, but the direct value it outputs to e.g. to vel_setpoint with odrv0.config.gpio3_pwm_mapping.endpoint = odrv0.axis0.controller._remote_attributes['vel_setpoint'], when the pwm signal is inside the limiter interval. For my example this would be zero.
    Otherwise, when you have an asymmetrical mapping.min/mapping.max interval, its hard to hit exactly 0 on the output, just by setting the fraction inbetween.

I would really appreciate it if you find the time to adjust the code!
Thank you in advance :slight_smile: