PhotoCar — Complete Build & Wiring Guide

The single source of truth for building the PhotoCar — consolidates the former assembly, MD25HV/Pi wiring, and Bluetooth-integration guides. Control-side facts (pins, PWM, service env) are read directly from the running firmware in motor-control/; part specs are the modeled PhotoCar parts.

Pin note (verified against firmware): the deployed service uses PWM = GPIO18 (PWM0, physical pin 12) and DIR = GPIO16 (physical pin 36), sharing any GND (pin 14 is right next to PWM). GPIO12 is dead/shorted-to-ground on this board, so PWM stays on GPIO18; DIR moved from the older GPIO23 to GPIO16. PWM and DIR are at opposite ends of the header, so this is not a single 1×3 plug. Source: motor-control/scripts/provision-photocar.sh.
ComputePi Zero 2 W
Motor driverCytron MD25HV
Control pins12 / 14 / 36
Power2× 12 V LiFePO4
Interface7" touch + BLE/WiFi
PWM = GPIO18 (PWM0), pin 12 DIR = GPIO16, pin 36 GND = pin 14 (any ground) 1 kHz hardware PWM Chain drive, single center wheel Never wire motor power to GPIO

1. Bill of Materials & Specs

PartQtySpecificationTerminals / role
Raspberry Pi Zero 2 W (or 2 WH)165 × 30 mm; 4× M2.5 on 58 × 23 mm; BCM43430 BLE 4.2 + WiFi; 40-pin J8 headerRuns the photocar-ble service; PWM/DIR out on GPIO18/16
Cytron MD25HV motor driver1Single channel, 7–58 V, 25 A, PWM/DIR mode (not I²C); PCB 111.76 × 60.96 × 1.6 mm; 4× Ø3 on 106.68 × 55.88 mmPower VB+/VB−, motor MA/MB; control GND/5VO/PWM/DIR
12 V wiper-style gear motor1~100 RPM; ~2.4 Ω → ~5.3 A / ~68 W running at 12.8 V; ~179 mm overall, Ø9.5 D-shaftTwo armature leads → MA/MB; park-switch taps unused
12 V 10 Ah LiFePO4 battery (A & B)212.8 V nominal, 20 A limit; 151 × 65 × 94 mm; F2 spade terminalsPOS/NEG → A/B/OFF selector
A/B/OFF battery selector1Rotary selector, red ringChooses pack A, pack B, or OFF
Emergency stop + master On/Off (DPST)1 eaE-stop cutoff; DPST master switchIn series between Main(+) bus and Switched(+) bus
Bus bars4Main(+), Main(−), Switched(+), Switched(−)Distribution to MD25HV + buck
5 V DC-DC buck converter167 × 38 × 14 mm; holes 61.05 × 31.45 mm; set output 5.1 V, ≥ 3 AINP/INN in, OUTP/OUTN out → Pi 5 V
Onboard LiFePO4 charger + inlet114.6 V 10 A LiFePO4 charger; 120 V AC charge inletCharges the pack(s) in place
Electronics mounting plate1180 × 180 × 2 mm PLA, 22 holes (Pi M2.5 Ø3.4, MD25/buck M3 Ø3.8, grid/corner M4 Ø4.7)Bolts the board stack to the deck
3D-printed board enclosure1Bolt-down case, side port cutout (board_case_*)Houses MD25HV / Pi / buck
7" touchscreen1HDMI + USB touchRuns the PhotoCar kiosk UI
2.54 mm connector housings + signal wire122–26 AWG; 1×2 for PWM+GND, plus a DIR leadPi control: PWM pin 12, GND pin 14, DIR pin 36
Single center knobby wheel, chain, sprocketssetOne-stage chain reductionMotor → chain → center drive wheel

2. Parts — Reuse, Buy & Budget

Conservative list including the small wiring and mounting parts that usually get missed. Buy the genuine Raspberry Pi from a trustworthy listing; save money on generic wiring, housings, heat-shrink, standoffs, fuse holders, and buck converters — never by removing the Pi fuse, undersizing the 5 V regulator, or powering the Pi from the MD25HV 5VO.

Reuse from the existing car

PartUseNotes
Cytron MD25HV motor driverMotor power stageKeep existing motor + battery screw-terminal wiring if it already runs the motor.
Charger, XT60 leads, power distributionCharging / wiringA LiFe-capable charger handles the 4S LiFePO4 pack; reuse XT60s and distribution.
12 VDC gear motor + connectorDrive motorLeave motor wiring as heavy-current wiring — never route motor current into GPIO harnesses.
Enclosure, glands, lever connectors, loomMounting / serviceReuse where practical; add strain relief where wires leave the box.

Buy / add

