diff --git a/docs/reference/openamr-platform-fw/concepts.md b/docs/reference/openamr-platform-fw/concepts.md index 90ee725..0566921 100644 --- a/docs/reference/openamr-platform-fw/concepts.md +++ b/docs/reference/openamr-platform-fw/concepts.md @@ -1,48 +1,180 @@ --- -title: Concepts +title: Firmware control architecture +tags: [developer, integrator] +status: experimental +description: Understand the Teensy 4.0 control loop, differential-drive kinematics, encoder feedback, PID control, and odometry. --- -
Under development

Concepts

Provide the learning-layer reference for concepts and point to its owning repository.

OpenAMRobot logo
+# Firmware control architecture -!!! info "Documentation framework" - This page is part of the approved OpenAMRobot knowledge architecture. It is intentionally published before full content is complete so contributors can fill it consistently. Do not treat unfinished guidance as a validated build or deployment instruction. +**Canonical source:** [`openamr-platform-fw/docs/architecture/control-loop.md`](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/control-loop.md) +**Applies to:** the documented OpenAMRobot reference mobile base; verify repository revision before changing hardware or firmware. -## What this page should contain +!!! warning "Experimental project documentation" + These instructions describe the current reference build and its measured behavior. Use physical safeguards, test with wheels clear of the floor, and revalidate after changing parts, wiring, firmware, battery chemistry, or geometry. -- **Audience and outcome:** who uses this page and what verified state they should reach. -- **Prerequisites:** required skills, tools, hardware, software, configuration and safety conditions. -- **Concept or procedure:** concise explanation followed by ordered, reproducible steps where applicable. -- **Verification:** observable output, measurement, test or acceptance criterion. -- **Troubleshooting:** likely failures, evidence to collect and safe recovery actions. -- **Next step:** one clear continuation in the ownership or development path. +*Applies to the Teensy 4.0 `linorobot2_overlay` firmware.* -## Content template +The firmware runs a fixed-rate control loop that turns `/cmd_vel` into per-wheel PWM, +publishes wheel odometry, and streams debug telemetry. This document describes the loop, +the velocity controller, and the compiled configuration for this robot. -| Field | To complete | -| --- | --- | -| For | Name one primary reader: operator, builder, integrator or developer | -| Before you start | List exact prerequisites or state “nothing” | -| When you finish | Describe a measurable outcome | -| Capability status | Stable, beta, experimental, planned, community or partner-supported | -| Applies to | Release, hardware revision and configuration | -| Safety | Hazards, limits, stop conditions and required supervision | -| Verification | What the reader should see, hear, measure or test | +## The 50 Hz loop (`src/firmware.ino`) -### Procedure or explanation +A micro-ROS timer fires every **20 ms** (50 Hz) → `controlCallback` → `moveBase()` then +`publishData()`. -1. Establish the starting state. -2. Complete one action or concept per subsection. -3. Record commands, parameters, screenshots or measurements where useful. -4. Verify the result before continuing. +``` +/cmd_vel (Twist) + │ + ▼ +kinematics.getRPM(vx, vy, wz) ─► target rpm per wheel (motor1 = LEFT, motor2 = RIGHT) + │ ▲ + │ encoder + velocity estimator ────┘ measured rpm (ripple-corrected) + ▼ +feedforward(target) + pid.compute(target, measured) ─► PWM ─► motor.spin() ─► driver ─► wheel + │ + ▼ +kinematics.getVelocities(rpm1..4) ─► measured vx, wz + │ + ▼ +odometry.update() ─► /odom/unfiltered +``` -### If it did not work +`moveBase()` selects one of three exclusive paths each tick, checked in this order: -Document symptoms separately from causes. Include diagnostic evidence and a safe rollback or escalation path. +1. **Open-loop diagnostic** — active only when a bounded `/debug/openloop` command is fresh + (< 300 ms). Bypasses the PID and drives a fixed PWM. See + [debug telemetry](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/debug-telemetry.md). +2. **Command watchdog stop** — if no `/cmd_vel` arrived within **200 ms**, the loop does a + deterministic full stop (brake + PID reset). See [motion safety](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/safety/motion-safety.md). +3. **Closed-loop control** — the normal path (below). -## Owning OpenAMRobot source +Odometry is integrated on **every** tick regardless of which path ran. -- [openamr-platform-fw](https://github.com/openAMRobot/openamr-platform-fw) – canonical source, versions, implementation and issue history. +## Velocity controller (closed-loop path) -## Contribution note +The closed-loop control path is shown in the block diagram below. -Replace this framework with tested project-specific content through the normal [contribution workflow](https://github.com/openAMRobot/openamrobot-docs/blob/main/CONTRIBUTING.md). Keep exact parameters and contracts synchronized with the owning repository. +![The 50 Hz per-wheel velocity controller: setpoint from /cmd_vel, error into a PID (Kp 2.0/Ki 0.1/Kd 0.1) with back-calculation anti-windup, plus feedforward + dither, to bounded PWM -> ZBLD driver -> BLDC motor; AS5040 encoder counts pass a runtime ripple table before becoming measured RPM](https://raw.githubusercontent.com/openAMRobot/openamr-platform-fw/main/docs/architecture/diagrams/motor-control-loop-per-wheel.svg) + + +Per wheel, the commanded PWM is a **feedforward + PID** sum: + +``` +pwm = feedforward(target_rpm) + pid.compute(target_rpm, measured_rpm) +``` + +- **Feedforward** supplies the bulk of the holding PWM directly: + `pwm_ff = kff · target_rpm ± ff_offset` (the `ff_offset` stiction term is added in the + direction of motion). Defaults: `KFF_DEFAULT = 7.87` PWM/rpm, `FF_OFFSET_DEFAULT = 21` PWM. + Because the feedforward already knows the PWM needed for a given speed, the integral barely + works, so the **closed-loop response has the same shape at every speed** (no + speed-dependent windup/overshoot). +- **PID** (`lib/pid/pid.cpp`) only trims the residual error. One PID per wheel, output clamped + to `[PWM_MIN, PWM_MAX]`. The integral uses **back-calculation anti-windup**: on saturation the + excess is subtracted straight back out of the integral (`integral -= (pid − limit) / K_I`), so + `K_I · integral` only ever supplies what is actually achievable. This *bleeds* the windup out + rather than a static clamp or a conditional freeze — a long saturated rise no longer overshoots. + Upstream linorobot2 had an unbounded integral that "catapulted" on saturation. +- **Right-wheel balance**: `motor2` PWM is scaled by `motor2_gain` (default `MOTOR2_GAIN = 1.000`). + The feedforward + integral now carry the drivetrain asymmetry, so no per-wheel gain scaling is + needed; the scalar is kept live-tunable for convenience. + +> **Differential-drive rule:** both wheels share a **single** `K_P/K_I/K_D` set (identical +> closed-loop dynamics → the robot tracks straight). Established left/right asymmetry is +> compensated with the scalar `motor2_gain`, **not** with per-wheel gains (per-wheel gains make +> the robot veer on start). + +### Low-speed handling + +At docking speeds the raw encoder rate is too coarse and static friction dominates. Two +mechanisms address this: + +- **Small-window velocity estimator** — instead of counts-per-fixed-20 ms (only ~1 count per + sample below ~5 rpm → ±70 % quantization noise that the PID would chase), the firmware measures + the time to accumulate a fixed **12-count** displacement (`Δcounts / Δt`, Δt at microsecond + precision). Look-back is capped at 200 ms. Lag is ~20–30 ms at nav speed (negligible). +- **Anti-stiction dither** — below `DITHER_BELOW_RPM = 13` rpm, a PWM of `±dither_amp` + (`DITHER_DEFAULT = 92`) is flipped every control tick (≈25 Hz square wave, net average 0). It + keeps the wheels micro-moving so static friction never grabs, converting the 0→9 rpm stick-slip + limit cycle into smooth slow motion down to ~0.06 m/s. Above 13 rpm it is disabled. + +See [encoder calibration](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/encoder-calibration.md) for the ripple correction applied to the +measured rpm, and [motion safety](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/safety/motion-safety.md) for the measured velocity floors. + +## Kinematics & odometry + +- `LINO_BASE = DIFFERENTIAL_DRIVE`; `motor1 = LEFT`, `motor2 = RIGHT` (motors 3/4 unused). +- For pure forward motion both wheels get the same target rpm. Per-wheel wheel velocity: + ``` + v_right = vx + wz · (LR_WHEELS_DISTANCE / 2) + v_left = vx − wz · (LR_WHEELS_DISTANCE / 2) + ``` + `LR_WHEELS_DISTANCE` (0.46 m) is the **track** (wheel separation), not the wheel diameter (0.2 m). +- `max_rpm = (MOTOR_POWER_MAX_VOLTAGE / MOTOR_OPERATING_VOLTAGE) · MOTOR_MAX_RPM · MAX_RPM_RATIO`. + With real 24 V power both voltages must be **24** or the RPM ceiling is halved. +- Odometry is integrated from the measured wheel velocities and published on `/odom/unfiltered` + (the host EKF fuses it with the IMU). An abnormal first/large `dt` (> 0.5 s) is rejected so the + first sample doesn't jump. + +## Compiled configuration (`config/lino_base_config.h`) + +Values for **this** robot (differ from upstream linorobot2 defaults): + +| `#define` | Value | Notes | +|---|---|---| +| `LINO_BASE` | `DIFFERENTIAL_DRIVE` | 2 driven wheels | +| `USE_GENERIC_2_IN_MOTOR_DRIVER` | — | PWM + 2 direction pins (INA/INB) | +| `USE_MPU9250_IMU` | — | chip is actually an **MPU-6500** (see [bringup](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/bringup/micro-ros-bringup.md)) | +| `K_P / K_I / K_D` | `2.0 / 0.1 / 0.1` | K_I low because the feedforward does the holding (2026-06-29) | +| `MOTOR2_GAIN` | `1.000` | right-wheel PWM scale; FF + integral carry the asymmetry | +| `MOTOR_MAX_RPM` | `80` | | +| `MAX_RPM_RATIO` | `0.85` | usable ceiling = 68 rpm | +| `MOTOR_OPERATING_VOLTAGE` / `MOTOR_POWER_MAX_VOLTAGE` | `24` / `24` | must match real supply | +| `COUNTS_PER_REV1..4` | `1024` | encoder CPR | +| `WHEEL_DIAMETER` | `0.2` | m | +| `LR_WHEELS_DISTANCE` | `0.46` | m, track (measured 2026-06-19) | +| `PWM_BITS` / `PWM_FREQUENCY` | `10` / `3000` | `PWM_MAX = 1023`, `PWM_MIN = −1023` | +| `MOTOR1_ENCODER_INV` / `MOTOR2_ENCODER_INV` | `true` / `false` | encoder sign | +| `MOTOR1_INV` / `MOTOR2_INV` | `false` / `true` | motor direction sign | +| `MOTOR1_PWM / IN_A / IN_B` | `1 / 20 / 21` | LEFT (pin 1 is PWM-capable on Teensy 4.x; 21 is not) | +| `MOTOR2_PWM / IN_A / IN_B` | `5 / 6 / 8` | RIGHT | +| `MOTOR1_ENCODER_A / B` | `14 / 15` | LEFT quadrature | +| `MOTOR2_ENCODER_A / B` | `11 / 12` | RIGHT quadrature | +| `BAUDRATE` | `115200` | **must match the micro-ROS agent** | + +The following live in `src/firmware.ino` (compiled defaults, live-tunable via `/debug/tune`): + +| Symbol | Default | Meaning | +|---|---|---| +| `KFF_DEFAULT` | `7.87` | feedforward gain (PWM/rpm) | +| `FF_OFFSET_DEFAULT` | `21` | feedforward stiction offset (PWM) | +| `DITHER_DEFAULT` | `92` | anti-stiction dither amplitude (PWM) | +| `DITHER_BELOW_RPM` | `13` | dither active only below this target rpm | + +> ⚠️ The build env `teensy40` uses `config/lino_base_config.h`, **not** any `dev_config.h`. +> Edit `lino_base_config.h` for gain/pin/geometry changes. + +## Tuning history (context) + +The gains reached the current values in two stages: + +1. **2026-06-18 step-response tune (no feedforward):** raised the original slow gains to + `K_P 0.6 / K_I 0.35 / K_D 0.15`; K_I was the dominant fix (killed a ~−26 % steady-state error). + Adding K_D did not help — it amplifies the quantized rpm noise, and the right-wheel overshoot + was dominated by driver dynamics + measurement quantization (the measurement noise floor), not + by gains. +2. **2026-06-29 feedforward re-architecture (current):** with the feedforward carrying the holding + PWM, K_I was lowered to `0.1` and K_P raised to `2.0`; the response became speed-independent and + `MOTOR2_GAIN` returned to `1.000`. The low-speed velocity estimator and anti-stiction dither were + added at the same time. + +The left wheel's low-speed "oscillation" was ultimately traced to an **encoder measurement** +artefact, not the gains — see [encoder calibration](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/encoder-calibration.md). + +## Engineering handoff + +- Record the repository commit, hardware revision, supply voltage, and test configuration with every result. +- Stop if observed wiring, component labels, geometry, or topic behavior differs from this page; resolve the discrepancy in the owning repository first. +- Report documentation or implementation defects through [the repository issue tracker](https://github.com/openAMRobot/openamr-platform-fw/issues). diff --git a/docs/reference/openamr-platform-fw/configuration.md b/docs/reference/openamr-platform-fw/configuration.md index f585149..6d0963e 100644 --- a/docs/reference/openamr-platform-fw/configuration.md +++ b/docs/reference/openamr-platform-fw/configuration.md @@ -1,48 +1,118 @@ --- -title: Configuration +title: Firmware configuration and tuning +tags: [developer, domain-expert] +status: experimental +description: Configure and tune the OpenAMRobot firmware through its compiled settings and runtime debug contract. --- -
Under development

Configuration

Provide the learning-layer reference for configuration and point to its owning repository.

