This project is a PlatformIO firmware for an Arduino Nano that controls a small puck-delivery mechanism. It combines a lead-screw stepper, a barrel indexer, a yaw axis, two firing servos, and a simple serial command interface so the system can be operated manually or through a higher-level controller.
The firmware is organized around four main behaviors:
- A lead-screw elevator that raises and lowers pucks to different levels.
- A rotating barrel indexer that selects the next chamber to fire from.
- A yaw axis that can aim the firing direction over a limited range.
- Two deployment servos that reset, arm, and fire the puck.
This firmware is meant to drive a mechanical puck launcher with a single-button fire workflow, but it also supports manual control over serial. In practice, the system can:
- detect whether a puck is present at the firing position
- fire one puck at a time
- advance the lead screw for the next puck level
- rotate the barrel to the next chamber
- return the elevator to the bottom reference position
- report the current state of the motors and servos
The repository is split into a small set of source and header files:
- src/main.cpp: top-level serial command parser and startup/loop logic
- src/Axes.cpp: control logic for lead screw, barrel, and yaw movement
- src/StepperController.cpp: low-level motion driver setup for the lead-screw TMC5160 and standalone barrel/yaw STEP/DIR control
- src/ServoController.cpp: servo reset/arm/fire behavior
- include/Config.h: hardware pins, motion profiles, servo angles, and mechanical constants
- Install PlatformIO and open this folder in VS Code.
- Connect the Arduino Nano to USB.
- Build and upload the
nanoatmega328environment from platformio.ini. - Open the serial monitor at 115200 baud.
- Try a simple command such as
eto arm the servos,Cto print the current system status, orTto run the lead-screw TMC5160 SPI connection test.
The firmware targets an Arduino Nano-compatible board and uses the following PlatformIO settings:
+----------------------+
| Arduino Nano |
|----------------------|
| Serial Commands |
| - parse/dispatch |
| - status reporting |
+----------+-----------+
|
+---------------------------+
| |
+----------v----------+ +--------v---------+
| Stepper Controller | | Servo Controller |
| - TMC5160 drivers | | - reset/arm/fire |
| - step generation | +------------------+
+----------+----------+
|
+----------v----------+
| Axes Controller |
| - lead screw |
| - barrel indexer |
| - yaw axis |
+---------------------+
[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328new
framework = arduino
monitor_speed = 115200
lib_deps =
teemuatlut/TMCStepper
arduino-libraries/ServoFor serial debugging, the default monitor settings are set to 115200 baud with newline handling enabled.
This project uses one TMC5160 stepper driver for the lead screw and two standalone TMC2209 STEP/DIR drivers for the barrel and yaw axes, plus two servos. The Nano pin mapping is defined in include/Config.h.
| Function | Nano pin |
|---|---|
| Lead STEP | D2 |
| Lead DIR | D3 |
| Barrel STEP | D6 |
| Barrel DIR | D5 |
| Yaw STEP | D8 |
| Yaw DIR | D7 |
| Lead SPI CS | D10 |
| Shared MOSI | D11 |
| Shared MISO | D12 |
| Shared SCK | D13 |
| Servo | Nano pin |
|---|---|
| Left servo signal | A1 |
| Right servo signal | A2 |
The servos should be powered from a suitable external 5 V supply, not from the Nano regulator. The servo ground and the Nano/driver ground should be connected together.
Most of the machine behavior is controlled from include/Config.h. The values you are most likely to adjust are:
PUCK_HEIGHT_MM: the vertical spacing between puck levelsBARREL_HEIGHT_MM: the overall travel height of the lead screwPUCK_COUNT: how many puck levels the system understandsFIRST_PUCK_EXTRA_OFFSET_MM: the extra offset applied before the first puck levelLEAD_STEPS_PER_MM: the step-per-millimeter calibration for the lead screwBARREL_POSITION_COUNT: how many barrel indexes existBARREL_MICROSTEPSandYAW_MICROSTEPS: the configured standalone-driver microstep resolutionYAW_MINIMUM_DEGREESandYAW_MAXIMUM_DEGREES: the allowed yaw range- servo angle constants such as
LEFT_SERVO_REST,LEFT_SERVO_ARM, andLEFT_SERVO_FIRE
The lead-screw calibration is especially important. The current value is a starting point and should be adjusted if the real motion does not match the commanded motion.
A few behaviors are worth knowing before using the machine:
- The elevator is tracked in terms of puck levels and also in physical step position.
- The barrel is treated as a circular indexer, so movement is optimized to take the shortest route to the requested chamber.
- The yaw axis is limited to a mechanical range and is clamped to that range when commands are issued.
- The barrel and yaw motors are driven as standalone TMC2209 STEP/DIR motors without UART, so their motion is controlled by step timing rather than driver configuration registers.
- The servo motion is smooth by default, and the fire action briefly holds the fire position before returning to rest.
- The firmware assumes the system is already roughly homed at startup: the lead screw starts at the bottom, the barrel at index 0, and yaw at 0 degrees.
The firmware listens for commands over the serial port at 115200 baud. Commands are processed when a newline is received.
| Command | Purpose |
|---|---|
F or f |
Run one full puck deployment cycle if a puck is present |
H or h |
Home the lead screw to the bottom position |
? |
Print the available commands |
C |
Print the current status of the axes and servos |
T or t |
Run the TMC5160 SPI connection test over the serial monitor |
X |
Disable all stepper drivers |
| Command | Purpose |
|---|---|
w |
Reset servos to the rest position |
e |
Move servos to the armed position |
p |
Fire the right servo once and return to rest |
l |
Fire the left servo once and return to rest |
m or M |
Fire both servos and return them to rest |
| Command | Purpose |
|---|---|
W |
Raise the elevator by one puck level |
S |
Lower the elevator by one puck level |
+ |
Move the lead screw up by 1 mm for alignment checks |
- |
Move the lead screw down by 1 mm for alignment checks |
A |
Move the lead screw to the full top position |
D |
Move the lead screw back to the bottom reference |
B |
Run the lead screw down, ignoring the remembered position |
L |
Treat the current physical position as the new bottom reference |
| Command | Purpose |
|---|---|
N |
Move the barrel to the next chamber index |
P |
Move the barrel to the previous chamber index |
I5 |
Move the barrel directly to chamber index 5 |
O |
Set the current barrel position as index 0 |
| Command | Purpose |
|---|---|
Y12.5 |
Move to an absolute yaw angle in degrees |
R0.25 |
Move by a relative yaw angle in degrees |
Z |
Set the current yaw position as zero |
The firmware does not currently use encoders or automatic homing sensors. If the mechanism is moved by hand, stalls, skips steps, or is changed while a motor is disabled, the software position can become inaccurate. In that case, the physical position should be re-established with the appropriate L, O, or Z command.