2 axis Joystick differential steering + Odrive Help

Hi,

I need to control 2 BLDC motors with a 2 axis joystick. What would be the best way to do this?

This is the type of Joystick I would like to use.

https://www.althencontrols.com/controllers-position-sensors/industrial-joystick-controllers/mini-joysticks/12028/ss1-dual-axis-mini-thumb-joystick/

Thanks!

Easy with a Python script which uses the Linux event device interface on a Raspberry Pi…
You can send commands over USB, or if you need more robustness to noise (e.g. with larger motors) then you could get a CAN HAT for the Pi and use CAN Bus.
If anything the CAN approach is simpler, since it’s connectionless, and you don’t need any additional libraries except evdev and can.

This was a simple script I wrote about a year ago to control two motors based on the X and Y axes of a mouse:

import time
import can
import struct
from evdev import InputDevice, categorize, ecodes
dev = InputDevice('/dev/input/event0')  # need to set this to your mouse device. There are ways to detect the correct device automatically

bustype = 'socketcan'
channel = 'can0'
bus = can.interface.Bus(channel=channel, bustype=bustype)
#** odrive_can_cmd()
# see: https://github.com/Wetmelon/ODrive/blob/RazorsEdge/docs/can-protocol.md
# @param node_id: ODrive assigned CAN bus node ID, one per axis
# @param cmd_id: CMD ID as per messages table
# @param data: Python list of signals, according to messages table
# @param format: Python Struct.pack format string for signals in 8-byte CAN message, encoded according to signals table

def odrive_can_cmd(node_id, cmd_id, data=[], format=''):
        data_frame = struct.pack(format , *data)
        msg = can.Message(arbitration_id=((node_id << 5) | cmd_id), data=data_frame)
        bus.send(msg)


# Constants
ODCMD_SET_INPUT_POS = 0x00c
ODCMD_RESET_ERRORS = 0x018
ODCMD_SET_AXIS_STATE = 0x007
AXIS_STATE_CLOSED_LOOP_CONTROL = 8

node_id=1 # set in ODrive config

# clear faults
odrive_can_cmd(node_id, ODCMD_RESET_ERRORS)
# put into position-hold
odrive_can_cmd(node_id, ODCMD_SET_AXIS_STATE, [AXIS_STATE_CLOSED_LOOP_CONTROL], 'h')

xpos = 0
for event in dev.read_loop():
    if (event.type == ecodes.EV_REL and event.code == 0):
        xpos = xpos + event.value * 4
        #  command to set  odrv0.axis1.controller.input_pos=xpos
        odrive_can_cmd(node_id, ODCMD_SET_INPUT_POS, [xpos, 0, 0], 'ihh')

1 Like

Thanks for this. I have never used the Raspberry but I guess it is time to start. I want to add some buttons and features as well as Accelerometer, so looks like I can do all of that with the PI.