OpenAMRobot logo
+# Firmware configuration and tuning -!!! info "Documentation framework" - This page is part of the approved OpenAMRobot knowledge architecture. It is intentionally published before full content is complete so contributors can fill it consistently. Do not treat unfinished guidance as a validated build or deployment instruction. +**Canonical source:** [`openamr-platform-fw/docs/architecture/debug-telemetry.md`](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/debug-telemetry.md) +**Applies to:** the documented OpenAMRobot reference mobile base; verify repository revision before changing hardware or firmware. -## What this page should contain +!!! warning "Experimental project documentation" + These instructions describe the current reference build and its measured behavior. Use physical safeguards, test with wheels clear of the floor, and revalidate after changing parts, wiring, firmware, battery chemistry, or geometry. -- **Audience and outcome:** who uses this page and what verified state they should reach. -- **Prerequisites:** required skills, tools, hardware, software, configuration and safety conditions. -- **Concept or procedure:** concise explanation followed by ordered, reproducible steps where applicable. -- **Verification:** observable output, measurement, test or acceptance criterion. -- **Troubleshooting:** likely failures, evidence to collect and safe recovery actions. -- **Next step:** one clear continuation in the ownership or development path. +*Applies to the Teensy 4.0 `linorobot2_overlay` firmware.* -## Content template +These topics are **additions to upstream linorobot2**, added for this robot. They were essential +to diagnose the drivetrain and remain the live-tuning and commissioning interface. This page is +the single source of truth for the debug interface; other docs link here. -| Field | To complete | -| --- | --- | -| For | Name one primary reader: operator, builder, integrator or developer | -| Before you start | List exact prerequisites or state “nothing” | -| When you finish | Describe a measurable outcome | -| Capability status | Stable, beta, experimental, planned, community or partner-supported | -| Applies to | Release, hardware revision and configuration | -| Safety | Hazards, limits, stop conditions and required supervision | -| Verification | What the reader should see, hear, measure or test | +## Published telemetry (Teensy → host) -### Procedure or explanation +The debug topic flow is shown below. -1. Establish the starting state. -2. Complete one action or concept per subsection. -3. Record commands, parameters, screenshots or measurements where useful. -4. Verify the result before continuing. +![The /debug topics split by direction: Teensy->host telemetry (best-effort) /debug/left, /debug/right, /debug/pwm; host->Teensy commands (reliable) /debug/openloop (gated by ENABLE_POWERED_DEBUG, can move the motors), /debug/tune, /debug/enc_cal](https://raw.githubusercontent.com/openAMRobot/openamr-platform-fw/main/docs/architecture/diagrams/debug-telemetry-topic-map.svg) -### If it did not work -Document symptoms separately from causes. Include diagnostic evidence and a safe rollback or escalation path. +All three are `geometry_msgs/msg/Vector3`, **BEST_EFFORT** QoS, published at the 50 Hz loop rate: -## Owning OpenAMRobot source +| Topic | x | y | z | +|---|---|---|---| +| `/debug/left` | target rpm (LEFT) | **measured rpm (LEFT, corrected)** | cumulative encoder counts (LEFT) | +| `/debug/right` | target rpm (RIGHT) | **measured rpm (RIGHT, corrected)** | cumulative encoder counts (RIGHT) | +| `/debug/pwm` | PWM LEFT | PWM RIGHT | 0 | -- [openamr-platform-fw](https://github.com/openAMRobot/openamr-platform-fw) – canonical source, versions, implementation and issue history. +> ⚠️ **The `y` field is the *corrected* rpm.** The firmware runs the measured rpm through the +> small-window velocity estimator **and** the runtime ripple table (`calib_rpm`) *before* +> publishing (`current_rpm1 → debug_cur_rpm1 → debug_left_msg.y`). Until an encoder table is +> loaded, the ripple correction is unity passthrough, but the velocity-estimator smoothing is +> always applied. If you need the raw signal, use the `z` counts. See +> [encoder calibration](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/encoder-calibration.md). -## Contribution note +> ⚠️ **BEST_EFFORT QoS:** a subscriber must request best-effort too, otherwise it receives +> nothing: +> ``` +> ros2 topic echo /debug/right --qos-reliability best_effort +> ``` -Replace this framework with tested project-specific content through the normal [contribution workflow](https://github.com/openAMRobot/openamrobot-docs/blob/main/CONTRIBUTING.md). Keep exact parameters and contracts synchronized with the owning repository. +## Commands (host → Teensy) + +### `/debug/openloop` — raw open-loop PWM (`geometry_msgs/msg/Vector3`, RELIABLE) + +Drives a **fixed PWM, bypassing the PID**, for hardware diagnosis (proving a motor/encoder +channel independently of the closed loop). + +- **Only the `x` field is used, and it is applied to *both* motors** (motor2 additionally scaled + by `motor2_gain`). The `y` and `z` fields are ignored. +- Active only when `|x| ≥ 1` **and** a message arrived within the last **300 ms** (its own + staleness timeout, separate from the `/cmd_vel` watchdog). Otherwise the loop falls back to + normal control. +- **Validated & bounded**: NaN/Inf are rejected, and the value is clamped to + `OPENLOOP_PWM_LIMIT = 0.7 · PWM_MAX ≈ ±716` so a stray/huge command cannot slam the motors. +- **Production gate**: driving motors from this path requires the `ENABLE_POWERED_DEBUG` build + flag (defined in the current commissioning build). In a production image with the flag removed, + the subscriber still exists (executor count unchanged) but cannot move the motors. + +``` +# hold both wheels at PWM 200, republished to beat the 300 ms staleness timeout +ros2 topic pub -r 10 /debug/openloop geometry_msgs/msg/Vector3 "{x: 200.0, y: 0.0, z: 0.0}" +``` + +> ⚠️ A prior note described `/debug/openloop` as `x = left PWM, y = right PWM`. That is **not** +> what the firmware does — `y` is ignored and `x` drives both wheels. Use `motor2_gain` (via +> `/debug/tune`) if you need to bias the right wheel. + +### `/debug/tune` — live gain tuning (`geometry_msgs/msg/Twist`, RELIABLE) + +Updates the controller in RAM (compiled defaults are unchanged; a reflash restores them). + +| Field | Target | Applied when | +|---|---|---| +| `linear.x / y / z` | `K_P / K_I / K_D` (both PIDs) | always | +| `angular.x` | `motor2_gain` (right-wheel PWM scale) | `> 0` | +| `angular.y` | `kff` (feedforward gain, PWM/rpm) | `> 0` | +| `angular.z` | `dither_amp` (anti-stiction dither, PWM) | `≥ 0` | + +> ⚠️ A code comment near the declaration lists `angular.z = ff_offset`; the **actual** callback +> uses `angular.z = dither_amp`. `ff_offset` is fixed at its tuned default. + +``` +# set K_P=2.0 K_I=0.1 K_D=0.1, motor2_gain=1.0, kff=7.87, dither=92 (the compiled defaults) +ros2 topic pub --once /debug/tune geometry_msgs/msg/Twist \ + "{linear: {x: 2.0, y: 0.1, z: 0.1}, angular: {x: 1.0, y: 7.87, z: 92.0}}" +``` + +> A field guarded by `> 0` is left untouched when sent as `0` (so you can nudge one gain without +> disturbing `motor2_gain`/`kff`); `angular.z` (dither) accepts `0` to disable it. + +### `/debug/enc_cal` — runtime encoder ripple table (`std_msgs/msg/Float32MultiArray`, RELIABLE) + +72 floats = 36 `LEFT_CAL` bins then 36 `RIGHT_CAL` bins. Loaded into RAM and applied instantly. +Full explanation in [encoder calibration](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/encoder-calibration.md). + +## Diagnostic recipes + +- **Motor/encoder health (wheels raised):** publish equal `/debug/openloop` on both wheels and + compare `/debug/left.y` vs `/debug/right.y` — this is how the motors/encoders were proven + healthy independently of the closed loop. +- **Step-response tuning:** command a `/cmd_vel` step and record `/debug/left|right` (`x` target, + `y` measured) at ≥ 0.25 m/s (below that the rpm is too quantized to tune on). +- All debug subscribers are RELIABLE; the telemetry publishers are BEST_EFFORT. + +## Engineering handoff + +- Record the repository commit, hardware revision, supply voltage, and test configuration with every result. +- Stop if observed wiring, component labels, geometry, or topic behavior differs from this page; resolve the discrepancy in the owning repository first. +- Report documentation or implementation defects through [the repository issue tracker](https://github.com/openAMRobot/openamr-platform-fw/issues). diff --git a/docs/reference/openamr-platform-fw/reference.md b/docs/reference/openamr-platform-fw/reference.md index df5c2db..bd8e661 100644 --- a/docs/reference/openamr-platform-fw/reference.md +++ b/docs/reference/openamr-platform-fw/reference.md @@ -1,48 +1,104 @@ --- -title: Reference +title: Firmware ROS 2 contract +tags: [developer, integrator] +status: experimental +description: Reference the micro-ROS transport, topic contract, startup state machine, IMU behavior, and LED diagnostics. --- -
Under development

Reference

Provide the learning-layer reference for reference and point to its owning repository.

OpenAMRobot logo
+# Firmware ROS 2 contract -!!! info "Documentation framework" - This page is part of the approved OpenAMRobot knowledge architecture. It is intentionally published before full content is complete so contributors can fill it consistently. Do not treat unfinished guidance as a validated build or deployment instruction. +**Canonical source:** [`openamr-platform-fw/docs/bringup/micro-ros-bringup.md`](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/bringup/micro-ros-bringup.md) +**Applies to:** the documented OpenAMRobot reference mobile base; verify repository revision before changing hardware or firmware. -## What this page should contain +!!! warning "Experimental project documentation" + These instructions describe the current reference build and its measured behavior. Use physical safeguards, test with wheels clear of the floor, and revalidate after changing parts, wiring, firmware, battery chemistry, or geometry. -- **Audience and outcome:** who uses this page and what verified state they should reach. -- **Prerequisites:** required skills, tools, hardware, software, configuration and safety conditions. -- **Concept or procedure:** concise explanation followed by ordered, reproducible steps where applicable. -- **Verification:** observable output, measurement, test or acceptance criterion. -- **Troubleshooting:** likely failures, evidence to collect and safe recovery actions. -- **Next step:** one clear continuation in the ownership or development path. +*Applies to the Teensy 4.0 `linorobot2_overlay` firmware.* -## Content template +The firmware is a **micro-ROS** application. It connects to a **micro-ROS agent** on the host over +USB serial and exposes the robot's topics. This page covers the connection, the topic contract, and +the LED status codes. -| Field | To complete | -| --- | --- | -| For | Name one primary reader: operator, builder, integrator or developer | -| Before you start | List exact prerequisites or state “nothing” | -| When you finish | Describe a measurable outcome | -| Capability status | Stable, beta, experimental, planned, community or partner-supported | -| Applies to | Release, hardware revision and configuration | -| Safety | Hazards, limits, stop conditions and required supervision | -| Verification | What the reader should see, hear, measure or test | +## Transport & agent -### Procedure or explanation +The micro-ROS transport topology is shown below. -1. Establish the starting state. -2. Complete one action or concept per subsection. -3. Record commands, parameters, screenshots or measurements where useful. -4. Verify the result before continuing. +![The Teensy 4.0 runs a micro-ROS client over USB serial 115200; the micro-ROS agent on the Pi 5 bridges it into the CycloneDDS ROS 2 graph. Teensy publishes /odom/unfiltered, /imu/data_raw, /imu/mag, /debug/left|right|pwm and subscribes /cmd_vel, /debug/openloop|tune|enc_cal; the host EKF/Madgwick produces filtered /imu/data + /odom for Nav2. The control loop runs only while the agent is connected; on disconnect the firmware fullStop()s](https://raw.githubusercontent.com/openAMRobot/openamr-platform-fw/main/docs/bringup/diagrams/micro-ros-node-topology.svg) -### If it did not work -Document symptoms separately from causes. Include diagnostic evidence and a safe rollback or escalation path. +- **USB serial** at **`BAUDRATE = 115200`** — this must match the agent exactly. +- Start the agent on the host, pointing at the Teensy's serial device. A non-interactive shell + does **not** source ROS, so source it and set the matching RMW/domain first (see the DDS note + below): + ```bash + source /opt/ros/jazzy/setup.bash + source ~/linorobot2_ws/install/setup.bash + export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp + export ROS_DOMAIN_ID=0 + ros2 run micro_ros_agent micro_ros_agent serial -b 115200 -D + ``` + Use the stable `/dev/serial/by-id/usb-Teensyduino_USB_Serial_*-if00` path (not `/dev/ttyACM*`, + which can renumber). +- The firmware also has an (unused here) WiFi transport option (`USE_WIFI_TRANSPORT`), disabled in + this config. -## Owning OpenAMRobot source +> ⚠️ **DDS must match the rest of the stack.** On this robot the host uses CycloneDDS on +> `ROS_DOMAIN_ID=0`. A host defaulting to a different RMW/domain will not see the topics. The agent +> may log harmless `Failed to parse type hash ... USER_DATA (null)` warnings — micro-ROS does not +> populate type hashes; they are not errors. -- [openamr-platform-fw](https://github.com/openAMRobot/openamr-platform-fw) – canonical source, versions, implementation and issue history. +## Connection state machine -## Contribution note +The firmware pings the agent and manages entities automatically: -Replace this framework with tested project-specific content through the normal [contribution workflow](https://github.com/openAMRobot/openamrobot-docs/blob/main/CONTRIBUTING.md). Keep exact parameters and contracts synchronized with the owning repository. +`WAITING_AGENT` → `AGENT_AVAILABLE` → `AGENT_CONNECTED` → (`AGENT_DISCONNECTED`) → `WAITING_AGENT`. + +On disconnect it calls `fullStop()` and destroys its ROS entities, then re-creates them when the +agent returns. Time is synchronised with the agent on connect so stamps are in ROS time. + +## Topic contract + +| Topic | Direction | Type | QoS | +|---|---|---|---| +| `/cmd_vel` | in | `geometry_msgs/Twist` | reliable | +| `/odom/unfiltered` | out | `nav_msgs/Odometry` | reliable | +| `/imu/data_raw` | out | `sensor_msgs/Imu` | reliable | +| `/imu/mag` | out | `sensor_msgs/MagneticField` | reliable | see note | +| `/debug/left`, `/debug/right`, `/debug/pwm` | out | `geometry_msgs/Vector3` | **best-effort** | +| `/debug/openloop` | in | `geometry_msgs/Vector3` | reliable | +| `/debug/tune` | in | `geometry_msgs/Twist` | reliable | +| `/debug/enc_cal` | in | `std_msgs/Float32MultiArray` | reliable | + +- The firmware publishes **raw** IMU (`/imu/data_raw` + `/imu/mag`); the host Madgwick/EKF pipeline + fuses them into the filtered `/imu/data` and `/odom`. +- ⚠️ **No real magnetometer.** The board carries an **MPU6500**, driven through the MPU9250 driver + (WHO_AM_I workaround). The MPU6500 has **no magnetometer**, so `/imu/mag` is published for + message-shape compatibility but carries **no meaningful magnetic field** — do not fuse it as a + heading source. The host EKF should use the gyro/accel only (yaw from the gyro rate). +- The `/debug/*` topics are covered in detail in + [debug telemetry](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/debug-telemetry.md). + +## IMU note + +The config enables `USE_MPU9250_IMU`, but the physical chip is an **MPU-6500** (`WHO_AM_I 0x70`). +The MPU9250 driver recognises it; the MPU6050 driver rejects it. IMU init failure is fatal (see LED +codes below). + +## LED status codes (pin 13) + +| Blink pattern | Meaning | +|---|---| +| Solid on | agent connected / idle (also toggles on each `/cmd_vel`) | +| Toggling with control | actively driving in closed loop | +| 2 blinks (loop) | fatal RCL error (`rclErrorLoop`) | +| 3 blinks | IMU init failed — **also** any `createEntities()` RCL failure (the non-syslog `RCCHECK` flashes 3 then retries) | +| 4 blinks | magnetometer init failed | + +After bringup, if you use the encoder ripple table, run the host alignment once per Teensy +power-cycle — see [encoder calibration](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/encoder-calibration.md). + +## Engineering handoff + +- Record the repository commit, hardware revision, supply voltage, and test configuration with every result. +- Stop if observed wiring, component labels, geometry, or topic behavior differs from this page; resolve the discrepancy in the owning repository first. +- Report documentation or implementation defects through [the repository issue tracker](https://github.com/openAMRobot/openamr-platform-fw/issues). diff --git a/docs/reference/openamr-platform-fw/setup.md b/docs/reference/openamr-platform-fw/setup.md index 1a45d09..a1def66 100644 --- a/docs/reference/openamr-platform-fw/setup.md +++ b/docs/reference/openamr-platform-fw/setup.md @@ -1,48 +1,68 @@ --- -title: Setup +title: Build and flash the firmware +tags: [builder, developer] +status: experimental +description: Build the pinned Teensy 4.0 firmware overlay and flash it with a reproducible toolchain. --- -
Under development

