|
|
||
|---|---|---|
| .. | ||
| .vscode | ||
| include | ||
| lib | ||
| src | ||
| test | ||
| .gitignore | ||
| README.md | ||
| compile_commands.json | ||
| deploy_firmware.sh | ||
| platformio.ini | ||
README.md
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.
Build:
pio run
Build and upload:
pio run --target upload
Clean:
pio run --target clean
Serial monitor:
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
rto 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):
dafter 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 accessDHT sensor library— Adafruit DHT11/22 driverAdafruit Unified SensorSPI— Arduino built-inEEPROM— Arduino built-in