I am trying to use multiple ODrives to control a cable robot. The four boards will be fed by a Quanser QPIDe Data Acquisition Device. The Quanser can only give out simple analog outputs. So, my question is multi-faceted.
is it even possible to control both motors of an Odrive with only analog inputs? if so, in what control mode?
how would you test such a system? would it be okay if I just attached a basic circuit (with variable resistance) to the analog input pins and then tested the system using differing resistances? or do I need something that can input a variable voltage?
I don’t know enough about the ODrive to know where to begin, so I am asking here before I start trying to edit firmware (which I assume is necessary to get a system like this working).
Yes that is perfectly possible. The best way is to make some changes to the firmware in Communication, add a make_protocol_function() or make_protocol_property(). From what I understand it is also possible to use the odrv0.config.gpio#_pwm_mapping() functions, but I don’t have experience using them.
You can read the GPIO values from your PC, using stock firmware, and write a control loop in python to test your control solution without modifying the firmware. Should work just fine. Just call odrv0.get_adc_voltage(#).
Lastly; be careful you don’t accidentaly fry any of your GPIO ports. Remember they are 0 - 3.2V (4096 bits). I think they are 5V tolerant, not sure, but the readout will not increase above 3.2V.
Thanks so much for your help. I, however, have no idea what you are talking about with your response to the first part of the question. I don’t know what it means to “add a make_protocol_function() or make_protocol_property()”.
After reading your comment @Riewert, this is what I was able to do:
But I guess I shouldn’t have done that before I knew how the functions worked. Nothing seems to have broken, but I can’t control the motor with the voltage input through GPIO3. Right now I just have the ability to vary the voltage input to GPIO3 between 3.3 and 0 volts. But changing the input does literally nothing other than change what I get when I run odrv0.get_adc_voltage(3).
I was able to write a python script that reads the value input to GPIO3 and control the motors through that. This, however, requires that I have a computer connected to each ODrive and have the script running in the background. This makes my processing very slow. The robot I am building needs to input information from the payload to the Quanser, have the computer compute the changes needed and then have the Quanser send commands to the ODrives. This is made significantly slower and more difficult if the output has to go from the computer to the Quanser and then back to the computer to be decoded.
I have tried to read through the firmware documentation but I don’t have nearly enough experience to understand what is going on in there. Any help as to what changes I have to do and where would be amazing. Thank you so much for any assistance you can provide.
No problem, I understand what you are going through.
I have no idea how odrv0.config.gpio3_analog_mapping.endpoint works, but from what your saying, maybe try making a mapping for gpio2 and gpio4. I noticed that the numbering of the GPIOs is not always consistent. I don’t know of anybody who has actually used the mapping functions… @Wetmelon Also, googleing led me to: https://flipsky.net/blogs/vesc-tool/how-to-use-fsodrive-base-on-odrive-3-14
It seems like the analog_mapping function is not working for me and doesn’t seem super well documented. So I doubt I will ever get it properly working. So, editing the firmware it is.
A slight issue, however, is that I don’t know how to compile the firmware (I actually don’t even know what that really means). I tried to go through the setup guide for windows on the documentation page here. But I don’t know if I downloaded the right materials in the right places because I don’t know how to use them in the first place.
I was able to download the firmware master and I can edit the code. But I am having issues with flashing the experimental firmware to the board. Whenever I’ve tried to flash the new code I bricked the board and had to completely reflash the master from here. Essentially I am asking if I have to compile the whole master (with my updates) into a single .hex file and then flash that? or if it is possible to flash a single .cpp file as an update to the old firmware? I can’t seem to find an answer online because I don’t know really anything about embedded systems.
Once again, thank you so much for all the help you have already given. You probably don’t know how much of godsend this is.
Yes, you need to compile the whole .hex file (even for the smallest changes). The easiest way to do that for me was through Visual Studio Code. How far are you getting with the compilation? Be sure to create a copy of tup.config for you board based on the tup.config.default file.
Also, how are you tranfering your code to the Odrive? Have you tried using the DFU mode over USB, by running odrivetool dfu custom_firmware.hex from the folder where the .hex file is? That works quite reliably for me.
I am currently in the process of working out how to compile the firmware in VSCode. But I ran into an issue that I can’t seem to surpass. I made a post about it here.
I think I correctly copied over the tup.config.default file and made it into a tup.config file correctly.
For flashing the firmware I was trying to use odrivetool dfu (file path) but that resulted in me bricking the board. The tool erased the old firmware and then crashed immediately afterward, resulting in a board with nothing on it. That meant that I couldn’t even run odrivetool dfu to put the firmware back on the board. So, I used the Upgrading firmware with a different DFU tool instructions to restore the firmware. I am more confident in my ability to flash the firmware than to edit it.
The main holdup right now is simply getting the firmware to compile into a flashable hex file. Which I am, slowly, making progress on.
Hi all.
Has there been any update to the analogue input use case since this thread in 2019?
I normally wouldn’t use an analogue input, but for my eBike conversion, it makes sense.
I have a Hall effect thumb throttle connected to GPIO5 (PC4 on the STM32). Is there any easy way to read that and map it to axis1.controller.input_current, or will I need to hack the firmware?
This sets the analog pin up to command between 0 and 10 amps. In my case I had to increase ‘min’ a bit to account for some offset in the thumb throttle.
However, I am using GPIO5, which doesn’t exist. To add it, I simply had to edit Firmware/odrive_interface.yaml (this seems to be a rather nice new feature in the Devel branch, but it has a couple of extra Python dependencies on build)
Well, I can confirm that ODrive works in an e-bike setting.
There’s a bit of noise induced onto the analogue input when the motor is running faster than a certain speed, and that can cause it to run indefinitely until I stop it with the manual brake.
I could probably fix that with a resistor to GND, since this is a Hall effect throttle, it can probably source enough current for a 10k pulldown without affecting its output value.
Oddly, putting it in INPUT_MODE_TORQUE_RAMP seems to make the problem worse.
Also, I’ve somehow managed to blow one of the 20A automotive fuses that I put in line with the motor phases, even though I have set the analogue mapping max to 10 (which produces a demand of 8A when at full throttle due to the offset/scaling of the throttle). Not sure how that could happen, unless the current controller is marginally stable, which wouldn’t surprise me. meas_l is 65400 (uH?) and I’m currently running from 19V.
I didn’t trip the 10A breaker which I fitted to the input to be on the safe side.
However, I’d now like to have a digital input control whether the bike applies forward or reverse thrust. This will be connected to the rear brake lever.
I’ll need to hack the firmware anyway, because I want that reverse thrust only to apply when the bike is moving above a certain positive speed. I don’t want a reverse gear! Also, I’d like it only to go into reverse “mode” when the throttle is zero, so I don’t get any sudden changes. (same applies to going forwards again)
But, not sure how best to define a digital input. Not sure that it’s possible in the odrive_interface.yaml file. I’d like it to map to any boolean or real-valued property in the same way the analogue input does.
I’m surprised, too!
But then it really is just another thing to go wrong. I have access to the source code of this wonderful open-source motor controller, so why not?