Setup

Provide the learning-layer reference for setup and point to its owning repository.

OpenAMRobot logo
+# Build and flash the firmware -!!! info "Documentation framework" - This page is part of the approved OpenAMRobot knowledge architecture. It is intentionally published before full content is complete so contributors can fill it consistently. Do not treat unfinished guidance as a validated build or deployment instruction. +**Canonical source:** [`openamr-platform-fw/docs/flashing/build-and-flash.md`](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/flashing/build-and-flash.md) +**Applies to:** the documented OpenAMRobot reference mobile base; verify repository revision before changing hardware or firmware. -## What this page should contain +!!! warning "Experimental project documentation" + These instructions describe the current reference build and its measured behavior. Use physical safeguards, test with wheels clear of the floor, and revalidate after changing parts, wiring, firmware, battery chemistry, or geometry. -- **Audience and outcome:** who uses this page and what verified state they should reach. -- **Prerequisites:** required skills, tools, hardware, software, configuration and safety conditions. -- **Concept or procedure:** concise explanation followed by ordered, reproducible steps where applicable. -- **Verification:** observable output, measurement, test or acceptance criterion. -- **Troubleshooting:** likely failures, evidence to collect and safe recovery actions. -- **Next step:** one clear continuation in the ownership or development path. +*Applies to the Teensy 4.0 `linorobot2_overlay` firmware.* -## Content template +The overlay is built on top of a linorobot2 firmware checkout with PlatformIO and flashed to the +Teensy 4.0 with `teensy_loader_cli`. See the [overlay README](https://github.com/openAMRobot/openamr-platform-fw/blob/main/boards/teensy_4_0/linorobot2_overlay/README.md) +for how the overlay files map onto the linorobot2 base. -| Field | To complete | -| --- | --- | -| For | Name one primary reader: operator, builder, integrator or developer | -| Before you start | List exact prerequisites or state “nothing” | -| When you finish | Describe a measurable outcome | -| Capability status | Stable, beta, experimental, planned, community or partner-supported | -| Applies to | Release, hardware revision and configuration | -| Safety | Hazards, limits, stop conditions and required supervision | -| Verification | What the reader should see, hear, measure or test | +## Build -### Procedure or explanation +PlatformIO builds the `teensy40` environment, which uses `config/lino_base_config.h` (**not** any +`dev_config.h`). -1. Establish the starting state. -2. Complete one action or concept per subsection. -3. Record commands, parameters, screenshots or measurements where useful. -4. Verify the result before continuing. +```bash +cd /firmware +ROS_DISTRO=jazzy ~/.platformio/penv/bin/pio run -e teensy40 +``` -### If it did not work +- On Ubuntu 24.04, PlatformIO **must** be run from its own venv (`~/.platformio/penv/bin/pio`, as + above) to avoid the PEP 668 "externally managed environment" restriction — a bare `pio` may fail. +- First build ≈ 5 min (compiles micro-ROS); incremental ≈ 8 s. +- The build output is `.pio/build/teensy40/firmware.hex`. -Document symptoms separately from causes. Include diagnostic evidence and a safe rollback or escalation path. +## Flash -## Owning OpenAMRobot source +Install `teensy_loader_cli` and the PJRC udev rules (`/etc/udev/rules.d/00-teensy.rules`). **Stop +the micro-ROS agent first** to free the serial port. -- [openamr-platform-fw](https://github.com/openAMRobot/openamr-platform-fw) – canonical source, versions, implementation and issue history. +```bash +pkill -f "[m]icro_ros_agent" +HEX=/firmware/.pio/build/teensy40/firmware.hex +sudo teensy_loader_cli --mcu=TEENSY40 -s -w -v "$HEX" # -s = soft reboot into the bootloader +``` -## Contribution note +> ⚠️ **`-s` (soft reboot) is timing-flaky** and may report `error writing`. When that happens the +> board is already in **HalfKay** (bootloader; LED off, and it stays there). Retry once **without** +> `-s`: +> ```bash +> sudo teensy_loader_cli --mcu=TEENSY40 -w -v "$HEX" +> ``` +> The most reliable method is to press the Teensy's **physical button** to force HalfKay, then flash +> with `-w`. A USB unplug/replug after a failed flash boots the last good firmware. -Replace this framework with tested project-specific content through the normal [contribution workflow](https://github.com/openAMRobot/openamrobot-docs/blob/main/CONTRIBUTING.md). Keep exact parameters and contracts synchronized with the owning repository. +After flashing, restart the micro-ROS agent (or the host bring-up). See +[micro-ROS bringup](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/bringup/micro-ros-bringup.md). + +> ⚠️ **A reflash reboots the Teensy and shifts the encoder zero.** If you use the encoder ripple +> table, re-run the host alignment after every flash/power-cycle — see +> [encoder calibration](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/encoder-calibration.md). + +## Engineering handoff + +- Record the repository commit, hardware revision, supply voltage, and test configuration with every result. +- Stop if observed wiring, component labels, geometry, or topic behavior differs from this page; resolve the discrepancy in the owning repository first. +- Report documentation or implementation defects through [the repository issue tracker](https://github.com/openAMRobot/openamr-platform-fw/issues). diff --git a/docs/reference/openamr-platform-fw/troubleshooting.md b/docs/reference/openamr-platform-fw/troubleshooting.md index 882e311..4086f56 100644 --- a/docs/reference/openamr-platform-fw/troubleshooting.md +++ b/docs/reference/openamr-platform-fw/troubleshooting.md @@ -1,48 +1,93 @@ --- -title: Troubleshooting +title: Firmware troubleshooting +tags: [builder, developer] +status: experimental +description: Diagnose firmware transport, flashing, encoder, PID, and powered-debug failures on the OpenAMRobot base. --- -
Under development

Troubleshooting

Provide the learning-layer reference for troubleshooting and point to its owning repository.

OpenAMRobot logo
+# Firmware troubleshooting -!!! info "Documentation framework" - This page is part of the approved OpenAMRobot knowledge architecture. It is intentionally published before full content is complete so contributors can fill it consistently. Do not treat unfinished guidance as a validated build or deployment instruction. +**Canonical source:** [`openamr-platform-fw/docs/troubleshooting/common-issues.md`](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/troubleshooting/common-issues.md) +**Applies to:** the documented OpenAMRobot reference mobile base; verify repository revision before changing hardware or firmware. -## What this page should contain +!!! warning "Experimental project documentation" + These instructions describe the current reference build and its measured behavior. Use physical safeguards, test with wheels clear of the floor, and revalidate after changing parts, wiring, firmware, battery chemistry, or geometry. -- **Audience and outcome:** who uses this page and what verified state they should reach. -- **Prerequisites:** required skills, tools, hardware, software, configuration and safety conditions. -- **Concept or procedure:** concise explanation followed by ordered, reproducible steps where applicable. -- **Verification:** observable output, measurement, test or acceptance criterion. -- **Troubleshooting:** likely failures, evidence to collect and safe recovery actions. -- **Next step:** one clear continuation in the ownership or development path. +*Applies to the Teensy 4.0 `linorobot2_overlay` firmware.* -## Content template +Quick index of the failure modes seen during commissioning and where each is explained in full. -| Field | To complete | -| --- | --- | -| For | Name one primary reader: operator, builder, integrator or developer | -| Before you start | List exact prerequisites or state “nothing” | -| When you finish | Describe a measurable outcome | -| Capability status | Stable, beta, experimental, planned, community or partner-supported | -| Applies to | Release, hardware revision and configuration | -| Safety | Hazards, limits, stop conditions and required supervision | -| Verification | What the reader should see, hear, measure or test | +## A `/debug/*` echo prints nothing -### Procedure or explanation +`/debug/left`, `/debug/right`, `/debug/pwm` are **BEST_EFFORT**. A default (reliable) subscriber +receives nothing. Request best-effort: +``` +ros2 topic echo /debug/right --qos-reliability best_effort +``` +See [debug telemetry](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/debug-telemetry.md). -1. Establish the starting state. -2. Complete one action or concept per subsection. -3. Record commands, parameters, screenshots or measurements where useful. -4. Verify the result before continuing. +## `/debug/openloop` moves both wheels / ignores `y` -### If it did not work +By design: the firmware reads only `x` and applies it to **both** motors (motor2 scaled by +`motor2_gain`). `y`/`z` are ignored. To bias the right wheel use `/debug/tune angular.x`. See +[debug telemetry](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/debug-telemetry.md#debugopenloop--raw-open-loop-pwm-geometry_msgsmsgvector3-reliable). -Document symptoms separately from causes. Include diagnostic evidence and a safe rollback or escalation path. +## `/debug/openloop` does nothing at all -## Owning OpenAMRobot source +- The command is only honoured for **300 ms** — republish it (`ros2 topic pub -r 10 ...`). +- In a **production build** (`ENABLE_POWERED_DEBUG` not defined) the powered path is disabled by + design. See [motion safety](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/safety/motion-safety.md). -- [openamr-platform-fw](https://github.com/openAMRobot/openamr-platform-fw) – canonical source, versions, implementation and issue history. +## Left wheel "oscillates" at low speed -## Contribution note +Not a PID problem — the left AS5040 magnet is off-centre, so the **measured** rpm carries a ~40 % +per-revolution ripple the PID chases. The deployed fix is the hot-loaded ripple table + +per-boot phase re-align (`align_enc_cal.py`, run after every Teensy power-cycle); the only durable +*hardware* fix is better encoder mounting. (A 512-count velocity filter was rejected for ~0.6 s +lag; the firmware's 12-count estimator only tames low-speed noise, it does not remove the ripple.) +See [encoder calibration](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/encoder-calibration.md). -Replace this framework with tested project-specific content through the normal [contribution workflow](https://github.com/openAMRobot/openamrobot-docs/blob/main/CONTRIBUTING.md). Keep exact parameters and contracts synchronized with the owning repository. +## Ripple got *worse* after calibration + +The alignment routine measured with a table already loaded and produced an **anti-phase** table +that doubles the ripple. Flatten the table to 1.0 before measuring, and re-align after every Teensy +power-cycle (the table lives in RAM). See +[encoder calibration](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/encoder-calibration.md). + +## Robot judders or stalls at very low speed + +You are below the measured velocity floors (linear ~0.04 m/s, angular ~0.15 rad/s). Command above +them; the anti-stiction dither only helps down to ~0.06 m/s. This is stick-slip, not a torque +shortfall. See [motion safety](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/safety/motion-safety.md). + +## Robot won't reach commanded speed / RPM ceiling looks halved + +`MOTOR_OPERATING_VOLTAGE` and `MOTOR_POWER_MAX_VOLTAGE` must both be **24** for the real 24 V +supply, or the computed max RPM is halved. See [control loop](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/control-loop.md). + +## Gain edits have no effect + +The `teensy40` build uses `config/lino_base_config.h`, not any `dev_config.h`. Live `/debug/tune` +changes are RAM-only and are lost on reflash/reboot. See +[control loop](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/control-loop.md) and [build & flash](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/flashing/build-and-flash.md). + +## Flashing reports `error writing` + +The soft-reboot flash (`-s`) is timing-flaky; the board is already in HalfKay. Retry without `-s`, +or press the physical button and flash with `-w`. See [build & flash](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/flashing/build-and-flash.md). + +## Host can't see any topics + +DDS/domain mismatch — match the robot's CycloneDDS + `ROS_DOMAIN_ID=0`, and confirm the agent baud +is 115200. See [micro-ROS bringup](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/bringup/micro-ros-bringup.md). + +## Dropped encoder counts / flaky encoders + +Check the encoder supply is on the **3.3 V rail** — the Teensy 4.0 is not 5 V tolerant, and a 5 V +supply over-drives the A/B inputs. See [motion safety](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/safety/motion-safety.md#hardware-safety-note--encoder-over-voltage). + +## Engineering handoff + +- Record the repository commit, hardware revision, supply voltage, and test configuration with every result. +- Stop if observed wiring, component labels, geometry, or topic behavior differs from this page; resolve the discrepancy in the owning repository first. +- Report documentation or implementation defects through [the repository issue tracker](https://github.com/openAMRobot/openamr-platform-fw/issues). diff --git a/docs/reference/openamr-platform-fw/tutorials.md b/docs/reference/openamr-platform-fw/tutorials.md index ade5a84..608aa70 100644 --- a/docs/reference/openamr-platform-fw/tutorials.md +++ b/docs/reference/openamr-platform-fw/tutorials.md @@ -1,48 +1,138 @@ --- -title: Tutorials +title: Calibrate encoder ripple +tags: [developer, domain-expert] +status: experimental +description: Measure, generate, apply, and verify the OpenAMRobot encoder ripple correction table. --- -
Under development

