Skip to content

Repository files navigation

Jumper Factory

Jumper Factory is a split-architecture wire cutting machine controller.

  • Raspberry Pi 5 is the primary controller (UI/orchestration owner; Qt touchscreen UI on a directly-connected MIPI DSI display).
  • Arduino UNO R4 Minima is the real-time executor and safety authority.
  • Pi and UNO R4 communicate over framed USB serial protocol v1.
  • Arduino UNO R4 Minima provides 32 KB SRAM (32,768 bytes) for runtime state.

This repository is migration-locked to Pi-first control flow. Legacy Arduino-only runtime is deprecated and not part of the active workspace.

Building your own machine? Start with GETTING_STARTED.md — it walks through hardware, wiring, software setup, and your first run in order. This README is the technical reference; the getting-started guide is the narrative path through it.

Repository Guide

  • firmware_uno/ - active Arduino firmware source of truth
  • firmware_uno/comm/ - v1 protocol parser/codec/dispatcher/watchdog modules
  • pi_controller/ - Python Pi runtime (serial client, orchestrator, Qt touchscreen UI)
  • docs/overview/ - theory/how-it-works docs for new learners (start at docs/overview/README.md)
  • docs/developer/SERIAL_PROTOCOL.md - wire protocol contract
  • docs/developer/DEVELOPER.md - architecture and contributor contract
  • Jumper_Factory.ino - generated monolith (do not edit directly)
  • cad/ - mechanical design files (CAD, drawings)
  • BOM.md - bill of materials
  • GETTING_STARTED.md - build-your-own walkthrough: hardware, wiring, software, first run
  • install.sh - guided setup script for a fresh Pi

Compatibility note:

  • Some legacy notes may still mention firmware_mega/ or scripts/flash_mega.sh.
  • In this workspace, use firmware_uno/ and scripts/flash_uno.sh.

Subsystem docs:

  • firmware_uno/README.md - UNO R4 wiring, pinout, runtime behavior, build/upload
  • pi_controller/README.md - Pi wiring, touchscreen DSI bring-up, runtime behavior, run/test

System Wiring Overview

                +---------------------------+
                | Raspberry Pi 5            |
                | - Python controller       |
                | - Qt touchscreen UI owner |
                +-------------+-------------+
                              | USB serial (protocol v1, heartbeat)
                              v
                +-------------+-------------+
                | Arduino UNO R4 Minima         |
                | - Motion execution (X/Y/Z)|
                | - Safety and failsafe     |
                | - Encoder capture/events  |
                +-------------+-------------+
                              |
              +---------------+----------------+
              | steppers, limits, IR, hall,    |
              | buzzer, wire handling hardware  |
              +---------------------------------+

Raspberry Pi 5's MIPI DSI port also connects directly to the touchscreen
(800x480, 5-point capacitive touch); the rotary encoder stays wired to the
UNO R4 and remains a secondary input alongside touch.

Quick Start

Use this sequence on a Raspberry Pi host. For the full narrative version (hardware list, wiring, first run), see GETTING_STARTED.md.

  1. Enter the repository root:
cd "Jumper-Factory"
  1. Run the guided installer, or run one-time Pi setup directly:
./install.sh                # guided: setup, flash, optional camera/autostart
# or, just the base setup:
./scripts/setup_pi5.sh
  1. Upload firmware to the UNO R4 (adjust port if needed; install.sh also offers this):
./scripts/flash_uno.sh --port /dev/ttyACM0
  1. Start the Pi controller + WebUI backend (recommended launcher):
./run_pi_app.sh
  1. Open the UI:
http://localhost:8787

From another device on the same network, use http://<pi-ip>:8787.

The dashboard has a dark/light theme toggle (top-right), iconography, and a guided run-batch flow. Set the remote web username/password from the Pi touchscreen under Settings → Web Access.

Startup Notes

  • Run the launcher from repository root. Running run_pi_app.sh from a parent directory without ./ can fail with exit code 127.
  • The launcher starts python -m jf_pi.app, enables web backend, and serves the frontend from pi_controller/webui/dist.
  • Launcher defaults to Pi-triggered jingles enabled (JF_AUDIO_SAFE_MODE=0) when run with no flags. Pass --safe-audio to suppress jingles (sets JF_AUDIO_SAFE_MODE=1); only skip it once buzzer driver-stage wiring is confirmed.
  • --enable-audio is explicit/redundant with the default but documents intent; --safe-audio is the flag that actually suppresses jingles.
  • The launcher reflashes the UNO R4 only when its firmware is out of date (compares semver JF_FW_VERSION_MAJOR/_MINOR/_PATCH against the running board); use --force-flash to override. Bump the firmware version in firmware_uno/comm/jf_protocol.h on every firmware change — see the per-version changelog in docs/developer/VERSIONS.md.
  • If the UNO R4 is missing, the launcher offers to boot without it, retry connecting, or exit. With --auto-offline (JF_AUTO_OFFLINE=1, used by the systemd service) it skips the prompt and boots offline directly. Booting offline keeps the touchscreen usable with a persistent "Arduino not connected" banner; use Settings -> Machine Link to retry connecting or flash. Settings you change persist across restarts and re-apply to the board on reconnect.
  • On startup, the touchscreen shows a brief splash screen ("Jumper Factory" + the Pi software version and Arduino firmware version) before the home screen appears.
  • Physical UI Settings -> Jingle Settings can toggle firmware jingle_enabled and trigger a short AUDIO_PLAY_SEQ test jingle.
  • Physical UI Settings -> Clock Format toggles the top-right header clock between 24-hour and 12-hour (AM/PM) display.
  • While a batch runs, the touchscreen run card and the web dashboard show elapsed time and a measured time-remaining estimate (based on how long each wire has actually taken this batch), and the completion screen shows the total run time. Wire → Recent Jobs lists the last 10 batches (with duration and outcome; tap one for stats or Repeat Job), and Wire → Profiles stores named wire setups you can load with one tap — both also available on the web dashboard's Jobs tab.
  • If serial ports differ from defaults, use the manual command block in pi_controller/README.md under Run.

