edit readme
This commit is contained in:
parent
e7301db427
commit
9c38c10300
|
|
@ -1,136 +1,214 @@
|
|||
# Firmware
|
||||
# FireWatchTower — 2-Axis Gimbal Controller
|
||||
|
||||
Arduino sketch for the LattePanda's onboard ATmega32U4 (Leonardo). Controls two stepper motor axes via TMC5160 drivers, manages thermal regulation, and communicates with the host over the serial link.
|
||||
Firmware for a 2-axis motorised gimbal (yaw + pitch) running on an Arduino-compatible AVR microcontroller. Built around the TMC5160 stepper driver chip, with encoder feedback, automatic homing, thermal management, and a serial command interface.
|
||||
|
||||
## PlatformIO Configuration
|
||||
---
|
||||
|
||||
Target: `leonardo` (ATmega32U4) at 115200 baud.
|
||||
## Hardware
|
||||
|
||||
```bash
|
||||
pio run --environment megaatmega2560 --target upload
|
||||
```
|
||||
| Component | Details |
|
||||
|---|---|
|
||||
| MCU | ATmega32U4 (Arduino Leonardo-compatible) |
|
||||
| Motor driver | TMC5160 × 2 (one per axis) |
|
||||
| Communication | SPI @ 4 MHz, Mode 3 |
|
||||
| Temperature sensor | DHT11 |
|
||||
| Fan control | PWM output + tachometer input |
|
||||
|
||||
### Dependencies
|
||||
### Pin assignments
|
||||
|
||||
| Library | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| adafruit/DHT sensor library | ^1.4.4 | DHT22 temperature/humidity readings |
|
||||
| adafruit/Adafruit Unified Sensor | ^1.1.4 | Unified sensor abstraction |
|
||||
| TMC5160 (bundled) | — | Stepper motor driver via SPI |
|
||||
| Pin | Function |
|
||||
|---|---|
|
||||
| 8 | TMC5160 CS — Yaw |
|
||||
| 7 | TMC5160 EN — Yaw |
|
||||
| 1 | TMC5160 CS — Pitch |
|
||||
| 0 | TMC5160 EN — Pitch |
|
||||
| 9 | DHT11 data |
|
||||
| 10 | Fan PWM output |
|
||||
| 11 | Fan tachometer input |
|
||||
|
||||
## Architecture
|
||||
### Axis parameters
|
||||
|
||||
| Parameter | Yaw | Pitch |
|
||||
|---|---|---|
|
||||
| Steps per revolution | 177,000 | 500,000 |
|
||||
| Gear ratio | 739.56 | 739.56 |
|
||||
| Default speed (VMAX) | 50,000 | 250,000 |
|
||||
| Global current scaler | 80 | 50 |
|
||||
|
||||
---
|
||||
|
||||
## Project structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── main.cpp # Entry point, main loop
|
||||
├── main.cpp
|
||||
├── config/
|
||||
│ ├── Constants.h # All tunable parameters
|
||||
│ └── Pins.h # Pin assignments
|
||||
│ ├── Constants.h — tuning values, thresholds, timing
|
||||
│ └── Pins.h — pin assignments
|
||||
├── motor/
|
||||
│ ├── MotorConfig.h # Axis IDs, status enum
|
||||
│ ├── MotorDriver.* # TMC5160 initialization, power control
|
||||
│ ├── MotorAxis.* # Per-axis state, register reads, SGT/encoder handling
|
||||
│ └── Homing.* # Endstop homing routine
|
||||
│ ├── MotorConfig.h — axis IDs, EEPROM layout, gimbal_status enum
|
||||
│ ├── MotorAxis.h/.cpp — per-axis state and TMC5160 register interface
|
||||
│ ├── MotorDriver.h/.cpp— SPI init, register config, enable/disable
|
||||
│ └── Homing.h/.cpp — homing state machines (non-blocking)
|
||||
├── serial/
|
||||
│ └── CommandParser.* # Serial command dispatch
|
||||
└── thermal/
|
||||
└── ThermalManager.* # DHT sensor + PWM fan control
|
||||
│ └── CommandParser.h/.cpp — serial command protocol
|
||||
├── thermal/
|
||||
│ └── ThermalManager.h/.cpp — DHT11 reading and fan PWM control
|
||||
└── hal/
|
||||
└── SPI_HAL.cpp — TMC-API SPI callbacks (chip select per axis)
|
||||
```
|
||||
|
||||
## Pinout
|
||||
---
|
||||
|
||||
| Pin | Function |
|
||||
|-----|----------|
|
||||
| 0 | TMC5160 ENABLE (Pitch) |
|
||||
| 1 | TMC5160 CS (Pitch) |
|
||||
| 7 | TMC5160 ENABLE (Yaw) |
|
||||
| 8 | TMC5160 CS (Yaw) |
|
||||
| 9 | DHT22 DATA |
|
||||
| 10 | Fan PWM |
|
||||
| 11 | Fan sense |
|
||||
## Building
|
||||
|
||||
## Motor Configuration
|
||||
This project uses [PlatformIO](https://platformio.org/).
|
||||
|
||||
Both axes use TMC5160 stepper drivers with closed-loop control.
|
||||
|
||||
| Parameter | Yaw | Pitch |
|
||||
|-----------|-----|-------|
|
||||
| Steps/round | 177,000 | 500,000 |
|
||||
| Gear ratio | 739.556 | 739.556 |
|
||||
| Global scaler | 80 | 50 |
|
||||
| Default Vmax | 50,000 | 250,000 |
|
||||
| Endstop speed | 25,000 | 150,000 |
|
||||
|
||||
Key constants in [config/Constants.h](src/config/Constants.h):
|
||||
- `ENC_DEVIATION_LIMIT` — Maximum allowed encoder-position deviation (1500 steps)
|
||||
- `ACCELERATION` — Default acceleration profile (20,000)
|
||||
|
||||
### Gimbal Status States
|
||||
|
||||
```c
|
||||
typedef enum {
|
||||
GIMBAL_STATUS_ERROR = -2,
|
||||
GIMBAL_STATUS_BOOT = -1,
|
||||
GIMBAL_STATUS_RESET = 0,
|
||||
GIMBAL_STATUS_ENC_INIT = 1,
|
||||
GIMBAL_STATUS_INITIALIZED= 2,
|
||||
GIMBAL_STATUS_AUTO = 3,
|
||||
GIMBAL_STATUS_MANUAL = 4
|
||||
} gimbal_status;
|
||||
**Build:**
|
||||
```bash
|
||||
pio run
|
||||
```
|
||||
|
||||
## Serial Protocol
|
||||
|
||||
Commands are received character-by-character. A leading command character is followed by optional comma-separated numeric arguments (hex by default; append `d` for decimal).
|
||||
|
||||
### Command Reference
|
||||
|
||||
| Command | Args | Description |
|
||||
|---------|------|-------------|
|
||||
| `r` | — | Reset motor params, power on both axes |
|
||||
| `q` | — | Run endstop homing on yaw then pitch |
|
||||
| `!` | — | Power off both motors |
|
||||
| `*` | — | Power on both motors |
|
||||
| `m` | pos, speed | Move yaw to position with given speed |
|
||||
| `s` | — | Stop both motors |
|
||||
| `b` | — | Reset encoder deviation warning flags |
|
||||
| `t` | — | Set Xenc to Xact (sync encoder to actual position) |
|
||||
| `e` | — | Reset SGT (step goal threshold) on both axes |
|
||||
| `w` | value | Set SGT value |
|
||||
| `u` | step_len | Set auto-scan step length (must be > 2) |
|
||||
| `h` | axis, hdg | Set heading calibration, save to EEPROM |
|
||||
| `y` | axis | Load heading calibration from EEPROM |
|
||||
| `d` | — | Set yaw to manual mode |
|
||||
| `p` | — | Step yaw to next position (used for scan trigger) |
|
||||
| `v` | speed | Set yaw Vmax |
|
||||
| `+` | — | Record right encoder position |
|
||||
| `-` | — | Record left encoder position |
|
||||
| `/` | right, left | Set right and left encoder positions |
|
||||
| `?` | — | Print encoder range info |
|
||||
| `;` | value | Write raw value to Yaw register 0x21 |
|
||||
|
||||
### Telemetry Output
|
||||
|
||||
Every `INFO_PRINT_INTERVAL_MS` (250 ms), both axes print status lines prefixed with `$`:
|
||||
```
|
||||
$Xenc;Xerr;sgt_val;sgt_stat;is_moving;control_status;hdg;deviation_warn;humid;temp;fan_pwm
|
||||
**Build and upload:**
|
||||
```bash
|
||||
pio run --target upload
|
||||
```
|
||||
|
||||
## Thermal Management
|
||||
**Clean:**
|
||||
```bash
|
||||
pio run --target clean
|
||||
```
|
||||
|
||||
DHT22 sensor on pin 9 drives a PWM fan on pin 10.
|
||||
**Serial monitor:**
|
||||
```bash
|
||||
pio device monitor --baud 115200
|
||||
```
|
||||
|
||||
| Parameter | Value | Description |
|
||||
|-----------|-------|-------------|
|
||||
| `THERMAL_FAN_ON_TEMP` | 25°C | Fan activation threshold |
|
||||
| `THERMAL_FAN_GAIN` | 20 | PWM gain per degree above threshold |
|
||||
| `THERMAL_FAN_MAX_PWM` | 255 | Maximum PWM duty cycle |
|
||||
| `THERMAL_LOOP_INTERVAL` | 250 ms | Sensor read interval |
|
||||
---
|
||||
|
||||
Fan PWM = `min(255, (temp - 25) * 20)`
|
||||
## Axis lifecycle
|
||||
|
||||
## EEPROM Storage
|
||||
Each axis progresses through the following states after power-on:
|
||||
|
||||
Heading calibration data is stored at EEPROM address 0:
|
||||
- Offset 0: `float` — current heading (`c_hdg`)
|
||||
- Offset 4: `int32_t` — encoder distance offset from heading reference
|
||||
```
|
||||
BOOT → RESET → ENC_INIT → INITIALIZED → AUTO / MANUAL
|
||||
↓
|
||||
ERROR (homing failed)
|
||||
```
|
||||
|
||||
- **BOOT** — initial state, hardware not yet configured
|
||||
- **RESET** — registers written, motor enabled, ready to home
|
||||
- **ENC_INIT** — homing sequence in progress
|
||||
- **INITIALIZED** — endstop limits known, axis ready for operation
|
||||
- **AUTO** — stepping through positions automatically
|
||||
- **MANUAL** — responding to direct move commands
|
||||
- **ERROR** — homing failed; send `r` to reset and try again
|
||||
|
||||
---
|
||||
|
||||
## Homing
|
||||
|
||||
Each axis must be homed before normal operation. Send `q` over serial to start.
|
||||
|
||||
**Yaw** uses stallGuard (encoder deviation detection) as a virtual endstop — the motor drives into a mechanical stop, the TMC5160 detects the current spike, and the position is recorded. No physical switches required.
|
||||
|
||||
**Pitch** uses physical hardware endstop switches. The TMC5160 latches the position (XLATCH) the instant a switch triggers, giving an accurate limit reading.
|
||||
|
||||
Once both limits are found, the axis validates the measured travel range and moves to the centre position.
|
||||
|
||||
---
|
||||
|
||||
## Serial command protocol
|
||||
|
||||
Connect at **115200 baud**. Commands are single characters sent over the serial port.
|
||||
|
||||
**Format:** `<cmd>[y|p][d]<arg1>,<arg2>`
|
||||
|
||||
- Axis specifier (optional): `y` = yaw only, `p` = pitch only, omit = both
|
||||
- Base specifier (optional): `d` after axis = decimal arguments (default is hex)
|
||||
|
||||
### Command reference
|
||||
|
||||
| Command | Description | Arguments |
|
||||
|---|---|---|
|
||||
| `r` | Reset: re-init registers and enable coils | — |
|
||||
| `q` | Start homing sequence | — |
|
||||
| `!` | Disable motor coils (free-wheel) | — |
|
||||
| `*` | Enable motor coils (holding torque) | — |
|
||||
| `m` | Move to absolute position | `<position>, <speed>` |
|
||||
| `;` | Overwrite XACTUAL register directly | `<value>` |
|
||||
| `s` | Stop (decelerate to zero) | — |
|
||||
| `b` | Clear encoder deviation warning flag | — |
|
||||
| `t` | Sync encoder to actual position | — |
|
||||
| `e` | Clear stallGuard event flag (both axes) | — |
|
||||
| `w` | Set stallGuard threshold | `<sgt>` |
|
||||
| `u` | Enter AUTO stepping mode | `<num_steps>` (must be > 2) |
|
||||
| `h` | Save heading calibration to EEPROM | `0, <heading_value>` |
|
||||
| `y` | Load heading calibration from EEPROM | `0` |
|
||||
| `d` | Enter MANUAL mode | — |
|
||||
| `p` | Advance yaw one step (AUTO mode) | — |
|
||||
| `v` | Set yaw speed | `<vmax>` |
|
||||
| `+` | Set yaw right limit to current position | — |
|
||||
| `-` | Set yaw left limit to current position | — |
|
||||
| `/` | Set both yaw limits manually | `<right>, <left>` |
|
||||
| `?` | Print current yaw endstop positions | — |
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
q — home both axes
|
||||
qy — home yaw only
|
||||
md 500000,35000 — move both axes to position 500000 at speed 35000 (decimal)
|
||||
my 1F400,8888 — move yaw to 0x1F400 at speed 0x8888 (hex, default)
|
||||
!p — disable pitch motor
|
||||
w 60 — set stallGuard threshold to 60 on both axes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Serial status output
|
||||
|
||||
Every 250 ms the firmware prints a status line for each axis:
|
||||
|
||||
**Yaw:**
|
||||
```
|
||||
YAW: <X_enc>, <X_act>, <X_err>, <dev_warn>, <sg_event>, <sg_status>, <sg_stop>
|
||||
```
|
||||
|
||||
**Pitch:**
|
||||
```
|
||||
PITCH: <X_enc>, <X_act>, <X_err>, <dev_warn>, <sg_event>, <sg_status>, <sg_stop>, <endstop_l>, <endstop_r>
|
||||
```
|
||||
|
||||
| Field | Description |
|
||||
|---|---|
|
||||
| `X_enc` | Encoder position (external encoder) |
|
||||
| `X_act` | Step counter position (internal) |
|
||||
| `X_err` | Tracking error (X_act − X_enc) |
|
||||
| `dev_warn` | Encoder deviation warning flag |
|
||||
| `sg_event` | StallGuard event flag |
|
||||
| `sg_status` | StallGuard status bit |
|
||||
| `sg_stop` | StallGuard stop flag |
|
||||
| `endstop_l` | Left endstop state (pitch only) |
|
||||
| `endstop_r` | Right endstop state (pitch only) |
|
||||
|
||||
---
|
||||
|
||||
## Thermal management
|
||||
|
||||
The DHT11 sensor is read every 250 ms. The fan PWM output is controlled proportionally:
|
||||
|
||||
- Below 25 °C: fan off
|
||||
- Above 25 °C: PWM = (temperature − 25) × 20, capped at 255
|
||||
|
||||
---
|
||||
|
||||
## Dependencies
|
||||
|
||||
Managed automatically by PlatformIO:
|
||||
|
||||
- `TMC-API` — Trinamic vendor library for TMC5160 register access
|
||||
- `DHT sensor library` — Adafruit DHT11/22 driver
|
||||
- `Adafruit Unified Sensor`
|
||||
- `SPI` — Arduino built-in
|
||||
- `EEPROM` — Arduino built-in
|
||||
Reference in New Issue