Tutorials

Provide the learning-layer reference for tutorials and point to its owning repository.

OpenAMRobot logo
+# Calibrate encoder ripple -!!! info "Documentation framework" - This page is part of the approved OpenAMRobot knowledge architecture. It is intentionally published before full content is complete so contributors can fill it consistently. Do not treat unfinished guidance as a validated build or deployment instruction. +**Canonical source:** [`openamr-platform-fw/docs/architecture/encoder-calibration.md`](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/encoder-calibration.md) +**Applies to:** the documented OpenAMRobot reference mobile base; verify repository revision before changing hardware or firmware. -## What this page should contain +!!! warning "Experimental project documentation" + These instructions describe the current reference build and its measured behavior. Use physical safeguards, test with wheels clear of the floor, and revalidate after changing parts, wiring, firmware, battery chemistry, or geometry. -- **Audience and outcome:** who uses this page and what verified state they should reach. -- **Prerequisites:** required skills, tools, hardware, software, configuration and safety conditions. -- **Concept or procedure:** concise explanation followed by ordered, reproducible steps where applicable. -- **Verification:** observable output, measurement, test or acceptance criterion. -- **Troubleshooting:** likely failures, evidence to collect and safe recovery actions. -- **Next step:** one clear continuation in the ownership or development path. +*Applies to the Teensy 4.0 `linorobot2_overlay` firmware.* -## Content template +The left wheel showed a slow low-speed "oscillation" (a ~1 s, ±6 rpm limit cycle) that barely +responded to PID gains. It was **not** a control-loop problem: the left AS5040 magnet is +off-centre, so the *measured* rpm carries a geometric ripple that the PID was chasing. This page +documents the ripple, the deployed runtime correction table + per-boot phase re-align (the working +fix), and why a static/compiled table can't work and the velocity filter was rejected. -| Field | To complete | -| --- | --- | -| For | Name one primary reader: operator, builder, integrator or developer | -| Before you start | List exact prerequisites or state “nothing” | -| When you finish | Describe a measurable outcome | -| Capability status | Stable, beta, experimental, planned, community or partner-supported | -| Applies to | Release, hardware revision and configuration | -| Safety | Hazards, limits, stop conditions and required supervision | -| Verification | What the reader should see, hear, measure or test | +## The ripple (measured) -### Procedure or explanation +An open-loop constant-speed sweep, binning measured rpm by wheel angle (`counts mod CPR`), showed: -1. Establish the starting state. -2. Complete one action or concept per subsection. -3. Record commands, parameters, screenshots or measurements where useful. -4. Verify the result before continuing. +- **LEFT wheel:** a **2-cycle-per-revolution, ~40 % peak-to-peak** error (≈ 0.85 → 1.22), + **identical at 120 / 180 / 250 PWM** → locked to wheel *angle*, not time = a mechanical encoder + defect (off-centre / tilted AS5040 magnet), not a real speed oscillation. +- **RIGHT wheel:** only ~±4 % (well aligned). -### If it did not work +No PID gain can remove an artefact that is in the measurement itself. -Document symptoms separately from causes. Include diagnostic evidence and a safe rollback or escalation path. +## Runtime correction table (`/debug/enc_cal`) -## Owning OpenAMRobot source +The firmware holds a per-wheel correction table and divides the measured rpm by the table entry at +the current wheel angle: -- [openamr-platform-fw](https://github.com/openAMRobot/openamr-platform-fw) – canonical source, versions, implementation and issue history. +``` +true_rpm = measured_rpm / CAL[bin], bin = (counts mod CPR) · NBINS / CPR +``` -## Contribution note +- `ENC_CAL_NBINS = 36` bins, `ENC_CAL_CPR = 1024`. Two tables: `LEFT_CAL[36]`, `RIGHT_CAL[36]`. +- Applied in `calib_rpm()` to `current_rpm1/2` **before** the PID and odometry — instant, no + averaging, no lag. A table entry ≤ 0.05 is ignored (guard against divide-by-tiny). +- Loaded at runtime via `/debug/enc_cal` (`std_msgs/Float32MultiArray`, 72 floats = 36 left then + 36 right). Until a table is received, both tables default to **1.0 = passthrough** (raw rpm), so + an un-calibrated boot behaves exactly like no correction. -Replace this framework with tested project-specific content through the normal [contribution workflow](https://github.com/openAMRobot/openamrobot-docs/blob/main/CONTRIBUTING.md). Keep exact parameters and contracts synchronized with the owning repository. +## Why the table is loaded at runtime, not compiled in + +The encoder is read **incrementally**: counts start from 0 at every Teensy boot, at whatever +position the wheel happens to be in. So `counts mod 1024` is an angle **relative to the boot +position**, not an absolute wheel angle. Every reflash reboots the Teensy and shifts the encoder +zero by a random (and different left/right) angle. + +A **compiled-in table would therefore be applied at the wrong phase** after every flash. A +compiled table was tried and failed to converge (it even produced an anti-phase result that +*doubled* the ripple). The working approach loads the table at runtime so its phase matches the +current boot's encoder zero. + +## Calibration workflow (host-side) + +The calibration workflow is shown below. + +![Per-boot encoder ripple calibration workflow: (1) power-cycle the Teensy immobile, (2) spin the wheels in the air with align_enc_cal.py (~8 s), (3) measure the AS5040 per-position ripple (~±40%), (4) compute and push the correction table over /debug/enc_cal, (5) the firmware loads it at runtime phase-aligned per boot → ripple drops to ~±4%. A compiled static table does not work because the incremental encoder loses phase at boot](https://raw.githubusercontent.com/openAMRobot/openamr-platform-fw/main/docs/architecture/diagrams/encoder-ripple-calibration-workflow.svg) + + +The **shape** of the ripple is fixed (it is the magnet geometry); only its **phase** moves per +boot. So the shape is captured once as a reference, and each boot only re-aligns the phase: + +1. A reference table (fixed shape) lives in the host tooling + ([`tools/encoder-calibration/encoder_ref_table.json`](https://github.com/openAMRobot/openamr-platform-fw/blob/main/tools/encoder-calibration)). The + alignment scripts are host-side (they run on the Pi / a dev PC, not on the Teensy) and are + vendored in this repo under [`tools/encoder-calibration/`](https://github.com/openAMRobot/openamr-platform-fw/blob/main/tools/encoder-calibration). +2. After **every Teensy power-cycle**, a short alignment run (~6–8 s) spins the wheels, measures + the raw per-angle ripple, correlates it sub-bin (~1°) against the reference to find the current + phase, rolls the reference to that phase, and publishes the 72-float table on `/debug/enc_cal`. + Run it from the host, wheels off the ground, with the micro-ROS agent up and 24 V power on: + ```bash + cd tools/encoder-calibration && source /opt/ros/jazzy/setup.bash \ + && export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp ROS_DOMAIN_ID=0 \ + && python3 align_enc_cal.py --arm 250 + ``` + (See [`tools/encoder-calibration/README.md`](https://github.com/openAMRobot/openamr-platform-fw/blob/main/tools/encoder-calibration/README.md) for the + full-recalibration workflow used when the magnet is physically disturbed.) +3. The table lives in Teensy RAM, so it must be re-sent after a power-cycle — a ROS restart on the + host does **not** require re-alignment, but a Teensy reboot does. + +> ⚠️ **Alignment gotcha:** the alignment routine must flatten the table to 1.0 (passthrough) +> *before* measuring. If it measures with a table already loaded, it reads the residual of the +> loaded table, computes the wrong phase, and produces an **anti-phase** table that *doubles* the +> ripple (~71 %, worse than raw). Symptom: the post-check shows a **larger** ripple than the raw +> baseline. + +The **±40 % (LEFT) / ±4 % (RIGHT)** figures above are the **raw, un-calibrated** ripple — what you +see when no table is loaded (unity passthrough) or before `align_enc_cal` has run this boot. After +alignment the residual is **boot-dependent** (the per-boot phase lock is never identical): a clean +full recalibration lands **under ±5 %** on the LEFT, while a fast per-boot alignment can sit higher +(**up to ~±11 %**) depending on how well the phase locked that boot. Either way it is flat, instant, +far below the ±40 % raw, and it survives a reboot once re-aligned. + +## The deployed fix (and the alternatives that were rejected) + +**The in-use, working ripple fix is the hot-loaded correction table (`calib_rpm`) + a per-boot +phase re-align (`align_enc_cal.py`, ~8 s).** That is what brings LEFT from ±40 % to ±4 % and +survives a reboot once re-aligned. It is a **per-boot ritual** — the phase must be re-aligned every +power-cycle, and the flatten-before-measure gotcha is easy to hit — but it is the deployed solution, +not a stopgap for something else. + +What does **not** work, and what was rejected: + +- **A static / compiled-in table fails.** The encoder is incremental, so `counts mod CPR` is an + angle relative to the boot position; every reboot shifts the encoder zero by a random (and + different left/right) angle, so a fixed table is applied at the wrong phase (see the section + above). Only a table that is re-aligned at runtime each boot can work. +- **A half-revolution angular velocity filter** (average over 512 counts) cancels the ripple + cleanly but adds **~0.6 s of lag** — **considered and rejected** for closed-loop control. The + deployed ripple fix is **not** this velocity filter. +- Do **not** conflate the ripple fix with the firmware's separate **small-window (12-count) + velocity estimator**: that is only a *low-speed quantization-noise* filter (see + [control loop](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/control-loop.md)), it does **not** remove the per-angle ripple — the align-table + does. + +**The only durable *hardware* fix is better encoder mounting** (a centred/untilted AS5040 magnet), +which removes the geometric ripple at the source. Until then, the runtime align-table + per-boot +re-alignment is the working solution. + +See [control loop](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/control-loop.md) for where `calib_rpm` sits in the loop, and +[debug telemetry](https://github.com/openAMRobot/openamr-platform-fw/blob/main/docs/architecture/debug-telemetry.md#debugenc_cal--runtime-encoder-ripple-table-std_msgsmsgfloat32multiarray-reliable) +for the wire format. + +## Engineering handoff + +- Record the repository commit, hardware revision, supply voltage, and test configuration with every result. +- Stop if observed wiring, component labels, geometry, or topic behavior differs from this page; resolve the discrepancy in the owning repository first. +- Report documentation or implementation defects through [the repository issue tracker](https://github.com/openAMRobot/openamr-platform-fw/issues). diff --git a/docs/reference/openamr-platform-hw/concepts.md b/docs/reference/openamr-platform-hw/concepts.md index 20adbfb..3fa308b 100644 --- a/docs/reference/openamr-platform-hw/concepts.md +++ b/docs/reference/openamr-platform-hw/concepts.md @@ -1,48 +1,62 @@ --- -title: Concepts +title: Hardware architecture +tags: [builder, integrator] +status: experimental +description: Understand the validated OpenAMRobot base platform, its subsystem boundaries, and the difference between the reference build and roadmap options. --- -
Under development

Concepts

Provide the learning-layer reference for concepts and point to its owning repository.

OpenAMRobot logo
+# Hardware architecture -!!! info "Documentation framework" - This page is part of the approved OpenAMRobot knowledge architecture. It is intentionally published before full content is complete so contributors can fill it consistently. Do not treat unfinished guidance as a validated build or deployment instruction. +**Canonical source:** [`openamr-platform-hw/product-architecture.md`](https://github.com/openAMRobot/openamr-platform-hw/blob/main/product-architecture.md) +**Applies to:** the documented OpenAMRobot reference mobile base; verify repository revision before changing hardware or firmware. -## What this page should contain +!!! warning "Experimental project documentation" + These instructions describe the current reference build and its measured behavior. Use physical safeguards, test with wheels clear of the floor, and revalidate after changing parts, wiring, firmware, battery chemistry, or geometry. -- **Audience and outcome:** who uses this page and what verified state they should reach. -- **Prerequisites:** required skills, tools, hardware, software, configuration and safety conditions. -- **Concept or procedure:** concise explanation followed by ordered, reproducible steps where applicable. -- **Verification:** observable output, measurement, test or acceptance criterion. -- **Troubleshooting:** likely failures, evidence to collect and safe recovery actions. -- **Next step:** one clear continuation in the ownership or development path. +This repository documents the **base OpenAMRobot differential-drive platform** — the robot that has +actually been wired, flashed, and driven. The base is one configuration of a larger product vision +(the "industrial product version"): the same chassis and compute, extended with optional attachments +and sensor packs. -## Content template +This page separates the two so nothing here implies the base build ships with a lift, a conveyor, or +a wireless charger — it does not. -| Field | To complete | -| --- | --- | -| For | Name one primary reader: operator, builder, integrator or developer | -| Before you start | List exact prerequisites or state “nothing” | -| When you finish | Describe a measurable outcome | -| Capability status | Stable, beta, experimental, planned, community or partner-supported | -| Applies to | Release, hardware revision and configuration | -| Safety | Hazards, limits, stop conditions and required supervision | -| Verification | What the reader should see, hear, measure or test | +## The full product architecture (superset) -### Procedure or explanation +![Full OpenAMRobot product architecture — cloud/fleet server, the AMR general node (navigation sensors, Raspberry Pi 5 + Nav2, options), the Teensy MC node (BLDC diff-drive with ZBLD.C20-120L2 drivers and AS5040 encoders, plus optional tilt/conveyor/lift), and the power node (BMS + battery, charging, e-stop)](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/assets/images/HW_schema_article.jpg) -1. Establish the starting state. -2. Complete one action or concept per subsection. -3. Record commands, parameters, screenshots or measurements where useful. -4. Verify the result before continuing. +## What the base build actually is -### If it did not work +The **✅ base** (this repo's electrical / firmware / software) is the core of that diagram: -Document symptoms separately from causes. Include diagnostic evidence and a safe rollback or escalation path. +- **Drive:** 2× BLDC wheels, **ZBLD.C20-120L2R** drivers, **AS5040** magnetic encoders, Teensy 4.0 + running micro-ROS motor control (electronics derived from the Linorobot project, motor + controller + upgraded to the ZD/ZBLD industrial parts). +- **Compute:** Raspberry Pi 5 + ROS 2 Jazzy + Nav2. +- **Sensing:** RPLIDAR A1 (2D), Pi Camera Module 3, MPU6500 IMU. +- **Power:** 24 V bus (any chemistry; reference build 2× 12 V; the product targets a LiFePO4 + BMS pack). -## Owning OpenAMRobot source +## What is optional / roadmap (⚙️ NOT on the base build) -- [openamr-platform-hw](https://github.com/openAMRobot/openamr-platform-hw) – canonical source, versions, implementation and issue history. +The same base platform, extended toward the full product vision (here with the dual-arm manipulator +attachment — **illustrative, not the base build**): -## Contribution note +![Product-vision render — the base platform carrying a vertical column with a depth camera and two robot arms; the base still shows the same front panel (E-stop, buttons, camera) and casters](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/mechanical/renderings/Open_AMR_.png) -Replace this framework with tested project-specific content through the normal [contribution workflow](https://github.com/openAMRobot/openamrobot-docs/blob/main/CONTRIBUTING.md). Keep exact parameters and contracts synchronized with the owning repository. +Shown in the architecture diagram but **not part of the base**: + +- **Extra safety pack** — ultrasonic (JSN-SR04) + IR (E18-D80NK) proximity rings. +- **Attachments** — tilt sorting, conveyor, **lift** (BLDC lift/rotate), end-effectors. +- **Charging** — **wireless charging** (WCM-300) with auto-docking. +- **Battery/BMS** — 24 V smart battery pack + BMS (serial), vs. the base's plain 24 V pack. +- **Higher-power drives** — ZLTech ZLAC8015D/8030L drivers, hub-motor wheels. +- **Tracking / AI** — QR + line tracking, on-board NVIDIA (Jetson) for heavier perception. +- **Fleet** — cloud server, fleet management, dashboards (RMF). + +Datasheets for the optional parts are under [`datasheets/`](https://github.com/openAMRobot/openamr-platform-hw/blob/main/datasheets) and clearly marked as options. + +## Engineering handoff + +- Record the repository commit, hardware revision, supply voltage, and test configuration with every result. +- Stop if observed wiring, component labels, geometry, or topic behavior differs from this page; resolve the discrepancy in the owning repository first. +- Report documentation or implementation defects through [the repository issue tracker](https://github.com/openAMRobot/openamr-platform-hw/issues). diff --git a/docs/reference/openamr-platform-hw/configuration.md b/docs/reference/openamr-platform-hw/configuration.md index 328ed95..9c03ed5 100644 --- a/docs/reference/openamr-platform-hw/configuration.md +++ b/docs/reference/openamr-platform-hw/configuration.md @@ -1,48 +1,164 @@ --- -title: Configuration +title: Wiring and pin configuration +tags: [builder, developer] +status: experimental +description: Use the verified Teensy, motor-driver, encoder, IMU, and power wiring for the OpenAMRobot mobile base. --- -
Under development

