techmannih/nema34-mounted-stepper-controller

A 48 V USB‑C PD 3.1 EPR NEMA‑34 stepper controller PCB combining STM32/TMC5160 control, external MOSFET motor bridges, protected power and regenerative braking, USB data, telemetry, diagnostics, status LEDs, and buzzer alarms.

Version
0.3.92
License
unset
Stars
1

hardware-contract.json

{
  "name": "PD1180-EPR \u2014 NEMA 34 Smart Motor-Mounted Stepper Controller with USB-C PD 3.1 EPR",
  "revision": "0.4.1-ECO",
  "controller": "STM32G0B1CEU6",
  "motor_driver": "TMC5160A with eight CSD19534Q5A MOSFETs",
  "usb_pd": "TPS26750 + TPD4S480, sink-only EPR",
  "usb_ports": {
    "J1": "Dedicated 48 V / 5 A USB-C PD 3.1 EPR POWER sink; no USB data",
    "J10": "USB 2.0 DATA plus independent, current-limited logic power; two 5.1k CC Rd; no PD negotiation and no connection to VMOTOR"
  },
  "mechanical": {
    "board_mm": [
      85.9,
      85.9
    ],
    "mounting_holes": [
      {
        "name": "H1",
        "diameter_mm": 4.2,
        "x_mm": 67.397132,
        "y_mm": 4.575689,
        "centered_x_mm": 24.447132,
        "centered_y_mm": -38.374311
      },
      {
        "name": "H2",
        "diameter_mm": 4.2,
        "x_mm": 81.324311,
        "y_mm": 67.397132,
        "centered_x_mm": 38.374311,
        "centered_y_mm": 24.447132
      },
      {
        "name": "H3",
        "diameter_mm": 4.2,
        "x_mm": 18.502868,
        "y_mm": 81.324311,
        "centered_x_mm": -24.447132,
        "centered_y_mm": 38.374311
      },
      {
        "name": "H4",
        "diameter_mm": 4.2,
        "x_mm": 4.575689,
        "y_mm": 18.502868,
        "centered_x_mm": -38.374311,
        "centered_y_mm": -24.447132
      }
    ],
    "outline": "TMCM-1180 V1.1 stepped perimeter with four 5.9 mm concave corner arcs",
    "reference": "engineering/mechanical/ordered-motor-pcb-reference.json",
    "assembly": "top-side only",
    "encoder": {
      "reference": "U18",
      "assembly_layer": "bottom",
      "centered_x_mm": 0,
      "centered_y_mm": 0,
      "validation": "Optional bottom-side U18 and both bypass capacitors are DNP. Sensor center matches the ordered motor axis at (0,0). The single-shaft motor has no documented rear rotating-shaft interface; no magnet/holder or working gap is qualified.",
      "do_not_place": true,
      "local_bypass_references": [
        "C52",
        "C53"
      ]
    },
    "motor_assembly": {
      "selected_motor": "STEPPERONLINE 34HS31-6004S1; user confirmed Amazon ASIN B091C83HWF on 2026-10-11",
      "definition": "engineering/mechanical/assembly.json",
      "preview_entrypoint": "motor-assembly.circuit.tsx",
      "direct_rear_mount_compatible": null,
      "status": "Exact ordered-motor CAD in an alignment preview; unsupported adapter/posts/fasteners removed. Existing four PCB holes unchanged. Rear thread/depth, secure mounting and encoder attachment remain unverified."
    }
  },
  "fabrication": {
    "layers": 4,
    "finished_thickness_mm": 1.6,
    "copper_oz_all_layers": 1,
    "minimum_trace_space_mm": 0.09,
    "solder_mask": "green",
    "surface_finish": "ENIG",
    "power_corridor_nominal_width_mm": 2.4,
    "power_zone_clearance_mm": 0.16,
    "signal_via_mm": {
      "diameter": 0.5,
      "drill": 0.3
    },
    "power_via_mm": {
      "diameter": 0.6,
      "drill": 0.3
    },
    "via_in_pad": "epoxy filled and copper capped for all 63 recorded via-in-pad locations; see docs/manufacturing-acceptance.md"
  },
  "rated_targets": {
    "pd_contract_v": 48,
    "pd_contract_a": 5,
    "motor_phase_rms_a": 3.8,
    "motor": "34HS31-6004S1",
    "motor_rated_phase_a": 6,
    "motor_current_note": "Conservative design ceiling for the ordered 6 A/phase motor: 3.8 A RMS target, GLOBALSCALER=139 gives 3.781 A nominal. The full-scale tolerance sensitivity peak is 5.671 A, below 6 A; this is not powered qualification. Initial commissioning uses IRUN=6, about 0.827 A RMS, 10 rpm and no attached load. Motion remains locked."
  },
  "reset_safe_outputs": {
    "POWER_PERMIT": 0,
    "MCU_RUN": 0,
    "SD_MODE": 0,
    "STATUS_GPIO": 0
  },
  "connectors": {
    "J1": "USB PD POWER",
    "J10": "USB DATA",
    "J2": "Motor A1/A2/B1/B2",
    "J3": "External regeneration brake resistor"
  },
  "logic_power": {
    "U5": "PD_VBUS -> V3V3_PD -> U23 -> board V3V3",
    "U22": "VMOTOR -> V3V3_MOTOR -> U24 -> board V3V3 (brake backup)",
    "motor_power": "J1 only; USB DATA cannot energize VMOTOR",
    "reverse_blocking": "Two cascaded status-interlocked LM66100 pairs; DATA and PD VBUS are never connected",
    "usb_default_budget": "Startup before enumeration and USB suspend current must be measured and qualified; the current limiter is overload protection, not a USB enumeration policy",
    "usb_data_power": "USB DATA alone powers MCU setup/diagnostics. Flash, encoder and sensors require board V3V3. CDC advertises a bus-powered 500 mA configuration.",
    "U25": "USB_DATA_VBUS -> TPS2553 U28 -> TLV75533 U25 -> V3V3_USB",
    "selection": "U26/U27 + R112: status-interlocked OR of board V3V3 and V3V3_USB into V3V3_MCU",
    "board_presence": "R119/R120 10k/10k divider into STM32 PB1; 2.9\u20133.6 V qualified for 20 ms before peripheral access. PD IRQ removed; status remains polled.",
    "suspend": "USB suspend disarms, invalidates telemetry, ends I2C, turns status low and enters STOP0. RTC/LSI wakes main every nominal 50 ms to service the 250 ms IWDG and sample DATA VBUS; USB resume/reset wakes normally. Physical current/timing validation remains open.",
    "gpio_backfeed": "Chip selects use open-drain release into board-domain pullups; no high drive into unpowered peripherals. Peripheral inputs and I2C pins become analog/high impedance when board power is absent or USB suspended."
  },
  "diagnostics": {
    "temperature": {
      "device": "TMP102AIDRLR",
      "address": 72,
      "hardware_inhibit": "TEMP_OK -> U33 AND -> RUN_SAFE",
      "trip_c": 70,
      "manual_rearm_max_c": 55,
      "derating_starts_c": 60,
      "stale_limit_ms": 500,
      "validation": "Board temperature only; MOSFET junction correlation and thresholds require load testing"
    },
    "phase_current": {
      "device": "INA240A1DR x2",
      "shunt_milliohm": 5,
      "shunt_nominal_watts": 1,
      "gain_v_per_v": 20,
      "output_offset_v": 1.65,
      "output_volts_per_ampere": 0.1,
      "mcu_channels": [
        "PA0",
        "PA1"
      ],
      "output_filter": {
        "series_ohm": 1000,
        "shunt_f": 1e-08
      },
      "validation": "Instantaneous diagnostics; nominal VDDA and offset require calibration. Not a short-circuit trip or an RMS estimate."
    },
    "bus_monitors": {
      "device": "ADS1115IDGSR",
      "address": 73,
      "ain0": "VMON_ADC",
      "ain1": "IIN_MON",
      "reference_range_v": 4.096,
      "sample_rate_sps": 128,
      "ain2": "BRAKE_FB",
      "brake_preflight": {
        "divider_ohm": [
          4700,
          4700,
          510
        ],
        "filter_f": 1e-08,
        "required_fresh_samples": 3,
        "valid_bus_mv": [
          44000,
          50400
        ],
        "return_ratio": [
          0.9,
          1.1
        ],
        "scope": "Continuity before each power-permit cycle, latched only while RUN. Not a proof of brake current, Q16 turn-on, heatsink capacity or runtime cable integrity."
      }
    },
    "indicators": {
      "gpio_expander": "PCA9538PWR",
      "i2c_address": 112,
      "supply": "PD_3V3, shared with PD_SCL/PD_SDA pull-ups and reset buffer U37",
      "reset": "PC13 / STATUS_GPIO with R132 10k pulldown drives U37 SN74LVC1G17DBVR input. PD_3V3-powered output U35_RESET_N has R137 47k pulldown. Assert low on MCU reset, rail loss, USB suspend or indicator bus failure; no direct MCU-rail drive into PCA9538 RESET.",
      "ports": {
        "P0": "RGB red cathode through 1k",
        "P1": "RGB green cathode through 330 ohm",
        "P2": "RGB blue cathode through 330 ohm",
        "P3": "Buzzer MOSFET gate through 1k; 100k gate pulldown",
        "P4-P7": "grounded inputs"
      },
      "power_indicator": "D17 red LED + 4.7k from board V3V3; does not indicate USB-only MCU power",
      "alarm": "FUET-9650B-3V active buzzer; AO3400A low-side switch; BAV21W flyback diode",
      "firmware_states": {
        "blue": "commissioning lock",
        "amber": "waiting for qualified telemetry/power after qualification",
        "green": "qualified supply/telemetry; RUN reported separately over USB",
        "red": "latched motor fault, reported driver fault or overtemperature; 200 ms alarm every 2 s"
      },
      "budget_status": "design allocation, not measured; buzzer max 30 mA specified at 3 V only, allow 60 mA at board-rail extremes pending qualification",
      "gate_drive": "R126 1k limits charging to <3.7 mA at 3.6 V; R127 100k pulls Q26 gate low when expander is reset",
      "qualification": "Current, sound, brightness, reset silence and source transitions require first-article measurements",
      "incremental_logic_rail_budget_ma": 75
    }
  },
  "motor_harness": {
    "definition": "engineering/motor-harness.json",
    "reference": "J2",
    "header": "B4P-VH(LF)(SN)",
    "pitch_mm": 3.96,
    "mate": "VHR-4N",
    "contacts": "SVH-41T-P1.1",
    "contact_quantity": 4,
    "termination_wire_awg": 16,
    "wire_insulation_diameter_mm": [
      1.7,
      3.0
    ],
    "rating_a_at_specified_wire": 10,
    "rating_v": 250,
    "wire_colours": [
      "black",
      "green",
      "red",
      "blue"
    ],
    "pin_to_net": {
      "1": "MOTOR_A1_OUT",
      "2": "MOTOR_A2",
      "3": "MOTOR_B1_OUT",
      "4": "MOTOR_B2"
    },
    "motor_leads_mm2": 0.75,
    "splice": "TE 320559, one 0.75 mm\u00b2 motor conductor to one 16 AWG pigtail per splice; four splices",
    "splice_supported_wire_mm2": [
      0.3,
      1.42
    ],
    "connection_status": "Defined harness; not supplied with PCB assembly. Harness maker must confirm crimp/insulation dimensions and provide continuity/pull-test records.",
    "current_note": "JST 10 A applies to the standard header with 16 AWG termination, not directly to the motor factory 0.75 mm\u00b2 wire. Motor current is still governed by its qualification; no 10 A motor rating is implied."
  },
  "pd_programming": {
    "definition": "docs/pd-programming.md",
    "switch": "U36 SN74LVC2G66DCUR opens both I2Cc wires when TP_PD_ISO is grounded",
    "target_power": "fixed 5 V supplied through J1; no EPR negotiation during fixture programming",
    "programmer": "3.3 V open-drain, ground first, VCC output disabled; TP_PD_VREF is sense only",
    "programming_status": "TI Full Flash candidate generated and register-reviewed; fixture acceptance, programming/readback, cold boot and fault/PD qualification pending"
  },
  "local_control": {
    "start_stop": "SW2, PC6 / USER_BUTTON_N, active-low with R133 10k pullup to V3V3_MCU",
    "reset": "SW1 / NRST",
    "motion_mode": "TMC5160 internal SPI ramp; SD_MODE low; unused U7 pins 17,18,23,24,25 grounded",
    "qualification": "Motion inhibited until TI configuration and powered bridge validation exist",
    "external_command_interfaces": "None; J7 and STEP/DIR/ENABLE/home/limit conditioning removed",
    "protection": "U10/U11/U33 and DRV_EN_N pullup retained; Q14 emitter grounded after removal of external-enable transistor Q15"
  },
  "input_protection": {
    "reference": "U6",
    "mpn": "TPS26630RGER",
    "lcsc": "C1850276",
    "mode": "1x active current limiting; MODE open latches faults",
    "current_set_resistor": {
      "reference": "R25",
      "ohm": 4990,
      "mpn": "RN73R1JTTD4991B25",
      "lcsc": "C7293210",
      "initial_tolerance_fraction": 0.001,
      "tcr_ppm_per_c": 25,
      "temperature_excursion_c": 100
    },
    "upstream_input_current_allocation_a": 0.25,
    "upstream_allocation_status": "Design allocation including upstream logic and controller consumption; not a measured upper bound",
    "limiting_status": "No 25.5 ms 2x pulse allowance; finite loop response and fast-trip transient remain subject to source/cable qualification",
    "hardware_qualified": false
  },
  "brake_protection": {
    "cutoff_resistor": {
      "reference": "R66",
      "ohm": 1200,
      "mpn": "RT0603BRD071K2L",
      "lcsc": "C136970",
      "tolerance_fraction": 0.001,
      "tcr_ppm_per_c": 25
    },
    "nominal_motor_cutoff_v": 53.20754716981132,
    "scope": "Restricted, unloaded rotor commissioning screen only; motion remains inhibited",
    "brake_continuity_detection_implemented": true,
    "brake_fault_hardware_qualified": false,
    "full_current_operation_authorized": false,
    "brake_divider_resistor": {
      "reference": "R61",
      "ohm": 16200,
      "mpn": "RT0603BRD0716K2L",
      "lcsc": "C728583",
      "tolerance_fraction": 0.001,
      "tcr_ppm_per_c": 25
    },
    "continuity_scope": "Startup: three fresh distinct bus/return pairs. RUN: both ADC timestamps checked; mismatches get one fixed 100 ms retry window for multiplexed sampling skew, with stale ADC and hard bus range faults immediate at the next check. Physical detection/inhibit latency is unqualified; no brake-current, resistance or backup energy proof."
  }
}