Only one channel reliably working?

What do you mean it reboots? It doesn’t normally reboot after calibration…?

Did you post the right video? That seems to be one of @Dev255’s videos and both motors seem to be spinning - i’m confused.

How is your arduino connected to the ODrive? You could try using CAN if you’ve got that available on your Arduino (you might need a transciever chip).

I did post the video, check the link? If that doesn’t work I can throw it on YouTube.

It’s connected the same way in the documentation GPIO 1 and 2 for UART. I didn’t deviate from what’s in the repo. I think everything is communicating, it’s just that I can’t get both channels going at once for some odd reason.

Ah sorry was the very quiet sound that confused me - when I turned the volume up there was Dev255’s youtube in the background on another tab.

HA! Yeah, I don’t talk in the first part. It’s mainly just to show the setup and such. I did a tad more research and it seems I might need 22nF caps on the encoder inputs. I’m going to try that.

If it was the encoder input that was getting interference, you’d most likely get ERROR_ILLEGAL_HALL_STATE, so I don’t think it’s that.
More likely interference is disrupting comms to your arduino - especially if it seems fine in odrivetool.

Can you use odrivetool to run both motors together? If you can, it pretty much rules out a problem with the ODrive itself.

I’d also be somewhat surprised if Hall sensors provide sufficient resolution for a self balancer. And I’m not sure how well the FOC control algorithm works with Hall sensors near to zero velocity. It might work, but be a bit wobbly and not be able to stay still.

Thanks for the info. I’ll try running both together. I’m really only using odrive because of the project linked in the first comment I made. I’ve seen several people get one working, so that’s why I’m following that as a guide. I thought this would be an easier way to get to the end result. Why would the communication be an issue when it’s really only an issue with one channel? If I run a single channel, it seems just fine.

This post makes me think it could be an issue with the encoders.

Just an update. I used odrivetool and could only get a single motor to actually drive! I tried a few different things, but I couldn’t get both working, just each one individually. The behavior is pretty similar, it either twitches a little bit or whines a little bit (stuck in place).

Also, where would I get the “ERROR_ILLEGAL_HALL_STATE” message? Where would that pop up, when I’m using odrivetool? Is there a log/output for error codes?

Er, when you use
dump_errors(odrv0, True)
(the True means acknowledge/reset errors, so you don’t have to reboot the thing)

I only suspected that because you said both channels work individually, but not simultaneously. If this was a noise problem, the noise would be greatest with both channels active. But it’s hard to tell without more info.

I see. I had assumed that you had followed the ODrive hoverboard guide - did you read that too?

Hi Robert, first thanks for watching my video ;-).

Have you looked at James Bruton projects? His video’s explain through balancing robots using ODrive and Arduino C platform, plus he shares his code on Github. Here is one of his video’s on balancing robots

As towen suggested, it’s well worth running through all the guides on here for your particular setup and making sure you understand the tuning guide as this will greatly improve the performance and reliability of the system.

Good luck,


I was getting ERROR_ILLEGAL_HALL_STATE from noise between the 3 phase wires and my encoder wires at one point. I fixed it by braiding (you can also twist) the 3 phase wires together and running the encoder wires through shielded Cat5 cable. Each of the hall sensor wires I twisted with GND. I also looped the 3 phase wires through a toroid ferrite ring three times. This was all recommended by @Wetmelon.

From your video it looks like you are using standard PC plug wires for the motor and you might be using Cat5 (hard to tell). It does not look like you have the hall wires twisted with GND nor that the Cat5 is shielded.

Also love your YouTube channel. Hope this helps!

I did read the guide, and that’s where I’m seeing that there could be some issues with the hall effect sensors. I try my best to only post when I’ve exhausted all other options. But I read through the original guide, the odrive hoverboard guide and saw a few other YouTube videos.

Got ya. I think I will focus a bit on the encoder wires. You are right though, I’m using standard 3-wire power cables for the motors and cat5 for the sensors. I just threw this together Saturday based on what I had in parts bins, this is just a first prototype. Neither are shielded though. I was eventually going to go with shielded cat5 and breakouts at each end, just to make the wiring a bit cleaner.