Configuration

Provide the learning-layer reference for configuration and point to its owning repository.

OpenAMRobot logo
+# Wiring and pin configuration -!!! info "Documentation framework" - This page is part of the approved OpenAMRobot knowledge architecture. It is intentionally published before full content is complete so contributors can fill it consistently. Do not treat unfinished guidance as a validated build or deployment instruction. +**Canonical source:** [`openamr-platform-hw/electrical/wiring/wiring-pinout.md`](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/wiring/wiring-pinout.md) +**Applies to:** the documented OpenAMRobot reference mobile base; verify repository revision before changing hardware or firmware. -## What this page should contain +!!! warning "Experimental project documentation" + These instructions describe the current reference build and its measured behavior. Use physical safeguards, test with wheels clear of the floor, and revalidate after changing parts, wiring, firmware, battery chemistry, or geometry. -- **Audience and outcome:** who uses this page and what verified state they should reach. -- **Prerequisites:** required skills, tools, hardware, software, configuration and safety conditions. -- **Concept or procedure:** concise explanation followed by ordered, reproducible steps where applicable. -- **Verification:** observable output, measurement, test or acceptance criterion. -- **Troubleshooting:** likely failures, evidence to collect and safe recovery actions. -- **Next step:** one clear continuation in the ownership or development path. +*Last updated: 2026-06-19.* -## Content template +Convention: **MOTOR1 = LEFT wheel, MOTOR2 = RIGHT wheel.** Logic level **3.3 V**. -| Field | To complete | -| --- | --- | -| For | Name one primary reader: operator, builder, integrator or developer | -| Before you start | List exact prerequisites or state “nothing” | -| When you finish | Describe a measurable outcome | -| Capability status | Stable, beta, experimental, planned, community or partner-supported | -| Applies to | Release, hardware revision and configuration | -| Safety | Hazards, limits, stop conditions and required supervision | -| Verification | What the reader should see, hear, measure or test | +> **Verification status (2026-06-19):** full wiring/component audit done. Physically verified — +> **drivers + motors** (ZBLD C20-120L2R + ZD Z4BLD60-24GN-30S, both drivers identical), **encoders** +> (AS5040; the 5 V→~4 V overvoltage was **fixed → now 3.3 V**, see [encoders.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/sensors/encoders.md)), **IMU** +> (MPU-6500, SDA18/SCL19, 3.3 V, 0x68), **Teensy = 4.0** (i.MX RT1062), **power/24 V** (no fuse / no +> battery cut-off — see [power.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/power_distribution/power.md)). Component list + datasheets: [components-bom.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/manufacturing/bom/components-bom.md). +> Still to read (completeness): LiDAR model sticker, DC-DC model, AC/DC converter, gearbox suffix. +> (Pi RAM confirmed **8 GB**, 2026-07-06 — see [raspberry-pi.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/computing/raspberry-pi.md).) -### Procedure or explanation +The complete power-and-signal wiring is shown in the harness diagram below; the sections that +follow give the exact pin/terminal tables behind it. -1. Establish the starting state. -2. Complete one action or concept per subsection. -3. Record commands, parameters, screenshots or measurements where useful. -4. Verify the result before continuing. +![Figure 1 — OpenAMRobot wiring harness: 24 V power and 3.3 V logic domains, every signal link](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/electrical/wiring/diagrams/wiring-harness.svg) -### If it did not work +## Teensy 4.0 pin assignment -Document symptoms separately from causes. Include diagnostic evidence and a safe rollback or escalation path. +| Function | Pin | Notes | +|---|---|---| +| **IMU** SDA | 18 | I²C data (MPU6500 @ 0x68) | +| **IMU** SCL | 19 | I²C clock | +| **Encoder LEFT (M1)** A | 14 | quadrature | +| **Encoder LEFT (M1)** B | 15 | quadrature | +| **Encoder RIGHT (M2)** A | 11 | quadrature | +| **Encoder RIGHT (M2)** B | 12 | quadrature | +| **Motor LEFT (M1)** PWM | 1 | → driver `VAR/AI2` (speed) | +| **Motor LEFT (M1)** IN_A / FWD | 20 | → driver `FWD/DI1` | +| **Motor LEFT (M1)** IN_B / REV | 21 | → driver `REV/DI2` | +| **Motor RIGHT (M2)** PWM | 5 | → driver `VAR/AI2` (speed) | +| **Motor RIGHT (M2)** IN_A / FWD | 6 | → driver `FWD/DI1` | +| **Motor RIGHT (M2)** IN_B / REV | 8 | → driver `REV/DI2` | +| Debug LED | 13 | init/status (3 blinks = init failure) | +| micro-ROS | USB | native serial, 115200 baud | -## Owning OpenAMRobot source +> These values are the firmware's pin configuration — see `openamr-platform-fw`. +> Note: `MOTOR1_PWM` is pin **1** (pin 21 is **not** a PWM pin on the Teensy 4.x — a common upstream pitfall). -- [openamr-platform-hw](https://github.com/openAMRobot/openamr-platform-hw) – canonical source, versions, implementation and issue history. +The same assignment is shown as a physical pin map below. -## Contribution note +![Figure 2 — Teensy 4.0 pin map: every used pin labeled by function](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/electrical/wiring/diagrams/teensy-pinout.svg) -Replace this framework with tested project-specific content through the normal [contribution workflow](https://github.com/openAMRobot/openamrobot-docs/blob/main/CONTRIBUTING.md). Keep exact parameters and contracts synchronized with the owning repository. +## Driver wiring — ZBLD C20-120L2R (VERIFIED 2026-06-19) + +Both drivers are wired **identically** (only the Teensy pins differ). The signal terminal block has 12 +positions; **exactly 4 are connected** per driver (read off the board: `x`=wired, `o`=empty, from FWD): + +``` +FWD/DI1 REV/DI2 JOG/DI3 CLR/DI4 BRK/DI5 COM VAR/AI2 +5V ERR/DO1 SPD/DO2 A+ B- + x x o o o x x o o o o (o) +``` + +| Driver terminal | Role | ← Teensy LEFT (M1) | ← Teensy RIGHT (M2) | +|---|---|---|---| +| `VAR/AI2` | speed setpoint, analog **0–5 V** (Teensy PWM @3 kHz, filtered) | PWM **1** | PWM **5** | +| `FWD/DI1` | forward direction (digital) | IN_A **20** | IN_A **6** | +| `REV/DI2` | reverse direction (digital) | IN_B **21** | IN_B **8** | +| `COM` | **common ground — mandatory** | GND | GND | + +The driver's connected terminals and their Teensy links are shown below. + +![Figure 3 — ZBLD.C20-120L2R driver connections: the 12-position signal block (only terminals 1/2/6/7 wired), 24 V power, and the 8-pin motor Molex](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/electrical/wiring/diagrams/driver-connections.svg) + +Unused: `JOG/DI3`, `CLR/DI4`, `BRK/DI5` (brake), `+5V`, `ERR/DO1` (no fault read-back), `SPD/DO2` +(no speed feedback to the Teensy), `A+/B−` (RS485 not used). Speed/gain is set by the on-board **VAR/AI1** +pot + **ACC/DEC** ramp pot (see [motors-drivers.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/motor_control/motors-drivers.md)). + +> ⚠️ The Teensy uses the `USE_GENERIC_2_IN_MOTOR_DRIVER` profile (PWM + INA + INB). On this BLDC driver +> that maps cleanly: PWM→speed (`VAR/AI2`), INA→`FWD/DI1`, INB→`REV/DI2`. The driver does its own +> commutation from the Hall sensors — the Teensy never sees U/V/W. + +### DIP switches (config applied 2026-06-19, identical both drivers) +| SW1 | SW2 | SW3 | SW4 | SW5 | SW6 | +|---|---|---|---|---|---| +| **OFF** | **ON** | OFF | **ON** | **ON** | OFF | + +The switch positions are shown below. + +![Figure 4 — driver DIP switches SW1..SW6 in the applied configuration (OFF·ON·OFF·ON·ON·OFF)](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/electrical/wiring/diagrams/driver-dip-switches.svg) + +- **SW1 = OFF → open loop** (driver is a power stage; the **Teensy PID** is the sole regulator — best + for this robot, removes the double loop). *Was ON (closed loop); changed 2026-06-19.* Validated: smooth. +- **SW2 = ON → speed source = AI2** (the external 0–5 V input where our PWM arrives). Must stay ON. +- **SW4 = ON, SW5 = ON → 5 pole pairs** (motor is P=5). *Was OFF/OFF (=2 pp, wrong); corrected.* + Irrelevant in open loop but set correctly for future closed-loop use. +- **SW6 = OFF** (no RS485). See the full rationale in [motors-drivers.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/motor_control/motors-drivers.md). +- ⚠️ With SW2=ON (AI2 source), the **VAR pot is inert** for balancing — speed comes from the PWM, not the + pot. The residual ~9 % open-loop L/R asymmetry is handled by the Teensy PID (→ ~0.2 %). + +## Motor wiring (per motor) — VERIFIED 2026-06-19 +Driver **power**: `V+ / V− = 24 V DC` (大 screw terminals, bottom-right, `电源DC24V`), fused. + +> ⚠️ **DC power wire colours on THIS robot** (confirmed 2026-06-18, counter-intuitive — AC-style colours on +> a DC bus): **brown = + (V+, i.e. the DC "red")**, **blue = − (V−, i.e. the DC "black")**. Colour is only a +> presumption — **verify with a multimeter** before connecting a 24 V lead. See [power.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/power_distribution/power.md). + +Driver **motor connector** (white Molex, 8 pins): + +| `U` | `V` | `W` | `Hu` | `Hv` | `Hw` | `Vcc` | `0V` | +|---|---|---|---|---|---|---|---| +| phase U | phase V | phase W | Hall U | Hall V | Hall W | +5 V (Hall supply) | GND (Hall) | + +> 🔧 **Left-wheel blocker:** the left signal wiring (4 terminals above) is **proven healthy**, so the +> intermittent left wheel is NOT here — it's on the **24 V power (V+/V−)** or the **motor connector** +> (a phase or the Molex). That's where to chase the faux-contact (continuity test while flexing). See +> the `openamr-platform-sw` troubleshooting doc (`docs/troubleshooting/diagnostics.md` in that repo) and the `amr-left-wheel-faux-contact` memo. + +## Grounding +All grounds must be common: **Teensy GND ↔ driver COM**. A floating COM was a real source of noise +concern (see the `openamr-platform-sw` troubleshooting doc (`docs/troubleshooting/diagnostics.md` in that repo)). + +## ASCII map +``` + Teensy 4.0 (3.3V) + IMU ── SDA18/SCL19 ───────────────► MPU6500 (I2C 0x68) + ENC L ── A14/B15 ──────────────────► encoder LEFT + ENC R ── A11/B12 ──────────────────► encoder RIGHT + M1 ── PWM1 / IN20 / IN21 ────────► driver LEFT ── U/V/W ─► motor LEFT + M2 ── PWM5 / IN6 / IN8 ──────────► driver RIGHT ── U/V/W ─► motor RIGHT + USB ───────────────────────────────► Raspberry Pi (micro-ROS 115200) + GND ───────────────────────────────► COM of both drivers (common) + +``` + +# Schematic to understand how Emergency switch and reset button works. + +![Power_connection_AMR_1](https://github.com/user-attachments/assets/316422bf-0235-4a99-9767-aef7b1126889) + +### [E-Stop button and Power distribution - OpenAMRobot discussions](https://github.com/orgs/openAMRobot/discussions/6) + +## Schneider (genuine, ~€20–35): +Harmony XB4-BS542 — Ø22 mm mount, red Ø40 mm mushroom, twist-to-release, metal bezel, 1NC (add a ZBE-102 block for a second NC channel). Certified positive-opening contacts per IEC 60947-5-5 — the one to use for anything CE-facing. +→ https://www.se.com/ww/en/product/XB4BS542/ +Plastic-bezel equivalent: XB5-AS542, same page structure at se.com. + +## Chinese clone (~€1–5): +XB2-BS542 — same Ø22/Ø40 form factor, 1NC, twist release, 10 A Ith, IP65, IEC 60947-5-1, but no e-stop-specific certification. Fine for prototypes and internal testing. +→ https://www.amazon.com/XB2-BS542-Emergency-Button-Switch-pushbutton/dp/B07Y7KZDSH +→ direct from manufacturer, ~$1/pc: https://www.finglai.com/products/switches/push-buttons/DIA22-XB2-B/XB2-BS542.html +LAY37 is the same class, usually sold as NO+NC: https://www.amazon.com/LAY37-Mushroom-Emergency-Button-Switch/dp/B07DL333VL [eBay](https://www.ebay.com/itm/356714450971)[Electric-b2c](https://www.electric-b2c.com/products/button-switch-self-reset-xb2-small-mushroom-head-emergency-stop-22mm-knob-key-start-inching-power-on-xb2-bs542-xb2-ba31-xb2-ba42) + +Reminder: contacts are ~3 A DC-13 at 24 V, so for the OpenAMRobot battery bus, break a contactor coil with the NC contacts rather than the full motor current. + +## Engineering handoff + +- Record the repository commit, hardware revision, supply voltage, and test configuration with every result. +- Stop if observed wiring, component labels, geometry, or topic behavior differs from this page; resolve the discrepancy in the owning repository first. +- Report documentation or implementation defects through [the repository issue tracker](https://github.com/openAMRobot/openamr-platform-hw/issues). diff --git a/docs/reference/openamr-platform-hw/reference.md b/docs/reference/openamr-platform-hw/reference.md index 5538583..cfb3c31 100644 --- a/docs/reference/openamr-platform-hw/reference.md +++ b/docs/reference/openamr-platform-hw/reference.md @@ -1,48 +1,113 @@ --- -title: Reference +title: Hardware specification +tags: [builder, integrator] +status: experimental +description: Reference the validated mobile-base components, drivetrain dimensions, motor-driver settings, sensors, compute, and power system. --- -
Under development

