KITT

// PROJECT KITT — BUILD ROADMAP v3 //

DUAL POWERARCHITECTURE v3.0

● PHASES 0–5
◆ POWER UPDATE
CR-Z SPECIFIC
DEMO MODE
JOE INTEGRATED
SCROLL
// DUAL POWER ARCHITECTURE — FULL BREAKDOWN //
⚡ STANDALONE + CAR-INTEGRATED · ZERO DRAMA
THE PI IS NO LONGER A CAR SLAVE
The core problem: any Pi in a car is a car-slave — the second the key goes off, the power cuts. Corrupt SD card, lost state, cold boot every time. The fix is a UPS HAT that sits between the Pi and all power sources and makes intelligent decisions. It's not a battery pack you plug into USB — it's a hardware-level power manager that the Pi doesn't even know is there.
🔋
BATTERY MODE
4× 21700 Li cells
8–12 hr runtime
Home / garage / meets
SimOBD test data
UPS
AUTO
HAT
🚗
CAR MODE
Fuse 13 → USB-C PD
Auto-charges battery
Runs off alternator
Key ON = instant boot
// FULL SYSTEM ARCHITECTURE — SIGNAL + POWER FLOW //
CAR SIDE Honda CR-Z Fuse 13 · 12V ACC Ignition-switched PD CHARGER 65W 12V→USB-C 5V/3A or 9V/3A PD out 12V DC WAVESHARE UPS HAT (E) INPUT: USB-C PD 5–20V bidirectional · 65W max CELL MGMT: BQ40Z80 Gas gauge · over-charge protect cell balancing · temp monitor OUTPUT: 5V / 6A BOOST 30W to Pi · screen · OBD dongle I2C BUS (addr 0x36) SOC · voltage · current · temp POGO PINS → PI GPIO No soldering · direct stack mount BATTERY PACK 4× Samsung 40T 21700 · 4000mAh each 16Ah total · 3.6V nom. 8–12h @ ~6W draw USB-C PD 65W charge/ discharge RASPBERRY PI 4 CPU: BCM2711 · 4-core A72 RAM: 4GB LPDDR4-3200 SD: 32GB SanDisk Endurance OS: Pi OS Lite 64-bit I2C · GPIO 17 · USB × 4 HDMI0 → Waveshare screen USB-A → ELM327 OBD dongle 5V/6A pogo I2C SCL/SDA GPIO 17 IGN detect WAVESHARE 7" 800×480 · HDMI + USB touch Capacitive · slim bezel Power via Pi USB-A ELM327 USB OBD2 USB-A → Pi · USB-B → OBD port CR-Z OBD2 port: under dash python-obd via /dev/ttyUSB0 SOFTWARE STACK SYSTEM SERVICES kitt-obd.service kitt-display.service ignition-monitor.service OBD BRIDGE obd_bridge.py WebSocket :8765 SimOBD fallback DASHBOARD Chromium kiosk kitt_dashboard.html 800×480 Blade Runner UI GAMES / ARCADE RetroArch + SNES9x Flask :8766 launcher PICO-8 Wangan Racer JOE VOICE AI Vosk wake word OpenAI / espeak TTS ━━ Power / Charging ╌╌ I2C Data Bus ╌╌ OBD2 / GPIO Signal ╌╌ Software / Process
← SWIPE TO SCROLL →
// UPS HAT POWER STATE MACHINE //
STATE A BATTERY ONLY Cells discharge at ~0.5A 5V/6A to Pi (from boost) 8–12h runtime STATE B CAR + CHARGING USB-C PD active (9V/3A) Cells charging at ~1A Pi runs off car power STATE C GRACEFUL HALT GPIO 17 LOW detected Joe announces · 60s timer sudo shutdown -h now key ON → USB-C present USB-C removed key OFF (GPIO 17 LOW) key ON again → UPS HAT auto-boots Pi
← SWIPE TO SCROLL →
🏠 HOME / GARAGE / MEET MODE
Pure battery — just unplug the car cable
Full dev environment, SSH, debug freely
SimOBD data runs the whole dashboard
Carry sled to Daikoku — demo without CRZ
Build Wangan Night Racer on PICO-8
🚗 CR-Z / ROAD MODE
Key ON → USB-C powers + charges pack
Battery stays topped automatically
Real OBD2 data live on amber screen
Key OFF → 60s grace → Joe announces halt
Never browns out, never corrupts SD
// BUILD PHASES //
0
// PHASE ZERO
DUAL POWER — UPS HAT + FUSE TAP + IGNITION MONITOR
Week 1 · ~¥9,700 · DO THIS FIRST
◆ DO FIRST
+

