From d868e7fb53c3bb0a0fe0271c1cc6456b84ff34ae Mon Sep 17 00:00:00 2001 From: Samuel Sadok Date: Wed, 14 Oct 2020 20:22:41 +0200 Subject: [PATCH] make HWIL tests less hardware-dependent --- docs/testing.md | 29 +++++--- tools/odrive/tests/calibration_test.py | 9 ++- tools/odrive/tests/can_test.py | 6 +- tools/odrive/tests/closed_loop_test.py | 2 +- tools/odrive/tests/fibre_test.py | 2 +- tools/odrive/tests/not_a_test.py | 19 +++-- tools/odrive/tests/pwm_input_test.py | 29 ++++---- tools/odrive/tests/step_dir_test.py | 6 +- tools/odrive/tests/test_runner.py | 40 ++++++----- tools/odrive/tests/uart_ascii_test.py | 50 +++++++------ tools/test-rig-rpi.yaml | 9 +-- tools/test-rig-rpi4.yaml | 98 ++++++++++++++++++++++++++ 12 files changed, 210 insertions(+), 89 deletions(-) create mode 100644 tools/test-rig-rpi4.yaml diff --git a/docs/testing.md b/docs/testing.md index 5ba1160b..720fee2e 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -44,7 +44,7 @@ If your test rig differs, you may be able to run some but not all of the tests. ## How to set up a Raspberry Pi as testing host - 1. Install Raspbian Lite on a Raspberry Pi 4.0. I used the NOOBS installer for this. + 1. Install Raspbian Lite on a Raspberry Pi 4.0. This is easiest if you have a keyboard, mouse and screen (micro-HDMI!). I used the [NOOBS Lite installer](https://www.raspberrypi.org/downloads/noobs/) for this. Paste the ZIP-file's contents onto a FAT32 formatted SD card (fs type `0b` in `fdisk`) and boot it. Then follow the on-screen instructions. 2. Prepare the installation: sudo systemctl enable ssh @@ -52,6 +52,7 @@ If your test rig differs, you may be able to run some but not all of the tests. # Transfer your public key for passwordless SSH. All subsequent steps can be done via SSH. sudo apt-get update sudo apt-get upgrade + # Change /etc/hostname to something meaningful 3. Add the following lines to `/boot/config.txt`: - `enable_uart=1` @@ -66,7 +67,7 @@ If your test rig differs, you may be able to run some but not all of the tests. 6. Install the prerequisites: - sudo apt-get install ipython3 python3-appdirs python3-yaml python3-usb python3-serial python3-can python3-scipy git openocd + sudo apt-get install ipython3 python3-appdirs python3-yaml python3-usb python3-serial python3-can python3-scipy python3-matplotlib python3-ipdb git openocd # Optionally, to be able to compile the firmware: sudo apt-get install gcc-arm-none-eabi @@ -74,30 +75,36 @@ If your test rig differs, you may be able to run some but not all of the tests. sudo apt-get install libfontconfig libxft2 libusb-dev - wget https://downloads.arduino.cc/arduino-1.8.12-linuxarm.tar.xz - tar -xf arduino-1.8.12-linuxarm.tar.xz - wget https://www.pjrc.com/teensy/td_151/TeensyduinoInstall.linuxarm + wget https://downloads.arduino.cc/arduino-1.8.13-linuxarm.tar.xz + tar -xf arduino-1.8.13-linuxarm.tar.xz + wget https://www.pjrc.com/teensy/td_153/TeensyduinoInstall.linuxarm chmod +x TeensyduinoInstall.linuxarm - ./TeensyduinoInstall.linuxarm --dir=arduino-1.8.12 - sudo cp -R arduino-1.8.12 /usr/share/arduino + ./TeensyduinoInstall.linuxarm --dir=arduino-1.8.13 + sudo cp -R arduino-1.8.13 /usr/share/arduino sudo ln -s /usr/share/arduino/arduino /usr/bin/arduino git clone https://github.com/PaulStoffregen/teensy_loader_cli pushd teensy_loader_cli + make sudo cp teensy_loader_cli /usr/bin/ sudo ln -s /usr/bin/teensy_loader_cli /usr/bin/teensy-loader-cli popd + curl https://www.pjrc.com/teensy/49-teensy.rules | sudo tee /etc/udev/rules.d/49-teensy.rules - 8. Add the following lines to `/etc/udev/rules.d/49-stlinkv2`: + 8. Add the following lines to `/etc/udev/rules.d/49-stlinkv2.rules`: SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE:="0666" SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE:="0666" - 9. `sudo ../../odrivetool udev-setup` + 9. `sudo mkdir /opt/odrivetest && sudo chown $USER /opt/odrivetest` - 10. `sudo udevadm trigger` + 10. At this point you need the ODrive repository. See next section to sync it from your main PC. We assume now that you navigated to `tools/odrive/tests/`. - 11. Run once after every reboot: `sudo ipython3 --pdb test_runner.py -- --setup-host --test-rig-yaml ../../test-rig-rpi.yaml` + 11. `sudo ../../odrivetool udev-setup` + + 12. `sudo udevadm trigger` + + 13. Run once after every reboot: `sudo ipython3 --pdb test_runner.py -- --setup-host --test-rig-yaml ../../test-rig-rpi.yaml` ## SSH testing flow diff --git a/tools/odrive/tests/calibration_test.py b/tools/odrive/tests/calibration_test.py index 3593fd14..476df3ef 100644 --- a/tools/odrive/tests/calibration_test.py +++ b/tools/odrive/tests/calibration_test.py @@ -34,8 +34,7 @@ class TestMotorCalibration(): axis_ctx.handle.motor.config.phase_inductance = 0.0 axis_ctx.handle.motor.config.pre_calibrated = False axis_ctx.handle.config.enable_watchdog = False - axis_ctx.parent.handle.config.brake_resistance = float(axis_ctx.parent.yaml['brake-resistance']) - axis_ctx.parent.handle.config.enable_brake_resistor = True + axis_ctx.parent.handle.config.dc_max_negative_current = -1.0 axis_ctx.parent.handle.clear_errors() @@ -87,7 +86,7 @@ class TestEncoderDirFind(): def get_test_cases(self, testrig: TestRig): for odrive in testrig.get_components(ODriveComponent): - for num in range(2): + for num in range(len(odrive.axes)): encoders = testrig.get_connected_components({ 'a': (odrive.encoders[num].a, False), 'b': (odrive.encoders[num].b, False) @@ -131,7 +130,7 @@ class TestEncoderOffsetCalibration(): def get_test_cases(self, testrig: TestRig): for odrive in testrig.get_components(ODriveComponent): - for num in range(2): + for num in range(len(odrive.axes)): encoders = testrig.get_connected_components({ 'a': (odrive.encoders[num].a, False), 'b': (odrive.encoders[num].b, False) @@ -180,7 +179,7 @@ class TestEncoderIndexSearch(): def get_test_cases(self, testrig: TestRig): for odrive in testrig.get_components(ODriveComponent): - for num in range(2): + for num in range(len(odrive.axes)): encoders = testrig.get_connected_components({ 'a': (odrive.encoders[num].a, False), 'b': (odrive.encoders[num].b, False) diff --git a/tools/odrive/tests/can_test.py b/tools/odrive/tests/can_test.py index 10ec2087..be1ce798 100644 --- a/tools/odrive/tests/can_test.py +++ b/tools/odrive/tests/can_test.py @@ -109,13 +109,13 @@ class TestSimpleCAN(): def run_test(self, odrive: ODriveComponent, canbus: CanInterfaceComponent, node_id: int, extended_id: bool, logger: Logger): odrive.disable_mappings() - if yaml['board-version'].startswith("v3."): + if odrive.yaml['board-version'].startswith("v3."): odrive.handle.config.gpio15_mode = GPIO_MODE_CAN_A odrive.handle.config.gpio16_mode = GPIO_MODE_CAN_A - elif yaml['board-version'].startswith("v4.0-"): + elif odrive.yaml['board-version'].startswith("v4."): pass # CAN pin configuration is hardcoded else: - raise Exception("unknown board version {}".format(yaml['board-version'])) + raise Exception("unknown board version {}".format(odrive.yaml['board-version'])) odrive.handle.config.enable_can_a = True odrive.save_config_and_reboot() diff --git a/tools/odrive/tests/closed_loop_test.py b/tools/odrive/tests/closed_loop_test.py index 241ca442..b21755a8 100644 --- a/tools/odrive/tests/closed_loop_test.py +++ b/tools/odrive/tests/closed_loop_test.py @@ -17,7 +17,7 @@ class TestClosedLoopControlBase(): def get_test_cases(self, testrig: TestRig): for odrive in testrig.get_components(ODriveComponent): - for num in range(2): + for num in range(len(odrive.axes)): encoders = testrig.get_connected_components({ 'a': (odrive.encoders[num].a, False), 'b': (odrive.encoders[num].b, False) diff --git a/tools/odrive/tests/fibre_test.py b/tools/odrive/tests/fibre_test.py index 68d08a3c..fc4e4f31 100644 --- a/tools/odrive/tests/fibre_test.py +++ b/tools/odrive/tests/fibre_test.py @@ -23,7 +23,7 @@ class FibreFunctionalTest(): test_assert_eq(odrive.handle.test_property, 0xffffffff) # Test function call - val = odrive.handle.get_adc_voltage(1) + val = odrive.handle.get_adc_voltage(2) # ADC pin on both ODrive 3 and 4 test_assert_within(val, 0.01, 3.29) # Test custom setter (aka property write hook) diff --git a/tools/odrive/tests/not_a_test.py b/tools/odrive/tests/not_a_test.py index 7be3e995..f8430aa8 100644 --- a/tools/odrive/tests/not_a_test.py +++ b/tools/odrive/tests/not_a_test.py @@ -11,17 +11,16 @@ class EncoderPassthrough(): def get_test_cases(self, testrig: TestRig): for odrive in testrig.get_components(ODriveComponent): - for num in range(1): - encoders = testrig.get_connected_components({ - 'a': (odrive.encoders[num].a, False), - 'b': (odrive.encoders[num].b, False), - 'z': (odrive.encoders[num].z, False) - }, EncoderComponent) - motors = testrig.get_connected_components(odrive.axes[num], MotorComponent) + encoders = testrig.get_connected_components({ + 'a': (odrive.encoders[0].a, False), + 'b': (odrive.encoders[0].b, False), + 'z': (odrive.encoders[0].z, False) + }, EncoderComponent) + motors = testrig.get_connected_components(odrive.axes[0], MotorComponent) - for motor, encoder in itertools.product(motors, encoders): - if encoder.impl in testrig.get_connected_components(motor): - yield (odrive.axes[num], motor, encoder) + for motor, encoder in itertools.product(motors, encoders): + if encoder.impl in testrig.get_connected_components(motor): + yield (odrive.axes[0], motor, encoder) def run_test(self, axis_ctx: ODriveAxisComponent, motor_ctx: MotorComponent, enc_ctx: EncoderComponent, logger: Logger): logger.debug(f'Encoder {axis_ctx.num} was passed through') diff --git a/tools/odrive/tests/pwm_input_test.py b/tools/odrive/tests/pwm_input_test.py index a79d8aac..c1951c02 100644 --- a/tools/odrive/tests/pwm_input_test.py +++ b/tools/odrive/tests/pwm_input_test.py @@ -49,11 +49,20 @@ class TestPwmInput(): def get_test_cases(self, testrig: TestRig): for odrive in testrig.get_components(ODriveComponent): - # Run a separate test for each PWM-capable GPIO. Use different min/max settings for each test. - yield (odrive, 1, -50, 200, list(testrig.get_connected_components(odrive.gpio1, TeensyGpio))) - yield (odrive, 2, 20, 400, list(testrig.get_connected_components(odrive.gpio2, TeensyGpio))) - yield (odrive, 3, -1000, 0, list(testrig.get_connected_components(odrive.gpio3, TeensyGpio))) - yield (odrive, 4, -20000, 20000, list(testrig.get_connected_components(odrive.gpio4, TeensyGpio))) + if odrive.yaml['board-version'].startswith('v3.'): + # Run a separate test for each PWM-capable GPIO. Use different min/max settings for each test. + yield (odrive, 1, -50, 200, list(testrig.get_connected_components(odrive.gpio1, TeensyGpio))) + yield (odrive, 2, 20, 400, list(testrig.get_connected_components(odrive.gpio2, TeensyGpio))) + yield (odrive, 3, -1000, 0, list(testrig.get_connected_components(odrive.gpio3, TeensyGpio))) + yield (odrive, 4, -20000, 20000, list(testrig.get_connected_components(odrive.gpio4, TeensyGpio))) + elif odrive.yaml['board-version'].startswith('v4.'): + # Run a separate test for each PWM-capable GPIO. Use different min/max settings for each test. + yield (odrive, 14, -50, 200, list(testrig.get_connected_components(odrive.gpio14, TeensyGpio))) + yield (odrive, 19, 20, 400, list(testrig.get_connected_components(odrive.gpio19, TeensyGpio))) + yield (odrive, 20, -20000, 20000, list(testrig.get_connected_components(odrive.gpio20, TeensyGpio))) + yield (odrive, 21, -1000, 0, list(testrig.get_connected_components(odrive.gpio21, TeensyGpio))) + else: + raise Exception(f"unknown board version {odrive.yaml['board-version']}") def run_test(self, odrive: ODriveComponent, odrive_gpio_num: int, min_val: float, max_val: float, teensy_gpio: Component, logger: Logger): teensy = teensy_gpio.parent @@ -63,14 +72,8 @@ class TestPwmInput(): logger.debug("Set up PWM input...") odrive.disable_mappings() - pwm_mapping = [ - odrive.handle.config.gpio1_pwm_mapping, - odrive.handle.config.gpio2_pwm_mapping, - odrive.handle.config.gpio3_pwm_mapping, - odrive.handle.config.gpio4_pwm_mapping - ][odrive_gpio_num - 1] - - setattr(odrive.handle.config, 'gpio' + str(odrive_gpio_num) + '_mode', GPIO_MODE_PWM) + setattr(odrive.handle.config, f'gpio{odrive_gpio_num}_mode', GPIO_MODE_PWM) + pwm_mapping = getattr(odrive.handle.config, f'gpio{odrive_gpio_num}_pwm_mapping') pwm_mapping.endpoint = odrive.handle.axis0.controller._remote_attributes['input_pos'] pwm_mapping.min = min_val pwm_mapping.max = max_val diff --git a/tools/odrive/tests/step_dir_test.py b/tools/odrive/tests/step_dir_test.py index c5d6fc27..153472e7 100644 --- a/tools/odrive/tests/step_dir_test.py +++ b/tools/odrive/tests/step_dir_test.py @@ -32,10 +32,12 @@ class TestStepDir(): yield (odrive.axes[0], 1, gpio_conns[0], 2, gpio_conns[1]) yield (odrive.axes[0], 5, gpio_conns[2], 6, gpio_conns[3]) - yield (odrive.axes[0], 7, gpio_conns[4], 8, gpio_conns[5]) # broken + yield (odrive.axes[0], 7, gpio_conns[4], 8, gpio_conns[5]) # yield (odrive.axes[0], 7, gpio_conns[6], 8, gpio_conns[7]) # broken - yield (odrive.axes[1], 7, gpio_conns[4], 8, gpio_conns[5]) + # test other axes + for i in range(1, len(odrive.axes)): + yield (odrive.axes[i], 7, gpio_conns[4], 8, gpio_conns[5]) def run_test(self, axis: ODriveAxisComponent, step_gpio_num: int, step_gpio: LinuxGpioComponent, dir_gpio_num: int, dir_gpio: LinuxGpioComponent, logger: Logger): step_gpio.config(output=True) diff --git a/tools/odrive/tests/test_runner.py b/tools/odrive/tests/test_runner.py index ae1f147c..28066800 100644 --- a/tools/odrive/tests/test_runner.py +++ b/tools/odrive/tests/test_runner.py @@ -17,6 +17,7 @@ import itertools import time import tempfile import io +import re from typing import Union, Tuple # needed for curve fitting @@ -211,13 +212,15 @@ class ODriveComponent(Component): if yaml['board-version'].startswith("v3."): self.encoders = [ODriveEncoderComponent(self, 0, yaml['encoder0']), ODriveEncoderComponent(self, 1, yaml['encoder1'])] self.axes = [ODriveAxisComponent(self, 0, yaml['motor0']), ODriveAxisComponent(self, 1, yaml['motor1'])] - elif yaml['board-version'].startswith("v4.0-"): + gpio_nums = range(1,9) + elif yaml['board-version'].startswith("v4."): self.encoders = [ODriveEncoderComponent(self, 0, yaml['encoder0'])] self.axes = [ODriveAxisComponent(self, 0, yaml['motor0'])] + gpio_nums = range(23) else: raise Exception("unknown board version {}".format(yaml['board-version'])) - for i in range(1,9): + for i in gpio_nums: self.__setattr__('gpio' + str(i), Component(self)) self.can = Component(self) self.sck = Component(self) @@ -229,8 +232,9 @@ class ODriveComponent(Component): yield 'encoder' + str(enc_ctx.num), enc_ctx for axis_ctx in self.axes: yield 'axis' + str(axis_ctx.num), axis_ctx - for i in range(1,9): - yield ('gpio' + str(i)), getattr(self, 'gpio' + str(i)) + for k in dir(self): + if k.startswith('gpio'): + yield k, getattr(self, k) yield 'can', self.can yield 'spi.sck', self.sck yield 'spi.miso', self.miso @@ -256,15 +260,12 @@ class ODriveComponent(Component): axis_ctx.handle = self.handle.__dict__['axis{}'.format(axis_idx)] def disable_mappings(self): - if yaml['board-version'].startswith("v3."): - self.handle.config.gpio1_pwm_mapping.endpoint = None - self.handle.config.gpio2_pwm_mapping.endpoint = None - self.handle.config.gpio3_pwm_mapping.endpoint = None - self.handle.config.gpio4_pwm_mapping.endpoint = None - self.handle.config.gpio3_analog_mapping.endpoint = None - self.handle.config.gpio4_analog_mapping.endpoint = None - else: - raise Exception("unknown board version {}".format(yaml['board-version'])) + for k in dir(self.handle.config): + if re.match(r'gpio[0-9]+_pwm_mapping', k): + getattr(self.handle.config, k).endpoint = None + for k in dir(self.handle.config): + if re.match(r'gpio[0-9]+_analog_mapping', k): + getattr(self.handle.config, k).endpoint = None def save_config_and_reboot(self): self.handle.save_configuration() @@ -392,7 +393,12 @@ class TeensyComponent(Component): def __init__(self, testrig, yaml: dict): self.testrig = testrig self.yaml = yaml - self.gpios = [TeensyGpio(self, i) for i in range(24)] + if self.yaml['board-version'] == 'teensy:avr:teensy40': + self.gpios = [TeensyGpio(self, i) for i in range(24)] + elif self.yaml['board-version'] == 'teensy:avr:teensy41': + self.gpios = [TeensyGpio(self, i) for i in range(42)] + else: + raise Exception(f"unknown Arduino board {self.yaml['board-version']}") self.routes = [] self.previous_routes = object() @@ -435,7 +441,7 @@ class TeensyComponent(Component): env = os.environ.copy() env['ARDUINO_COMPILE_DESTINATION'] = hexfile run_shell( - ['arduino', '--board', 'teensy:avr:teensy40', '--verify', sketchfile], + ['arduino', '--board', self.yaml['board-version'], '--verify', sketchfile], logger, env = env, timeout = 120) def program(self, hex_file_path: str, logger: Logger): @@ -454,7 +460,7 @@ class TeensyComponent(Component): time.sleep(0.1) program_gpio.write(True) - run_shell(["teensy-loader-cli", "-mmcu=imxrt1062", "-w", hex_file_path], logger, timeout = 5) + run_shell(["teensy-loader-cli", "-mmcu=" + self.yaml['board-version'].rpartition(':')[2].upper(), "-w", hex_file_path], logger, timeout = 5) time.sleep(0.5) # give it some time to boot def compile_and_program(self, code: str): @@ -518,7 +524,7 @@ class TestRig(): add_component(component_yaml['name'], ODriveComponent(component_yaml)) elif component_yaml['type'] == 'generalpurpose': add_component(component_yaml['name'], GeneralPurposeComponent(component_yaml)) - elif component_yaml['type'] == 'teensy': + elif component_yaml['type'] == 'arduino': add_component(component_yaml['name'], TeensyComponent(self, component_yaml)) elif component_yaml['type'] == 'motor': add_component(component_yaml['name'], MotorComponent(component_yaml)) diff --git a/tools/odrive/tests/uart_ascii_test.py b/tools/odrive/tests/uart_ascii_test.py index 52a1c64e..c11e6a23 100644 --- a/tools/odrive/tests/uart_ascii_test.py +++ b/tools/odrive/tests/uart_ascii_test.py @@ -37,19 +37,28 @@ class TestUartAscii(): def get_test_cases(self, testrig: TestRig): for odrive in testrig.get_components(ODriveComponent): - ports = list(testrig.get_connected_components({ - 'rx': (odrive.gpio1, True), - 'tx': (odrive.gpio2, False) - }, SerialPortComponent)) - yield (odrive, 0, ports) + if odrive.yaml['board-version'].startswith('v3.'): + ports = list(testrig.get_connected_components({ + 'rx': (odrive.gpio1, True), + 'tx': (odrive.gpio2, False) + }, SerialPortComponent)) + yield (odrive, 0, 1, 2, ports) - # Enable the line below to manually test UART_B. For this you need - # to manually move to the wires go to GPIO1/2 to GPIO3/4. The ones - # that normally go to GPIO3/4 have a low pass filter. - #yield (odrive, 1, ports) + # Enable the line below to manually test UART_B. For this you need + # to manually move to the wires go to GPIO1/2 to GPIO3/4. The ones + # that normally go to GPIO3/4 have a low pass filter. + #yield (odrive, 1, 3, 4, ports) + elif odrive.yaml['board-version'].startswith('v4.'): + ports = list(testrig.get_connected_components({ + 'rx': (odrive.gpio15, True), + 'tx': (odrive.gpio14, False) + }, SerialPortComponent)) + yield (odrive, 0, 15, 14, ports) + else: + raise TestFailed("unknown board version") - def run_test(self, odrive: ODriveComponent, uart_num: int, port: SerialPortComponent, logger: Logger): - logger.debug('Enabling UART {}...'.format(uart_num)) + def run_test(self, odrive: ODriveComponent, uart_num: int, tx_gpio: list, rx_gpio: list, port: SerialPortComponent, logger: Logger): + logger.debug('Enabling UART {}...'.format(chr(ord('A') + uart_num))) # GPIOs might be in use by something other than UART and some components # might be configured so that they would fail in the later test. @@ -63,16 +72,17 @@ class TestUartAscii(): if uart_num == 0: odrive.handle.config.enable_uart_a = True - odrive.handle.config.gpio1_mode = GPIO_MODE_UART_A - odrive.handle.config.gpio2_mode = GPIO_MODE_UART_A - odrive.handle.config.gpio3_mode = GPIO_MODE_ANALOG_IN - odrive.handle.config.gpio4_mode = GPIO_MODE_ANALOG_IN - else: + mode = GPIO_MODE_UART_A + elif uart_num == 1: odrive.handle.config.enable_uart_b = True - odrive.handle.config.gpio1_mode = GPIO_MODE_ANALOG_IN - odrive.handle.config.gpio2_mode = GPIO_MODE_ANALOG_IN - odrive.handle.config.gpio3_mode = GPIO_MODE_UART_B - odrive.handle.config.gpio4_mode = GPIO_MODE_UART_B + mode = GPIO_MODE_UART_B + elif uart_num == 2: + odrive.handle.config.enable_uart_c = True + mode = GPIO_MODE_UART_C + else: + raise TestFailed(f"unknown UART: {uart_num}") + setattr(odrive.handle.config, f'gpio{tx_gpio}_mode', mode) + setattr(odrive.handle.config, f'gpio{rx_gpio}_mode', mode) odrive.save_config_and_reboot() diff --git a/tools/test-rig-rpi.yaml b/tools/test-rig-rpi.yaml index 45022206..0026ca30 100644 --- a/tools/test-rig-rpi.yaml +++ b/tools/test-rig-rpi.yaml @@ -23,13 +23,9 @@ components: - {type: gpio, num: 20} - {type: gpio, num: 26} -# - type: programmer -# name: The Blue STLink/v2 -# id: '\x53\x3f\x75\x06\x49\x3f\x49\x51\x44\x54\x19\x3f' - - type: odrive name: odrive - board-version: v3.6-58V + board-version: v3.6-56V serial-number: "20703595524B" brake-resistance: 2.0 usb: auto @@ -56,8 +52,9 @@ components: cpr: 8192 max-rpm: 7000 - - type: teensy + - type: arduino name: teensy + board-version: teensy:avr:teensy40 - {type: lpf, name: lpf0} - {type: lpf, name: lpf1} diff --git a/tools/test-rig-rpi4.yaml b/tools/test-rig-rpi4.yaml new file mode 100644 index 00000000..44002dca --- /dev/null +++ b/tools/test-rig-rpi4.yaml @@ -0,0 +1,98 @@ + +components: + - type: generalpurpose + name: homenet + net: homenet + + - type: generalpurpose + name: rpi + ssh: odrv + net: homenet + components: + - type: uart + name: uart0 + port: /dev/ttyS0 + connected-to: main_uart + # need to specify GPIOs explicitly for the generalpurpose type + - {type: gpio, num: 4} + - {type: gpio, num: 18} + - {type: gpio, num: 23} + + - type: odrive + name: odrive + board-version: v4.1-58V + serial-number: "206730814E53" + brake-resistance: 0.0 + usb: auto + can: main_canbus + vbus-voltage: 24 # [V] + max-brake-power: 0 # [W] + encoder0: virtual_encoder0 + motor0: D5065-270KV_0 + + - type: motor + name: D5065-270KV_0 + phase-resistance: 0.039 + phase-inductance: 1.57e-05 + pole-pairs: 7 + direction: 1 + kv: 270 + max-current: 70 + max-voltage: 40 + + - type: encoder + name: real_encoder + cpr: 8192 + max-rpm: 7000 + + - type: arduino + name: teensy + board-version: teensy:avr:teensy41 + + - {type: lpf, name: lpf0} + - {type: lpf, name: lpf1} + +connections: + - ['teensy.program', 'rpi.gpio4'] + - ['teensy.gpio14', 'rpi.uart0.tx'] + - ['teensy.gpio15', 'rpi.uart0.rx'] + - ['teensy.gpio16', 'rpi.gpio18'] + - ['teensy.gpio17', 'rpi.gpio23'] + + # J8 + - ['teensy.gpio0', 'odrive.gpio6'] + - ['teensy.gpio1', 'odrive.gpio5'] + - ['teensy.gpio2', 'odrive.gpio4'] + - ['teensy.gpio3', 'odrive.gpio3'] + - ['teensy.gpio4', 'odrive.gpio0'] + - ['teensy.gpio5', 'odrive.gpio1'] + - ['teensy.gpio6', 'odrive.gpio2'] + + - ['teensy.gpio8', 'odrive.gpio16'] + - ['teensy.gpio9', 'odrive.gpio17'] + - ['teensy.gpio10', 'odrive.gpio18'] + - ['teensy.gpio11', 'odrive.gpio19'] + - ['teensy.gpio12', 'odrive.gpio20'] + - ['teensy.gpio24', 'odrive.gpio21'] + - ['teensy.gpio25', 'odrive.gpio22'] + + - ['teensy.gpio26', 'odrive.gpio10'] + - ['teensy.gpio27', 'odrive.gpio11'] + - ['teensy.gpio28', 'odrive.gpio15'] + - ['teensy.gpio29', 'odrive.gpio14'] + - ['teensy.gpio30', 'odrive.gpio13'] + - ['teensy.gpio31', 'odrive.gpio12'] + + - ['teensy.gpio23', 'real_encoder.b'] + - ['teensy.gpio22', 'real_encoder.a'] + - ['teensy.gpio21', 'real_encoder.z'] + - ['odrive.axis0', 'D5065-270KV_0'] + - ['D5065-270KV_0', 'real_encoder'] + + - ['odrive.encoder0.a', 'odrive.gpio0'] + - ['odrive.encoder0.b', 'odrive.gpio5'] + - ['odrive.encoder0.z', 'odrive.gpio6'] # TODO + +# - ['odrive.encoder1.a', 'odrive.gpio0'] +# - ['odrive.encoder1.b', 'odrive.gpio5'] +# - ['odrive.encoder1.z', 'odrive.gpio6'] # TODO