Reference

Provide the learning-layer reference for reference and point to its owning repository.

OpenAMRobot logo
+# Hardware specification -!!! info "Documentation framework" - This page is part of the approved OpenAMRobot knowledge architecture. It is intentionally published before full content is complete so contributors can fill it consistently. Do not treat unfinished guidance as a validated build or deployment instruction. +**Canonical source:** [`openamr-platform-hw/manufacturing/bom/components-bom.md`](https://github.com/openAMRobot/openamr-platform-hw/blob/main/manufacturing/bom/components-bom.md) +**Applies to:** the documented OpenAMRobot reference mobile base; verify repository revision before changing hardware or firmware. -## What this page should contain +!!! warning "Experimental project documentation" + These instructions describe the current reference build and its measured behavior. Use physical safeguards, test with wheels clear of the floor, and revalidate after changing parts, wiring, firmware, battery chemistry, or geometry. -- **Audience and outcome:** who uses this page and what verified state they should reach. -- **Prerequisites:** required skills, tools, hardware, software, configuration and safety conditions. -- **Concept or procedure:** concise explanation followed by ordered, reproducible steps where applicable. -- **Verification:** observable output, measurement, test or acceptance criterion. -- **Troubleshooting:** likely failures, evidence to collect and safe recovery actions. -- **Next step:** one clear continuation in the ownership or development path. +*Last updated: 2026-06-19.* Identification done by reading the real labels on the robot + manufacturer +datasheets. Status: ✅ = confirmed (label + datasheet), ⏳ = to read the exact label/marking. -## Content template +> **Two BOMs, by scope.** This file is the **electrical / electronic** BOM (compute, drivers, motors, +> sensors, power). The **mechanical** BOM — sheet-metal parts, fasteners, technological operations, and +> the Blickle wheel/castor — is [`mechanical-bom.md`](https://github.com/openAMRobot/openamr-platform-hw/blob/main/manufacturing/bom/mechanical-bom.md) + the source workbook +> [`BOM_specs_MMP.xlsx`](https://github.com/openAMRobot/openamr-platform-hw/blob/main/manufacturing/bom/BOM_specs_MMP.xlsx). Component datasheets are under [`../../datasheets/`](https://github.com/openAMRobot/openamr-platform-hw/blob/main/datasheets). -| Field | To complete | -| --- | --- | -| For | Name one primary reader: operator, builder, integrator or developer | -| Before you start | List exact prerequisites or state “nothing” | -| When you finish | Describe a measurable outcome | -| Capability status | Stable, beta, experimental, planned, community or partner-supported | -| Applies to | Release, hardware revision and configuration | -| Safety | Hazards, limits, stop conditions and required supervision | -| Verification | What the reader should see, hear, measure or test | +| # | Component | Exact name / part number | Status | Datasheet / source | +|---|---|---|---|---| +| 1 | Microcontroller | **Teensy 4.0** (MCU NXP **i.MX RT1062**, Cortex-M7 600 MHz) | ✅ | [pjrc.com/store/teensy40](https://www.pjrc.com/store/teensy40.html) | +| 2 | Motor drivers ×2 | **ZBLD.C20-120L2R** (Ningbo Zhongda Leader / ZD) | ✅ | [manual V1.02 (PDF)](https://image.yhdfa.com/Uploads/Picture/PDF/FZ02_11/ZBLD.C20.pdf) · [product](https://www.zd-motor.com/product/ZBLD.C20-120L2R-64.html) | +| 3 | Motors ×2 | **Z4BLD60-24GN-30S** (ZD geared BLDC, 60 W / 24 V / 3.8 A / 3000 rpm / **P=5**) | ✅ nameplate | [analog F5B60-24GN-30S spec](https://www.omc-stepperonline.com/24v-60w-100rpm-geared-brushless-dc-motor-4-18nm-591-94oz-in-30-1-spur-gearbox-f5b60-24gn-30s-5gn30k) · [ZD](https://en.zd-motor.com/) | +| 4 | Encoders ×2 | **AMS AS5040** (magnetic, quadrature A/B, marking "AS5040 AB 2.2") | ✅ | [AS5040 datasheet (ams, PDF)](https://www.mouser.com/datasheet/2/588/AS5040_DS000374_4_00-2066720.pdf) | +| 5 | IMU | **TDK InvenSense MPU-6500** (board silk says "MPU-6050"/GY-521, but the chip is a 6500) | ✅ | MPU-6500 datasheet (TDK/InvenSense) | +| 6 | LiDAR | **Slamtec RPLIDAR A1** (A1M8, by shape) | ⏳ confirm sticker | [slamtec.com RPLIDAR A1](https://www.slamtec.com/en/Lidar/A1) | +| 7 | Camera | **Sony IMX708** = Raspberry Pi **Camera Module 3 NoIR** | ✅ | [raspberrypi.com camera-3](https://www.raspberrypi.com/products/camera-module-3/) | +| 8 | SBC | **Raspberry Pi 5** (Model B Rev 1.1, **8 GB** RAM — confirmed 2026-07-06 on the current board) | ✅ | [raspberrypi.com Pi 5](https://www.raspberrypi.com/products/raspberry-pi-5/) | +| 9 | DC-DC 24 V→5 V | generic **~300 W 20 A CC/CV buck** (toroid + 2 trimpots) | ⏳ no clear model | (generic) | +| 10 | Battery | **any 24 V pack** (chemistry up to you). Reference build: 4× **DM12-7S** 12 V **7 Ah** lead-acid (AGM), 2 in series → 24 V | ✅ | DM12-7S SLA datasheet (reference; any 24 V source works) | +| 11 | AC/DC 230→24 V | unknown | ⏳ read label | — | -### Procedure or explanation +## Key specs that affect configuration -1. Establish the starting state. -2. Complete one action or concept per subsection. -3. Record commands, parameters, screenshots or measurements where useful. -4. Verify the result before continuing. +### Motors — Z4BLD60-24GN-30S (ZD geared BLDC) +*Nameplate read 2026-06-19: 60 W, 24 VDC, 3000 RPM, 3.8 A, Class B Cont, IP20, **P=5**, dated 2021/07/11.* +- **3-phase, P=5 → 5 pole pairs** (confirmed on the nameplate), 24 V, **60 W**, rated current **3.8 A**. +- Motor **3000 rpm**, **spur gearbox 1:25** (gearbox **`4GN 25K`**, confirmed by the OpenAMRobot + [sizing calculations](https://github.com/openAMRobot/openamr-platform-hw/blob/main/datasheets/motor-sizing-calculations.md) and the mechanical BOM) → **120 rpm + at the wheel** (rated torque ~3.48 N·m at 25:1). ⚠️ The motor suffix **`-30S`** is a ZD series code, + **not** the ratio — the gearbox is 4GN 25K = **25:1** (an earlier "~30:1" here was inferred from an + analog part number and is superseded). +- **Hall sensors** for the driver's commutation (separate from the AS5040 encoder). +- ⚠️ **Pole pairs = 5** → the driver **DIP SW4/SW5** must be set for 5 pole pairs. **Set to ON/ON (= 5 pp) + on 2026-06-19** (were OFF/OFF = 2 pp, wrong). A wrong pole-pair setting throws off the driver's + closed-loop speed scaling (irrelevant in the current open-loop config, but set correctly). See + [motors-drivers.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/motor_control/motors-drivers.md). +- ⚠️ **Gearbox 1:25** → odometry: `COUNTS_PER_REV = 1024` must be **per wheel revolution**. + The firmware works at wheel scale (`MOTOR_MAX_RPM 80` = the configured cap, a modest headroom below + the 120 rpm mechanical output; open-loop ~14 rpm at 20 % PWM), so the **AS5040 reads at wheel scale** + (mounted on the output side / 1024 cnt = 1 wheel rev). **Still verify physically**: drive exactly 1 m, + compare `/odom`. -### If it did not work +### Drivetrain dimensions (for kinematics / odometry) +**Ground truth = the firmware config** (`lino_base_config.h`), physically measured: +- **Wheel diameter = 0.2 m** (radius 0.10 m). +- **Track (wheel separation) = 0.46 m** (`LR_WHEELS_DISTANCE`), **confirmed by tape-measure** + (centre-to-centre of the two wheels). The CAD/URDF value of 0.4075 m is **wrong** (CAD artifact) — + use 0.46 m; the sim `robot.sdf` still needs correcting (see the sim note below). +- With the firmware cap (`MOTOR_MAX_RPM 80` × `MAX_RPM_RATIO 0.85` = 68 rpm) → **max linear ≈ 0.71 m/s** + (mechanical no-load ≈ **1.26 m/s** at the full **120 rpm** output — see the + [sizing calculations](https://github.com/openAMRobot/openamr-platform-hw/blob/main/datasheets/motor-sizing-calculations.md)); rated torque **~3.48 N·m/wheel** (25:1). + Reliable low-speed floors (measured on the ground): **linear 0.04–0.05 m/s, angular 0.15 rad/s** — see + [motors-drivers.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/motor_control/motors-drivers.md) "measured velocity floors". -Document symptoms separately from causes. Include diagnostic evidence and a safe rollback or escalation path. +> ⚠️ **Do NOT use 0.046533 m as the wheel radius.** Earlier revisions of this BOM listed a wheel radius +> of 0.046533 m (⌀ 0.093 m) "measured on the real robot" — that was **wrong**. `0.046533` is the wheel +> **axle height (Z)** in the CAD-exported URDF, mis-propagated into the Gazebo `robot.sdf` diff-drive +> `wheel_radius` and copied here by mistake. The physical wheel is ⌀ 0.2 m (firmware, measured). +> +> **Latent simulation bug (openamr-platform-sw):** `robot.sdf` uses `wheel_radius 0.046533` / +> `wheel_separation 0.4075` while the wheel's own visual/collision cylinder is `radius 0.11` — so sim +> odometry/kinematics are scaled ~2× vs the visible model. Fix in `openamrobot_description`: +> set the diff-drive `wheel_radius` to 0.10 and `wheel_separation` to 0.46. -## Owning OpenAMRobot source +### Drivers — ZBLD.C20-120L2R +- **24 V ±20 %**, output **7.5 A**, **120 W**, open/closed loop (±0.5 %), ACC/DEC 0.3–10 s, 5 DI (NPN) / 2 DO. +- Speed command: internal knob (**VAR/AI1**), external **analog 0–5/10 V**, or **PWM 0–20 kHz** → on this + robot the Teensy PWM goes to **VAR/AI2** (SW2=ON selects AI2). See [wiring-pinout.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/wiring/wiring-pinout.md). -- [openamr-platform-hw](https://github.com/openAMRobot/openamr-platform-hw) – canonical source, versions, implementation and issue history. +### Encoders — AMS AS5040 +- 10-bit magnetic; **default incremental = 256 PPR → 1024 counts/rev** in quadrature = `COUNTS_PER_REV`. ✅ +- Supply **4.5–5.5 V**, but an **internal regulator allows 3.3 V operation**. **Output high level = supply + voltage** → powered at 5 V it drove **5 V** on A/B (measured ~4 V overvoltage into the non-5 V-tolerant + Teensy 4.0). **Fix APPLIED 2026-06-19:** supply moved to the **3.3 V** rail → 3.3 V outputs → safe. + (Alternatives had it browned out: series R / divider / level-shifter.) See + [encoders.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/sensors/encoders.md). -## Contribution note +### Battery — 24 V (reference: DM12-7S) +- The design takes **any 24 V battery**. Reference build: **12 V, 7 Ah** sealed lead-acid (AGM), a pair + in series = **24 V 7 Ah**. Any 24 V chemistry (LiFePO4 / Li-ion) works too — mind its own BMS/charger + and adjust the voltage thresholds in [power.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/power_distribution/power.md). Batteries + sag under load. ⚠️ No fuse / no disconnect currently — see the safety gaps in [power.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/power_distribution/power.md). + Fuse sizing: 2 motors × **3.8 A** (nameplate) ≈ 7.6 A nominal + DC-DC → a **~15–20 A** fuse (above + nominal, below the wire/battery limit). ⚠️ This is above *nominal*, not the *stall* current (a jammed + motor draws well above 3.8 A) — confirm the stall current before finalising. -Replace this framework with tested project-specific content through the normal [contribution workflow](https://github.com/openAMRobot/openamrobot-docs/blob/main/CONTRIBUTING.md). Keep exact parameters and contracts synchronized with the owning repository. +## Still to read off the robot +- **LiDAR**: confirm the model sticker (A1M8 vs other). +- **DC-DC buck**: any printed model / the regulator IC. +- **AC/DC 230→24 V converter**: brand + model + rating. +- **Gearbox**: ~~confirm the ratio~~ — **done: `4GN 25K` = 1:25** (matches the OpenAMRobot sizing calcs). + +## Engineering handoff + +- Record the repository commit, hardware revision, supply voltage, and test configuration with every result. +- Stop if observed wiring, component labels, geometry, or topic behavior differs from this page; resolve the discrepancy in the owning repository first. +- Report documentation or implementation defects through [the repository issue tracker](https://github.com/openAMRobot/openamr-platform-hw/issues). diff --git a/docs/reference/openamr-platform-hw/setup.md b/docs/reference/openamr-platform-hw/setup.md index 883a410..bb2f861 100644 --- a/docs/reference/openamr-platform-hw/setup.md +++ b/docs/reference/openamr-platform-hw/setup.md @@ -1,48 +1,48 @@ --- -title: Setup +title: Mechanical assembly +tags: [builder] +status: experimental +description: Assemble and inspect the OpenAMRobot wheel modules using the maintained hardware procedure. --- -
Under development

