1. For downloading SimTools plugins you need a Download Package. Get it with virtual coins that you receive for forum activity or Buy Download Package - We have a zero Spam tolerance so read our forum rules first.

    Buy Now a Download Plan!
  2. Do not try to cheat our system and do not post an unnecessary amount of useless posts only to earn credits here. We have a zero spam tolerance policy and this will cause a ban of your user account. Otherwise we wish you a pleasant stay here! Read the forum rules
  3. We have a few rules which you need to read and accept before posting anything here! Following these rules will keep the forum clean and your stay pleasant. Do not follow these rules can lead to permanent exclusion from this website: Read the forum rules.
    Are you a company? Read our company rules

Question Odrive assistant needed

Discussion in 'DIY Motion Simulator Projects' started by lee.1970, Feb 20, 2021.

  1. lee.1970

    lee.1970 New Member

    Joined:
    Feb 14, 2015
    Messages:
    2
    Occupation:
    Field service engineer
    Location:
    Devon U.K.
    Balance:
    - 7Coins
    Ratings:
    +0 / 0 / -0
    My Motion Simulator:
    3DOF, DC motor, JRK
    Hi Guy's
    can anyone shed some light on Odrive configurations,
    I've stupidly bought Odrives thinking that it would be easy to figure out but I'm having a hard time figuring it out, I've had a few pointers from @SilentChill but really need some one to one help , I know that everyone has many commitments but would appreciate some help.
    Cheers Guys
    Lee
    Discord (lee1970)
    Last edited by a moderator: Feb 20, 2021
  2. Ads Master

    Ads Master

    Balance:
    Coins
    Ratings:
    +0 / 0 / -0
  3. jimmejames

    jimmejames New Member

    Joined:
    Mar 28, 2015
    Messages:
    3
    Balance:
    15Coins
    Ratings:
    +3 / 0 / -0
    My Motion Simulator:
    6DOF
    Background - I've got a mix of official and "opensource" (read: knockoff) Odrives (all V3.6-56V) using AMT103-V encoders (currently I don't have endstops). The opensource boards do not have the OTPs set, so I am not able to upgrade the firmware past 0.5.1 (0.5.3 says it can run on drives without the OTP set, but I've been unsuccessful in getting the odrivetool started on Anaconda (running a Win 10 box). I'm building a sim heavily influenced by @PeterW, @Carelsbergh_Stijn, and @SilentChill, and using @pmvcda's FlyPT mover, but will post details on that setup in another post.

    Here's what I used to configure both axis on the opensource Odrive's:
    Code:
    odrv0.erase_configuration()
    odrv0.config.brake_resistance = 2.0
    odrv0.config.dc_bus_undervoltage_trip_level = 8.0
    odrv0.config.dc_bus_overvoltage_trip_level = 56.0
    odrv0.save_configuration()
    odrv0.axis0.controller.config.vel_limit = 2
    odrv0.axis0.motor.config.pole_pairs = 7
    odrv0.axis0.motor.config.calibration_current = 5
    odrv0.axis0.motor.config.current_lim = 30
    odrv0.axis0.motor.config.torque_constant = 0.04135
    odrv0.axis0.motor.config.motor_type = MOTOR_TYPE_HIGH_CURRENT
    odrv0.save_configuration()
    odrv0.axis0.requested_state = AXIS_STATE_MOTOR_CALIBRATION
    odrv0.axis0.motor.config.pre_calibrated = True
    odrv0.save_configuration()
    odrv0.axis0.encoder.config.mode = ENCODER_MODE_INCREMENTAL
    odrv0.axis0.encoder.config.cpr = 8192
    odrv0.axis0.encoder.config.use_index = True
    odrv0.axis0.requested_state = AXIS_STATE_ENCODER_INDEX_SEARCH
    odrv0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
    odrv0.axis0.encoder.config.pre_calibrated = True
    odrv0.axis0.config.startup_encoder_index_search = True
    odrv0.axis0.config.startup_encoder_offset_calibration = True
    odrv0.save_configuration()
    odrv0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
    odrv0.axis0.config.startup_closed_loop_control = True
    odrv0.save_configuration()
    odrv0.axis1.controller.config.vel_limit = 2
    odrv0.axis1.motor.config.pole_pairs = 7
    odrv0.axis1.motor.config.calibration_current = 5
    odrv0.axis1.motor.config.current_lim = 30
    odrv0.axis1.motor.config.torque_constant = 0.04135
    odrv0.axis1.motor.config.motor_type = MOTOR_TYPE_HIGH_CURRENT
    odrv0.save_configuration()
    odrv0.axis1.requested_state = AXIS_STATE_MOTOR_CALIBRATION
    odrv0.axis1.motor.config.pre_calibrated = True
    odrv0.save_configuration()
    odrv0.axis1.encoder.config.mode = ENCODER_MODE_INCREMENTAL
    odrv0.axis1.encoder.config.cpr = 8192
    odrv0.axis1.encoder.config.use_index = True
    odrv0.axis1.requested_state = AXIS_STATE_ENCODER_INDEX_SEARCH
    odrv0.axis1.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
    odrv0.axis1.encoder.config.pre_calibrated = True
    odrv0.axis1.config.startup_encoder_index_search = True
    odrv0.axis1.config.startup_encoder_offset_calibration = True
    odrv0.save_configuration()
    odrv0.axis1.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
    odrv0.axis1.config.startup_closed_loop_control = True
    odrv0.save_configuration()
    odrv0.reboot()
    Verification steps:
    odrv0.axis0.error
    odrv0.axis1.error
    #both the above commands should print out 0
    Note, the above values are based on my configuration (e.g. pole_pairs are based on my motors- I'm using BDUAV 6364-200KV BLDCs from AliExpress, and torque_constant is 8.27 / KV of your motor). It's very likely I don't need near as many "odrv0.save_configuration()" during the loading... to be determined. I just finished the above start to finish and my drives responded to FlyPT inputs.

    I'm struggling to get my own FlyPT configuration setup- just looking for a basic sine-wave input driving both motors. So, the next is how I'm currently verifying my motors are getting a signal- it's not meant as the final product. I'll keep working through that, but for now I use @PeterW's "Flugprofil" from here: https://www.xsimulator.net/community/threads/weird-odrive-issue.16405/#post-219688.
    Once you open that *.mover file in FlyPT, left click "OUTPUT :: SERIAL1", set your Port as required, I cleared all entries in the "Start string" and "Stop string" fields, and replaced the "Output string" field with:
    Code:
    p 0 <Axis1a> 0 <13>p 1 <Axis2a> 0 <13>
    . After clicking "Connect", both drives rotate about 15 complete rotations (don't yet know why). Then, left click on "POSE :: FROM MOTION (1)" and move the "Heave" slider bar for the "In/Out value" and your motors should respond immediately.

    Last note (as a precursor to all of the above and done on a Ubuntu 20.04.4 LTS box with Visual Studio Code v1.68.0)- the 0.5.1 firmware doesn't let you add to the "axis.encoder_.config_.cpr" and compile the ascii_protocol.cpp as discussed in various other posts. As such, given that appears to just be the cpr count of the encoder (8192 (2048 * 4) in my case given my AMT103-V encoders), I changed row 108 of the ascii_protocol.cpp (in the "firmware/communication" folder of the official 0.5.1 source code) to:
    Code:
    axis->controller_.input_pos_ = pos_setpoint / 8192;
    I do not know if this is correct! And my trainer isn't far enough along, but the firmware will not compile with the original suggestion and without the "/ 8192" I think the motor gets the wrong values.
    Then, I renamed "tup.config.default" to just "tub.config" (in the "firmware" folder) and changed row 3 to:
    Code:
    CONFIG_BOARD_VERSION=V3.6-56V
    "make all" then "make flash" on a terminal in uploaded the firmware to my opensource Odrive via a ST-LinkV2 where I've connected only SWCLK, SWDIO, and GND.
    • Like Like x 1
  4. jimmejames

    jimmejames New Member

    Joined:
    Mar 28, 2015
    Messages:
    3
    Balance:
    15Coins
    Ratings:
    +3 / 0 / -0
    My Motion Simulator:
    6DOF
    While the 0.5.1 firmware works, there were some nice features added in the 0.5.4 version and, if I replace "opensource" boards with official boards in the future, I'd like them all running the same firmware.

    Here's what I did to get 0.5.4 working on "opensource" boards.

    Firmware 0.5.4-
    • Within Visual Studio Code (I'm running 1.68.0 on a Ubuntu 20.04.4 LTS 64bit machine)
      • Rename "tub.config.default" to "tub.config" in the Firmware folder from the source zip
      • In that "tub.config file", change line #3 to your board. Mine is:
        Code:
        CONFIG_BOARD_VERSION=v3.6-56V
        .
        • Save the file.
      • Change row 145 to:
        Code:
        axis.controller_.input_pos_ = pos_setpoint / axis.encoder_.config_.cpr;
        • Save the file
    • Select "New Terminal" within Visual Studio Code and run the following commands after connecting the ST-LINK V2 to your Odrive (pins SWCLK, SWDIO, and GNS) and powering the Odrive from a separate power supply:
    Code:
    make all
    make flash
    Mine took about 50s to make and 16s to flash to my Odrive. There were two notes that appeared not to make any difference:
    Within Anaconda (I'm running Anaconda3-2022.05-Windows-x86_64 on a Win 10 Pro machine):
    Upon running 'odrivetool', I get two errors:
    followed by the location information for a "shell.py" file.

    To address the task exception error, navigate to the location of that "shell.py" file and edit line 20.
    Code:
    #    display_name, serial_number, var_name = mount_result
        serial_number, var_name = mount_result
        display_name = "generic"
    You can probably set the display_name to about anything you want, but I got another error setting it to "serial_number", so something other than that :)

    From there, calibration of each motor was pretty similar to the above post with two main exceptions:
    1) The commands all start with "dev0" vs "odrv0".
    2) If not explicitly told to be idle, the motor states would cause the save commands to fail. This was a bigger problem on the second motor and required me to periodically set the first motor to idle- so the "dev0.axis0.requested_state = AXIS_STATE_IDLE" in the middle of configuring the odev0.axis1 are not typos.

    Code:
    dev0.erase_configuration()
    dev0.config.enable_brake_resistor = True
    dev0.config.brake_resistance = 2.0
    dev0.config.dc_bus_undervoltage_trip_level = 8.0
    dev0.config.dc_bus_overvoltage_trip_level = 56.0
    dev0.save_configuration()
    dev0.axis0.controller.config.vel_limit = 2
    dev0.axis0.motor.config.pole_pairs = 7
    dev0.axis0.motor.config.calibration_current = 5
    dev0.axis0.motor.config.current_lim = 30
    dev0.axis0.motor.config.torque_constant = 0.04135
    dev0.axis0.motor.config.motor_type = MOTOR_TYPE_HIGH_CURRENT
    dev0.save_configuration()
    dev0.axis0.requested_state = AXIS_STATE_MOTOR_CALIBRATION
    dev0.axis0.motor.config.pre_calibrated = True
    dev0.save_configuration()
    dev0.axis0.encoder.config.mode = ENCODER_MODE_INCREMENTAL
    dev0.axis0.encoder.config.cpr = 8192
    dev0.axis0.encoder.config.use_index = True
    dev0.axis0.requested_state = AXIS_STATE_ENCODER_INDEX_SEARCH
    dev0.axis0.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
    dev0.axis0.encoder.config.pre_calibrated = True
    dev0.axis0.config.startup_encoder_index_search = True
    dev0.axis0.config.startup_encoder_offset_calibration = True
    dev0.save_configuration()
    dev0.axis0.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
    dev0.axis0.config.startup_closed_loop_control = True
    dev0.axis0.requested_state = AXIS_STATE_IDLE
    dev0.save_configuration()
    dev0.axis1.controller.config.vel_limit = 2
    dev0.axis1.motor.config.pole_pairs = 7
    dev0.axis1.motor.config.calibration_current = 5
    dev0.axis1.motor.config.current_lim = 30
    dev0.axis1.motor.config.torque_constant = 0.04135
    dev0.axis1.motor.config.motor_type = MOTOR_TYPE_HIGH_CURRENT
    dev0.axis0.requested_state = AXIS_STATE_IDLE
    dev0.save_configuration()
    dev0.axis1.requested_state = AXIS_STATE_MOTOR_CALIBRATION
    dev0.axis1.motor.config.pre_calibrated = True
    dev0.axis0.requested_state = AXIS_STATE_IDLE
    dev0.save_configuration()
    dev0.axis1.encoder.config.mode = ENCODER_MODE_INCREMENTAL
    dev0.axis1.encoder.config.cpr = 8192
    dev0.axis1.encoder.config.use_index = True
    dev0.axis1.requested_state = AXIS_STATE_ENCODER_INDEX_SEARCH
    dev0.axis1.requested_state = AXIS_STATE_ENCODER_OFFSET_CALIBRATION
    dev0.axis1.encoder.config.pre_calibrated = True
    dev0.axis1.config.startup_encoder_index_search = True
    dev0.axis1.config.startup_encoder_offset_calibration = True
    dev0.axis0.requested_state = AXIS_STATE_IDLE
    dev0.save_configuration()
    dev0.axis1.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
    dev0.axis1.config.startup_closed_loop_control = True
    dev0.axis0.requested_state = AXIS_STATE_IDLE
    dev0.axis1.requested_state = AXIS_STATE_IDLE
    dev0.save_configuration()
    dev0.reboot()
    Same disclaimers as above, YMMV, I probably save way too many times, and I don't have a solid procedure for getting the FlyPT setup- hopefully a third and final post after the weekend will have this last piece.
    • Like Like x 1
  5. jimmejames

    jimmejames New Member

    Joined:
    Mar 28, 2015
    Messages:
    3
    Balance:
    15Coins
    Ratings:
    +3 / 0 / -0
    My Motion Simulator:
    6DOF
    This wasn't requested in the original post, but given FlyPT is opensource, an excellent tool, and an easy way to verify operation of the Odrives, here's the configuration I used. Note, the intent is simply to verify the Odrive is responsive to inputs, this could not be dropped into a trainer as-is (there are plenty of other examples in the forums of others' setups).

    This was done on an opensource Odrive running the 0.5.4 firmware (board from the post immediately above) and on FlyPT Mover 3.5.3.

    upload_2022-6-25_20-52-44.png

    If difficult to read, I added:
    • (qty 1) Serial Output
      • Type of output: Decimal
      • Interval loops 1
      • Serial Speed: 115200
      • Stop bits: 1
      • Data bits: 8
      • Parity: None
      • Port: [computer specific- click "Open devices" and located your port for your Odrive]. And/or, click "Update ports" and select from the available.
      • Start string: [blank]
      • Output: p 0 <Axis1a> 0 <13>p 1 <Axis2a> 0 <13>
      • Stop string: [blank]
      • Input string [blank]
    • (qty 2) Simple Direct
      • Actuator key: Axis1a [for one simple direct and Axis2a for the other]
      • Bit output: 18
      • Value range to big range from: 0.0 to 100.0
      • Value for the actuator: [doesn't appear to matter what you select]
    Then, sliding the Actuator slider on each Simple Direct will cause your motors to spin.

    Now, it appears the <Actuator key> in the simple directs can be about anything you want to be AS LONG AS they match what you have in the Output string in the Output Serial.

    For example, this works:
    • Serial Output:
      • Output string: p 0 <IamAxis0> 0 <13>p 1 <IamAxis1> 0 <13>
    • Simple Direct (#1)
      • Actuator key: IamAxis0
    • Simple Direct (#2)
      • Actuator key: IamAxis1
    But, the names are case specific, so Actuator key: Iamaxis0 will fail as the "a" is not capitalized.

    Troubleshooting:
    The first time through, my Axis 1 did not spin. I reopened Anaconda and checked for errors:
    Code:
    dev0.axis0.error
    dev0.axis1.error
    Both had in Out of 0 (signaling no errors). I then reset the requested state and startup information for Axis 1:
    Code:
    dev0.axis1.requested_state = AXIS_STATE_CLOSED_LOOP_CONTROL
    dev0.axis1.config.startup_closed_loop_control = True
    dev0.axis0.requested_state = AXIS_STATE_IDLE
    dev0.axis1.requested_state = AXIS_STATE_IDLE
    dev0.save_configuration()
    
    I have not been able to replicate the original error, so perhaps I had a typo in FlyPT?!?

    I'm not allowed to upload my *.mover file (too few posts?)- hopefully the above instructions an image will suffice.
    • Informative Informative x 1