// WAVESHARE UPS HAT (E) — TECHNICAL SPECIFICATION //

PARAMETERVALUENOTES
Input voltage range5V – 20VUSB-C PD negotiates 9V/3A = 27W from car charger
Output to Pi5V / 6A (30W)Regulated boost converter — stable even when cells are at 3.2V
Cell configuration4S1P (4 cells series)Nominal 14.4V pack, 4000mAh per cell
Charge ICBQ25895 (Ti)Smart PD negotiation, thermal regulation, MPPT
Gas gauge ICBQ40Z80 (Ti)I2C @ 0x36 — reports SOC, voltage, current, temp, health
I2C address0x36SDA → GPIO 2, SCL → GPIO 3 (Pi standard)
Low-battery shutdownConfigurable <5%HAT cuts power after Pi OS halts cleanly
Auto-boot on powerHardware enableSet via raspi-config → Boot on power restore
Estimated runtime8–12 hrsPi4 + 7" screen + OBD dongle ≈ 6–8W total draw

// BQ40Z80 I2C READABLE REGISTERS //

0x00
RelativeSOC
Battery % (0–100)
0x09
Voltage
Pack voltage (mV)
0x0A
Current
Charge/discharge (mA)
0x08
Temperature
Cell temp (°K × 10)
0x0F
RemainingCap
mAh remaining
0x10
FullChargeCap
mAh at full (ages)
0x11
RunTimeToEmpty
Minutes remaining
0x16
BatteryStatus
Status flags byte
📦
Order: Waveshare UPS HAT (E) + 4× Samsung 40T 21700 Cells
The UPS HAT stacks directly onto the Pi 4 via pogo pins — physically no different to installing any HAT, but electrically it becomes the Pi's power source. The Pi doesn't see a battery — it just sees clean 5V. The HAT decides where that 5V comes from. Get genuine Samsung 40T or Molicel P42A cells. Avoid AliExpress clones — they lie about capacity and have no thermal protection.
Waveshare UPS HAT (E) ............ ~¥4,500 # model: E specifically — has PD input 4× Samsung 40T 21700 (4000mAh) .. ~¥3,000 # genuine from reputable seller 65W 12V→USB-C PD charger ........ ~¥1,500 # must support PD negotiation Add-a-Circuit fuse tap (mini) .... ~¥300 # mini fuse size for CR-Z USB-C cable (right-angle, 1m) .... ~¥400 # right-angle fits under dash cleaner ────────────────────────────────────────── TOTAL PHASE 0 .................... ~¥9,700
← SWIPE TO SCROLL →
🔌
Car Side: Tap Fuse 13 (CR-Z Interior Fuse Box — Under Dash Driver Side)
Fuse 13 is the Accessory Socket fuse — ignition-switched, cuts when key is off. The Add-a-Circuit tap is literally a fuse with a second output — no cutting, no splicing. Completely non-destructive. Remove it and the car is factory stock again.
(dash, driver side) └── [ACCESSORY SOCKET · 15A · ignition-switched] └── Add-a-Circuit tap (mini blade · add 10A fuse) └── 12V line → 65W 12V→USB-C PD Charger └── USB-C cable (1m, right-angle) └── → │ ┌───────────┴──────────────────┐ │ UPS HAT (E) │ │ BQ25895 (charge IC) │ │ BQ40Z80 (gas gauge, 0x36) │ │ 5V/6A boost output │ └──────┬──────────────┬─────────┘ │ pogo pins │ 4× 21700 ┌──────▼──────┐ ┌───▼────────┐ │ Pi 4 (5V) │ │ Battery │ └────────────┘ └────────────┘
← SWIPE TO SCROLL →
🎛️
Optional: GPIO 17 Ignition Detection Circuit
A second thin wire from the same fuse tap goes through a resistor divider to GPIO 17. This brings 12V down to Pi-safe 3.3V. Total cost: ¥20 in resistors from any electronics shop.
# VOLTAGE DIVIDER — 12V → 3.2V (Pi GPIO safe) # 3.2 = 12 × 47k / (100k + 47k) = 3.224V ✓ Fuse 13 (+12V) ──[100kΩ]──┬──[47kΩ]── GND │ GPIO 17 # ~3.2V when car ON · ~0V when car OFF # Parts: 100kΩ + 47kΩ resistors (~¥10 total)
← SWIPE TO SCROLL →
🐍
Software: Ignition Monitor systemd Service
Reads GPIO 17 (ignition) and I2C battery level every second. Key off → Joe speaks shutdown line → 60s timer → halt. Battery below 5% → emergency halt in 30s. Auto-starts on boot via systemd.
# /home/pi/kitt/ignition_monitor.py (key excerpt) while True: now = GPIO.input(17) batt = read_battery_pct() if was_on and not now: speak("Engine cut. Shutdown in 60s. Good run tonight.") graceful_halt("ignition_off", 60) if batt <= 5: speak("Battery critical. Shutting down in 30 seconds.") graceful_halt("low_battery", 30) was_on = now time.sleep(1)
← SWIPE TO SCROLL →
🖥️
raspi-config: Two Critical Settings
I2C enables the UPS HAT gas gauge. Auto-boot makes the Pi start when the car key turns on — without it the Pi stays off even with power present.
sudo raspi-config → Interface Options → I2C → Enable → System Options → Power Button → Boot on power restore # Verify I2C sees UPS HAT: sudo i2cdetect -y 1 # should see 0x36 # Read battery %: python3 -c "import smbus2; b=smbus2.SMBus(1); print(b.read_word_data(0x36,0x00),'%')"
← SWIPE TO SCROLL →
📐
Physical Stack: Under-Dash Sled
Full stack (Pi + UPS HAT + cells) ≈ 100×70×50mm. Velcro or 3D-printed bracket under the dash. The single USB-C cable is the only car connection. Unplug it and the whole sled is a portable battery unit.
┌──────────────────────────────┐ │ Waveshare 7" HDMI Screen │ ← dash mount └──────────────┬───────────────┘ │ HDMI + USB ┌──────────────▼───────────────┐ ← velcro/sled under dash │ Raspberry Pi 4 (4GB) │ └──────────────┬───────────────┘ │ pogo pins ┌──────────────▼───────────────┐ │ Waveshare UPS HAT (E) │ └──────────────┬───────────────┘ │ wire leads ┌──────────────▼───────────────┐ │ 4× Samsung 40T 21700 │ └──────────────────────────────┘ USB-C → PD Charger → Fuse 13 GPIO 17 → voltage divider → Fuse 13
← SWIPE TO SCROLL →
DEMO MODE: Unplug the one USB-C cable from the fuse tap and the sled is a fully self-contained battery device. obd_bridge.py falls back to SimOBD automatically. Dashboard, Joe, arcade — all runs identically. Walk into Daikoku with the screen already running. No CRZ required.
1
// PHASE ONE
HARDWARE SETUP + OBD2 READING + SIM FALLBACK
Week 1–2 · Core hardware + first live OBD2 data
● ACTIVE
+
// OBD2 DATA FLOW — LIVE MODE vs SIM MODE //
CR-Z ECU Speed · RPM Coolant · MAF Fuel · O2 · throttle ELM327 USB OBD2 → USB serial /dev/ttyUSB0 38400 baud obd_bridge.py if ELM327 connected: use live OBD2 data else: use SimOBD data WebSocket :8765 @ 10Hz DASHBOARD WebSocket client Blade Runner amber UI Dials update @ 10Hz
← SWIPE TO SCROLL →
🛒
Full Shopping List (Core + Power)
Raspberry Pi 4 (4GB)
~¥8,000
Quad-core A72. Handles dashboard + arcade + Joe concurrently.
CORE
Waveshare 7" HDMI Touch
~¥6,500
800×480 · capacitive touch · HDMI + USB HID · powered via USB-A from Pi.
SCREEN
ELM327 USB OBD2 Dongle
~¥1,500
USB (not Bluetooth) — /dev/ttyUSB0, deterministic. BAFX Products or Vgate USB.
OBD2
32GB SanDisk Endurance
~¥800
Rated for continuous write cycles. Standard SD cards fail in 3–6 months.
STORAGE
Waveshare UPS HAT (E)
~¥4,500
Pogo-pin direct stack. 5V/6A output. BQ25895 + BQ40Z80 I2C gas gauge.
◆ NEW
4× Samsung 40T 21700
~¥3,000
4000mAh each · 4S · 16Ah total. 8–12h runtime.
◆ NEW
65W 12V→USB-C PD Charger
~¥1,500
PD negotiation required. Car side. Charges UPS HAT while running Pi.
◆ NEW
Add-a-Circuit Fuse Tap
~¥300
Mini blade type for CR-Z. Taps Fuse 13 non-destructively.
◆ NEW
PHASE 0 + 1 TOTAL
Complete physical unit
~¥26,100
🔧
Flash Pi OS + First Boot Config
Pi OS Imager → Lite 64-bit. Set SSH + WiFi in the Imager gear icon before flashing. First boot ~90s. Then raspi-config for I2C + auto-boot.
sudo apt update && sudo apt upgrade -y sudo apt install -y python3-pip python3-smbus2 \ i2c-tools git espeak chromium-browser pip install obd websockets smbus2 RPi.GPIO \ --break-system-packages sudo i2cdetect -y 1 # verify 0x36 ls /dev/ttyUSB* # verify OBD dongle
← SWIPE TO SCROLL →
🐍
obd_bridge.py — Live OBD2 or SimOBD Fallback
WebSocket server on :8765. Tries ELM327 on startup. If found → real PIDs at 10Hz. If not → SimOBD realistic fake data. Dashboard receives identical JSON regardless of mode.
# PIDs polled: SPEED · RPM · COOLANT_TEMP · THROTTLE_POS FUEL_LEVEL · MAF · O2_SENSORS # WebSocket JSON @ 10Hz: { "speed": 87, "rpm": 3240, "coolant": 88, "fuel": 74, "source": "live" // or "sim" }
← SWIPE TO SCROLL →
2
// PHASE TWO
BLADE RUNNER DASHBOARD — DEPLOY + KIOSK CONFIG
Weeks 2–4 · Software only · Dashboard already built on Surface Pro
○ NEXT
+
// BOOT-TO-DASHBOARD SEQUENCE //
POWER ON UPS HAT 5V applied BOOT (~15s) Linux kernel systemd init OBD SERVICE kitt-obd.service WS :8765 up KIOSK START kitt-display.service Chromium opens DASHBOARD ~20s post-power Amber UI live IGN MONITOR GPIO + I2C watching 0s ~3s ~13s ~16s ~20s ~14s
← SWIPE TO SCROLL →
📐
Tune Dashboard to 800×480
Add custom device in Chrome DevTools (800×480, pixel ratio 1.0) and test there first. When pixel-perfect on Surface Pro, it'll be pixel-perfect on the Pi.
🚀
Two systemd Services: OBD Bridge + Chromium Kiosk
OBD bridge first, display second (3s delay). Both have Restart=always. Kiosk flags hide all browser chrome — pure fullscreen amber UI.
ExecStart=/usr/bin/chromium-browser --kiosk \ --noerrdialogs --disable-infobars \ --no-first-run --hide-scrollbars \ file:///home/pi/kitt/kitt_dashboard.html
← SWIPE TO SCROLL →
DEMO FLEX: Unplug from car, carry to a meet — full Blade Runner amber dashboard on battery, SimOBD dials moving, Joe ready to talk. No CRZ needed. This is the whole point of Phase 0.
3
// PHASE THREE
RETROARCH + GAME LAUNCHER
Weeks 3–5 · Software only
○ QUEUED
+
🎮
RetroArch + Two-Player Keyboard Config
SNES9x, FBA, Genesis GX cores. Write retroarch.cfg on Surface Pro, test there, scp to Pi. Two-player keyboard: WASD = P1, arrows = P2. Set video_fullscreen_x=800, video_fullscreen_y=480.
🚀
Flask Game Launcher — HTTP Bridge from Dashboard
Flask on :8766 receives GET /launch/snes?rom=sf2.sfc and calls subprocess.run() to start RetroArch. On exit (ESC), sends callback to dashboard to switch back to main view.
# Dashboard: GET http://localhost:8766/launch/snes?rom=sf2.sfc subprocess.run([ "retroarch", "-L", "/cores/snes9x_libretro.so", f"/roms/snes/{rom}", "--fullscreen" ])
← SWIPE TO SCROLL →
4
// PHASE FOUR
PICO-8 + WANGAN NIGHT RACER
Ongoing · ¥1,980 one-time · Surface Pro dev, Pi deploy
○ ONGOING
+
🎮
Buy PICO-8 + Game Architecture
¥1,980 at lexaloffle.com. One license covers Surface Pro dev + Pi deploy — same .p8 cart, zero porting. Top-down Wangan night racer: overhead C1 inner loop, 2-player split, amber palette matching KITT aesthetic. OBD integration potential in Phase 5 — real RPM driving the in-game speedometer.
-- Wangan Night Racer v0.1 skeleton function _init() p1={x=64,y=100,spd=0,ang=0} p2={x=70,y=100,spd=0,ang=0} track=load_track("c1_loop") end function _update60() handle_input(p1, btn_set_a) handle_input(p2, btn_set_b) update_physics(p1) update_physics(p2) end function _draw() cls(0) draw_track(track) draw_car(p1, 9) -- 9 = orange/amber draw_car(p2, 12) -- 12 = blue draw_hud() end
← SWIPE TO SCROLL →
BATTERY PLAY: Build the game at home on battery. Take the sled to Daikoku. Two-player arcade cabinet that also shows real engine data. The UPS HAT makes this whole scenario possible without the car present.
5
// PHASE FIVE
JOE — VOICE AI COPILOT + IGNITION SYNC + OBD CONTEXT
Month 2–3 · Most complex · Most satisfying
○ FUTURE
+
// JOE VOICE PIPELINE //
MICROPHONE USB or 3.5mm continuous audio stream VOSK wake word detect offline / local "hey kitt" CONTEXT BUILDER inject live OBD: speed · RPM coolant · fuel + user query → prompt str LLM API OpenAI GPT-4o or local model (llama.cpp) 1–2 sentence response max ESPEAK TTS robotic voice pitch −40 spoken aloud
← SWIPE TO SCROLL →
🎤
Wake Word → Context → API → TTS Pipeline
Vosk runs locally — no internet needed for wake word. "Hey kitt" detected → Whisper transcribes → OBD context injected into system prompt → response in ~1s → espeak speaks it. In battery/home mode SimOBD provides context. Joe doesn't know the difference.
🛣️
Joe's System Prompt — KITT Persona with Live Data
System prompt rebuilt on every query with fresh OBD values. Max 1–2 sentence responses — critical for in-car use. Joe knows Shutoko, Daikoku, C1, Wangan.
SYSTEM_PROMPT = f""" You are KITT, Kris's AI driving copilot in a Honda CR-Z. Live data: speed {speed}km/h · RPM {rpm} coolant {coolant}°C · fuel {fuel}% You know the Shutoko, C1, Daikoku PA, Wangan. Respond in 1–2 sentences max. Be direct and calm. Sound like KITT from Knight Rider. """
← SWIPE TO SCROLL →
Ignition-Synced Shutdown Voice
Phase 0 already wires the shutdown trigger. Phase 5 upgrades from bare espeak to Joe's full voice API — same quality as regular queries. Shutdown line is fully customisable per scenario.
# Default "Engine cut. Saving session. Shutdown in 60s. Good run tonight." # Low battery "Battery critical. All systems shutting down in 30 seconds." # Upgrade to OpenAI TTS for voice quality: resp = openai.audio.speech.create( model="tts-1", voice="onyx", input=text) resp.stream_to_file("/tmp/shutdown.mp3") subprocess.run(["mpg123", "/tmp/shutdown.mp3"])
← SWIPE TO SCROLL →
// TOTAL BUILD COST //
CORE HARDWARE
¥16,800
Pi4 + screen + OBD + SD
◆ POWER ADD-ON
¥9,700
UPS HAT + cells + fuse tap
SOFTWARE
¥1,980
PICO-8 only
FULL BUILD TOTAL
Everything. One time. No subscriptions.
~¥28,480
THE REAL VALUE: For ¥9,700 the Pi becomes a portable Blade Runner kiosk — 8–12 hours anywhere, demo at meets without the CRZ, home dev sessions, ignition-synced on/off with Joe announcing shutdown. One USB-C cable is the only difference between car mode and battery mode.