Setup

Provide the learning-layer reference for setup and point to its owning repository.

OpenAMRobot logo
+# Mechanical assembly -!!! info "Documentation framework" - This page is part of the approved OpenAMRobot knowledge architecture. It is intentionally published before full content is complete so contributors can fill it consistently. Do not treat unfinished guidance as a validated build or deployment instruction. +**Canonical source:** [`openamr-platform-hw/manufacturing/assembly/README.md`](https://github.com/openAMRobot/openamr-platform-hw/blob/main/manufacturing/assembly/README.md) +**Applies to:** the documented OpenAMRobot reference mobile base; verify repository revision before changing hardware or firmware. -## What this page should contain +!!! warning "Experimental project documentation" + These instructions describe the current reference build and its measured behavior. Use physical safeguards, test with wheels clear of the floor, and revalidate after changing parts, wiring, firmware, battery chemistry, or geometry. -- **Audience and outcome:** who uses this page and what verified state they should reach. -- **Prerequisites:** required skills, tools, hardware, software, configuration and safety conditions. -- **Concept or procedure:** concise explanation followed by ordered, reproducible steps where applicable. -- **Verification:** observable output, measurement, test or acceptance criterion. -- **Troubleshooting:** likely failures, evidence to collect and safe recovery actions. -- **Next step:** one clear continuation in the ownership or development path. +## 🔩 Wheel Assembly Tutorial -## Content template +[![Wheel Assembly](https://img.youtube.com/vi/FlsYwoiEAsk/maxresdefault.jpg)](https://youtu.be/FlsYwoiEAsk?list=PLlQYRQ1Q-yzqA89n-1vjrnNSw8hSucCKi) -| Field | To complete | -| --- | --- | -| For | Name one primary reader: operator, builder, integrator or developer | -| Before you start | List exact prerequisites or state “nothing” | -| When you finish | Describe a measurable outcome | -| Capability status | Stable, beta, experimental, planned, community or partner-supported | -| Applies to | Release, hardware revision and configuration | -| Safety | Hazards, limits, stop conditions and required supervision | -| Verification | What the reader should see, hear, measure or test | +▶️ Step-by-step assembly of the OpenAMRobot drive wheel module. -### Procedure or explanation +The drive-wheel assembly (motor + gearbox + drive shaft + brackets, `MMP.03.*` in +[../../mechanical/](https://github.com/openAMRobot/openamr-platform-hw/blob/main/mechanical)) is assembled in the sequence shown below. Follow the same +order left and right. -1. Establish the starting state. -2. Complete one action or concept per subsection. -3. Record commands, parameters, screenshots or measurements where useful. -4. Verify the result before continuing. +**Step 1** +![Wheel assembly step 1](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/manufacturing/assembly/AMR_wheel_assembly_1.png) -### If it did not work +**Step 2** +![Wheel assembly step 2](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/manufacturing/assembly/AMR_wheel_assembly_2.png) -Document symptoms separately from causes. Include diagnostic evidence and a safe rollback or escalation path. +**Step 3** +![Wheel assembly step 3](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/manufacturing/assembly/AMR_wheel_assembly_3.png) -## Owning OpenAMRobot source +**Step 4** +![Wheel assembly step 4](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/manufacturing/assembly/AMR_wheel_assembly_4.png) -- [openamr-platform-hw](https://github.com/openAMRobot/openamr-platform-hw) – canonical source, versions, implementation and issue history. +**Step 5** +![Wheel assembly step 5](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/manufacturing/assembly/AMR_wheel_assembly_5.png) -## Contribution note +See the per-part production drawings (PDF/DXF) in +[../../mechanical/cad/production_files/](https://github.com/openAMRobot/openamr-platform-hw/blob/main/mechanical/cad/production_files). -Replace this framework with tested project-specific content through the normal [contribution workflow](https://github.com/openAMRobot/openamrobot-docs/blob/main/CONTRIBUTING.md). Keep exact parameters and contracts synchronized with the owning repository. +## Engineering handoff + +- Record the repository commit, hardware revision, supply voltage, and test configuration with every result. +- Stop if observed wiring, component labels, geometry, or topic behavior differs from this page; resolve the discrepancy in the owning repository first. +- Report documentation or implementation defects through [the repository issue tracker](https://github.com/openAMRobot/openamr-platform-hw/issues). diff --git a/docs/reference/openamr-platform-hw/troubleshooting.md b/docs/reference/openamr-platform-hw/troubleshooting.md index 9541311..0dcd1d9 100644 --- a/docs/reference/openamr-platform-hw/troubleshooting.md +++ b/docs/reference/openamr-platform-hw/troubleshooting.md @@ -1,48 +1,101 @@ --- -title: Troubleshooting +title: Hardware troubleshooting +tags: [builder, domain-expert] +status: experimental +description: Diagnose ZBLD motor-driver faults and distinguish electrical, power, wiring, and control problems. --- -
Under development

Troubleshooting

Provide the learning-layer reference for troubleshooting and point to its owning repository.

OpenAMRobot logo
+# Hardware troubleshooting -!!! info "Documentation framework" - This page is part of the approved OpenAMRobot knowledge architecture. It is intentionally published before full content is complete so contributors can fill it consistently. Do not treat unfinished guidance as a validated build or deployment instruction. +**Canonical source:** [`openamr-platform-hw/electrical/motor_control/motor-driver-fault-codes.md`](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/motor_control/motor-driver-fault-codes.md) +**Applies to:** the documented OpenAMRobot reference mobile base; verify repository revision before changing hardware or firmware. -## What this page should contain +!!! warning "Experimental project documentation" + These instructions describe the current reference build and its measured behavior. Use physical safeguards, test with wheels clear of the floor, and revalidate after changing parts, wiring, firmware, battery chemistry, or geometry. -- **Audience and outcome:** who uses this page and what verified state they should reach. -- **Prerequisites:** required skills, tools, hardware, software, configuration and safety conditions. -- **Concept or procedure:** concise explanation followed by ordered, reproducible steps where applicable. -- **Verification:** observable output, measurement, test or acceptance criterion. -- **Troubleshooting:** likely failures, evidence to collect and safe recovery actions. -- **Next step:** one clear continuation in the ownership or development path. +*How to read the driver's LED blink code and the full fault-code table. Driver: **ZBLD.C20-120L2R** +(Ningbo Zhongda Leader / ZD), 24 V ±20 %, 7.5 A, 120 W. One per wheel (LEFT = M1, RIGHT = M2).* -## Content template +*Last updated: 2026-06-26.* -| Field | To complete | -| --- | --- | -| For | Name one primary reader: operator, builder, integrator or developer | -| Before you start | List exact prerequisites or state “nothing” | -| When you finish | Describe a measurable outcome | -| Capability status | Stable, beta, experimental, planned, community or partner-supported | -| Applies to | Release, hardware revision and configuration | -| Safety | Hazards, limits, stop conditions and required supervision | -| Verification | What the reader should see, hear, measure or test | +> When a driver detects a fault it **STOPS the motor** and blinks an error code on its LEDs. So a red LED +> is not cosmetic — the motor will not turn until the fault is cleared, even though the Teensy keeps +> sending PWM (you can confirm the Teensy side is fine: `/debug/pwm` still shows the commanded value). -### Procedure or explanation +## Reading the LED blink code -1. Establish the starting state. -2. Complete one action or concept per subsection. -3. Record commands, parameters, screenshots or measurements where useful. -4. Verify the result before continuing. +Each driver has a **green** and a **red** indicator. On a fault they flash a repeating pattern: -### If it did not work +``` +ERROR CODE = (number of GREEN flashes × 5) + (number of RED flashes) +``` -Document symptoms separately from causes. Include diagnostic evidence and a safe rollback or escalation path. +Count one full cycle: the **green** flashes first (each green = 5), then the **red** flashes (each red = 1), +then it repeats. **Count green and red separately** — do NOT add them into one running count. -## Owning OpenAMRobot source +> ⚠️ **The encoding is NOT a clean base-5 code, so `green×5 + red` can alias** (e.g. 1 green + 5 red and +> 2 green + 0 red both arithmetic to 10). Do not "carry" a 5th red into an extra green — read the *actual +> emitted pattern* the driver blinks. Below are the patterns **observed on this robot** (field-confirmed); +> for any code not seen here, read the pattern off the driver and cross-check the fault-code table. -- [openamr-platform-hw](https://github.com/openAMRobot/openamr-platform-hw) – canonical source, versions, implementation and issue history. +| You see (emitted pattern) | Code | Meaning | Confirmed | +|---|---|---|---| +| **1 green, 5 red** | **10** | busbar under-voltage | ✅ seen on this robot (2026-06-26) | +| **2 green, 4 red** | **14** | locked rotor | ✅ seen on this robot (2026-07-01, wheel jammed on wall) | -## Contribution note +*(Other codes in the fault-code table below are from the manufacturer manual and have not been observed +here — read the blink pattern off the driver, then look up the code. Green contributes 5 each, red 1 each, +but trust the pattern the driver actually shows, not a computed sum.)* -Replace this framework with tested project-specific content through the normal [contribution workflow](https://github.com/openAMRobot/openamrobot-docs/blob/main/CONTRIBUTING.md). Keep exact parameters and contracts synchronized with the owning repository. +## Fault-code table + +| Code | Fault | Typical cause | +|---|---|---| +| **1–6** | **Over-current** (during acceleration / deceleration / constant speed) | short on the motor phases, motor stalled/jammed, wrong wiring, current limit too low | +| **7–9** | **Over-voltage** (different operating phases) | supply > 28.8 V, or regenerative braking spikes (decel) with no bleed | +| **10** | **Busbar under-voltage** | **24 V too low**: flat/weak battery, voltage drop under load, supply can't hold the current spike at fast acceleration, or driver HW fault | +| **11** | **Motor overload** | motor drawing too much for too long (load too high, gearbox binding) | +| **12** | **Driver overload** | driver output beyond its rating (7.5 A / 120 W) | +| **13** | **Hall sensor error** | Hall connector loose/miswired/disconnected → driver can't commutate | +| **14** | **Locked rotor** | motor blocked / can't turn (mechanical jam, brake on) | +| **16** | **Driver over-temperature** | heatsink too hot — sustained high load / poor cooling | +| **19** | Current sense error | internal current-measurement fault | +| **27** | Data storage error | driver parameter/EEPROM error | +| **29** | Over-current feedback error | current-feedback path fault | +| **30** | **Lack of input phase** | a motor phase (U / V / W) is missing — phase wire disconnected | + +*(Codes grouped 1–6 / 7–9 cover the same fault type at different motion phases; exact sub-code detail is +in the manufacturer's manual, [ZBLD.C20.pdf](https://image.yhdfa.com/Uploads/Picture/PDF/FZ02_11/ZBLD.C20.pdf).)* + +## Clearing a fault +1. **Fix the cause first** (see the table — e.g. for code 10, recharge the battery to ≥ 25 V). +2. **Power-cycle the 24 V** (cut, wait a few seconds, restore). Faults **latch** until a power cycle. +3. The red LED should go out and the motor respond again. + +## Most common on this robot — code 10 (under-voltage) +**Both drivers showing code 10 at once = a shared cause = the 24 V bus is too low** (they share one +battery). The ZBLD.C20 needs **24 V ±20 % (≈ 19.2–28.8 V)**; below that → under-voltage → both stop. +- Diagnosis: measure the battery at rest — if **< ~22 V** (let alone < 19 V), that's it. +- Note: a *charged but weak* battery can still trip code 10 **under load** ("voltage drop / fast + acceleration") — the pack sags at the current spike. Same root as the Pi 5 brown-outs + ([raspberry-pi.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/computing/raspberry-pi.md) / [power.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/power_distribution/power.md)): keep the + battery healthy + ≥ 25 V, with short, thick 24 V wiring. +- Fix: **charge to ≥ 25 V → power-cycle the 24 V → red LED off → wheels turn** (`ros2 topic pub --rate 15 + /debug/openloop geometry_msgs/msg/Vector3 "{x: 100.0}"` with the robot lifted). + +## If it is NOT under-voltage (battery confirmed good) +- **Code 13 (Hall error) / 30 (missing phase)** → a motor connector is loose/disconnected (check the + Hall and U/V/W wiring; brown = +, blue = − for power leads). +- **Code 1–6 (over-current) / 14 (locked rotor)** → the motor is jammed or shorted — check the wheel + turns freely and the phase wiring isn't shorted. +- **Code 16 (over-temp)** → let it cool; reduce sustained load. + +See also: [motors-drivers.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/motor_control/motors-drivers.md) (driver model, DIP switches, pots), +[power.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/power_distribution/power.md) (battery / 24 V), and the `openamr-platform-sw` +troubleshooting doc (`docs/troubleshooting/diagnostics.md` in that repo). + +## Engineering handoff + +- Record the repository commit, hardware revision, supply voltage, and test configuration with every result. +- Stop if observed wiring, component labels, geometry, or topic behavior differs from this page; resolve the discrepancy in the owning repository first. +- Report documentation or implementation defects through [the repository issue tracker](https://github.com/openAMRobot/openamr-platform-hw/issues). diff --git a/docs/reference/openamr-platform-hw/tutorials.md b/docs/reference/openamr-platform-hw/tutorials.md index 44cc5ab..e69ebc8 100644 --- a/docs/reference/openamr-platform-hw/tutorials.md +++ b/docs/reference/openamr-platform-hw/tutorials.md @@ -1,48 +1,154 @@ --- -title: Tutorials +title: Commission the drivetrain +tags: [builder, developer] +status: experimental +description: Configure and commission the OpenAMRobot BLDC motors and ZBLD motor drivers safely. --- -
Under development

