This repository has been archived on 2026-06-17. You can view files and clone it, but cannot push or open issues or pull requests.
FireWatchTower_2axis/firmware/README.md

214 lines
6.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# FireWatchTower — 2-Axis Gimbal Controller
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.
---
## Hardware
| 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 |
### Pin assignments
| 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 |
### 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
├── config/
│ ├── Constants.h — tuning values, thresholds, timing
│ └── Pins.h — pin assignments
├── motor/
│ ├── 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.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)
```
---
## Building
This project uses [PlatformIO](https://platformio.org/).
**Build:**
```bash
pio run
```
**Build and upload:**
```bash
pio run --target upload
```
**Clean:**
```bash
pio run --target clean
```
**Serial monitor:**
```bash
pio device monitor --baud 115200
```
---
## Axis lifecycle
Each axis progresses through the following states after power-on:
```
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