Autostart (systemd service), power-loss recovery, and closing the app

  • The app runs as a systemd user service (jumper-factory.service): it starts automatically at boot — including after a power loss — and restarts itself if it crashes. Install/update it with ./scripts/install_systemd_service.sh (or via ./install.sh); manage it with systemctl --user status|restart|stop jumper-factory and journalctl --user -u jumper-factory -f. See deploy/systemd/README.md. This relies on the Pi being configured for desktop autologin (raspi-config → System Options → Boot / Auto Login → Desktop Autologin) so the graphical session the Qt UI renders into comes up without anyone signing in.
  • The service launches run_pi_app.sh --force-restart --auto-offline: if the UNO R4 isn't connected at boot, the app comes up in offline banner mode (no tty prompt) and the operator reconnects from Settings → Machine Link → Retry Connect / Flash Firmware on the touchscreen.
  • Power-loss recovery: while a batch is cutting, the Pi checkpoints progress to pi_controller/data/active_job.json. If power (or the app) dies mid-batch, the next link bring-up shows a "Batch interrupted — Resume (N left) / Discard" prompt on the touchscreen; Resume opens the normal Start wizard preloaded with the remaining quantity (wire check → homing → cut). A batch that ends normally (complete/STOP/CANCEL) deletes the checkpoint, so the prompt only appears after an unclean death. The wire that was mid-cut at the moment of power loss is scrap — inspect/trim it before resuming.
  • The legacy ~/.config/autostart/jumper-factory.desktop lxterminal autostart is disabled by the service installer (kept on disk with Hidden=true). Don't run ./run_pi_app.sh manually while the service is enabled — use systemctl --user restart jumper-factory instead.
  • ~/Desktop/Jumper Factory Pi App.desktop remains as a manual-launch shortcut for setups without the service (runs run_pi_app.sh in a terminal, where the offline/retry prompt is interactive).
  • The touchscreen UI has an X button in the top-right header (next to minimize) that asks for confirmation before closing; confirming quits the app fully (Qt UI + backend thread). Note: with the service enabled, systemd treats a clean exit as stopped-until-next-boot (Restart=on-failure), so relaunch with systemctl --user start jumper-factory.

Raspberry Pi Setup Scripts

From repository root:

./scripts/setup_pi5.sh

This script:

  • creates/updates pi_controller/.venv,
  • installs Python dependencies and editable package,
  • installs Arduino core arduino:renesas_uno and required libraries (U8g2, Encoder, AccelStepper),
  • runs Pi unit tests.

Flash firmware with Arduino CLI:

./scripts/flash_uno.sh --port /dev/ttyACM0

Compile-only check (no hardware required):

./scripts/flash_uno.sh --compile-only

./install.sh runs the above in order and offers the optional camera driver and autostart service steps interactively — see GETTING_STARTED.md.

How The Code Works

  • UNO R4 setup()/loop() entry points are in firmware_uno/jf_setup_loop.h and included by firmware_uno/jumper_factory_main.ino.
  • UNO R4 loop always services steppers, sensors, safety checks, comms watchdog, serial command handling, encoder events, and production state machine.
  • Protocol/event functions are in firmware_uno/jf_serial.h plus firmware_uno/comm/jf_*.h.
  • Pi runtime entry point is pi_controller/src/jf_pi/app.py (thin CLI wrapper); the backend loop itself is ControllerRuntime in pi_controller/src/jf_pi/orchestrator/runtime.py. New to the codebase? The module map in docs/developer/DEVELOPER.md ("Pi controller") is the guided tour.
  • Pi runtime sends heartbeat, polls state, consumes async events, updates UI state, and renders Qt touchscreen frames. Unless --headless is passed, the backend loop runs on a background thread while Qt's event loop owns the main thread; the two communicate only through ui/ui_bridge.py's thread-safe UiBridge.