I’ll try the filter caps, and see where that gets me. Thanks!


I have seen James’ stuff, but it’s not really an ‘intro primer’. I’m not a programmer, so the software side of things is usually where I get hung up. His stuff is great, but not necessarily all that straightforward for someone to just pick up and dissect, which is why I was basing this off the guide I linked to in the first comment. Eventually I can break out some big brushless motors and get this thing really going, but this was just the first proof of concept so I wanted to keep things simple.

But yes, I have run through every guide that’s available, but I’m not quite at that step yet. Each motor can drive independently through odrive and through the arduino serial interface, but driving both is causing an issue, possibly due to interference (best guess right now). The motors work, the wiring works, the arduino communication seems to work, the battery is good, the only unknown is the odrive.

You might also try routing the 3 phase wires and the encoder wires along different paths on your chassis. That way they are farther away from each other and less likely to cross talk. I had to run them both through the same drag chain so it could not be helped.

Noted! I will try that. The body has so much spare room, I can easily separate them.

Hi Robert, me neither and totally understand as I am fairly new to ODrive, okay at the programming side of Arduino, but very little on Python, just learn as I go. Sorry it was @towen watching the vide, just re-read.

I just tried to mimic your 2 motors rapidly changing direction at max speed (although I have an AMT102 not hall encoder) with all the wire close and constantly sending commands, where I’m getting an occasional failure as follows: -

axis: Error(s):
motor: Error(s):
encoder: no error
controller: Error(s):
axis: no error
motor: no error
encoder: no error
controller: no error

I don’t know if this will help, but though I’d give it a go. My wires to the ODrive D5065-270KV motors are AWG8 (8.4mm2 or 3.3mm dia) over 1.5m and work perfectly well without twists, although as @CthulhuLabs suggested putting a twist in cancels out a lot of EMI as does the Cat5 cable, I may even braid mine too.

I hope you get your bot moving, would be good to see it all working.

OK, I gotta ask one more time, I’m still not clear. Where would I be seeing these errors? Is there a realtime debugging terminal that spits out errors? I’m used to controllers that have loggers and realtime terminals, etc. This is quite a bit different and more frustrating than using a VESC. Where do I find if I’m getting errors?

Ah sorry, from the “Anaconda 3 powershell” program that you can download if you are using windows. You can then connect the ODrive directly to a PC and then type commands to it.

Here is the walkthrough to get it all working: -

I would highly recommend using the liveplotter command from the Anaconda software mentioned above: -

start_liveplotter(lambda:[odrv0.axis0.encoder.pos_estimate, odrv0.axis0.controller.pos_setpoint, odrv0.axis1.encoder.pos_estimate, odrv0.axis1.controller.pos_setpoint])

this to see both motors and encoder positions.

You can also type these to see your config and any errors:-

dump_errors(odrv0, True)

Hope that helps.

Here is my setup also, although I’m using the AMT 102 rotary encoder, hence the 8192cpr value: -

odrv0.axis0.controller.config.pos_gain = 62.0
odrv0.axis0.controller.config.vel_gain = 5 / 10000.0
odrv0.axis0.controller.config.vel_integrator_gain = 25.0 / 10000.0
odrv0.axis0.motor.config.current_lim = 40
odrv0.axis0.controller.config.vel_limit = 360284.0 # Max Velocity
odrv0.axis0.controller.config.vel_limit = 20000.0 # Min Velocity
odrv0.config.brake_resistance = 0.5
odrv0.axis0.motor.config.calibration_current = 20
odrv0.axis0.motor.config.pole_pairs = 7
odrv0.axis0.motor.config.motor_type = MOTOR_TYPE_HIGH_CURRENT
odrv0.axis0.encoder.config.cpr = 8192

odrv0.axis0.requested_state = AXIS_STATE_FULL_CALIBRATION_SEQUENCE
odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
odrv0.axis0.controller.pos_setpoint = 0

From what I can tell there is no mention of it in the documentation, but while in the odrivetool simply type:

dump_errors(odrv0, False)

to see if there are any errors and see the human readable #defines for them. To clear the errors you can run:

dump_errors(odrv0, True)