mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-09-26 12:27:45 +08:00
add dump errors util function
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
# Unreleased Features
|
||||
Please add a note of your changes below this heading if you make a Pull Request.
|
||||
|
||||
### Added
|
||||
* `dump_errors()` utility function in odrivetool to dump, decode and optionally clear errors.
|
||||
|
||||
# Releases
|
||||
## [0.4.7] - 2018-11-28
|
||||
### Added
|
||||
|
||||
+2
-14
@@ -14,21 +14,9 @@ Table of Contents:
|
||||
<!-- /TOC -->
|
||||
|
||||
## Error codes
|
||||
If your ODrive is not working as expected, run `odrivetool` and type `hex(<axis>.error)` <kbd>Enter</kbd> where `<axis>` is the axis that isn't working. This will display a [hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) representation of the error code. Each bit represents one error flag.
|
||||
|
||||
<details><summary markdown="span">Example</summary><div markdown="block">
|
||||
Say you got this error output:
|
||||
```python
|
||||
In [1]: hex(odrv0.axis0.error)
|
||||
Out[1]: '0x6'
|
||||
```
|
||||
|
||||
Written in binary, the number `0x6` corresponds to `110`, that means bits 1 and 2 are set (counting starts at 0).
|
||||
Looking at the reference below, this means that both `ERROR_DC_BUS_UNDER_VOLTAGE` and `ERROR_DC_BUS_OVER_VOLTAGE` occurred.
|
||||
</div></details>
|
||||
|
||||
The axis error may say that some other component has failed. Say it reports `ERROR_ENCODER_FAILED`, then you need to go check the encoder error: `hex(<axis>.encoder.error)`.
|
||||
If your ODrive is not working as expected, run `odrivetool` and type `dump_errors(odrv0)` <kbd>Enter</kbd>. This will dump a list of all the errors that are present. To also clear all the errors, you can run `dump_errors(odrv0, True)`.
|
||||
|
||||
The following sections will give some guidance on the most common errors. You may also check the code for the full list of errors:
|
||||
* Axis error flags defined [here](../Firmware/MotorControl/axis.hpp).
|
||||
* Motor error flags defined [here](../Firmware/MotorControl/motor.hpp).
|
||||
* Encoder error flags defined [here](../Firmware/MotorControl/encoder.hpp).
|
||||
|
||||
+41
-11
@@ -11,17 +11,47 @@ AXIS_STATE_ENCODER_INDEX_SEARCH = 6
|
||||
AXIS_STATE_ENCODER_OFFSET_CALIBRATION = 7
|
||||
AXIS_STATE_CLOSED_LOOP_CONTROL = 8
|
||||
|
||||
AXIS_ERROR_NONE = 0
|
||||
AXIS_ERROR_INVALID_STATE = 1
|
||||
#AXIS_ERROR_DC_BUS_UNDER_VOLTAGE = 2
|
||||
#AXIS_ERROR_DC_BUS_OVER_VOLTAGE = 3
|
||||
#AXIS_ERROR_CURRENT_MEASUREMENT_TIMEOUT = 4
|
||||
#AXIS_ERROR_CONTROL_LOOP_TIMEOUT = 5
|
||||
#AXIS_ERROR_MOTOR_FAILED = 6
|
||||
#AXIS_ERROR_SENSORLESS_ESTIMATOR_FAILED = 7
|
||||
#AXIS_ERROR_ENCODER_FAILED = 8
|
||||
#AXIS_ERROR_CONTROLLER_FAILED = 9
|
||||
#AXIS_ERROR_POS_CTRL_DURING_SENSORLESS = 10
|
||||
class errors:
|
||||
class axis:
|
||||
ERROR_NONE = 0x00
|
||||
ERROR_INVALID_STATE = 0x01 #<! an invalid state was requested
|
||||
ERROR_DC_BUS_UNDER_VOLTAGE = 0x02
|
||||
ERROR_DC_BUS_OVER_VOLTAGE = 0x04
|
||||
ERROR_CURRENT_MEASUREMENT_TIMEOUT = 0x08
|
||||
ERROR_BRAKE_RESISTOR_DISARMED = 0x10 #<! the brake resistor was unexpectedly disarmed
|
||||
ERROR_MOTOR_DISARMED = 0x20 #<! the motor was unexpectedly disarmed
|
||||
ERROR_MOTOR_FAILED = 0x40 # Go to motor.hpp for information, check odrvX.axisX.motor.error for error value
|
||||
ERROR_SENSORLESS_ESTIMATOR_FAILED = 0x80
|
||||
ERROR_ENCODER_FAILED = 0x100 # Go to encoder.hpp for information, check odrvX.axisX.encoder.error for error value
|
||||
ERROR_CONTROLLER_FAILED = 0x200
|
||||
ERROR_POS_CTRL_DURING_SENSORLESS = 0x400
|
||||
|
||||
class motor:
|
||||
ERROR_NONE = 0
|
||||
ERROR_PHASE_RESISTANCE_OUT_OF_RANGE = 0x0001
|
||||
ERROR_PHASE_INDUCTANCE_OUT_OF_RANGE = 0x0002
|
||||
ERROR_ADC_FAILED = 0x0004
|
||||
ERROR_DRV_FAULT = 0x0008
|
||||
ERROR_CONTROL_DEADLINE_MISSED = 0x0010
|
||||
ERROR_NOT_IMPLEMENTED_MOTOR_TYPE = 0x0020
|
||||
ERROR_BRAKE_CURRENT_OUT_OF_RANGE = 0x0040
|
||||
ERROR_MODULATION_MAGNITUDE = 0x0080
|
||||
ERROR_BRAKE_DEADTIME_VIOLATION = 0x0100
|
||||
ERROR_UNEXPECTED_TIMER_CALLBACK = 0x0200
|
||||
ERROR_CURRENT_SENSE_SATURATION = 0x0400
|
||||
|
||||
class encoder:
|
||||
ERROR_NONE = 0
|
||||
ERROR_UNSTABLE_GAIN = 0x01
|
||||
ERROR_CPR_OUT_OF_RANGE = 0x02
|
||||
ERROR_NO_RESPONSE = 0x04
|
||||
ERROR_UNSUPPORTED_ENCODER_MODE = 0x08
|
||||
ERROR_ILLEGAL_HALL_STATE = 0x10
|
||||
ERROR_INDEX_NOT_FOUND_YET = 0x20
|
||||
|
||||
class controller:
|
||||
ERROR_NONE = 0
|
||||
ERROR_OVERSPEED = 0x01
|
||||
|
||||
MOTOR_TYPE_HIGH_CURRENT = 0
|
||||
#MOTOR_TYPE_LOW_CURRENT = 1
|
||||
|
||||
@@ -5,7 +5,7 @@ import threading
|
||||
import fibre
|
||||
import odrive
|
||||
import odrive.enums
|
||||
from odrive.utils import start_liveplotter
|
||||
from odrive.utils import start_liveplotter, dump_errors
|
||||
#from odrive.enums import * # pylint: disable=W0614
|
||||
|
||||
def print_banner():
|
||||
@@ -76,7 +76,8 @@ def launch_shell(args, logger, app_shutdown_token):
|
||||
"""
|
||||
|
||||
interactive_variables = {
|
||||
'start_liveplotter': start_liveplotter
|
||||
'start_liveplotter': start_liveplotter,
|
||||
'dump_errors': dump_errors
|
||||
}
|
||||
|
||||
# Expose all enums from odrive.enums
|
||||
|
||||
+39
-3
@@ -7,6 +7,7 @@ import platform
|
||||
import subprocess
|
||||
import os
|
||||
from fibre.utils import Event
|
||||
from odrive.enums import errors
|
||||
|
||||
try:
|
||||
if platform.system() == 'Windows':
|
||||
@@ -19,13 +20,48 @@ except ImportError:
|
||||
sys.stdout.flush()
|
||||
pass
|
||||
|
||||
data_rate = 100
|
||||
plot_rate = 10
|
||||
num_samples = 1000
|
||||
_VT100Colors = {
|
||||
'green': '\x1b[92;1m',
|
||||
'cyan': '\x1b[96;1m',
|
||||
'yellow': '\x1b[93;1m',
|
||||
'red': '\x1b[91;1m',
|
||||
'default': '\x1b[0m'
|
||||
}
|
||||
|
||||
class OperationAbortedException(Exception):
|
||||
pass
|
||||
|
||||
def dump_errors(odrv, clear=False):
|
||||
axes = [axis for name, axis in odrv._remote_attributes.items() if 'axis' in name]
|
||||
for num, axis in enumerate(axes):
|
||||
print('Axis{}:'.format(num))
|
||||
|
||||
# Flatten axis and submodules
|
||||
# (name, remote_obj, errorcode)
|
||||
module_decode_map = [
|
||||
('axis', axis, errors.axis),
|
||||
('motor', axis.motor, errors.motor),
|
||||
('encoder', axis.encoder, errors.encoder),
|
||||
('controller', axis.controller, errors.controller),
|
||||
]
|
||||
|
||||
# Module error decode
|
||||
for name, remote_obj, errorcodes in module_decode_map:
|
||||
prefix = ' '*2 + name + ": "
|
||||
if (remote_obj.error != errorcodes.ERROR_NONE):
|
||||
print(prefix + _VT100Colors['red'] + "Error(s):" + _VT100Colors['default'])
|
||||
errorcodes_tup = [(name, val) for name, val in errorcodes.__dict__.items() if 'ERROR_' in name]
|
||||
for codename, codeval in errorcodes_tup:
|
||||
if remote_obj.error & codeval != 0:
|
||||
print(" " + codename)
|
||||
if clear:
|
||||
remote_obj.error = errorcodes.ERROR_NONE
|
||||
else:
|
||||
print(prefix + _VT100Colors['green'] + "no error" + _VT100Colors['default'])
|
||||
|
||||
data_rate = 100
|
||||
plot_rate = 10
|
||||
num_samples = 1000
|
||||
def start_liveplotter(get_var_callback):
|
||||
"""
|
||||
Starts a liveplotter.
|
||||
|
||||
Reference in New Issue
Block a user