PartQtyMinimum specWhy
4S LiFePO4 battery pack1–212.8 V nominal (14.6 V full), 10 Ah, balance lead; BMS ≥ 20 A continuousMain power. 12.8 V matches the 12 V motor. Two packs + A/B/OFF selector for runtime.
Raspberry Pi Zero 2 WH (or 2 W + soldered header)1Onboard BLE, 40-pin headerWH saves soldering. Runs the photocar-ble service.
microSD card116–32 GB, reputable brandRaspberry Pi OS + control program.
5 V DC-DC buck converter1Input 8–30 V; output 5.1 V; ≥ 3 A (LM2596/MP1584)Powers the Pi from the 12.8 V bus. Set to 5.1 V before connecting the Pi.
Inline fuse holder + fuses1Mini blade, 2 A to startProtects the buck/Pi branch.
Pre-crimped 1-pin Dupont leads20–4022–26 AWG, 2.54 mmEach conductor starts as a 1-pin lead, then loads into housings.
2.54 mm connector housingsassort.1×3, 1×4, plus 1×2 / 2×nBuild keyed groups: the Pi control plug and power plugs.
18 AWG red/black wire6–10 ftStranded copperBattery branch to fuse, switch, buck input.
22–26 AWG signal wire3–6 ftBlue / black / purplePWM, GND, DIR control leads.
Ferrules / heat-shrink / zip ties / M2.5 nylon standoffssetsMatch gaugesClean terminations, strain relief, and a non-conductive Pi mount.
Multimeter1DC volts + continuityRequired to verify buck output before plugging the Pi.

Optional add-ons

PartInclude when
Pi Camera Module + Zero CSI ribbonThe car should capture photos/video (narrow Pi-Zero ribbon).
Micro-USB OTG adapterSetup / rescue access before BLE is stable.
Low-current status LED/buzzer (via resistor/driver)Boot/control status feedback — never drive high current from GPIO.
Budget: a minimum cart (new 4S LiFePO4 pack, genuine Pi Zero 2 WH, microSD, buck, fuse, switch, Dupont kit, wire, heat-shrink, standoffs) runs roughly $130–210 on Amazon US, assuming the motor driver, charger, enclosure, and basic tools are reused. Verify live prices, and confirm a genuine 4S LiFePO4 pack (not LiPo) with a ≥ 20 A BMS and real Pi Zero 2 W/WH branding.

3. System Architecture

High-current drive power and low-current control signals stay on separate paths. The selected battery feeds a main bus, through the E-stop and master switch to a switched bus, which feeds both the MD25HV power input and the buck converter. The buck powers the Pi at 5 V. The Pi commands the MD25HV with three signal wires: PWM, DIR, and a shared GND.

Power current and control signals stay on separate paths Battery A / B 12.8 V LiFePO4 A/B/OFF selector E-stop + On/Off (DPST) via main bus Switched bus + / − MD25HV VB± in, MA/MB out Wiper Motor 12 V gear motor → chain → wheel 5 V Buck 5.1 V, ≥ 3 A MA/MB Pi Zero 2 W control firmware BLE + WiFi (7777) GPIO18 / GPIO16 7" Touchscreen kiosk UI 5 V PWM / DIR / GND HDMI+USB
Hard safety rule: never connect motor power, battery, or charger output to a Raspberry Pi GPIO pin. GPIO is a 3.3 V signal interface. Motor current lives only on the MD25HV power/motor screw terminals. The Pi sends only PWM and DIR plus a shared ground.

4. Control Wiring — Pi to MD25HV

The MD25HV runs in PWM/DIR mode. Three wires connect it to the Pi: PWM = GPIO18 (physical pin 12), DIR = GPIO16 (physical pin 36), and a shared GND. GPIO18 is used because GPIO12 is dead/shorted-to-ground on this board. PWM (pin 12) and DIR (pin 36) sit at opposite ends of the header, so they are not one 1×3 plug — pair PWM with the adjacent ground on pin 14, and run DIR as its own keyed lead.

Pi Zero header → MD25HV

Pi physical pinPi signalMD25HV terminalWire
Pin 12GPIO18 (PWM0)PWMBlue — motor speed
Pin 14GNDGNDBlack — common reference (next to PWM)
Pin 36GPIO16DIRPurple — direction
no connection5VOLeave empty / unwired

Verified in provision-photocar.sh (PHOTOCAR_PWM_GPIO=18, PHOTOCAR_DIR_GPIO=16) and MotorController.ts. Any ground pin works for GND; pin 14 is chosen because it is adjacent to PWM.