Physical UI Input Behavior

  • Rotary encoder deltas from UNO R4 are coalesced and then applied on Pi at a stable visual cadence to reduce jumpy redraw bursts.
  • Touch tap-to-activate and submenu drag/kinetic scrolling are handled natively by Qt's widgets - there is no custom touch debounce state machine to maintain.
  • Root tiles and guided wizard buttons remain tap-focused interactions.
  • Touchscreen header includes a digital clock at top-right with an operator-selectable 12h/24h format.
  • Physical Wire menu is organized as Load / Unload Wire (submenu), Length, Quantity, Wire Ends (3-way cycler: Off / Strip / Notch - Strip runs the Method A dual-end strip with the trailing-end pass always following; Notch scores rings at the strip boundaries without removing insulation), Strip Length, Wire Gauge/Diameter, Back - no Start row, since the Home screen's Start tile is the only entry point into the cut wizard.
  • Length, Quantity, and Wire Gauge/Diameter each open a dedicated value-picker screen: tap an on-screen preset or dial/-/+ for a custom value, then Set to commit as SET_JOB_PARAMS or Back to discard the edit (a real cancel - entering the screen snapshots the current value and restores it on discard).
  • Physical wire edits use machine-safe ranges and increments: length step 5 mm (5-5000), quantity step 1 (1-999), gauge step 1 AWG (10-40), diameter step 0.1 mm (0.1-8.0).
  • Wire Gauge/Diameter is a mode screen (AWG / Custom Diameter tabs): AWG mode shows wire size everywhere as 22 AWG (0.64 mm) (gauge plus a display-only mm conversion in brackets); Custom mode shows only the diameter, e.g. 1.50 mm. The mode is a Pi-local display preference only - AWG and diameter remain the two distinct values firmware uses together for the strip-cut safety math, so no firmware/protocol changes are involved.
  • Physical Start now opens a guided full-screen Run Batch flow that enforces sequence order: verify wire present -> guide wire insert if missing -> run homing -> start cutting, with STOP and CANCEL visible during active stages.
  • Physical Load Wire/Unload Wire actions run as guided touchscreen flows with step prompts, debounced sensor confirmation, explicit Complete at load verification, always-available cancel (STOP), and manual Feed More/Retract More adjustments.
  • Physical Control -> Home Axes now opens a guided Home flow with Start Home confirmation, in-progress Cancel support, and Done dismissal on completion/error.
  • Guided load/unload stages include distinct buzzer cues for start, verification/extra-adjust, completion, and cancel/error milestones.
  • Web RUN BATCH now opens a full-screen flow that enforces the same startup sequence (wire check, guided insert, homing, then cutting) with interrupt controls (STOP/CANCEL) and a completion Done screen.

Build And Generation

UNO R4 build/upload is done in Arduino IDE targeting Arduino UNO R4 Minima.

Board package for Arduino CLI/IDE: arduino:renesas_uno.

Required Arduino libraries:

  • U8g2
  • Encoder
  • AccelStepper

When firmware modules change, regenerate monolith output:

python tools/generate_monolith.py

Safety Notes

  • Do not bypass limit switches or comms timeout alarm behavior.
  • UNO R4 keeps limitFailsafeLatched and comms-timeout safety local and authoritative.
  • If communication drops during active motion, UNO R4 stops and latches ALARM_COMMS_TIMEOUT.
  • Pi now applies command preflight gating before serial send: invalid UI/web commands are blocked by machine state and state freshness.
  • Non-emergency commands fail closed when machine state is unknown or stale; STOP remains allowed as emergency intent.
  • Do not wire a buzzer directly to UNO R4 D13; use a transistor/MOSFET driver stage for buzzer loads.
  • run_pi_app.sh defaults to Pi-triggered jingles enabled (JF_AUDIO_SAFE_MODE=0); pass --safe-audio (JF_AUDIO_SAFE_MODE=1) to suppress them until buzzer driver-stage wiring is confirmed.

Additional Documentation

  • GETTING_STARTED.md - build-your-own walkthrough, start to finish
  • BOM.md - bill of materials
  • cad/ - mechanical design files
  • docs/overview/ - start here: theory and how-it-works docs for new learners (README.md, 01-06 chapters, GLOSSARY.md)
  • docs/developer/ - contributor reference contracts: DEVELOPER.md, SAFETY_MODEL.md, SERIAL_PROTOCOL.md, STATE_MACHINES.md, UI_MENU_SYSTEM_MAP.md, PROGRAM_ARCHITECTURE_MERMAID_CATALOG.md, VERSIONS.md, CHANGELOG.md

License

The plans and code are publicly available to build, study, and modify for noncommercial use — this is a source-available project, not an OSI-approved "open source" one, because commercial use is restricted to the original author.

  • Firmware and software (firmware_uno/, Jumper_Factory.ino, pi_controller/, scripts/, tools/, deploy/, install.sh) — PolyForm Noncommercial 1.0.0.
  • Hardware and mechanical design (cad/, BOM.md, wiring diagrams) — CC BY-NC-SA 4.0.

Building your own machine, and modifying or sharing the design and code, is permitted and encouraged for personal, educational, and research use. Selling assembled units, kits, or derivative products based on this design is a commercial use reserved exclusively to Bryan Ma; contact him if you're interested in a commercial license.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages