How to ? Odrivetool command macros

I realize the purpose of Odrivetool is to provide an interactive shell to control the device manually (good thing!). And the docs show how to use Python scripts which import the odrive package and interact with the drive (very good thing!). But i was hoping for something in between, where i could have both at once - manual interaction where i might bundle multi-statement actions into python “macro scripts”. But i have not yet figured out how to make that work effectively.

A “macro” script would need to share the namespace with the interactive shell. That does not happen. See this simple example log.

Connected to ODrive 205337925753 as odrv0
In [1]: import macro
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
C:\programs\Odrive\Python3.8.6\Lib\site-packages\odrive\pyfibre\fibre\shell.py in <module>
----> 1 import macro

c:\data\Vuba\MCU\macro.py in <module>
      8 import odrive
      9
---> 10 odrv0.vbus_voltage
     11
     12 # ----------------------- end of code ------------------------

NameError: name 'odrv0' is not defined

In [2]:

You can see after connecting i do a single import, and you can see the entire imported macro.py file (3 lines) . It fails to see the odrivetool’s odrv0 variable. ‘from macros import *’ encountered the same failure.

I tried a number of ways without success. Has to be a 2 step process - import then call. odrv0 can’t be passed as an argument. Macros have to “rediscover” odrive using find_any(serial_number). Macro commands do not echo on the console…and more. So before i run off too far into the woods…

Is there anything already in odrivetool that i don’t know about, or a plan of attack you may already have
thought about, for how to make this work ?

Odrivetool is based on ipython - you can define python functions and import modules as you guessed, but - the module you defined doesn’t know about this odrv0 object.

You need to make a python class in your module, and then pass the odrv0 object (or better, the axis you want to use) in to its constructor.

e.g. make a file odriveMacros.py with a class like this:

class macro:
   def __init__(self, axis):
       self.axis = axis
   def jog(self, turns):
       self.axis.controller.input_pos = self.axis.encoder.pos_estimate + turns

Then something like this would work in odrivetool

import odriveMacros

m = odriveMacros.macro(odrv0.axis0)
m.jog(3)

Also note: the macros can’t rediscover the odrive with find_any() because the main script (odrivetool) is already using the device. So you have to pass the object as an argument.

Also to make the commands echo to the console, you need to print or return them to the calling script e.g.

def pos_err(self):
       return self.axis.controller.input_pos - self.axis.encoder.pos_estimate
1 Like