Back to projects

DriveWire mini EV telemetry platform

A real bench-build in progress: ESP32-S3 motor-control firmware validated on hardware, scheduled distance and electrical telemetry, CAD fixtures, and a protected custom PCB power path taking shape in Altium.

DriveWire bench prototype wired on a chassis in front of firmware code
Current phaseTelemetry scheduling
ControllerESP32-S3
Motor PWM17.5 kHz
ToF range tested~1.3 m
Bench replay · Jul 14 sessionidleBUS 5.73 VCURRENT 2.8 mAPOWER 16 mW
Build state

A system brought up on the bench.

What exists today

DriveWire has moved from parts collection into physical integration. The motor terminals are soldered, both wheels run on the printed test stand, and the firmware now supports forward, reverse, coast, and active braking. A front-mounted VL53L0X reports distance over serial and produced reliable readings to approximately 1.3 m under the tested indoor conditions.

Swap-based debugging isolated a failed motor-driver channel and brought both wheels online using two working channels. A controlled PWM frequency sweep then traced audible motor noise to the carrier frequency, leading to an effectively unnoticeable 17.5 kHz operating point. The V1 sensor module now refreshes electrical and distance telemetry, tracks sensor status, and preserves the last valid value when a poll fails. A FreeRTOS task now performs those refreshes every 1.5 seconds and publishes copied state snapshots to the main loop through a queue. All while the first custom PCB battery power schematic continues in Altium.

Bench test

Debugging video showing the two-driver workaround and both wheels spinning on the printed support stand.

Architecture

One controller, one power path, visible telemetry.

How the system hangs together

An ESP32-S3 sits at the center. Firmware serial commands drive a DRV8833 dual H-bridge, which powers the two DC gear motors. Power flows from the AA pack through a switch and the INA219 current sensor, so the firmware can watch bus voltage, shunt voltage, current, and calculated power while tracking whether the sensor is online.

A VL53L0X time-of-flight sensor is now wired and mounted at the front of the chassis. A 1 Hz serial test measured reliable range to approximately 1.3 m under the tested indoor conditions. The new refresh path rejects invalid measurements without erasing the last valid distance and reports disconnection through shared hardware status. A dedicated sensor task now schedules the combined refresh and sends the latest state snapshot to the main loop through a single-item queue. Reinitialization after a ToF power cycle remains a follow-up.

System diagram

DriveWire system architectureBlock diagram showing the AA battery pack feeding a switch, INA219 current sensor, and DRV8833 H-bridge driving two motors, with an ESP32-S3 controlling PWM, reading I2C telemetry and USB serial commands, plus ToF sensing tested to approximately 1.3 m and a planned Wi-Fi dashboard.POWER PATHAA batterypackSwitchINA219shuntDRV8833H-bridgeMotor LMotor RESP32-S3sensor task + telemetryUSB serialbring-upVL53L0X ToF~1.3 m testedWi-Fi dashboardplannedPWMI2C

17.5 kHz motor control · queued sensor snapshots · fault-aware telemetry

Power design

The custom PCB starts with a protected power path.

Battery entry architecture

The first Altium schematic moves DriveWire toward cleaner vehicle electronics. Battery power enters through a screw terminal and planned 5 A MINI blade fuse before reaching two AOD4185 PMOS stages.

01

Fuse protection limits major short-circuit current at the battery input.

02

A reverse-connected PMOS blocks current if the battery polarity is wrong.

03

A second PMOS carries the load while the 200 mA slide switch only controls its gate bias.

04

ESP32-controlled shutdown is being evaluated before the V1 schematic is frozen.

Battery power schematic

Altium schematic showing the DriveWire battery input fuse, reverse-polarity PMOS, and PMOS-controlled main power switch
Battery input protection and switching · July 20
Engineering stories

Debugging that actually happened.

Fault isolation

The dead motor channel

Symptom

During dual-motor bring-up, one wheel ran cleanly while the other stayed dead.

Hypothesis

The fault could live in the firmware pin mapping, the wiring, or one output channel of the DRV8833 driver itself.

Test

Swapped the driver's inputs and outputs so each suspect carried the other's signal, and watched whether the dead behavior followed the wiring or stayed with the driver output.

Fix

The fault stayed with one driver output. That channel was retired, and the second wheel now runs on the working channel of a backup driver, so both wheels spin.

