Skip to main content

Grafito CANStepper

Closed-loop stepper motor control over CAN. Each board carries an ESP32-C3, a TMC2209 driver, an MT6701 14-bit magnetic encoder and a CAN transceiver; up to 31 boards daisy-chain on one 1 Mbps bus and are driven from Python through the USB port of any board on the chain.

can_stepper/
├── firmware/GrafitoCANStepper_C3/          # node firmware (GCSP v1, fw 1.9)
├── firmware/GrafitoCANStepper_C3_CANopen/  # optional CiA 301/402 SKU (fw 2.0)
├── canstepper/                      # Python package (grafito-canstepper)
├── examples/                        # runnable examples + machine.toml
├── tests/                           # pytest suite (runs on a software sim)
├── model_assets/                    # assembly render, PCB drawing PDF, STEP CAD
└── docs/
    ├── PRD.md                       # product requirements
    ├── protocol.md                  # GCSP v1 wire protocol reference
    ├── quickstart.md                # unboxing -> moving motor
    └── grafito_visualizer_integration.md  # machine visualizer + dual-H/J achievement

Highlights

  • Layered Python API — raw frames → StepperNode → NodeGroup → Axis (mm units via rotation_distance) → DualMotorAxis / IndependentDualAxis / Cartesian / CoreXY / MotionGroup → declarative machine.toml.
  • Safety scopes — node.estop(), group.estop(), bus.estop_all() (single broadcast frame); e-stop is latched until re-enabled.
  • Homing — physical endstop on IO8, sensorless (StallGuard), or set-zero; configurable current, backoff and timeout.
  • Closed loop — firmware ≥1.2 plans a rest-to-rest trapezoidal trajectory with velocity feedforward and a light tracking PID on the MT6701 encoder (settle + stall watchdog). All motion limits are configurable defaults, never hard clamps.
  • On-bus leader/follower — dual-motor gantries stay coupled with no host in the loop (DualMotorAxis).
  • Encoder-gated dual screws — IndependentDualAxis commands both motors independently (optional invert for mirrored SFU1204 frames) and blocks the next pass until both encoders are within mm tolerance of the target (closed-loop reverse/straight oscillate).
  • Grafito machine visualizer — live magnetic-encoder SSE into the open-loop 3D UI (dual-H frame + Clipper Vertical J, absolute cycles); see docs/grafito_visualizer_integration.md.
  • Simulator included — canstepper.sim.SimNetwork implements the whole protocol in software; the test suite and the examples run without hardware.

Install & first spin

PyPI: grafito-canstepper
Import: canstepper · Docs: https://docs.grafito.in
Buy: CANStepper Adapter Board

pip install grafito-canstepper

# Development (from this directory):
# pip install -U pip setuptools && pip install -e ".[dev]"
from canstepper import CANStepperBus

with CANStepperBus.serial("/dev/ttyACM0") as bus:
    print(bus.discover())
    node = bus.node(1)
    node.set_run_current(40).enable()
    node.move_to(360.0, blocking=True)

Continue with:

G-code examples (from this directory):

# Cartesian mechanism (independent X/Y[/Z] steppers)
PYTHONPATH=. python3 examples/gcode_cartesian.py /dev/ttyACM0 1 2
PYTHONPATH=. python3 examples/gcode_cartesian.py /dev/ttyACM0 1 2 3
# CoreXY belts
PYTHONPATH=. python3 examples/gcode_corexy.py /dev/ttyACM0 1 2
PYTHONPATH=. python3 examples/gcode_repl.py /dev/ttyACM0 1 2
PYTHONPATH=. python3 examples/gcode_from_file.py examples/gcode/square.gcode

Homing examples (IO8 endstop, StallGuard sensorless, set-zero):

PYTHONPATH=. python3 examples/endstop_monitor.py /dev/ttyACM0 1 30
PYTHONPATH=. python3 examples/home_endstop.py /dev/ttyACM0 1 -1
PYTHONPATH=. python3 examples/home_sensorless.py /dev/ttyACM0 1 -1 60
PYTHONPATH=. python3 examples/home_set_zero.py /dev/ttyACM0 1
PYTHONPATH=. python3 examples/home_axis_mm.py endstop /dev/ttyACM0 1 -1

Docs: https://docs.grafito.in/docs/homing

Belt axis (mm, high-speed soak — absolute ±50 about median):

PYTHONPATH=. python3 examples/belt_move_mm.py /dev/ttyACM0 1 50 77.2 150
PYTHONPATH=. python3 examples/belt_oscillate.py /dev/ttyACM0 1 200 10
PYTHONPATH=. python3 examples/belt_speed_ramp.py /dev/ttyACM0 1 150 30 600

Docs: https://docs.grafito.in/docs/belt-axis

Development

cd can_stepper
python3 -m pytest            # simulator suite
python3 tools/board_e2e.py /dev/ttyACM0 1                # new-board E2E + CL tune (persists)
python3 tools/hw_validate.py /dev/ttyACM0 1              # full API suite (restores params)
python3 tools/cl_speed_validate.py /dev/ttyACM0 1 70 8   # hardware OL vs CL ladder

Current GCSP firmware is 1.9 (motors off at boot until enable()). Optional CANopen 2.0 (EDS/DCF for PLC) lives in firmware/GrafitoCANStepper_C3_CANopen/ — see https://docs.grafito.in/docs/canopen. Do not mix GCSP and CANopen on one bus.

Firmware builds with Arduino IDE or arduino-cli (ESP32C3 Dev Module, USB CDC On Boot = Enabled; libraries: FastAccelStepper, TMC2209 janelia-arduino). Apply Vin (5–24 V, typically 24 V) before upload — USB-C is data only and does not power the ESP32 for programming. CAN termination is on by default (0 Ω jumper); remove that 0 Ω on mid-chain daisy-chain nodes.

arduino-cli compile --fqbn esp32:esp32:esp32c3:CDCOnBoot=cdc \
  firmware/GrafitoCANStepper_C3
arduino-cli upload -p /dev/ttyACM0 --fqbn esp32:esp32:esp32c3:CDCOnBoot=cdc \
  firmware/GrafitoCANStepper_C3

Note on older paths

CANStepperNode_C3/ and canbus.py are obsolete bring-up sketches. Use firmware/GrafitoCANStepper_C3/ and the canstepper package (GCSP v1) for all new work.

Metadata

Release files for grafito-canstepper 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for grafito-canstepper 0.2.1
File Size Uploaded
grafito_canstepper-0.2.1.tar.gz 80.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for grafito-canstepper 0.2.1
File Interpreter ABI Platform
grafito_canstepper-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 152.5 kB

Release files / grafito_canstepper-0.2.1.tar.gz

Download URL grafito_canstepper-0.2.1.tar.gz
Size 80.1 kB
Tags Source
SHA-256 checksum
How to use checksums
65bb344bce78ea40eb6f6281b5524c4654f214bde0d61d40f22b4dad25772765
BLAKE2b-256 checksum
How to use checksums
fb760b7db3112320e1da3720490258be1d3d8456fe524f14f817ce05393a92a1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.12

Release files / grafito_canstepper-0.2.1-py3-none-any.whl

Download URL grafito_canstepper-0.2.1-py3-none-any.whl
Size 72.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6b67472a44693fc8aa3db52a7d4baf70f48de44cc52cdf8ef50203db41d04d55
BLAKE2b-256 checksum
How to use checksums
a31f4bdb8ca2ab0b6e267c60e4d154e82d15b577a95e1217e4721bc215735eb7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.12

Release history Release notifications | RSS feed

0.2.3

2 release files

0.2.2

2 release files

This release

0.2.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page