OnStepX ConfiguratorOnStep Configuration Generator

Generate Config.h, compile online, and flash over USB

Language / Langue
Companion 3D designs: 🔧 GT2 Gearbox 📷 Canon Rotator/Derotator 🧰 Fysetc E4 Case 📦 MaxSTM3.6 Case 🔭 Motorized Focuser
GT2 Gearbox — thanks to Chad for the original design 🙏
Axis1 RA/Azimuth — Steps Per Degree Calculator
Typical: 200 (1.8°) or 400 (0.9°)
TMC driver microstep mode for tracking
Worm wheel teeth count
Additional reduction ratio (1 if none)
= (motor_steps × microsteps × worm × pulley) / 360
Total steps for a full 360°
Formula: steps_per_degree = (motor_steps × microsteps × overall_gear_reduction) / 360
Axis2 Dec/Altitude — Steps Per Degree Calculator
Typical: 200 (1.8°) or 400 (0.9°)
TMC driver microstep mode for tracking
Worm wheel teeth count
Additional reduction ratio (1 if none)
= (motor_steps × microsteps × worm × pulley) / 360
Total steps for a full 360°
Axis3 Rotator/De-Rotator — Steps Per Degree Calculator
Horizontal pixels
Vertical pixels
Stepper motor steps
Driver microstep mode
e.g. 110 teeth driven
e.g. 30 teeth driving
= (diagonal_pixels × 2) / 360
= (motor_steps × microsteps × gear_ratio) / 360
Slew Rate & Timing Calculator
Desired base slew rate
During slews, lower microsteps = faster but coarser
μs/step at base slew rate
μs/step at half slew rate
μs/step at double slew rate
= 3600 / steps_per_degree
= 3600 / steps_per_degree
PULSE allows ~1.6x faster rates than SQUARE
Platform Rate Limits (minimum μs/step) — green = OK, red = too fast for this MCU at fastest (2x) slew:
PlatformSQUARE minPULSE minStatus
Mega25604830
ESP324025
STM32 F1033421.25
STM32 F303/F401/F4112012.5
STM32 F446 / Teensy3.2148.75
Teensy3.5127.5
Teensy3.62.61.625
Teensy4.0 / 4.11.5N/A
PEC Calculator
Auto-filled from Axis1 worm gear
= (AXIS1_STEPS_PER_DEGREE × 360) / worm_gear
Controller
Hostname up to 16 chars// Hostname for this device up to 16 chars.
Board pinmap selection. MaxPCB4w (WiFi) and MaxPCB4e (Ethernet) variants share the MaxPCB4 pinmap — the difference is on-PCB wiring, not the firmware constant. Same goes for MaxESP4i: pick MaxESP4 here and set NV_DRIVER=NV_MB85RC64 below for the FRAM variant. Teensy 3.2 / 4.1 boards flash one-click via WebHID; ESP32 boards (MaxESP3/4, FYSETC_E4, CNC3) flash via WebSerial; BTT_SKR_PRO flashes via WebUSB DFU (BOOT0 jumper + reset). CNC3 is deprecated — see the OnStep wiki for alternatives. // Choose from: MiniPCB, MiniPCB2, MaxPCB4, MaxESP4, MaxSTM3, FYSETC_E4,
Fill in driver model, microsteps, current, etc. for the selected PINMAP
Serial Ports
Serial A baud rate// n. Where n=9600,19200,57600,115200,230400,460800 (common baud rates.)
Serial B baud rate// n. Baud rate as above. See (src/pinmaps/) for Serial port assignments.
Upload ESP8266 firmware via Serial B// ON Upload ESP8266 WiFi firmware through SERIAL_B with :ESPFLASH# cmd.
Serial C baud rate// n. Baud rate as above. See (src/pinmaps/) for Serial port assignments.
Serial D baud rate// n. Baud rate as above. See (src/pinmaps/) for Serial port assignments.
Serial E baud rate// n. Baud rate as above. See (src/pinmaps/) for Serial port assignments.
ESP32 wireless mode — this enables the SmartWebServer that is built into OnStepX on ESP32 boards (no separate ESP needed). WIFI_ACCESS_POINT = the board creates its OWN WiFi network "OnStepX" — no router needed, best in the field; connect your phone/PC to it, then open http://192.168.0.1. WIFI_STATION = the board JOINS your existing home WiFi/router — best indoors with internet on the same device; find its IP in the serial monitor or your router's client list. Default WiFi password: "password" — change it! BLUETOOTH = pair over Bluetooth instead of WiFi.// Use BLUETOOTH or WIFI_ACCESS_POINT or WIFI_STATION (ESP32 only.)
Status & Misc
Status LED on controller// Steady illumination if no error, blinks w/error code otherwise.
OFF or 0..255 brightness// n. Where n=0..255 (0..100%) activates feature sets default brightness.
Remember brightness across power cycles// ON Remember reticle brightness across power cycles.
Invert control (0V = max brightness)// ON Inverts control for cases where 0V is max brightness.
Weather sensor type// BME280 (I2C 0x77,) BME280_0x76, BME280_SPI (see pinmap for CS.)
Step pulse waveform. Use SQUARE on long wiring or Teensy 4.x; PULSE squeezes more rate out of slower MCUs.// PULSE Step signal wave form faster rates. SQUARE best signal integrity.
Where OnStepX stores runtime settings. Leave on NV_DEFAULT unless your board has a documented external EEPROM/FRAM (e.g. MaxESP4i ⇒ NV_MB85RC64).// Use platforms default non-volatile device to remember runtime settings.
Axis1 RA/Azimuth — Driver
Motor driver model// Enter motor driver model (above) in both axes to activate the mount.
Use Calculator tab! steps/degree// n. Number of steps per degree:
Reverse movement direction// ON Reverses movement direction, or reverse wiring instead to correct.
-90..-360 degrees// n. Where n= -90..-360 (degrees.) Minimum "Hour Angle" or Azimuth.
90..360 degrees// n. Where n= 90.. 360 (degrees.) Maximum "Hour Angle" or Azimuth.
OFF or 0..90 degrees// n. Where n= 0..90 (degrees.) Allow sync/reset only within this +/-range.
Axis1 — Microsteps & Current
Microstep mode for tracking// n. Microstep mode when tracking.
Microstep mode for slewing// n. Microstep mode used during slews. OFF uses _DRIVER_MICROSTEPS.
OFF or mA for standstill current// n, (mA.) Current during standstill. OFF uses IRUN/2.0
OFF or mA for tracking current// n, (mA.) Current during tracking, appropriate for stepper/driver/etc.
OFF or mA for slew current// n, (mA.) Current during slews. OFF uses IRUN.
Axis1 — Advanced
Driver status/fault detection// ON, HIGH, or LOW. For driver status info/fault detection.
Tracking decay override (default: STEALTHCHOP)// Tracking decay mode default override. TMC default is STEALTHCHOP.
Goto decay override (default: SPREADCYCLE)// Decay mode goto default override. TMC default is SPREADCYCLE.
Power off after movement stops// ON Powers off 30sec after movement stops or 10min after last<=1x guide.
Home position sense// HIGH or LOW enables & state clockwise home position, as seen from front.
Min limit switch// HIGH or LOW state on limit sense switch stops movement.
Max limit switch// HIGH or LOW state on limit sense switch stops movement.
Axis2 Dec/Altitude — Driver
Motor driver model// Enter motor driver model (above) in both axes to activate the mount.
Use Calculator tab!// n. Number of steps per degree:
Reverse movement direction// ON Reverses movement direction, or reverse wiring instead to correct.
-90..0 degrees// n. Where n=-90..0 (degrees.) Minimum allowed Declination or Altitude.
0..90 degrees// n. Where n= 0..90 (degrees.) Maximum allowed Declination or Altitude.
OFF or 0..90 degrees// n. Where n= 0..90 (degrees.) Allow sync/reset only within this +/-range.
Axis2 — Microsteps & Current
Microstep mode for tracking// n. Microstep mode when tracking.
Microstep mode for slewing// n. Microstep mode used during slews. OFF uses _DRIVER_MICROSTEPS.
OFF or mA// n, (mA.) Current during standstill. OFF uses IRUN/2.0
OFF or mA// n, (mA.) Current during tracking, appropriate for stepper/driver/etc.
OFF or mA// n, (mA.) Current during slews. OFF uses IRUN.
Axis2 — Advanced
Driver status/fault detection// ON, HIGH, or LOW. Polling for driver status info/fault detection.
Tracking decay override// Tracking decay mode default override. TMC default is STEALTHCHOP.
Goto decay override// Decay mode goto default override. TMC default is SPREADCYCLE.
Power off after movement stops// ON Powers off 30sec after movement stops or 10min after last<=1x guide.
Home position sense// HIGH or LOW enables & state clockwise home position, as seen from above.
Min limit switch// HIGH or LOW state on limit sense switch stops movement.
Max limit switch// HIGH or LOW state on limit sense switch stops movement.
Mount Type
Mount type// GEM German Equatorial Mount, etc. that need meridian flips.
Meridian flips for FORK / Zenith pass for ALTAZM// ON Enables Meridian Flips for FORK mounts and passing through the
Startup trust mode// SA_STRICT, or SA_PERMISSIVE. Controls when startup trust is granted.
Coordinate refraction mode// Applies refraction to coordinates to/from OnStep, except exactly
Remember coords across power cycles (needs FRAM)// ON Remembers approximate mount coordinates across power cycles.
Enable drivers in standby// ON Enables mount motor drivers while in standby.
Time & Location
Date/Time source// DS3231 (I2C,) SD3031 (I2C,) TEENSY (T3.2 etc,) GPS, or NTP source.
PPS signal edge detection// HIGH senses PPS (pulse per second,) signal rising edge, or use LOW for
Status
Movement rate LED// ON Flashes proportional to rate of movement or solid on for slews.
OFF, ON, or 100..6000 Hz// ON, n. Where n=100..6000 (Hz freq.) for speaker. ON for piezo buzzer.
Start with buzzer enabled// ON starts w/buzzer sound enabled.
Remember buzzer setting// ON to remember buzzer sound setting across power cycles.
ST4 Interface
ST4 guide interface// ON enables interface. <= 1X guides unless hand control mode.
Hand controller features// ON for hand controller special features and SHC support.
Focuser control via hand controller// ON alternate to above: Focuser move [E]f1 [W]f2 [N]- [S]+
Guiding, Limits, Parking
0..120 seconds (0 = disabled)// n. Time limit n=0..120 seconds. Use 0 to disable.
Disable backlash during guiding// Disable backlash takeup during guiding at <= 1X.
Limit switch state// HIGH or LOW state on limit sense switch stops movement.
Park orientation sensor// HIGH or LOW state indicates mount is in the park orientation.
Park input signal trigger// HIGH or LOW state park input signal triggers parking.
Park status output// signals with a HIGH or LOW state when successfully parked.
PEC (Periodic Error Correction)
0 disables, use Calculator tab// n. Steps per worm rotation (0 disables else 720 sec buffer allocated.)
PEC sensor edge// HIGH. Senses the PEC signal rising edge or use LOW for falling edge.
Seconds of PEC buffer// Seconds of PEC buffer allowed.
Tracking & Slewing
2..50 (x sidereal rate)// n. Where n=2..50 (x sidereal rate) during backlash takeup.
Start with tracking enabled// ON Start with tracking enabled.
Tracking compensation// No compensation or REFRACTION, REFRACTION_DUAL, MODEL, MODEL_DUAL.
Remember compensation setting// ON Remembers refraction/pointing model compensated tracking settings.
°/sec base slew rate// n. Desired slew rate in deg/sec. Adjustable at run-time from
Remember slew rate// ON Remembers rates set across power cycles.
Degrees for acceleration// n, (degrees.) Approx. distance for acceleration (and deceleration.)
Degrees to stop on abort// n, (degrees.) Approx. distance required to stop when a slew
Enable Goto features// Use OFF to disable mount Goto features.
Degrees offset for unidirectional approach// Offset in deg's for goto target unidirectional approach, 0.0 disables
Skip final goto phase for alignment stars// ON skips final phase of goto for align stars so user tends to approach
Pier Side & Alignment
Skip home during meridian flip// ON Goto directly to the destination without visiting home position.
Auto meridian flips at startup// ON Start with automatic meridian flips enabled.
Remember auto flip setting// ON Remember automatic meridian flip setting across power cycles.
Pause at home during flip// ON Start with meridian flip pause at home enabed.
Remember pause setting// ON Remember meridian flip pause at home setting across power cycles.
Sync can change pier side (GEM)// ON Allows sync to change pier side, for GEM mounts.
Preferred pier side// BEST Stays on current side if possible. EAST or WEST switch if possible.
Remember pier side setting// ON Remember preferred pier side setting across power cycles.
Use home switches for alignment// ON uses home switches to find home first when starting an align.
Restore pointing model from NV// ON Restores any pointing model saved in NV at startup.
AUTO or 1, 3..9// Uses HAL specified default (either 6 or 9 stars.)
Axis3 Rotator
Motor driver model// Enter motor driver model (above) to activate the rotator.
°/sec slew rate// n. Desired slew rate in deg/sec. Adjustable at run-time from
Steps per degree (use Calculator)// n. Number of steps per degree for rotator/de-rotator.
Reverse direction// ON Reverses movement direction, or reverse wiring instead to correct.
-360..0 degrees// n. Where n=-360..0 (degrees.) Minimum allowed rotator angle.
0..360 degrees// n. Where n=0..360 (degrees.) Maximum allowed rotator angle.
Microstep mode tracking// n. Microstep mode when tracking.
Microstep mode slewing// n. Microstep mode used during slews. OFF uses _DRIVER_MICROSTEPS.
OFF or mA// n, (mA.) Current during standstill. OFF uses IRUN/2.0
OFF or mA// n, (mA.) Current during tracking, appropriate for stepper/driver/etc.
OFF or mA// n, (mA.) Current during slews. OFF uses IRUN.
Status/fault detection// ON, HIGH, or LOW. For driver status info/fault detection.
Tracking decay override// Tracking decay mode default override. TMC default is STEALTHCHOP.
Goto decay override// Decay mode goto default override. TMC default is SPREADCYCLE.
Power off after stop// ON Powers off 30 seconds after movement stops.
Home position sense// HIGH or LOW enables & state clockwise home position, as seen from above.
Min limit switch// HIGH or LOW state on limit sense switch stops movement.
Max limit switch// HIGH or LOW state on limit sense switch stops movement.
Axis4 Focuser 1
Motor driver model// Enter motor driver model (above) to activate the focuser.
200..5000 μm/s slew rate// n, Where n=200..5000 (um/s.) Adjustable at run-time from
5..200 μm/s minimum// n. Where n=5..200 (um/s.) Minimum microns/second.
Steps per micrometer// n. Steps per micrometer. Figure this out by testing or other means.
Reverse direction// ON Reverses movement direction, or reverse wiring instead to correct.
0..500 mm minimum// n. Where n=0..500 (millimeters.) Minimum allowed position.
0..500 mm maximum// n. Where n=0..500 (millimeters.) Maximum allowed position.
Microstep mode// n. Microstep mode when tracking.
Microstep mode slewing// n. Microstep mode used during slews. OFF uses _DRIVER_MICROSTEPS.
OFF or mA// n, (mA.) Current during standstill. OFF uses IRUN/2.0
OFF or mA// n, (mA.) Current during tracking, appropriate for stepper/driver/etc.
OFF or mA// n, (mA.) Current during slews. OFF uses IRUN.
Status/fault detection// ON, HIGH, or LOW. For driver status info/fault detection.
Tracking decay override// Tracking decay mode default override. TMC default is STEALTHCHOP.
Goto decay override// Decay mode goto default override. TMC default is SPREADCYCLE.
Power off after stop// ON Powers off 30 seconds after movement stops.
Home sense// HIGH or LOW enables & state clockwise home position, as seen from above.
Min limit// HIGH or LOW state on limit sense switch stops movement.
Max limit// HIGH or LOW state on limit sense switch stops movement.
OFF, THERMISTOR, or DS18B20 s/n// THERMISTOR or n. Where n is the ds18b20 s/n for focuser temp.
Display
UI language as declared in upstream SHC src/locales. Strings_xx.h shipped upstream for en/us, cn, de and ro (Romanian); es/fr are declared but have no Strings file yet.// English. Specify language with two letter country code, if supported.
OLED model in your hand controller// OLED 1.3" I2C display commonly used. SSD1306 is a 0.96" OLED display.
Show weather (temp/pressure/humidity) in display rotation// ON to show ambient conditions in the display rotation
Allow menus to wrap around (bottom → top)// ON allows menus to wrap so moving past bottom returns to top, etc.
Time entry / display format// OFF to use 12 hour format for entering time.
Initial OLED contrast (user can change in-menu later)// Use 0 to 3 for Min, Low, High, Max respectively.
Keypad
Optional analog joystick add-on// JS1 for Jerry's analog joystick
Joystick deadband in ADC counts (larger = less sensitive)// Sensitivity of joystick in ADC counts (larger is less sensitive)
Connection to OnStep mount

The SHC needs to talk to your OnStep/OnStepX mount controller. Pick whichever cabling matches your hardware. SERIAL_ST4 is the simplest (single short cable to OnStep's ST4 port). Standard async serial (Serial / Serial1) works if you wire UART. Radio is cleanest for ESP32 builds.

Wired link to the mount controller// Allow SERIAL_ST4 OnStep connections using its ST4 port synchronous
Baud rate for async serial mode (ignored for SERIAL_ST4)// Common baud rates for these parameters are 9600,19200,57600,115200.
Wireless link to OnStep (ESP32 builds only)// Allow BLUETOOTH, WIFI_STATION, or BOTH OnStep connections (ESP32 only.)
Weather sensor
Optional ambient sensor on the I2C bus// BME280 (I2C 0x77,) BME280_0x76, BMP280 (I2C 0x77,) BMP280_0x76
Auxiliary
OFF, or 0–255 brightness (0–100%) for the utility LED// n. Where n=0..255 (0..100%) activates feature sets default brightness.
Pass-through ST4 jack for autoguider// ON enables auxillary "pass-through" ST4 interface.
Network
Device name (≤16 chars). Becomes mDNS "onstepsws.local"// This devices name up to 16 chars (collapses to mDNS name "onstepsws".)
Network stack. WIFI is the most common choice on ESP32/ESP8266.// Or use ETHERNET_W5100 or ETHERNET_W5500
Serial link to OnStep
Startup baud used to talk to OnStep// Common baud rates for this parameter are 9600,19200,57600,115200,etc.
Negotiated baud after connection (not all devices support > 115200)// Or use 19200,57600,115200,230400,460800 (not all devices support > 115200)
ESP8266-style TX/RX swap selection// Automatic check both, ON for swapped port or OFF for default port only.
Status LED
Onboard LED blinks while connecting, steady once connected// Enable LED flashes while connecting then steady once connected.
Debug
Leave OFF for production. ON / VERBOSE prints to SERIAL_DEBUG; REMOTE streams over the network.// Use ON for background error messages only, use VERBOSE for all
Which UART to use for debug prints (only meaningful when DEBUG ≠ OFF)// Or use any h/w serial port. Serial1 or Serial2, etc. as supported.
Baud rate for debug UART// n. Where n=9600,19200,57600,115200 (common baud rates.)
NV Storage
Wipes all stored network credentials on boot. Use only when you need the values below to actually take effect — SWS reads them from NV after the first flash and ignores any later changes here unless NV is wiped. Workflow: set ON → flash → wait 1–2 min for the wipe to finish → set back to OFF → flash again. Leaving it ON permanently will erase your settings on every boot. // Causes the defaults to be written back into NV (FLASH,EEPROM,etc.)
Web UI access
Admin password for the SWS web UI. Change from "password" before deploying.// For access to these settings, this can be changed at runtime also.
Access Point (SWS hosts its own WiFi)
true = SWS broadcasts its own WiFi network ("ONSTEP" by default)// Wifi Access Point Enabled.
Min 8 chars (WPA2). Empty string = open network.// Wifi Access Point password.
2.4 GHz channel 1–13// Wifi Access Point channel.
SWS IP when in AP mode. Emitted as {n,n,n,n}.// Wifi Access Point IP Address.
Gateway (usually identical to AP_IP_ADDR)// Wifi Access Point GATEWAY Address.
Subnet mask// Wifi Access Point SUBNET Mask.
Station Mode (SWS joins your existing WiFi)
true = SWS connects to your home/observatory router// Wifi Station Enabled.
Password for your existing WiFi network// Wifi Station mode password.
true = let the router assign an IP; false = use the static IP below// Wifi Station/Ethernet DHCP Enabled.
Static IP — only used when STA_DHCP_ENABLED = false// Wifi Station/Ethernet IP Address.
Static gateway — only used when STA_DHCP_ENABLED = false// Wifi Station/Ethernet GATEWAY Address.
Static subnet mask — only used when STA_DHCP_ENABLED = false// Wifi Station/Ethernet SUBNET Mask.
Ethernet (only if OPERATIONAL_MODE = ETHERNET_*)
Six hex bytes for the W5100/W5500 Ethernet shield. Ignored in WIFI mode.// Ethernet unique MAC address.
Web UI appearance
UI language & default locale units// English. Or L_ca, L_cn, L_de, L_en, L_es, L_fr, L_it, L_jp, L_ro, L_us.
Show ambient conditions (temp / pressure / humidity)// ON ambient conditions in locale default units.
Show MCU internal temperature// ON internal MCU temp. in locale default units.
Reset button on UI (FWU option exposes the STM32 bootloader pin)// ON allows reset if supported, FWU for STM32 firmware upload pin HIGH.
Show coordinate-origin tile on Mount page// ON to display the coordinate origin control tile on the mount page.
OnStepX servo monitor panel (any axis)// ON to display the servo monitor for OnStepX (any axis.)
Encoder global behaviour
Automatically sync encoders → OnStep// Automatically sync Encoders to OnStep.
Persist auto-sync setting across power cycles// ON Remember automatic sync setting across power cycles.
High-res encoders correct pointing mid-goto// ON high resolution encoders correct pointing even for gotos.
Axis 1 encoder (RA / Azm)
Axis 1 encoder type// AB, AB_ESP32, CW_CCW, PULSE_DIR, AS37_H39B_B. RA/Azm (A/MA) & (B/SLO.)
Ticks per degree// n, (ticks/degree.) Encoder ticks per degree.
Flip count direction// ON to reverse the count direction.
arcsec: min diff to sync encoder → OnStep// n, (arcsec.) Minimum diff. between encoder/OnStep for sync. to OnStep.
arcsec or OFF: max diff to sync OnStep → encoder// n, (arcsec.) Maximum diff. between encoder/OnStep for sync. from OnStep.
Axis 2 encoder (Dec / Alt)
Axis 2 encoder type// AB, AB_ESP32, CW_CCW, PULSE_DIR, AS37_H39B_B. Dec/Alt (A/MA) & (B/SLO.)
Ticks per degree// n, (ticks/degree.) Encoder ticks per degree.
Flip count direction// ON to reverse the count direction.
arcsec: min diff to sync encoder → OnStep// n, (arcsec.) Minimum diff. between encoder/OnStep for sync. to OnStep.
arcsec or OFF: max diff to sync OnStep → encoder// n, (arcsec.) Maximum diff. between encoder/OnStep for sync. from OnStep.
BLE gamepad (ESP32 only)
Enable BLE gamepad (ACGAM R1 etc.)// ON to allow BLE gamepad connection for ESP32 only.
Gamepad #1 MAC address (colon-separated)// GamePad MAC address #1
Gamepad #2 MAC address (leave as ff:…:ff if unused)// GamePad MAC address #2
Paste a raw GitHub URL (raw.githubusercontent.com/..., not github.com/.../blob/...). Leave empty to pull the FYSETC E4 reference config.
Compile uses whatever is in this textarea. Imports and file loads preserve the raw source exactly. Clicking Generate Config.h patches form values into existing content — imported extras like THERMISTOR1_*, DISPLAY_WEATHER stay put. To start totally fresh, click ↻ Reset to Defaults in the page header.
Compile Online

The Config.h you've generated will be sent to a GitHub Actions runner that clones the latest hjd1964/OnStepX source, replaces Config.h with your version, compiles with PlatformIO, and returns the firmware. Builds typically take 1-3 minutes.

Auto-selected from your PINMAP choice
Branch / tag / commit SHA of the upstream repo. Leave as main for latest.
Will build: resolving…
OnStepX plugins (optional)
Check the plugins you want bundled into this OnStepX firmware — the workflow will clone OnStepX-Plugins, copy the selected folders into src/plugins/, and wire up Plugins.config.h automatically. Leave all unchecked for a stock build.
Checking…
    Idle — click "Compile Firmware" to begin.
    Flash to Board via USB

    Connect your board via USB and put it into programming mode:

    User Guide

    What this site does: you answer a handful of questions about your telescope mount (motors, gearing, drivers, board) — or your hand pendant, or your web-server bridge — click a button, and get firmware ready to flash, without installing Arduino IDE, PlatformIO, or any C++ toolchain on your computer. The mode switch at the top of the page picks which firmware you're building: OnStepX (mount controller), SmartHandController (hand pendant), or SmartWebServer (Web UI / WiFi·Ethernet bridge).

    Everything happens either inside your browser tab or on free cloud services (GitHub Pages, GitHub Actions, Cloudflare Workers). The project source is always the latest upstream — hjd1964/OnStepX, hjd1964/SmartHandController, or hjd1964/SmartWebServer depending on the mode you pick — we never bundle a stale copy.

    Before you flash anything: make sure your wiring and PINMAP selection match the board you're flashing. A mismatched pinmap can drive step/enable pins that are tied to other things and damage stepper drivers, limit switches, or the MCU. When in doubt, flash once with no motors connected, watch the serial output, and only then plug in the steppers.

    Contents

    1. How it works (behind the curtain)
    2. OnStepX vs SmartHandController vs SmartWebServer — the mode switch
    3. Quick start — board to firmware in 8 steps
    4. What each tab does
    5. The settings you actually have to change
    6. Picking an upstream version (Source ref)
    7. The preflight checklist
    8. OnStepX plugins — how the bundling works
    9. Board-by-board USB preparation
    10. Browser requirements
    11. Privacy & what gets logged
    12. Troubleshooting
    13. FAQ
    1 · How it works (behind the curtain)

    A normal OnStepX workflow looks like: install Arduino IDE or PlatformIO → clone the source → edit Config.h → wait for the toolchain to download → build → flash. That's a lot of setup just to try the firmware once. This site replaces every step with a click.

    Here's what actually happens when you click Compile Firmware:

      +--------------------------------------+
      |  1. YOUR BROWSER                     |
      |     You pick mount/motor/driver      |
      |     settings. Your browser builds    |
      |     a Config.h file locally. No      |
      |     data is sent until you click     |
      |     Compile.                         |
      +-----------------+--------------------+
                        |  POST /compile
                        |  { config.h, board, onstepx_ref }
                        v
      +--------------------------------------+
      |  2. CLOUDFLARE WORKER (a "bridge")   |
      |     Tiny serverless endpoint at      |
      |     onstepx-build-bridge.*.workers.dev
      |     Validates your inputs, adds a    |
      |     GitHub token (which your browser |
      |     shouldn't see), and asks GitHub  |
      |     Actions to start a build.        |
      +-----------------+--------------------+
                        |  workflow_dispatch
                        v
      +--------------------------------------+
      |  3. GITHUB ACTIONS (the build farm)  |
      |     In christm45/onstepx-build-      |
      |     service, a fresh Ubuntu VM:
      |       a) clones the upstream repo    |
      |          for the firmware you picked |
      |          — hjd1964/OnStepX,          |
      |            hjd1964/SmartHandController,
      |            or hjd1964/SmartWebServer —
      |          at your chosen branch/tag/SHA
      |       b) overwrites its Config.h     |
      |          with the one you sent       |
      |       c) runs PlatformIO to compile  |
      |          for your chosen MCU         |
      |       d) packages firmware as a zip  |
      |          and publishes it as a       |
      |          "workflow artifact"         |
      +-----------------+--------------------+
                        |  firmware.zip
                        |  (bootloader, partitions, firmware.bin, merged.bin…)
                        v
      +--------------------------------------+
      |  4. WORKER FETCHES THE ARTIFACT      |
      |     and streams it back to your      |
      |     browser.                         |
      +-----------------+--------------------+
                        |
                        v
      +--------------------------------------+
      |  5. YOUR BROWSER                     |
      |     Unzips the archive in memory,    |
      |     talks to your board over USB     |
      |     (Web Serial / WebUSB), and       |
      |     writes the firmware. The board   |
      |     reboots into OnStepX.            |
      +--------------------------------------+
        

    Piece by piece:

    The configurator (this page)

    Runs entirely in your browser. The HTML/CSS/JavaScript was served by GitHub Pages when you loaded the tab, and from then on everything is local — even the Config.h generation and the browser-based flasher. The page never phones home just for you being here.

    A few UI niceties worth knowing:

    The Cloudflare Worker (the "bridge")

    A ~200-line JavaScript function that Cloudflare runs on-demand when your browser pings it. Its only job is to accept your /compile request, attach a private GitHub API token (which, critically, your browser shouldn't see), and tell GitHub Actions to start a build. It also proxies the resulting firmware zip back to you. The Worker doesn't store anything — each request is independent.

    Why it's needed: GitHub Pages is static-only (it serves files, it can't call protected APIs). A tiny serverless function is the simplest way to bridge a static site to an authenticated API without standing up a server you have to maintain.

    GitHub Actions + the build-service repo

    The repo christm45/onstepx-build-service holds a platformio.ini (build recipe) and a workflow file (.github/workflows/build.yml). When the Worker triggers the workflow, GitHub spins up a fresh Ubuntu virtual machine, runs the steps, then throws the VM away. The steps are:

    1. Check out this repo's build recipe
    2. Install PlatformIO (Python package)
    3. git clone the upstream repo that matches the mode you picked — hjd1964/OnStepX (mount controller), hjd1964/SmartHandController (hand pendant), or hjd1964/SmartWebServer (web/WiFi bridge) — then git checkout at the branch/tag/commit you typed in the Source ref field (default: latest main)
    4. Write your generated Config.h over the upstream's default
    5. Run pio run -e <env> — the env is selected from the Target MCU dropdown on the Compile tab. OnStepX builds use esp32 / teensy32 / teensy40 / teensy41 / blackpill_f411 / f446_fysetc_s6 / skr_pro_f407; SHC builds use the shc_* variants; SWS builds use sws_esp32 or sws_esp8266. PlatformIO downloads the MCU toolchain and any external libraries the project needs, then compiles.
    6. Bundle the outputs (firmware binary, bootloader, partitions, and — for ESP32 — a pre-merged single-file image) into firmware-<uuid>.zip, published as a 1-day-retention workflow artifact

    The browser flasher

    Once your browser has the firmware zip, it unzips in memory and uses one of the Web APIs modern Chromium browsers expose to talk to USB devices:

    Under the hood: the Teensy WebHID flasher

    Of the three browser flashers, the Teensy one is the most custom. PJRC's official tool is teensy_loader_cli, a small C program that talks to the Teensy's HalfKay bootloader over USB HID using libusb/hidapi. The Teensy has no serial bootloader and no DFU interface — HalfKay is the only path in. To do the same thing from a browser we need an API that can send HID output reports to an arbitrary vendor device, and that's exactly what WebHID gives us (Chrome/Edge only; no Firefox or Safari support yet).

    Every Teensy 3.2 / 4.0 / 4.1 sits in ROM as HalfKay whenever you press the white program button. In that mode it appears as a USB HID device with vendor/product IDs 0x16C0 / 0x0478 — same VID:PID across models. The browser's device picker filters on those IDs, so only a Teensy in bootloader mode shows up in the dialog; the running OnStepX sketch, with its own USB identity, is ignored. That also means the dialog is empty until you press the program button — Chrome polls for new devices, so the Teensy pops in as soon as HalfKay activates.

    Once the device is open, flashing is a loop of 1088-byte HID output reports with this layout:

     byte  0   1   2   3 ............. 63  64 ........................ 1087
          +---+---+---+------ zeros ------+------ 1024 bytes of data -------+
          |   flash offset  |  padding    |    .hex payload for this page   |
          |  little-endian  |  (61 bytes) |                                 |
          |    3 bytes      |             |                                 |
          +---+---+---+-----+-------------+---------------------------------+
        

    Block 0 is always sent, even if blank, because that's the trigger that erases the whole chip; subsequent all-0xFF pages are skipped to speed things up. The first five blocks get a long 45-second timeout because the chip erase takes a few seconds before the first write is acknowledged; later blocks complete in milliseconds. After the last data block we send one more 1088-byte report with the offset bytes set to 0xFF 0xFF 0xFF — HalfKay reads that as "reboot into the app." The bootloader often resets mid-ACK, so a missing reply on that final packet is expected, not an error.

    Parsing the firmware is its own step. On Teensy 4.x, PlatformIO emits an Intel HEX file whose data records carry absolute addresses starting at 0x60000000 (the IMXRT1062 flash base); on Teensy 3.2 the addresses start at 0. The parser auto-detects which by looking at the first data record, handles extended-linear-address prefixes (record type 0x04), verifies each line's checksum, and collapses everything into a flat Uint8Array indexed from offset 0. Unused gaps are filled with 0xFF so they look like erased flash. The code_size picked from the env name (2 MB for 4.0, 8 MB for 4.1, 256 KB for 3.2) bounds the write and catches "wrong firmware for this board" early.

    Everything above lives in flash/teensy.js — roughly 300 lines, no external dependencies beyond the ES-module imports this page uses everywhere. If the browser doesn't expose WebHID, or you dismiss the device picker, or any step throws mid-flash, we fall back to the original path: save firmware.hex and show the Teensy Loader instructions. HalfKay is in ROM and cannot be overwritten, so a partial flash never bricks the board — worst case you click Flash again and retry.

    Nothing runs on anyone's private server. All three free-tier services are transparent: you can inspect the configurator source (GitHub Pages serves it), the Worker source, the build workflow, the PlatformIO config. If the whole thing disappeared tomorrow, you could clone all three repos and deploy your own in under an hour — see SETUP-COMPILE-SERVICE.md in the configurator repo.
    1b · OnStepX vs SmartHandController vs SmartWebServer — the mode switch

    The big toggle at the top of the page picks which firmware you're building:

    The three firmwares run on separate MCUs — you don't combine them onto one chip. A typical full setup is: one board (ESP32 / Teensy / STM32) running OnStepX inside the mount, plus one ESP32 running SWS for the web UI, plus (optionally) one ESP32 running SHC inside a hand pendant. They all talk to each other at runtime over the links you configure (ST4 cable, serial, WiFi, BLE).

    When you flip the mode switch:

    Building both? Configure OnStepX in OnStepX mode → Compile & Flash to your mount controller board. Then flip to SHC mode, configure the hand pendant, Compile & Flash to your SHC board. Two separate flashes, one site.
    2 · Quick start — board to firmware in 8 steps
    1. Open the Controller tab. Set PINMAP to whatever board you have — MaxPCB4 (covers MaxPCB4w/MaxPCB4e variants), MaxESP3/MaxESP4 (covers MaxESP4i + FRAM), MaxSTM3/MaxSTM3I, FYSETC_E4, FYSETC_S6 (V1.2 / V2.0 — STM32F446, 6-axis), CNC3 (WeMos R32 — deprecated), MiniPCB (v1 embed-in-mount or v2 stand-alone case), or BTT_SKR_PRO. Click Apply board defaults right below the PINMAP dropdown to autofill driver model, microsteps, and run current for that board.
    2. Open the Calculator tab. Fill in your mount's worm teeth, motor steps/rev, and gear ratio for each axis — the steps/deg values used by Axis1/Axis2 are calculated from this.
    3. Open Axis1 and Axis2. Set AXIS_DRIVER_MODEL to whatever you're using (TMC2209, TMC5160, DRV8825, …) and pick the microstepping. Review the pre-filled steps/deg values.
    4. Open Mount. Pick MOUNT_TYPE (GEM, FORK, or ALTAZM).
    5. Optional: extras on Rotator, Focuser, Auxiliary.
    6. Click the sticky Generate & View Config.h button at the bottom. Skim the output; the #define PINMAP, driver, and mount lines should look right.
    7. Open Compile & Flash. The MCU target auto-follows your PINMAP. The preflight checklist tells you whether the build will even try. Click Compile Firmware. Wait 1–3 min.
    8. Put the board in bootloader mode (see below), plug in USB, click Flash to Board, pick the device in the browser prompt. Done.
    First build is slower (~2–3 min) because GitHub Actions has to download the PlatformIO toolchain and OnStepX's external libraries. Subsequent builds of the same board are ~30–60 s thanks to caching.
    3 · What each tab does
    4 · The settings you actually have to change

    Most defaults are fine. These are the ones you almost always have to set:

    Shortcut: once you've picked your PINMAP, click the Apply board defaults button right under the dropdown. For MaxESP3/4, MaxPCB4, MaxSTM3, BTT SKR PRO, MiniPCB, CNC3, and FYSETC_E4, that fills in the driver model, microsteps, run current, and mount type with known-good values — so you only need to touch the steps/deg (from the Calculator) and the values specific to your scope.

    Required (compile will fail without these)

    Very common adjustments

    Leave alone unless you know why

    You can load an existing Config.h on the Output tab. The form fields will populate from the file, so you can take a working config from your current firmware and tweak from there.
    5 · Picking an upstream version (Source ref)

    On the Compile & Flash tab, the Source ref field controls which version of the firmware gets compiled. The default is main — the latest commit on the upstream repo's main branch. Which upstream that is depends on the mode you picked at the top of the page: hjd1964/OnStepX in OnStepX mode, hjd1964/SmartHandController in SHC mode, or hjd1964/SmartWebServer in SWS mode.

    You can type any of:

    Just below the field you'll see a live preview that resolves your input against GitHub and shows the commit hash, author, date, and the first line of the commit message, so you know exactly what's about to be compiled. The repo prefix (hjd1964/OnStepX, hjd1964/SmartHandController, or hjd1964/SmartWebServer) reflects the current mode — the example below is from OnStepX mode:

      Will build: hjd1964/OnStepX @ main · 1a2b3c4 · Howard Dutton · 3 days ago
                  Add X-axis soft-limit check to mount park routine
        

    If the ref doesn't exist (typo, or tag hasn't been published yet), you'll see a red "could not resolve" message.

    6 · The preflight checklist

    Before any Compile actually goes to the cloud, a local validator scans your form for common mistakes so you don't waste a 2-minute build on an obvious oversight:

    You see each issue listed with a red ✗ (error) or yellow ⚠ (warning) icon. The Compile button stays disabled until you either resolve the issues or tick the "I understand the issues above — build anyway" override. This is intentional: the checklist is a safety net for beginners, not a straightjacket for power users who know what they're doing.

    Your form state is saved automatically to your browser's local storage every time you change a field, so a refresh won't lose your work. The ↻ Reset to Defaults button in the header clears it.
    7 · OnStepX plugins — how the bundling works
    This section applies to OnStepX mode only. SmartHandController and SmartWebServer don't use a plugin system — the OnStepX plugins box is hidden in those modes, and you can skip ahead to the next section.

    Plugins live in their own repo — hjd1964/OnStepX-Plugins — and the OnStepX main branch deliberately doesn't ship them. When you tick a plugin checkbox in the Compile tab's OnStepX plugins box, the build service does this for you:

    GitHub Actions runner:
      1. git clone hjd1964/OnStepX (the version you picked in Source ref)
      2. git clone hjd1964/OnStepX-Plugins
      3. For each ticked plugin (e.g. "website"):
           cp -r plugins-src/website   →   OnStepX/src/plugins/website/
      4. Generate OnStepX/src/plugins/Plugins.config.h:
           #define PLUGIN1                   website
           #include "website/Website.h"
           #define PLUGIN1_COMMAND_PROCESSING    OFF
           (slots 2-8 → OFF)
      5. Drop your Config.h on top of OnStepX/Config.h
      6. pio run -e <your env>
           → compiles src/plugins/website/*.cpp into the firmware binary
      7. Bundle firmware.bin (+ manifest.json + Plugins.config.h) into the
         artifact zip you download.
        

    Concrete example: FYSETC E4 + Website plugin (ESP32). Click Apply FYSETC E4 defaults and the configurator auto-ticks the Website checkbox. Click Compile and the workflow ends up with OnStepX/Config.h from the E4 branch + OnStepX/src/plugins/website/ from OnStepX-Plugins + Plugins.config.h wiring Website to slot 1. After flashing, the ESP32 boots OnStepX, exposes its WiFi (SSID and password live in src/plugins/website/Config.h — the plugin's own config, not yours), and the web UI is reachable at the IP it prints on the serial console.

    How to verify a plugin is actually compiled in

    Four places, in increasing order of "you really want to be sure":

    1. The compile log on this page. When you click Compile, the log streams these lines:
      > POST .../compile { project: onstepx, board: esp32, ref: main, plugins: [website] }
        plugins: website — workflow will copy each into src/plugins/<name>/ and wire up Plugins.config.h
        request_id = …
      and after success:
      ✓ Plugins compiled into this firmware: website
        --- Plugins.config.h (from artifact) ---
        #define PLUGIN1                   website
        #include "website/Website.h"
        #define PLUGIN1_COMMAND_PROCESSING    OFF
        …
        --- end Plugins.config.h ---
      That's the source of truth — the Plugins.config.h block is the actual file the workflow used to build your firmware, copied straight out of your downloaded artifact.
    2. Flash size. Without Website, an ESP32 OnStepX build is ~600KB. With Website it's ~1.0–1.1MB. The Flash: indicator that appears under the Compile button after a successful build will jump accordingly. If you tick Website and the size barely moves, something's wrong — open the run URL and read the workflow log.
    3. The downloaded firmware zip. Unzip it; you should see Plugins.config.h next to firmware.bin / merged-firmware.bin (and a manifest.json with a "plugins": ["website", …] field). If those are missing, your build server is running an older workflow that didn't include them — the firmware is still correctly built, you just have to fall back to method (4) to confirm.
    4. The GitHub Actions log. The compile log on this page prints run URL: https://github.com/…/runs/<id> after the build queues. Open it, expand the step "Bundle OnStepX plugins", and search for === Generated Plugins.config.h ===. The next ~10 lines are the exact file the workflow wrote into the source tree before compiling.

    Why you don't see src/plugins/website/ in any repo on disk

    The bundling happens on a fresh ephemeral GitHub-hosted runner that's torn down the moment the workflow finishes. Nothing is committed back to a repo — not to the build-service repo, not to OnStepX, not to anywhere. The only persistent output is the firmware artifact, and (with the workflow change shipped alongside this help section) the Plugins.config.h dropped next to it.

    If you want to inspect the plugin source before a build, browse it directly at github.com/hjd1964/OnStepX-Plugins/website — it's a normal folder of .h / .cpp files plus the plugin's own Config.h.

    Plugins that need extras

    8 · Board-by-board USB preparation

    ESP32 (MaxESP3, MaxESP4, FYSETC_E4, generic ESP32 dev boards)

    1. Connect USB. Most dev boards (and MaxESP*) auto-reset into bootloader when esptool grabs the port.
    2. If auto-reset fails: hold BOOT / IO0, tap EN / RST, release BOOT.
    3. Click Flash to Board, pick the port in the browser prompt (it'll be labeled something like CP2102, CH340, or USB JTAG/serial debug unit).
    4. Flashing takes 15–40 s. Board auto-resets into firmware when done.

    Reference wikis: MaxESP v3 · MaxESP build notes.

    ESP8266 (NodeMCU, Wemos D1 mini, ESP-01 — SWS only)

    1. Connect USB.
    2. NodeMCU / Wemos D1 mini auto-reset into the ROM bootloader (DTR/RTS wiring on their USB bridge). Bare ESP-01 modules don't — you need to pull GPIO0 to GND, power cycle, and release.
    3. Click Flash to Board, pick the port (same USB-UART families as ESP32: CP2102, CH340, FTDI).
    4. ESP8266 flash is a single firmware.bin written at 0x0 — much simpler than ESP32's four-partition layout. Takes 20–60 s.
    5. If you see "Failed to connect", drop the baud: most ESP8266 modules prefer 460 800 or 115 200. Our flasher already uses 460 800 by default; if that fails, the chip itself is the issue (check USB cable, try the boot procedure manually).

    STM32 BlackPill F411CE (and MaxSTM3)

    1. Connect USB.
    2. Hold BOOT0, tap NRST, release BOOT0. The board re-enumerates as STM32 BOOTLOADER (VID 0483 / PID DF11).
    3. Click Flash to Board, pick STM32 BOOTLOADER in the browser prompt.
    4. Wait for "Flash complete", then tap NRST to run your firmware.
    Windows driver note: on Windows you may need the WinUSB driver for the DFU device. If the browser can't open the device, install Zadig, select "STM32 BOOTLOADER", and replace the driver with WinUSB.

    BTT SKR PRO V1.2 (STM32F407)

    BigTreeTech's 3D-printer board repurposed for OnStep. Same ST DFU protocol as the BlackPill, just a different entry procedure:

    1. Power off the board.
    2. Place the BOOT0 jumper (pins are silkscreened next to the reset button) to hold BOOT0 high.
    3. Power on via USB — the board comes up as STM32 BOOTLOADER (VID 0483 / PID DF11) instead of running the old firmware.
    4. Click Flash to Board, pick STM32 BOOTLOADER in the picker.
    5. After "Flash complete", power off, remove the BOOT0 jumper, power back on. Board boots into OnStepX.

    Reference wiki: BTT SKR PRO on OnStep wiki. Same Windows WinUSB / Zadig note as the BlackPill applies.

    FYSETC S6 V1.2 / V2.0 (STM32F446VE)

    FYSETC's 6-axis 3D-printer board. Same ST DFU protocol as the SKR PRO, but the BOOT0 control on newer S6 revisions is a 3-pin header instead of a jumper (centre + right pin = boot to DFU).

    1. Hold BOOT0 (jumper or 3-pin header → centre + right) high.
    2. Tap NRST — board comes up as STM32 BOOTLOADER (VID 0483 / PID DF11).
    3. Click Flash to Board, pick the device in the browser picker.
    4. After "Flash complete", remove the BOOT0 link and tap NRST.

    ⚠ Driver compatibility: per the OnStep wiki, FYSETC S6 only supports TMC2130 / TMC5160 (SPI), LV8729 or S109. The UART steppers (TMC2208 / TMC2209 / TMC2226) will not work on this board even though they're in the dropdown — picking one fires a preflight error.

    Reference wiki: FYSETC S6 on OnStep wiki. Same Windows WinUSB / Zadig note as the BlackPill applies.

    MiniPCB v1 / v2 (Teensy 3.2 or Teensy 4.0)

    Two iterations on the OnStep wiki:

    Both run on Teensy 3.2 (moderately fast) or Teensy 4.0 (very fast). Both work with most StepStick drivers (DRV8825 / A4988 / LV8729) plus TMC2130 and TMC5160. Teensy 3.2 uses the HalfKay bootloader in the same "block_size ≥ 512" branch as 4.0/4.1 — the WebHID flasher covers all of them:

    1. Plug the Teensy into USB.
    2. Click Flash to Board.
    3. When the browser picker appears, press the white program button — "Teensy" shows up in the dialog, pick it and click Connect.
    4. Progress streams to the flash log; the board reboots into OnStepX when done.

    If you have a Teensy 4.0 mounted instead of 3.2, switch the Target MCU on the Compile & Flash tab from teensy32 to teensy40 before clicking Compile.

    Fallback (Firefox / Safari / WebHID unavailable): we save firmware.hex; drop it into Teensy Loader and press the white program button. CLI alternative: teensy_loader_cli --mcu=mk20dx256 -w -v firmware.hex (Teensy 3.2) or teensy_loader_cli --mcu=imxrt1062 -w -v firmware.hex (Teensy 4.0).

    Reference wikis: MiniPCB overview · MiniPCB v2.

    Teensy 4.0 / 4.1 / MaxPCB4

    One-click browser flash (Chrome / Edge):

    1. Plug the Teensy into USB.
    2. Click Flash to Board.
    3. When the browser picker appears, press the white program button on the Teensy. It'll show up as "Teensy" in the dialog — pick it and click Connect.
    4. Progress streams to the flash log; the Teensy reboots into the new firmware when it's done. Typical time: 3–8 seconds.

    If the browser dialog is empty, the Teensy isn't in HalfKay bootloader mode yet — just press the white program button and it'll pop in.

    Fallback (Firefox / Safari / WebHID unavailable): we save firmware.hex to your Downloads folder. Then:

    1. Open Teensy Loader (comes with Teensyduino).
    2. Drop firmware.hex onto the window.
    3. Press the white program button on the Teensy — it flashes and reboots automatically.

    CLI alternative if you have Teensyduino installed:

    teensy_loader_cli --mcu=TEENSY41 -w -v firmware.hex   # 4.1 / MaxPCB4
    teensy_loader_cli --mcu=TEENSY40 -w -v firmware.hex   # 4.0
    9 · Browser requirements
    Browser Configurator & Compile ESP32 / ESP8266 flash STM32 DFU flash Teensy 3.2 / 4.0 / 4.1 flash
    Chrome, Edge, Opera, Brave (Chromium) yes yes (Web Serial) yes (WebUSB) yes (WebHID)
    Firefox yes no no no (download .hex)
    Safari yes no no no (download .hex)

    Firefox / Safari can generate a config, trigger a compile, and download the firmware — they just can't flash via the browser. If you're on one of those, download the firmware and use esptool.py (ESP32), dfu-util (STM32), or Teensy Loader (Teensy) locally.

    10 · Privacy & what gets logged

    Here's exactly what leaves your browser and where it ends up:

    Data Where it goes How long it stays
    Your Config.h (base64-encoded) Cloudflare Worker → GitHub Actions as a workflow input Logged in the Actions run metadata indefinitely (public repo)
    Board selection & OnStepX ref Same as above Same
    Your IP address (for rate limiting only) Cloudflare Worker KV (if rate limit is enabled) 1 hour
    The compiled firmware GitHub Actions artifact storage 24 hours, then deleted automatically
    Form state (all your settings) Your browser's localStorage Until you click Reset to Defaults or clear site data
    Don't put WiFi passwords, API keys, or other secrets in Config.h. The workflow input is visible in the public Actions log. Leave those fields at OFF / empty and configure them over the OnStepX web UI after flashing, where they only live on your board.

    The configurator itself sends no analytics, no telemetry, no trackers. Nothing leaves your browser until you click Compile.

    11 · Troubleshooting

    "Compile service is not configured yet"

    The site owner hasn't deployed the Cloudflare Worker, or WORKER_URL in compile.js still has the placeholder. For the owner: follow SETUP-COMPILE-SERVICE.md.

    Compile starts but fails

    Click the run URL printed in the compile log. That opens the GitHub Actions page for your build. The "PlatformIO build" step contains the compiler error. Common causes:

    Build succeeded, Flash button is disabled

    The firmware artifact couldn't be downloaded. Reload the page, re-compile, and watch for a firmware download failed line in the compile log. Usually means the artifact already expired (24 h retention) or the Worker URL is wrong.

    "Your config has changed since this firmware was built"

    You edited the form after compiling. The firmware on disk is stale. Click Compile Firmware again, or click Cancel to flash the outdated firmware anyway (rarely what you want).

    Flashing ESP32: "Failed to connect"

    1. Close any other program holding the port (Arduino Serial Monitor, screen, PuTTY).
    2. Unplug USB, replug.
    3. Hold BOOT, tap EN, release BOOT, then click Flash.
    4. Try a different USB cable — a surprising number are charge-only.

    Flashing STM32: device doesn't appear in the picker

    1. Make sure you actually entered DFU. BlackPill: hold BOOT0, tap NRST, release. BTT SKR PRO V1.2: set the BOOT0 jumper, then power-cycle — the device name in Device Manager / lsusb should change.
    2. On Windows: install the WinUSB driver via Zadig (see the BlackPill warning above).
    3. Confirm VID:PID 0483:DF11 is present.

    Flashing Teensy: device picker is empty

    The Teensy isn't in HalfKay bootloader mode yet. Leave the browser dialog open and press the white program button on the Teensy — Chrome polls for new devices and it'll appear. This applies to 3.2, 4.0, 4.1, and MaxPCB4. If the picker still won't show it after the button press, the USB cable may be charge-only (try another).

    Flashing Teensy: "WebHID not available in this browser"

    WebHID is Chromium-only. On Firefox/Safari the flasher silently falls back to saving firmware.hex which you then drop into the PJRC Teensy Loader app. Same result, one more step.

    Teensy Loader doesn't see my .hex

    Drag the file onto the Teensy Loader window, or File → Open HEX File. If it opens but doesn't flash, press the white program button on the Teensy — it flashes on button press, not on file open.

    Flash log stops at "First block sent (chip erase…)"

    Normal. Block 0 on a Teensy triggers a full chip erase; the ACK for that first write arrives only after the erase finishes (a few seconds on 3.2, a bit longer on 4.1's 8 MB flash). The flasher allows up to 45 s per block for the first five blocks. If it actually times out, unplug / replug the Teensy and retry — HalfKay is ROM-resident, nothing can be bricked.

    Firmware runs but axis moves wrong direction / doesn't move

    That's config, not firmware. Toggle AXIS1_DRIVER_REVERSE / AXIS2_DRIVER_REVERSE, re-generate, re-compile, re-flash. If nothing moves at all, check the wiring — if step/dir pins aren't connected, the firmware is fine but the stepper won't move.

    Rate limit hit

    If the service enforces rate limits (default: 10 builds/hour/IP), wait an hour. If you're iterating heavily, set up a local PlatformIO checkout: clone the upstream that matches the firmware you're building — hjd1964/OnStepX, hjd1964/SmartHandController, or hjd1964/SmartWebServer — drop your Config.h in, pio run -e <env>.

    12 · FAQ

    Which upstream version does this build?

    Whatever you type in the Source ref field on the Compile & Flash tab — defaults to main (latest). The upstream repo it resolves against depends on the mode (OnStepX, SHC, or SWS). The live preview under the field shows the exact commit. See Picking an upstream version.

    Is my Config.h sent anywhere permanent?

    Yes — each compile request base64-encodes your Config.h and sends it as a GitHub Actions workflow input. Public-repo Actions logs are visible to anyone, so treat Config.h as public. See Privacy.

    Where do I configure network / WiFi / Ethernet?

    Depends on the flow:

    Which boards can I build for?

    Everything in the PINMAP dropdown is wired to a matching PlatformIO env on the build side. Today that covers:

    To add a board that's not listed, the build service needs a new PlatformIO env — edit build-service/platformio.ini (plus the whitelist in build.yml and the Worker's ALLOWED_BOARDS set), then update the PINMAP dropdown and PINMAP_TO_ENV / PINMAP_MCU mappings here.

    Can I run this offline?

    You can generate Config.h offline — this page works fully offline once loaded. Compiling needs the online service. For a fully offline toolchain, install PlatformIO, clone the upstream that matches the firmware you're building (hjd1964/OnStepX for the mount controller, hjd1964/SmartHandController for the hand pendant, or hjd1964/SmartWebServer for the web/WiFi bridge), and run pio run -e <env>.

    Why did the form change after I flashed?

    In OnStepX mode, after a successful flash the form auto-resets to the selected board's starter defaults, so the next build starts from a clean baseline for that board. This only happens for boards where a starter config is shipped (see the hint next to the "Apply board defaults" button on the Controller tab). Your pre-flash state is stashed in localStorage under onstepx-configurator-v2-preflash — to restore it, open DevTools → Console and run:

    localStorage.setItem('onstepx-configurator-v2', localStorage.getItem('onstepx-configurator-v2-preflash'));
    location.reload();

    The simpler alternative: before flashing, click Download Config.h on the Output tab to save a copy; re-load it later with Load Existing Config.h.

    SHC / SWS modes do not auto-reset — their configs are small enough that overwriting would be annoying rather than helpful.

    How much does this cost the site owner?

    Zero at the scale of a hobby project. GitHub Pages, GitHub Actions (on public repos), and Cloudflare Workers all have free tiers that comfortably fit hundreds of builds per day.

    Can someone else clone this and run their own instance?

    Yes. Everything is open-source. Fork christm45/OnStepX-Configurator, follow SETUP-COMPILE-SERVICE.md, redeploy. The whole pipeline takes under an hour end-to-end.

    The configurator is broken / giving weird output

    File an issue at the configurator repo. If the issue is with the firmware itself (mount behavior on OnStepX, hand-pendant behavior on SHC, or web-UI / network behavior on SWS), use the OnStep group or the relevant upstream issue tracker: OnStepX, SmartHandController, or SmartWebServer.