Summary on how I got going with windows 10


#1

Hi everybody,

I wanted to do a quick write up on how I got going with my ODrive and Windows10. Overall, I think the description in the getting started are pretty good, yet sometimes a bit more detail would be great. So essentially here is a write up, first of all to have a documentation for myself, and it might be useful for other people.

Components
As I’m not much of an expert in any of the fields involved, especially not electronics, I went for the usual combination of an 600 count encoder and the N5065 Motor. Furthermore, I ordered a 6/8mm coupler. In my case I had a Mean Well 24V 13A power supply around for powering the whole setup.

Motor holder
As I didn’t find any 3d printable sketch right away, I quickly sketched up a holder for this motor encoder combination. The baseplate is not completely symmetric, but does the job for testing purposes. If you are interested check this thingiverse thing.

Wire up
Okay, so people will make fun of me but this literally cost me 6-8 hours until I realized that I wired up my encoder incorrectly. So the motor is straightforward, I just plugged the 3 wires into the terminal, as different wiring only results in different spin direction as far as I understand. The encoder was plugged in this way, colors are the wires coming from the encoder (this is the correct way, or at least the way which is working for me): red - 5V, green - A, white - B, black - gnd. The power supply was connected, yet not powered on. The ST-Link V2 (included with the board, thanks a lot for this) , was plugged in the following: SWDIO - SWD, SWCLK - SWC, GND-GND. The resistor (also coming with the board, thanks!) was plugged into AUX terminal.

What I was doing wrong before and symptoms: Very first I plugged red into vcc. I was able to flash the board and the initialization routine was running. Yet, I was not able to send commands to the board. After a while I realized the motor was shutting off after the initialization routine, meaning I was able to spin it easily without any resistance. I watched the reference video and realized that my motor only briefly spins in one direction and doesn’t reverse, which I assumed points out that the encoder is not signaling. Once everything is wired up correctly, the motor spins around 1/8 of a rotation in one direction, and then the same reverse. After this it is possible to feel the position control if it is being rotated by hand.

Firmware setup / flash
The guide here is good in my opinion. The only brief struggle I had was putting everything into path, as I wasn’t able to figure out how to do this in cmd right away. I went the advanced systems settings -> Environment Variables -> Path to get all tools into path. From git the V3.3 branch was cloned by:

git clone <url> --branch <branch> --single-branch

<url> from git master
<branch> V3.3-pinout

Next, as mandatory, the motor specs were added into the low_level.c file in MotorControl. As the motor I’m using seems to be fairly standard, the settings were all okay right out of the box. However, as I was just testing one motor first (which I plugged into M1), I deactivated the M0 motor by .enable_control = false and .do_calibration = false in the // M0 section. Subsequently, in git bash, make and make flash worked right away.

Motor control
Here I failed for a long time, as the encoder was not correctly plugged in. Also the Python tool doesn’t work in my hands so far as the use of the print() function seems to be python3 specific, yet this can be fixed easily for python2 by adding from future import print_function at the very beginning of test_bulk.py. Yet, so far it is not recognizing the board and sends: ODrive BulkDevice Not Found I tried to get pyusb going for myself but this also didn’t work independently, so there might be an error to fix in my case.

What did work for me was the suggestion of tokol0sh. Using git bash I used ls /dev/ | grep “tty” to find the device ID of my board, which is /dev/ttyS5. Then I was able to use echo “p 1 1000 0 0” > /dev/ttyS5 to get the motor moving. Once there was a ‘permission denied’ error which just needed a re plugging of the USB connection to be fixed.

Motor tuning
I did an initial tune, which is very rudimentary (I wish there was a good youtube tutorial on this to get it straight). The velocity gain for me was pretty much already perfectly set, I tried to step it up the 30% way, and ended back at the original settings .vel_gain = 15.0f / 10000.0f, // [A/(counts/s)] as the motor started shaking very soon after stepping the value up. The position gain I was able to set up to .pos_gain = 200.0f,, and now gives me very tight control which I’ll need for integration into a CNC machine. The overshoots out of a spinning motion are good, so it stops very abruptly, but precisely. However, the motor starts vibrating a bit, not visible at the shaft, but the whole rig is slowly moving on the table. If I push it even more, to .pos_gain = 250.0f,, this gets really strong.

Maybe someone will find some use in this post if running in the same issues as I did.

One very pressing question I have is, if it is possible to avoid the start up routine for a non-changing setup?
I think the relatively heavy loads of a CNC machine will disturb this process.

Anyways, so far this looks very promising!

Cheers!


#2

Awesome write-up. These definitely help get people going! I’m also on Windows 10, and it can be a pain getting everything to play nice.

I went the advanced systems settings -> Environment Variables -> Path to get all tools into path.

