diff --git a/docs/testing.md b/docs/testing.md index 1c4e42c3..5ba1160b 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -17,6 +17,7 @@ The testing facility consists of the following components: - `can_test.py`: Partial coverage of the commands described in [CAN Protocol](can-protocol) - `closed_loop_test.py`: Velocity control, position control (TODO: sensorless control), brake regen current hard limit, current control with velocity limiting - `encoder_test.py`: Incremental encoder, hall effect encoder, sin/cos encoder, SPI encoders (AMS, CUI) + - `fibre_test.py`: General USB protocol tests - `nvm_test.py`: Configuration storage - `pwm_input_test.py`: PWM input - `step_dir_test.py`: Step/dir input diff --git a/tools/odrive/tests/fibre_test.py b/tools/odrive/tests/fibre_test.py new file mode 100644 index 00000000..75801a5b --- /dev/null +++ b/tools/odrive/tests/fibre_test.py @@ -0,0 +1,56 @@ + +import test_runner + +import time + +from fibre.utils import Logger +from odrive.enums import * +from test_runner import * + +class FibreFunctionalTest(): + """ + Tests basic protocol functionality. + """ + + def get_test_cases(self, testrig: TestRig): + return testrig.get_components(ODriveComponent) + + def run_test(self, odrive: ODriveComponent, logger: Logger): + # Test property read/write + odrive.handle.test_property = 42 + test_assert_eq(odrive.handle.test_property, 42) + odrive.handle.test_property = 0xffffffff + test_assert_eq(odrive.handle.test_property, 0xffffffff) + + # Test function call + val = odrive.handle.get_adc_voltage(0) + test_assert_within(val, 0.01, 3.29) + + # Test custom setter (aka property write hook) + odrive.handle.axis0.motor.config.phase_resistance = 1 + odrive.handle.axis0.motor.config.phase_inductance = 1 + odrive.handle.axis0.motor.config.current_control_bandwidth = 1000 + old_gain = odrive.handle.axis0.motor.current_control.p_gain + test_assert_eq(old_gain, 1000, accuracy=0.0001) # must be non-zero for subsequent check to work + odrive.handle.axis0.motor.config.current_control_bandwidth /= 2 + test_assert_eq(odrive.handle.axis0.motor.current_control.p_gain, old_gain / 2, accuracy=0.0001) + +class FibreBurnInTest(): + """ + Tests continuous usage of the protocol. + """ + + def get_test_cases(self, testrig: TestRig): + return testrig.get_components(ODriveComponent) + + def run_test(self, odrive: ODriveComponent, logger: Logger): + data = record_log(lambda: [odrive.handle.vbus_voltage], duration=10.0) + expected_data = np.mean(data[:,1]) * np.ones(data[:,1].size) + test_curve_fit(data, expected_data, max_mean_err = 0.1, inlier_range = 0.5, max_outliers = 0) + + +if __name__ == '__main__': + test_runner.run([ + FibreFunctionalTest(), + FibreBurnInTest(), + ]) diff --git a/tools/odrive/tests/uart_ascii_test.py b/tools/odrive/tests/uart_ascii_test.py index 17cf85f8..ee9a3fa4 100644 --- a/tools/odrive/tests/uart_ascii_test.py +++ b/tools/odrive/tests/uart_ascii_test.py @@ -89,6 +89,15 @@ class TestUartAscii(): response = int(ser.readline().strip()) test_assert_eq(response, 12345) + # Test custom setter (aka property write hook) + odrive.handle.axis0.motor.config.phase_resistance = 1 + odrive.handle.axis0.motor.config.phase_inductance = 1 + odrive.handle.axis0.motor.config.current_control_bandwidth = 1000 + old_gain = odrive.handle.axis0.motor.current_control.p_gain + test_assert_eq(old_gain, 1000, accuracy=0.0001) # must be non-zero for subsequent check to work + ser.write('w axis0.motor.config.current_control_bandwidth {}\n'.format(odrive.handle.axis0.motor.config.current_control_bandwidth / 2).encode('ascii')) + test_assert_eq(ser.readline(), b'') + test_assert_eq(odrive.handle.axis0.motor.current_control.p_gain, old_gain / 2, accuracy=0.0001) # Test 'c', 'v', 'p', 'q' and 'f' commands