# ForgeYantra ESP32 Controller v2 This is a reference controller and firmware for the original ESP32-WROOM board with a TB6612FNG motor-driver adapter. Software compilation and simulation do not validate an assembled car. Complete the hardware checks below before enabling motor output. This is not drop-in firmware for an Arduino/HC-05 car, a different driver, or every ESP32 variant. ## Build and upload 1. Install Arduino IDE and Espressif's Arduino-ESP32 board package **3.3.1**. Select **ESP32 Dev Module**, 4 MB flash and **Huge APP (3MB No OTA/1MB SPIFFS)** partition scheme. The equivalent CLI target is `esp32:esp32:esp32:PartitionScheme=huge_app`. 2. Open `forgeyantra_controller/forgeyantra_controller.ino`. Keep the accompanying `.h` files in that same folder. No separate Arduino libraries are required. 3. Start with motor power and external 5V disconnected before connecting USB. Upload the stock firmware over USB. It serves the controller and checks connectivity, but its motor GPIOs are not configured or energized because `FY_MOTOR_SETUP_CONFIRMED` defaults to `0`. 4. Open Serial Monitor at **115200 baud**. It displays a per-device Wi-Fi password and six-digit pairing/control PIN. These are generated once and retained on the device. Record them privately for the kit owner. Do not publish them on the website or in a public repository. Erasing all flash also erases these credentials. 5. Confirm the hardware checklist and choose `FY_WIRING_PROFILE=1` or `2` using the table below. Only then set `FY_MOTOR_SETUP_CONFIRMED` to `1` in `motor_config.h`, rebuild and upload. The default profile `0` refuses motor-enabled compilation. LED setup has a separate `FY_LED_SETUP_CONFIRMED` flag; set it to `1` only after checking both LED branches. LEDs can be tested with motor setup still locked. The reference adapter has a 50% PWM ceiling for initial lifted-wheel testing; a percentage is not a measured wheel speed. ## Hardware checklist (builder confirmation required) - Check that this is an original ESP32-WROOM board and that the GPIO assignments below match the actual harness. This map is an example, not the finalized sports-car circuit. GPIO16/17 may be reserved on other boards. - Choose the matching pin map below. Check left/right and motor polarity with wheels lifted. Adjust reverse flags if needed. Do not transfer an old motor-enabled configuration into v2 without selecting and checking the wiring profile. - Use an appropriate motor driver and regulated supplies for the **actual** motors. Verify the combined stall current for every motor sharing a channel. Do not assume one TB6612FNG safely supports four parallel motors. - Do not connect the battery pack directly to ESP32 GPIOs or assume a motor's rated voltage matches the battery. Validate logic voltage, motor supply, regulator, common ground, protection and decoupling with the actual parts. - Hold TB6612 STBY low with an external pull-down (for example 10 kΩ) so the driver stays disabled while the ESP32 resets or boots. Provide an accessible physical motor-power switch. Software Stop cannot protect against every hardware fault. ## Wiring profiles and LEDs The motor pin schedule in **ForgeYantra-4WD-Circuit-Diagram.pdf (13 September 2026)** differs from the original Controller v1 reference. Do not mix these maps. Both remain conditional on actual wiring and current validation. | Signal | Profile 1: original v1 reference | Profile 2: 13 Sep circuit | | --- | --- | --- | | AIN1 / AIN2 / PWMA | 26 / 27 / 25 | 25 / 26 / 27 | | BIN1 / BIN2 / PWMB | 16 / 17 / 14 | 32 / 33 / 14 | | STBY | 33 | 13 | | LED1 / LED2 | 18 / 19 | 18 / 19 | Each LED needs its **own** branch: GPIO18 or GPIO19 → 220 Ω resistor → red LED anode; cathode → common GND. Use the specified small indicator LEDs, not a strip or high-power lamp. Mount LED1 on the left and LED2 on the right for indicator modes. GPIO labels are not physical pin positions. The latest circuit uses a protected 3S pack, a regulated 5V logic supply and a **separate adequately rated motor regulator**. A 50% software PWM ceiling does not make a 12.6V supply suitable for 3–6V motors. Follow the circuit's current, protection, regulator and charger checks before replication. LED outputs use independent PWM channels 8/9 at 2kHz, 8-bit resolution. Motor PWM stays at 20kHz. The firmware refuses overlapping motor/LED pins; an LED channel setup failure leaves LEDs unavailable. ## Bluetooth Open https://www.forgeyantra.in/controller in a browser with Web Bluetooth, for example Chrome on Android. Tap **Connect Bluetooth** and choose your ForgeYantra device. Bluetooth uses authenticated encrypted pairing. If your phone asks for a pairing code, use the six-digit PIN shown by the kit. Enter that PIN in the controller to enable controls. If only LED wiring is confirmed, the page offers **Enable lights**, while driving stays locked. Browser support varies. A paired device does not imply the page can drive it. The page checks the ForgeYantra service, characteristic and protocol before enabling controls. It does not transmit old F/B/L/R/S sketches' commands to unrelated devices. Use local Wi-Fi if your browser does not support Web Bluetooth. A browser cannot configure the phone's Wi-Fi automatically. ## Local Wi-Fi Join the kit's `ForgeYantra-...` Wi-Fi using its setup password. Stay connected if the phone reports no internet. Open **http://192.168.4.1/** directly in the browser. The ESP32 serves all HTML, CSS and JavaScript locally, including when the internet is unavailable. This is a separate local page; the HTTPS storefront does not proxy or send mixed-content requests to the car. Tap **Connect Wi-Fi car**, enter the kit PIN and enable controls. The access point allows one Wi-Fi station. Successful arming creates a random control-session token; command endpoints require it and reject cross-origin requests. Switching between Bluetooth and Wi-Fi requires stopping and releasing the existing controller first. An idle abandoned session expires after 15 seconds. ## Controls and fail-safe behavior - Hold a direction to move; release to stop. Left/right are differential turns with one side stopped. - Reverse-left/right and pivot-left/right are available on v2. Hold Q/E for reverse turns and Z/C for pivots when the controller has focus. Pivoting reverses one motor pair; validate its current and direction on raised wheels. - Speed presets are 20%, 40% and 60%; the slider remains available. These are command percentages, not measured speed. - Speed changes stop movement; hold a direction again to continue at the new setting. - **STOP**, Space or Escape disarms the controller. Re-enable with the kit PIN before moving again. - Pointer cancellation, loss of page focus, hiding the page and leaving the page stop and lock the browser controls. A disconnect clears ownership on Bluetooth. - The browser keeps only the newest command and discards pending movement after release. It never queues a backlog of drive commands or resumes movement automatically after reconnecting. - A firmware task independent of HTTP request handling checks motor commands every 10 ms. Missing movement commands for 500 ms disarms and requests zero output. A 100 ms neutral interval is imposed before reversing direction. These timings still require measurement on real hardware; they are not a certified emergency-stop system. - Practice mode has no hardware connection and is explicitly labeled. No battery percentage, physical speed or sensor measurement is invented. ## Light controls Choose a mode and brightness, then **Apply lights**. The page first requests and acknowledges a motor stop, then sends the light command. Hold a direction again if you want to continue driving. There is no automatic restart. | Mode | Output | | --- | --- | | All off | Both LEDs off | | Both LEDs on | Both at the chosen brightness | | Left / LED1 or Right / LED2 | Only that LED on | | Left or right indicator | Chosen side flashes: 350ms on / 350ms off | | Hazard flash | Both flash together at the same interval | | Automatic lights | Both run at one-quarter of chosen brightness; the turning side flashes; releasing a moving direction brightens both for 800ms | Automatic brake lights are derived from drive/release commands; there is **no brake or speed sensor**. They do not physically brake the motors. Stop, disconnection, invalid owned commands and timeouts turn both LEDs off. LED modes require an authenticated control session and do not persist across re-arming or power cycles. Idle heartbeats keep an active session; missing them for 15 seconds locks all outputs. Light commands do not extend the movement watchdog and defensively stop motor output. Practice mode sends no hardware commands. An acknowledgement means the firmware accepted a light setting; it is not an optical measurement. Horn/buzzer, RGB colours, obstacle avoidance and battery voltage are not implemented because the corresponding hardware is not in the confirmed circuit. ## Upgrade compatibility The website supports both v1 and v2. It reads v2 capabilities before enabling added features. Original v1 kits retain F/B/L/R driving, speed and Stop; new movement and LED commands are never sent to v1. The original v1 setup ZIP remains available, unchanged, for recovery. Upgrade the ESP32 over USB to use the new features; deploying the website does not flash customers' cars. The v2 capability response reports which output setup checks succeeded. It cannot inspect physical wiring. Keep the default flags at 0 until the builder checks the actual circuit. The control PIN and Wi-Fi password remain in the same device storage namespace during a normal firmware upgrade. ## Lifted-wheel acceptance test 1. Confirm motor output stays off during boot, unconfirmed setup, wrong PIN and before arming. 2. At low speed, verify each direction and release-to-stop with wheels clear of people and objects. 3. While moving, release outside the button, press Stop, switch tabs, lock the phone, disconnect Bluetooth and move out of Wi-Fi range. Confirm stop and no automatic restart in every case. 4. Deliberately interrupt commands and measure stop latency. Confirm that delayed HTTP requests cannot block the firmware watchdog. Test direction reversal and combined motor load using appropriate current-limited equipment. 5. Try a second connection; it must not take ownership while the first transport owns the car. Verify invalid commands, invalid PINs and reconnects cannot restart motors. 6. With motors disconnected, check each LED, brightness, both indicators, hazards and automatic output. Confirm Stop, idle timeout, connection loss and re-arming leave lights off. Then verify auto indicators and the release light during raised-wheel movement. 7. Test v1 compatibility, v2 motor-only and v2 LED-only configurations. A pending light command must not execute after Stop or disconnect. 8. Repeat on the customer devices/browsers you intend to support before advertising compatibility or shipping pre-flashed kits. ## Protocol (developer reference) Service UUID: `f0a10001-7a9e-4a21-9d00-464f52474559` Command characteristic (acknowledged write): `f0a10002-7a9e-4a21-9d00-464f52474559` Status characteristic (read + notify): `f0a10003-7a9e-4a21-9d00-464f52474559` Capabilities characteristic (read): `f0a10004-7a9e-4a21-9d00-464f52474559`. It returns JSON such as `{"v":2,"drive":true,"lights":true}`. Wi-Fi includes the same object as `capabilities` in `/api/hello`. Missing capability data denotes legacy v1; malformed/unknown capability versions are rejected. Status responses retain the `FY1:` prefix for protocol compatibility. ASCII commands, at most 20 bytes, no terminator: `A:123456` (example PIN, not a default credential), `D:F:30`, `D:B:30`, `D:L:30`, `D:R:30`, plus v2 `D:Q:30` (reverse left), `D:E:30` (reverse right), `D:Z:30` (pivot left), `D:C:30` (pivot right), `S` (stop movement), `X` (stop and disarm), `H` (status/idle heartbeat). Responses start with `FY1:` and one of `LOCKED`, `ARMED`, `SETUP`, `BUSY`, `BADPIN`, `LOCKOUT`, `TIMEOUT`, `ERROR`. Light command: `L::<0–100>`, with modes `O` (off), `N` (both), `1`, `2`, `L`, `R`, `H` (hazards), `A` (automatic). Example `L:H:50`. Only the current owner with confirmed LED setup may use these. The controller UI offers brightness from 10% to 100%, and All off separately. Wi-Fi uses POST `/api/hello`, `/api/arm`, `/api/command`, `Content-Type: text/plain` and `X-FY-Controller: 1`. `/api/arm` returns a random `session` on success; commands require `X-FY-Session`. Session credentials never go to Railway, analytics or localStorage. No CORS permission is provided to external sites. ## Regeneration and source references `python3 review/build-controller-pack.py` regenerates the embedded Wi-Fi page and downloadable ZIP from the same frontend JavaScript and CSS. Do not hand-edit `web_ui.h` or the ZIP. - https://developer.chrome.com/docs/capabilities/bluetooth - https://docs.espressif.com/projects/arduino-esp32/en/latest/api/wifi.html - https://docs.espressif.com/projects/arduino-esp32/en/latest/api/ledc.html - https://github.com/espressif/arduino-esp32/tree/3.3.1/libraries/BLE The firmware does not affect store checkout, customer data, Railway variables or product pricing.