Honestly, this is the easiest way to do it. One of the annoyances of cmd is making sure you’re in an elevated command prompt, which is easy to forget. Windows Key -> type “Environment Variables”, use the GUI is easy.

print() function seems to be python3 specific

Correct, the script won’t work with Python2 without modification.

Yet, so far it is not recognizing the board and sends: ODrive BulkDevice Not Found I tried to get pyusb going for myself but this also didn’t work independently, so there might be an error to fix in my case.

I just fought with this last night. You need to have the following things:

  • Python3, preferably
  • pip install --pre pyusb
  • Plug in the STLink to power the board
  • Plug in a separate USB cable into the microUSB connector on ODrive
  • Use Zadig utility to set ODrive (not STLink!) driver to libusb
  • Run test_bulk.py

Then it should finally work.

One very pressing question I have is, if it is possible to avoid the start up routine for a non-changing setup?
I think the relatively heavy loads of a CNC machine will disturb this process.

Define “start-up routine”. All of the gains, motor parameters, etc are hard-coded. Only the bits in “calibration” are not. Such as phase resistance, inductance, encoder direction, etc. Oskar and I talked a bit ago about ways to save configuration values, it’ll probably be in Flash on the STM32. I and others on here have started looking into autotuning methods also. So it’ll get there, it’s just slow with only a few people working on code!


#3

Hi Wetmelon,

Thanks for your answer!

Define “start-up routine”. All of the gains, motor parameters, etc are hard-coded. Only the bits in “calibration” are not.

I think I mean the process of acquiring the calibration values. So if I understand correctly when the board is starting up and the motor spins in both direction, there may not be any loads attached to it right? This is what I refer to:

Note: the rotor must be allowed to rotate without any biased load during startup. That means mass and weak friction loads are fine, but gravity or spring loads are not okay. Also note that in the video, the motors spin after initalisation, but in the current software the default behaviour is to do position control to position 0 (i.e. the position at startup)

The python code is currently not overly important to me as the next step will be step/dir control using grbl. Let’s see how this will work out.

Another project will be a rpm regulated motor for my lathe, maybe someone has an idea how to go from Arduino to setting rpms on this board?

Cheers!


#4

First of all: thank you so much for taking the time to write this up. It’s difficult for someone like myself who’s been hacking around on this project for 3 years to know what’s unclear from an outside perspective. Feedback like this is extremely valuable, so again: thank you!

Motor Holder

Thanks a lot for that contribution. We should figure out a way to organise contributions like this and to make it easy for people to find. Maybe I will make a summary post, and link from the getting-started post.

Wiring

There very much needs to be a decent wiring-diagram. I apologise profusely for the lack of such, it’s actually something that we’ve said for a long time that it should be made. I’ll make one today!

Firmware setup / flash

Yes this is the correct way to do it on Windows. I’ll add a note about that in the guide to make it more clear.

Note that the new Master handles all boards now! Instead of separate branches, you can set some defines, instructions here.

Awesome!! ;D

Motor control

I think the easiest fix here is to just install Python3. It should work alongside your existing python2 install: the command python will be python2, and python3 will be Python3. I think in the future maybe we will recommend installing an Anaconda distribution to make sure a bunch of prerequisites that we will be using for auto-tuning will be present in the expected configuration.
As for the pyusb, I think the instructions that @wetmelon gave is correct. To make it more straightforward, I added an enhancement task to improve the script.

@wetmelon: can you make a PR that puts these instructions in a good place in the Readme? Thanks!

One day, we will get to implementing Autotuning. This feature has had much discussion and planning, we just need to get past some other pressing features before we can start implementation. Here is the corresponding task.

Meanwhile, if you want to push the tunings with some manual tweaking, I would suggest bumping current_control_bandwidth (this) to something like 2k to 3k. The available response from the position/vel loop becomes faster if the current controller is faster, the tradeoff is higher acoustic noise from amplified current-sensor noise.
You can also try playing with the velocity filter bandwith: encoder_pll_bandwidth, (this). Higher values means you can keep track of higher accelerations without too much phase lag (this should let you increase vel_gain more!), but the tradeoff is that the finite resolution of the encoder becomes more choppy: less filtering of the discrete encoder ticks = more noise.

Again, once we have the auto-tuning framework, we can start identifying the load, and use model parameters and corresponding feed-forward terms to improve the dynamic response considerably.

Not really, not with an incremental encoder. The best solution I think is to turn up the calibration current to something “large”. Basically large enough to overcome the load of the attached machine but not enough to overheat the motor (it won’t have forced air cooling when stopped/going slow). Try something like 40A on the N5065. If you have a thermal camera or IR thermometer, you can keep an eye on the temperature of the coils.

Enabling UART comms from an Arduino (and accompanying tutorial/sample project on Arduino) is a high priority task. This is highly requested, and we’ll announce when it’s ready on the mailing list.