Velocity / direction control with analog and gpio

Hello all.
I am using odrive v3.6 and trying to control hover motor with an anlog input and gpio pin.
Say, analog input is for velocity 0~10 and gpio for direction +/- per input state.
1 anlaog input connected to GPIO_3
1 gpio input connected to GPIO_5
I was able to turn the motor using the analog mapping however direction does not change.
Below is my setup to set gpio for direction control.

odrv0.config.gpio5_mode = GPIO_MODE_DIGITAL_PULL_UP
odrv0.axis0.config.enable_step_dir = True
odrv0.axis0.controller.config.circular_setpoints = True

What am I missing here?
Any suggestions?

I want to do the exact same thing, but I haven’t found any way to set up a digital input to reverse direction in velocity mode. Step/dir is like stepper motor emulation, not what we want. I think we’d have to modify the firmware or use a separate microcontroller to send commands, but I’ll probably just skip the reverse mode for now.

Would you mind showing how you set up the analog input? I can’t even get that to work. 11k potentiometer, middle pin connected to GPIO1, other two to AVCC and AGND. Then send odrv0.config.gpio1_mode = GPIO_MODE_ANALOG_IN, and odrv0.get_adc_voltage(1) always reads about 0.65 regardless of potentiometer position (or if it’s even connected or not). Checking with a multimeter, the voltage on the middle pin changes as expected. Am I missing something? I tried using the regular 3.3V and GND pins too, same result.


I also found that step/dir is only for position control mode and not for velocity control which means I have to modify the firmware myself.

Per the analog control, I hooked up my potentiometer output to GPIO_3 and

odrv0.config.gpio3_mode = GPIO_MODE_ANALOG_IN
odrv0.config.gpio3_analog_mapping.min = 0
odrv0.config.gpio3_analog_mapping.max = 8

to check the input, try plot the value by entering below in odrivetool

start_liveplotter(lambda: [odrv0.get_adc_voltage(3)])

Thank you! gpio1_analog_mapping doesn’t seem to exist, but after changing to gpio3 I get good adc readings.

I thought of a potential way to do the reverse mode… can you use one analog mapping to control the range of another? Like odrv0.config.gpio4_analog_mapping.endpoint = odrv0.config.gpio3_analog_mapping.max
Then set gpio4 min = -8, max = +8. The switch will output 0V or 3.3V, so reading as an analog value should toggle between those min/max values, and then our gpio3 will output positive or negative velocity as we desire.

Is it safe for the switch to connect 3.3V directly to a gpio pin without a resistor?

Great! I didn’t know gpio1 has no analog mapping before.

I kinda figured out how to modify the firmware to change direction of input in a unsafe way.
odrv0.axis0.controller.input_vel is set in controller.cpp

   vel_setpoint_ = input_vel_;

So I need to figure out how gpio pin can switch the sign of input_vel_
In axis.cpp there is this line of code which called every control loop

bool Axis::run_closed_loop_control_loop() {
   while ((requested_state_ == AXIS_STATE_UNDEFINED) && motor_.is_armed_) {



Here I can get the dir_gpio by calling get_gpio(config_.dir_gpio_pin);
By reading the value of the pin, I can switch the value of input_vel_
And now it is working as expected!
Next thing is to make it safer so that it would not switch direction while motor is moving.

Also note, it is always safe to put a small resistor (about 1k) between VCC to gpio.

Looks like my idea works too. After sending odrv0.config.gpio4_analog_mapping.endpoint = odrv0.config.gpio3_analog_mapping._max_property and connecting the potentiometer to gpio4, I can control the value of odrv0.config.gpio3_analog_mapping.max. But it is rather noisy, varying about ±0.25 out of the total -8 to +8 range. But that may not be an issue once I wire up a switch instead of the potentiometer.