Tutorials

Provide the learning-layer reference for tutorials and point to its owning repository.

OpenAMRobot logo
+# Commission the drivetrain -!!! info "Documentation framework" - This page is part of the approved OpenAMRobot knowledge architecture. It is intentionally published before full content is complete so contributors can fill it consistently. Do not treat unfinished guidance as a validated build or deployment instruction. +**Canonical source:** [`openamr-platform-hw/electrical/motor_control/motors-drivers.md`](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/motor_control/motors-drivers.md) +**Applies to:** the documented OpenAMRobot reference mobile base; verify repository revision before changing hardware or firmware. -## What this page should contain +!!! warning "Experimental project documentation" + These instructions describe the current reference build and its measured behavior. Use physical safeguards, test with wheels clear of the floor, and revalidate after changing parts, wiring, firmware, battery chemistry, or geometry. -- **Audience and outcome:** who uses this page and what verified state they should reach. -- **Prerequisites:** required skills, tools, hardware, software, configuration and safety conditions. -- **Concept or procedure:** concise explanation followed by ordered, reproducible steps where applicable. -- **Verification:** observable output, measurement, test or acceptance criterion. -- **Troubleshooting:** likely failures, evidence to collect and safe recovery actions. -- **Next step:** one clear continuation in the ownership or development path. +*Last updated: 2026-06-17.* -## Content template +## Overview +Two **BLDC** (brushless) motors, one per wheel, each driven by its own **ZBLD** driver. The Teensy +sends low-current logic signals to the drivers; the drivers deliver the 24 V power to the motor phases. -| Field | To complete | -| --- | --- | -| For | Name one primary reader: operator, builder, integrator or developer | -| Before you start | List exact prerequisites or state “nothing” | -| When you finish | Describe a measurable outcome | -| Capability status | Stable, beta, experimental, planned, community or partner-supported | -| Applies to | Release, hardware revision and configuration | -| Safety | Hazards, limits, stop conditions and required supervision | -| Verification | What the reader should see, hear, measure or test | +- **Motors**: **ZD Z4BLD60-24GN-30S** ×2 — 3-phase BLDC, 24 V, **60 W**, **P=5 (5 pole pairs, on the + nameplate)**, **3000 rpm** motor + **1:25 spur gearbox** (4GN 25K) → **120 rpm** wheel, rated **3.8 A**. + U/V/W + Hall. (LEFT=M1, RIGHT=M2) See the [sizing calculations](https://github.com/openAMRobot/openamr-platform-hw/blob/main/datasheets/motor-sizing-calculations.md). +- **Drivers**: **ZBLD.C20-120L2R** ×2 (24 V, 7.5 A, 120 W). Full specs + datasheets: + [components-bom.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/manufacturing/bom/components-bom.md). **Red LED / fault blink codes:** + [motor-driver-fault-codes.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/electrical/motor_control/motor-driver-fault-codes.md). +- ⚠️ **Pole pairs = 5** → verify the driver **DIP SW4/SW5** are set to 5 pole pairs (read the silkscreen + table on the driver). A wrong pole-pair setting throws off the driver's closed-loop speed scaling. -### Procedure or explanation +## Manufacturer reference diagram -1. Establish the starting state. -2. Complete one action or concept per subsection. -3. Record commands, parameters, screenshots or measurements where useful. -4. Verify the result before continuing. +The driver's full terminal layout, DIP-switch table, and LED status codes, from the manufacturer: -### If it did not work +![ZBLD.C20-120L2R driver setup: 24 V DC+/DC- (fused), motor phases U/V/W + Hall sensors, control inputs FWD/DI1, REV/DI2, JOG/DI3, CLR/DI4, BRK/DI5, COM, VAR/AI2, +5V, ERR/DO1, SPD/DO2, RS485 A/B, the SW1-SW6 DIP-switch configuration table, and the LED status/fault codes](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/electrical/motor_control/diagrams/zbld-driver-setup-reference.jpg) -Document symptoms separately from causes. Include diagnostic evidence and a safe rollback or escalation path. +*Source: ZD **ZBLD.C20-120L2R** product manual (manufacturer reference figure). This robot wires only a +subset of these terminals and uses a specific DIP configuration — both are detailed below.* -## Owning OpenAMRobot source +## Communication (Teensy → driver) -- [openamr-platform-hw](https://github.com/openAMRobot/openamr-platform-hw) – canonical source, versions, implementation and issue history. +The motor-control signal chain is shown below. -## Contribution note +![Figure — per-wheel signal chain: /cmd_vel → Teensy PID (closed loop) → ZBLD driver (open loop) → BLDC → 25:1 gearbox → wheel → AS5040 encoder back to the PID](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/electrical/motor_control/diagrams/signal-chain.svg) -Replace this framework with tested project-specific content through the normal [contribution workflow](https://github.com/openAMRobot/openamrobot-docs/blob/main/CONTRIBUTING.md). Keep exact parameters and contracts synchronized with the owning repository. +Per motor, 3 logic lines from the Teensy: + +| Teensy signal | Driver input | Meaning | Left pin | Right pin | +|---|---|---|---|---| +| PWM | `VAR / AI2` | speed setpoint — Teensy PWM @ **3 kHz** on this robot (driver capability: PWM 0–20 kHz, or analog 0–5 V) | **1** | **5** | +| IN_A | `FWD / DI1` | forward direction | **20** | **6** | +| IN_B | `REV / DI2` | reverse direction | **21** | **8** | +| GND | `COM` | **common ground (mandatory)** | GND | GND | + +- Power side: `DC+ / DC− = 24 V` (with a fuse). Motor side: phases U/V/W + Hall. +- ⚠️ The driver `COM` **must** be tied to the Teensy GND, otherwise signals/encoders are noisy. + +Of the driver's twelve control terminals, this robot wires only **four** — the connections are shown below: + +![Driver terminal wiring: only DI1 (FWD), DI2 (REV), COM (GND), and AI2 (VAR/PWM speed setpoint) go to the Teensy; DC+/DC- take the fused 24 V and U/V/W + Hall go to the motor](https://raw.githubusercontent.com/openAMRobot/openamr-platform-hw/main/electrical/wiring/diagrams/driver-connections.svg) + +## Driver configuration — DIP switches (SW1–SW6) +Both drivers must be set **identically**. Functions read from the driver silkscreen (2026-06-19): + +| Switch | Function | What it does | Was (pre 06-19) | **Now (applied 06-19)** | +|---|---|---|---|---| +| **SW1** | open / closed loop (`开环/闭环`) | ON = driver regulates speed itself from the Halls; OFF = driver is just a power stage (Teensy regulates) | ON | **OFF** | +| **SW2** | speed source (`AI1/AI2`) | OFF = internal VAR knob; ON = external 0–5 V on `VAR/AI2` (our Teensy PWM) | ON | ON | +| **SW3** | secondary (direction/internal) | no effect here (direction is driven by FWD/REV pins) | OFF | OFF | +| **SW4 / SW5** | **motor pole pairs** (`极对数`) | tells the driver the pole-pair count (2/3/4/5) to convert Hall freq → RPM. **Only used in closed loop** | OFF/OFF (= 2 pp ⚠️) | **ON/ON (= 5 pp)** | +| **SW6** | RS485 termination (`485 终端电阻`) | bus end resistor; not used (no RS485) | OFF | OFF | + +> 🔶 **Pole-pair mismatch found & corrected (2026-06-19):** the motor is **P=5** (5 pole pairs, on the +> nameplate) but SW4/SW5 were OFF/OFF (= 2 pole pairs). Now set to **ON/ON (= 5 pp)**. (Only matters in +> closed loop; harmless but correct in the current open-loop config.) + +### Which controller is best — driver vs Teensy PID? +The **Teensy PID is the better controller for this robot** and should be the authoritative one: +- it reads the **AS5040 encoder (1024 cnt/rev)** → fine resolution, and measures the **wheel** speed + (post-gearbox) — the variable we actually care about (motion + odometry); +- it is **fully tunable** (K_P/K_I/K_D, already tuned to ±2 %), and feeds ROS `/odom`. +- the driver's loop measures the **motor shaft** (pre-gearbox) with **coarse Hall** sensors, is **opaque** + (only VAR/ACC pots), and needs correct pole pairs. + +→ **Run the driver open-loop (SW1=OFF)** so the Teensy is the sole regulator (removes the double-loop that +worsens snaking; makes pole pairs irrelevant). **Plan B** if low-speed cogging appears: go back to closed +loop (SW1=ON) **with SW4/SW5=ON/ON (5 pp)** for a proper cascade (fast driver inner loop + Teensy outer). +The only edge the driver loop has: at low *wheel* speed the motor shaft still spins ~30× faster → richer +Hall signal → potentially smoother very-low-speed than the 50 Hz Teensy loop. + +**Config applied 2026-06-19 (both drivers):** `SW1 OFF · SW2 ON · SW3 OFF · SW4 ON · SW5 ON · SW6 OFF`. +(Was SW1 ON, SW2 ON, rest OFF.) **Validated** over 3 motor runs — see +the `openamr-platform-sw` troubleshooting doc (`docs/troubleshooting/diagnostics.md` in that repo). + +> ⚠️ **VAR pot is inert in this config**: with SW2=ON the speed comes from AI2 (the PWM), not the VAR/AI1 +> pot, so turning VAR does **not** balance the wheels (confirmed: no change across runs). The residual +> ~9 % open-loop L/R asymmetry (right faster) is corrected by the **Teensy PID** (→ ~0.2 % in closed loop). + +## Driver configuration — TWO trim pots (CRITICAL) +Each driver has **two** potentiometers. **They must match between LEFT and RIGHT** (calibrate the right +to the left, the known-good reference). + +> ⚠️ **Read this alongside the config state.** The VAR **gain** effect below (and the "runaway" root cause) +> applies when **VAR is in the speed path** — i.e. the *original* config (VAR/AI1 selected, or an AI2 gain +> that scales the PWM). In the **current config (SW1=OFF open loop, SW2=ON → AI2)** the **speed comes from +> the PWM on AI2, so the VAR pot is inert for balancing** (see the note above) — the values below are the +> setting to leave it at, not a live balancing knob. ACC/DEC still ramps in either config. + +| Pot | Location | Function | Correct setting | Symptom if wrong (when VAR is in the speed path) | +|---|---|---|---|---| +| **VAR** | top | speed / gain (PWM → speed) | ~3.5/10, **same** both sides | too high → wheel runs ~8× too fast → **runaway** | +| **ACC/DEC** | near the DIP switches | acceleration/deceleration ramp | **4/10**, same both sides | =0 → no smoothing → **jerks/oscillation** in closed loop | + +See the full story in the `openamr-platform-sw` troubleshooting doc (`docs/troubleshooting/diagnostics.md` in that repo). + +## Low-speed behaviour — measured velocity floors (2026-07-02) +Closed-loop sweep **on the ground / under load** (`/cmd_vel` with the PID + dither, as in docking), +real velocity read on `/odom/unfiltered`: + +| Axis | Stall | Judder | **Reliable floor** | Clean | +|---|---|---|---|---| +| **Linear** | ≤ 0.02 m/s | 0.03 (min 0, std 0.018) | **0.04 m/s** (min 0.020) | **0.05 m/s** (std 0.004); 0.06–0.10 perfect | +| **Angular** | ≤ 0.08 rad/s | 0.10–0.12 (min 0, high std) | **0.15 rad/s** (min 0.093) | 0.20–0.30 perfect | + +> ✅ **The motor is WELL-SIZED (over-sized on torque).** Above the floors the real/commanded ratio is +> **~1.0** → no torque shortfall. The floors are **stick-slip (static friction) + coarse Hall commutation +> at low RPM** (an *operating-point* limit, not a sizing one). Reference: the Z4BLD60-24GN-30S + **1:25** +> gearbox gives a mechanical no-load max of ~**1.26 m/s** (software-capped to ~0.71 m/s) and ~**3.48 N·m/wheel** +> (specs in [components-bom.md](https://github.com/openAMRobot/openamr-platform-hw/blob/main/manufacturing/bom/components-bom.md), derivation in the +> [sizing calculations](https://github.com/openAMRobot/openamr-platform-hw/blob/main/datasheets/motor-sizing-calculations.md)). + +**Consequence:** keep commanded velocities **above the floors**. Docking applies this (drive taper floored +at 0.05 m/s, scan rotation 0.17 rad/s, a `min_turn_omega` of 0.15 rad/s with a small deadband so +sub-floor yaw corrections are snapped up or zeroed rather than stalling). Judder on each start-from-standstill +is the static-friction breakaway; a taper (or the driver ACC/DEC ramp) mitigates it. + +## Good to know / gotchas +- The original fault ("right wheel runs away, robot doesn't go straight") was **100 % driver tuning**, in + the **original config where VAR was in the speed path**: the right VAR pot was at max (10) and its + ACC/DEC pot at 0. After matching both pots to the left, the right wheel tracked correctly. *(Separately, + during open-loop balancing on 2026-06-19, raising the right VAR made the right wheel speed up to match a + faster left — same knob, opposite direction, because it was a different starting point.)* +- ⚠️ In the **current config (SW2=ON, AI2 source)** VAR no longer balances the wheels — the residual L/R + asymmetry is handled entirely by the **Teensy PID** (the right channel needs slightly more PWM for the + same speed; the PID compensates → ~0.2 % in closed loop). Do not chase balance with the VAR pot here. +- Test the motors safely with the **open-loop mode** (`/debug/openloop`) which bypasses the PID — useful + to compare the two channels at identical PWM. See the `openamr-platform-fw` debug-telemetry doc (`docs/architecture/debug-telemetry.md`). +- **Always**: wheels off the ground, 24 V on, a hand on the 24 V cut-off for the first tests. + +## Engineering handoff + +- Record the repository commit, hardware revision, supply voltage, and test configuration with every result. +- Stop if observed wiring, component labels, geometry, or topic behavior differs from this page; resolve the discrepancy in the owning repository first. +- Report documentation or implementation defects through [the repository issue tracker](https://github.com/openAMRobot/openamr-platform-hw/issues).