Connector plan

  • Pi side: a 1×2 housing on pins 12 / 14 (PWM = GPIO18, GND), and a separate keyed lead for DIR on pin 36 (GPIO16). PWM and DIR are at opposite ends of the header.
  • MD25HV side: land on the green control screw terminal at the PWM, GND, and DIR positions; use ferrules.
  • The 5VO terminal stays empty. Do not use it to power the Pi.
  • Do not use loose single-pin jumpers for the PWM/GND pair — they shake loose in a moving car. Secure the DIR lead with a tie.
  • Pi GPIO is 3.3 V and the MD25HV accepts it directly. No level shifter needed.
Pi Zero header — PWM pin 12 + GND pin 14 (a 1×2) and DIR pin 36 (separate) Outer (even) row shown, pins 2…40 left→right. PWM/GND are together; DIR is at the opposite end. 2 12 14 36 40 1×2: PWM + GND DIR lead Pin 12 = GPIO18 / PWM0 → MD25HV PWM Pin 14 = GND → MD25HV GND (adjacent to PWM) Pin 36 = GPIO16 → MD25HV DIR (far end)

MD25HV board — connect here, not there

The MD25HV has more than one control area. Ignore the small manual potentiometer/rocker headers (those were for standalone manual control). For Pi/software control, land on the green control screw terminal silk-screened GND / 5VO / PWM / DIR. Battery power goes to the high-current terminals on the opposite edge: VB+, VB−, and the motor on MA / MB. Match the printed labels on your physical board before powering anything.

MD25HV terminal map — control on one edge, power/motor on the other Cytron MD25HV PWM/DIR mode control (green) GND 5VO × PWM DIR high current VB+ VB− MA MB Pi → PWM / GND / DIR · leave 5VO empty battery → VB± · motor → MA/MB
Motor leads: the wiper gear motor's connector carries the two armature (drive) leads plus unused park-switch taps. Only the two armature leads go to MA / MB. The 5VO terminal stays empty — never use it to power the Pi.
Direction sense and PWM mode: firmware default is DIR_FORWARD_LEVEL=1 (forward = DIR high). PWM is hardware-timed at 1 kHz on PWM channel 0 via dtoverlay=pwm,pin=18,func=2; on boot the firmware sets GPIO18 to its ALT5 PWM function with pinctrl. If the motor spins the wrong way, swap the two motor leads or flip DIR_FORWARD_LEVEL.

5. Power Wiring

The car's power path is: selected battery → main bus → E-stop → master On/Off (DPST) → switched bus → MD25HV power input and buck converter. Negatives return through the Main(−) and Switched(−) bus bars. The buck output powers the Pi at 5 V, which also establishes the Pi–MD25HV common ground through the control cable.

FromToMethodNotes
Battery A/B POS / NEGA/B/OFF selectorF2 spadeSelector picks pack A, B, or OFF.
Selector out (+)Main(+) busBus barSingle main positive distribution.
Main(+) busE-stop → On/Off (DPST)InlineE-stop then master switch in series.
On/Off outSwitched(+) busBus barEverything downstream is switch-controlled.
Switched(+) busMD25HV VB+Screw / ferruleHeavy wire (motor current).
Switched(+) busBuck INPScrew / solderBattery voltage in — not from MD25HV 5VO.
Battery NEGMain(−) / Switched(−) busBus barCommon ground.
Switched(−) busMD25HV VB− + Buck INNScrew / ferruleMotor + buck return.
Buck OUTP/OUTNPi 5 V inputExisting Pi power methodVerify 5.1 V with a meter before plugging the Pi.
MD25HV MA/MBWiper motor armature leadsScrew terminalSwap leads to invert direction.
Charge inlet (120 V AC)Onboard 14.6 V LiFePO4 charger → packInlet + leadsCharges in place; do not drive while charging.

Soldered Y-split harness (positive & negative distribution)

Where the switched bus feeds both the MD25HV and the buck, a clean removable harness is a soldered Y-split rather than soldering directly to fixed components:

  1. Cut one trunk wire (from the switched bus / switch output) and two branch wires (MD25HV + buck).
  2. Slide adhesive-lined heat-shrink onto the trunk before soldering.
  3. Strip enough insulation that the three copper ends overlap mechanically; twist the two branches together, then wrap with the trunk.
  4. Solder so it flows through the joint, not just on the outside; let it cool without movement.
  5. Cover with the adhesive heat-shrink; add an outer sleeve or cable wrap if the harness will vibrate.
  6. Repeat for the negative side. Use heavier wire on the MD25HV branch (motor current) than on the buck branch.
Fuse choice: size the fuse for your wiring and expected motor current, not the MD25HV's 25 A ceiling. The driver can pass far more than your harness; protect the wire, connectors, and battery harness. Start conservative and validate under load.
Before first power-up: measure the pack at full charge, verify MD25HV power polarity and buck input polarity, set the buck to 5.1 V and confirm it at the Pi end, and confirm MD25HV 5VO is not wired to the Pi. Lift the wheel off the ground for the first motor test.