Learned

Swap-based isolation pins a fault to a single stage quickly, without special equipment. A command truth table then separated the remaining direction-mapping problem from the hardware failure.

Motor terminal wiring with soldered automotive wire and heat shrink
Motor wiring under test
Frequency sweep

Making the motors effectively silent

Symptom

Both motors produced an audible tone during low-duty operation, making the drivetrain sound rough even when it was working correctly.

Hypothesis

The default PWM carrier was exciting the motor windings, housing, or gearbox at a frequency inside the audible range.

Test

Held motor duty constant and swept the PWM carrier from 1 kHz through 18 kHz. The tone rose predictably with frequency, becoming barely audible at 17 kHz and effectively unnoticeable at 17.5 kHz.

Fix

Replaced implicit analogWrite control with explicit ESP32 LEDC channels at 17.5 kHz, while preserving the existing 8-bit 0 to 255 command scale.

Learned

The implementation had to match Arduino-ESP32 core 2.0.17 rather than the newer 3.x API. Hardware testing confirmed the noise source and version-aware firmware made the fix repeatable.

DriveWire chassis wired on the bench in front of firmware code
Drive electronics under firmware test
Test fixture

A test stand instead of a runaway robot

Problem

Bench-testing drive commands with the chassis on a desk was unsafe and unrepeatable: the wheels needed to spin freely without the vehicle going anywhere.

Approach

Modeled a custom support stand in SolidWorks to hold the chassis with the wheels suspended, iterated the support geometry, and printed it in black PLA on a Raise3D E2.

Iteration

A printer error stopped the first print early. The second attempt reached late-stage progress with slight corner lift, noted for brim and bed-temperature tuning.

Result

The finished stand holds the chassis securely with the wheels free to spin. It has been the stable testbench used for every motor debugging session since.

Learned

Test fixtures are part of the engineering. A repeatable bench setup made every debugging pass after it faster and safer.

Finished black PLA DriveWire support stand with engraved front lettering
Final print on the bench
Wireframe render of the custom DriveWire support stand CAD model with engraved lettering
Custom DriveWire support stand · SolidWorks
Roadmap

Speed with direction.

01

Working now

  • 17.5 kHz motor PWM
  • Fault-aware sensor telemetry
  • 1.5 s queued sensor task
02

In progress

  • Sensor reconnection strategy
  • Minimum starting-duty comparison
  • Turn-command mapping correction
03

Next up

  • Obstacle braking logic
  • Complete custom PCB schematic
  • Wi-Fi control interface
04

Later V2

  • Custom PCB layout and bring-up
  • Upgraded battery pack
  • Camera / autonomy
Firmware

Firmware tuned against real hardware.

Current firmware signals

01

Modular left and right motor control through a shared drive state

02

Explicit four-channel ESP32 LEDC setup at 17.5 kHz and 8-bit resolution

03

Forward, reverse, coast, and active brake behavior tested on hardware

04

INA219 voltage, current, and power refresh with online status tracking

05

VL53L0X distance refresh rejects invalid range without erasing the last good value

06

One FreeRTOS task publishes 1.5-second sensor snapshots through a single-item queue

const TickType_t sensorPeriod =
  pdMS_TO_TICKS(1500);

TickType_t lastWakeTime =
  xTaskGetTickCount();

for (;;) {
  refreshAllSensors(*sensorState);
  xQueueOverwrite(sensorQueue, sensorState);

  xTaskDelayUntil(
    &lastWakeTime,
    sensorPeriod
  );
}
Records

The paper trail.

Dated build log16 entries · June 12 to August 13
June 12

Mechanical chassis assembled

Built the 2WD chassis with DC motors, wheels, front caster, and wheel encoder discs to create the rolling test platform.

June 13

ESP32-S3 communication confirmed

Brought up the microcontroller over serial and confirmed the board could communicate cleanly with the development machine.

June 14

Motor driver soldered and direction tested

Soldered the DRV8833 motor driver board, wired an initial powertrain circuit, and confirmed motor forward/reverse behavior from firmware.

June 29

Full bench circuit wired and PWM issue debugged

Soldered motor leads, heat-shrunk joints, mounted the battery pack and breadboard, added current and ToF sensor boards, and solved a low-PWM static-friction issue by raising the duty value to 140.