6. Software & Control

The Pi runs motor-control (TypeScript/Node) as the systemd service photocar-ble.service, installed by scripts/provision-photocar.sh. It accepts drive commands over Bluetooth LE, a WiFi TCP control port, and the on-car touchscreen kiosk.

Provisioning a fresh Pi

Service environment (the source of truth for pins)

VariableValueMeaning
PWM_GPIO18Throttle PWM on GPIO18 / PWM0 (physical pin 12). GPIO12 is dead on this board.
DIR_GPIO16Direction on GPIO16 (physical pin 36).
PWM_FREQUENCY_HZ10001 kHz hardware PWM (period 1 ms). Keep ≤~1 kHz — the MD25HV only responds at 100% duty near 20 kHz.
MAX_THROTTLE100Throttle is clamped 0–100%.
WATCHDOG_TIMEOUT_MS1200Motor stops if no command arrives within 1.2 s.
DIRECTION_CHANGE_PAUSE_MS20Ramps to 0 then pauses before reversing.
WIFI_CONTROL_PORT / HOST7777 / 0.0.0.0WiFi TCP control listener.
BLUETOOTH_ENABLED1BLE GATT control enabled (BCM43430, HCI 4.2).
PHOTOCAR_REAL_MOTOR11 = drive real GPIO/PWM; 0 = dry run.

Boot config line written by the provisioner: dtoverlay=pwm,pin=18,func=2 (GPIO18 reaches the PWM block via ALT5). Reboot once after first adding it.

PhotoCar state: READY dir: FWD thr: 50% 25% 50% 75% 100% HOLD FORWARD BACK STOP POWER DOWN WiFi EXIT

On-car 7" kiosk UI: top status bar (state / direction / throttle), throttle presets 25/50/75/100% + HOLD, then FORWARD / BACK / STOP / POWER DOWN, plus WiFi and EXIT.

Driving commands: over BLE or the WiFi port the car accepts JSON like {"cmd":"drive","dir":"forward","throttle":50,"seq":1}, plus stop, ping, and (when ALLOW_SHUTDOWN=1) power-off. The 1.2 s watchdog stops the motor if commands stop arriving, so a dropped link fails safe. Pack-voltage telemetry on the UI requires an ADC/voltage divider wired to the Pi (BATTERY_VOLTAGE_FILE); until then the UI marks battery as not configured.

7. Assembly Steps

1. Bench-test the Pi before installing it

microSD Raspberry Pi OS Pi Zero pair Bluetooth test GPIO output Ready

Image Raspberry Pi OS and enable Bluetooth; on the Pi run bash scripts/provision-photocar.sh.

Pair the tablet/controller while on USB bench power.

Confirm PWM hardware drives: bash scripts/provision-photocar.sh selftest before touching car wiring.

2. Mount the Pi and buck converter

Vacuum debris from the enclosure; mount the Pi on non-conductive standoffs on the electronics plate.

Place the buck close enough to keep the 5 V leads short; keep the Pi antenna area clear of metal and large bundles.

Keep low-current electronics away from the battery terminals and motor leads.

3. Add the fused, switched buck branch

Switched bus+ / − Fusenear tap SwitchPi branch 5 V BuckINP / INN

Install the fuse close to the bus tap, not next to the Pi; verify buck input polarity before connecting power.

Set buck output to 5.1 V with a meter before plugging into the Pi.

4. Build the control harness from 1-pin pre-crimp leads

Build a 1×2 housing for PWM + GND (GPIO18 pin 12 / GND pin 14) and a separate keyed lead for DIR (GPIO16 pin 36), in the same order as the wiring table.

Tug-test each lead after insertion; if a crimp backs out, replace that lead. Label the harness before plugging it in.

Do not solder loose wires directly to the Pi header — serviceable connectors survive a moving car.

5. Connect to the MD25HV control terminal only

Pi Zero GPIO18, GPIO16, GND pins 12 / 36 (+GND 14) MD25HV PWM, DIR, GND PWM DIR GND Never connect motor output to GPIO

Land on the MD25HV green control screw terminal (GND / 5VO / PWM / DIR), not the heavy motor terminals; leave 5VO empty.

Keep existing motor screw-terminal wiring intact. After plugging in, check continuity from Pi GND to MD25HV GND.

First motor test at low throttle with the wheel lifted off the ground.

8. Bring-Up Checklist

Source Notes

Control-side facts (pins, PWM mode, frequency, service env, provisioning, kiosk UI) are read from the live firmware in motor-control/ — primarily scripts/provision-photocar.sh and src/MotorController.ts. Part specifications (MD25HV, Pi Zero 2 W, buck, battery, motor, mounting plate, bus/selector/E-stop power chain) are the modeled PhotoCar parts.