July 1-3

SolidWorks support stand designed for testing

Modeled a custom DriveWire stand, iterated support geometry, sliced the STL, and started a black PLA print on a Raise3D E2 so the wheels can spin safely during bench tests.

July 6

Support stand print restarted and adhesion issue noted

A printer error stopped the first stand print early, so the job was restarted. The second attempt reached late-stage progress, with slight corner lift noted for future brim, bed-temperature, or first-layer tuning.

July 7

Printed stand became the DriveWire testbench

Picked up the successful black PLA support stand and confirmed the chassis mounts securely and remains stable, creating a safer bench setup for motor debugging and firmware bring-up.

July 8

Motor driver fault isolated and both wheels brought online

Swapped motor driver inputs and outputs to isolate the dead channel, confirmed the fault stayed with one driver output, then used the working channel on a backup driver so both wheels spin. The active bug is now turn-command direction mapping.

July 20

Custom PCB battery power architecture started in Altium

Designed the first battery-entry schematic for the custom DriveWire PCB, including a planned 5 A fuse, AOD4185 PMOS reverse-polarity protection, and a second PMOS so a low-current slide switch can control the main power rail safely.

July 23

VL53L0X ranging tested on the chassis

Wired and mounted the time-of-flight sensor, then wrote a 1 Hz serial-ranging test. Reliable readings reached approximately 1.3 m under the tested indoor conditions, providing a measured starting point for obstacle detection and braking logic.

July 24

Motor-control module and braking behavior validated

Completed the motors.cpp and motors.h module, tested forward drive, reverse, coast, and brake at different speeds, and confirmed that active braking stops the wheels much faster than coasting from full speed.

July 29

PWM frequency sweep eliminated audible motor noise

Swept the carrier from 1 kHz to 18 kHz at constant duty, linked the changing motor tone to PWM-driven vibration, and selected 17.5 kHz as an effectively unnoticeable operating point. Explicit LEDC control preserves the existing 8-bit command scale and matches Arduino-ESP32 core 2.0.17.

July 31

Electrical telemetry module tested with fault injection

Added INA219 voltage, current, and power refresh logic to sensors.cpp, verified healthy serial output, then unplugged the sensor to confirm the module marks it offline and exits on the first failed poll without overwriting the last valid readings.

August 1

V1 sensor refresh pipeline completed and tested

Completed distance and combined-sensor refresh functions, then tested valid range, out-of-range data, and sensor disconnection. Invalid measurements preserve the last good distance while hardware status reports the fault. A direct Wire-based INA219 register read also matched the library voltage result.

August 10

Firmware prepared for task-based operation

Restructured main.cpp for continued serial bring-up and upcoming FreeRTOS work, while organizing the repository with the early Altium PCB files under Hardware and the existing support-stand model under Mechanical CAD.

August 13

First FreeRTOS sensor task verified on hardware

Added one dedicated task that refreshes the INA219 and VL53L0X every 1.5 seconds with xTaskDelayUntil, then overwrites a single-item queue with the latest DriveWireState snapshot. The Arduino loop receives and prints its own copy, and setup stops safely if the queue or task cannot be created. The firmware built successfully and produced live sensor telemetry.

V1 bill of materials8 items in use
01

ESP32-S3 DevKitC-1-N8R8 main controller

02

Pololu DRV8833 dual motor driver under active test

03

2WD robot chassis with wired DC gear motors

04

AA battery pack for motor power during V1 bench tests

05

INA219 current sensor soldered for current and power measurement

06

VL53L0X distance sensor mounted and tested to approximately 1.3 m indoors

07

22 AWG automotive wire, heat shrink, zip ties, and mounted breadboard

08

SolidWorks support stand printed in black PLA for safer debugging

Next

DriveWire is moving.

Both wheels run on the printed stand with forward, reverse, coast, and active braking under modular firmware control. The motor carrier is effectively unnoticeable at 17.5 kHz, and the front-mounted VL53L0X has produced reliable readings to approximately 1.3 m. Electrical and distance refresh functions now preserve valid telemetry through bad polls and report sensor status. One scheduled task now publishes sensor snapshots to the main loop every 1.5 seconds. The immediate work is defining reconnection behavior, correcting turn mapping, comparing minimum starting duty, and turning measured range into obstacle-braking behavior.