Community project

Assistive Vision Smart Glasses

ESP32
Photo of Assistive Vision Smart Glasses
Generated with AI

dune Ai

Published October 31, 2026

These smart glasses combine computer vision, spatial awareness, and audio feedback to assist users with navigation and object detection. Built around an ESP32-S3 microcontroller, the system integrates a 2MP camera for visual input, an 8×8 time-of-flight sensor for precise distance mapping, a 6-axis IMU for head orientation tracking, and audio/haptic feedback channels for non-visual alerts.

This guide provides a complete wiring diagram, full parts list, and step-by-step assembly instructions starting with the power delivery system and progressing through sensor integration and firmware bring-up. Builders will learn how to wire a LiPo charging circuit with protection, connect multiple I2C sensors, configure audio amplification, and implement haptic feedback—all the essentials for a wearable assistive device.

Wiring diagram

Loading diagram…

Gather all the parts

QtyComponent
1

Arducam OV2640 2 MP 20-pin DVP Camera Module

A 3.3 V OV2640 camera module with onboard regulators and an 8-bit parallel digital-video connector.

1

Pololu 3417 VL53L5CX 8×8 ToF Carrier

A regulated 3.3 V logic-compatible breakout that measures distances in an 8 by 8 zone grid.

1

MPU-6050 6-axis IMU IC

A 3.3 V six-axis accelerometer and gyroscope fitted to the main PCB.

1

MAX98357A I2S Class-D Mono Amplifier Breakout

I2S-input Class-D mono audio amplifier IC on a compact breakout board. Accepts I2S digital audio input (BCLK, LRC, DIN) and drives a small speaker or transducer directly. No I2C/SPI control bus is needed. The amplifier supply range is 2.5V-5.5V, and the I2S input pins are compatible with 3.3V logic. SD/MODE controls shutdown and channel selection; GAIN selects 3 dB, 6 dB, 9 dB, 12 dB, or 15 dB gain.

1

2-pin Open-ear 8 Ω 1 W Speaker Connector

A keyed two-pin connector for an 8 ohm open-ear or bone-conduction transducer.

1

3 V Coin Vibration Motor

A small vibration motor that gives tactile alerts.

1

AO3400A Logic-level N-channel MOSFET

A low-side electronic switch that safely turns the vibration motor on and off.

1

SS14 Schottky Flyback Diode

A diode that safely absorbs the motor's turn-off voltage spike.

1

USB-C Receptacle, USB 2.0 Sink

The USB-C connector that provides 5 V charging input and native USB programming data.

1

TI BQ24074RGTR 1-cell LiPo Power-Path Charger

A protected power-path charger that runs the glasses while charging a single-cell LiPo.

1

DW01A + FS8205A 1S LiPo Protection Circuit

A one-cell battery protector that disconnects the cell during overcharge, over-discharge, or overcurrent.

1

JST-GH 3-pin LiPo Battery Connector

A keyed connector for a protected single-cell LiPo with an NTC temperature wire.

1

TI TPS63070RTER 3.3 V Buck-Boost Regulator

A high-current buck-boost regulator that holds the logic supply at 3.3 V as the LiPo discharges.

1

5.1 kΩ USB-C CC1 Resistor

5.1 kΩ

A pull-down resistor that tells a USB-C source this board is a 5 V power sink.

1

5.1 kΩ USB-C CC2 Resistor

5.1 kΩ

A pull-down resistor that tells a USB-C source this board is a 5 V power sink.

1

100 Ω MOSFET Gate Resistor

100 Ω

A resistor that limits the short switching-current spike into the motor MOSFET gate.

1

100 kΩ MOSFET Gate Pulldown

100 kΩ

A resistor that keeps the motor switched off while the ESP32 is starting.

1

1.0 MΩ Battery Divider Top Resistor

1.0 MΩ

The upper resistor in the protected battery-voltage monitor divider.

1

330 kΩ Battery Divider Bottom Resistor

330 kΩ

The lower resistor in the battery monitor divider that keeps the ESP32 ADC input below 3.3 V.

1

TPD2EUSB30 USB ESD Protection Array

A low-capacitance protection part that diverts static electricity from the USB data wires to ground.

1

4.7 kΩ I2C SDA Pull-up

4.7 kΩ

A pull-up resistor that lets the shared sensor data wire return to 3.3 V.

1

4.7 kΩ I2C SCL Pull-up

4.7 kΩ

A pull-up resistor that lets the shared sensor clock wire return to 3.3 V.

Assemble it in 5 steps

1. Build the power section first

Place the USB-C receptacle, BQ24074 charger, battery-protection circuit, TPS63070 regulator, and JST-GH battery connector together at one board end. Keep the charger and regulator capacitor loops as short as their datasheets require; the 3.3 V rail must not touch USB 5 V directly.

  • Put the USB ESD part directly behind the USB-C connector.
  • Use a protected 1-cell LiPo with an NTC lead that matches the charger temperature input.
  • Do not plug in a battery until a meter confirms there is no short from the protected battery positive wire to ground; a shorted LiPo can overheat or catch fire.
  • Do not connect USB 5 V to the 3.3 V rail; doing so can damage every 3.3 V part.

2. Fit the ESP32-S3 and camera connector

Place the ESP32-S3-WROOM-1-N8R8 module so its antenna end faces the board edge and has no copper, battery, connector, or metal directly under or in front of it. Put the 20-pin OV2640 connector close to GPIO4 through GPIO17 and route the eight data wires, PCLK, HREF, VSYNC, and XCLK as one short, equal-style group.

  • Keep a solid ground plane below the camera routing and avoid vias in the pixel-clock route where possible.
  • GPIO35, GPIO36, and GPIO37 belong to the module's PSRAM and must not be routed to connectors.
  • Do not place copper or the LiPo battery in the antenna keep-out area; this can severely reduce wireless range.

3. Connect the distance and motion sensors

Connect the VL53L5CX carrier and the MPU-6050 to the 3.3 V rail and ground. Join their SDA wires on GPIO1 and their SCL wires on GPIO2, then fit only the planned 4.7 kΩ pull-ups on the main PCB. Connect LiDAR INT to GPIO18 and IMU INT to GPIO21; tie MPU-6050 AD0 to ground so it uses address 0x68.

  • Before fitting a sensor breakout with its own pull-ups, check its schematic and remove or disable duplicate pull-ups if the total pull-up resistance would be too low.
  • The Pololu carrier must be powered from 3.3 V in this design because its I2C high level follows VIN; powering it at 5 V can send 5 V logic into the ESP32.

4. Wire audio and haptics

Connect the MAX98357A to 3.3 V and ground, then connect BCLK to GPIO38, LRC to GPIO39, DIN to GPIO40, and SD to GPIO41. Connect the two speaker wires only to SPK+ and SPK-. Feed the motor from 3.3 V and route its negative wire through the AO3400A drain; fit the SS14 across the motor with its striped cathode at motor positive, use the 100 Ω gate resistor from GPIO42, and fit the 100 kΩ gate-to-ground resistor.

  • Keep the motor loop away from the IMU and camera connector because the motor creates electrical noise.
  • Use an 8 ohm, 1 W or higher open-ear transducer.
  • Never connect either MAX98357A speaker terminal to ground; its two output wires both switch and grounding either can damage the amplifier.

5. Add monitoring and bring-up points

Fit the 1.0 MΩ and 330 kΩ battery divider between protected battery positive, GPIO3, and ground. Add labeled pads for VBAT, USB5V, 3V3, GND, SDA, SCL, EN, GPIO0, UART0 TX, and UART0 RX. Fit four mounting holes and inspect every connector label before power-up.

  • Use a high-impedance meter when checking the battery divider; it should be about one quarter of the protected battery voltage at GPIO3.
  • Use a four-layer board with an uninterrupted inner ground plane; separate the buck-boost switching loop from camera and sensor traces.
  • Do not use this prototype as a mobility or medical safety device until it has been independently tested in the intended enclosure and environment.

Review all connections

1. Connections between "camera_ov2640" and "ESP32"

Functioncamera_ov2640ESP32
powerVCC → camera power3V3
groundGND → camera groundGND
i2cSDA → camera SCCB dataGPIO 16
i2cSCL → camera SCCB clockGPIO 17
digitalVSYNC → camera frame syncGPIO 14
digitalHREF → camera line validGPIO 13
digitalPCLK → camera pixel clockGPIO 12
digitalXCLK → camera master clockGPIO 15
dataD0 → camera data bit 0GPIO 4
dataD1 → camera data bit 1GPIO 5
dataD2 → camera data bit 2GPIO 6
dataD3 → camera data bit 3GPIO 7
dataD4 → camera data bit 4GPIO 8
dataD5 → camera data bit 5GPIO 9
dataD6 → camera data bit 6GPIO 10
dataD7 → camera data bit 7GPIO 11

2. Connections between "lidar_vl53l5cx" and "ESP32"

Functionlidar_vl53l5cxESP32
powerVIN → 3.3 V sensor supply3V3
groundGND → sensor groundGND
i2cSDA → shared I2C dataGPIO 1
i2cSCL → shared I2C clockGPIO 2
digitalINT → range-data-ready interruptGPIO 18

3. Connections between "imu_mpu6050" and "ESP32"

Functionimu_mpu6050ESP32
powerVDD → IMU power3V3
groundGND → IMU groundGND
digitalINT → motion interruptGPIO 21
groundAD0 → select I2C address 0x68GND
i2cSDA → Pololu 3417 VL53L5CX 8×8 ToF Carrier SDAEXT
i2cSCL → Pololu 3417 VL53L5CX 8×8 ToF Carrier SCLEXT

4. Connections between "amp_max98357a" and "ESP32"

Functionamp_max98357aESP32
powerVIN → amplifier power3V3
groundGND → amplifier groundGND
dataBCLK → I2S bit clockGPIO 38
dataLRC → I2S word-select clockGPIO 39
dataDIN → I2S audio dataGPIO 40
digitalSD → audio amplifier enableGPIO 41
dataSPK+ → 2-pin Open-ear 8 Ω 1 W Speaker Connector SPK+EXT
dataSPK- → 2-pin Open-ear 8 Ω 1 W Speaker Connector SPK-EXT

5. Connections between "motor" and "ESP32"

FunctionmotorESP32
powerM+ → motor supply3V3
digitalM- → AO3400A Logic-level N-channel MOSFET DEXT

6. Connections between "motor_mosfet" and "ESP32"

Functionmotor_mosfetESP32
digitalG → 100 Ω MOSFET Gate Resistor 2EXT
groundS → motor switch groundGND

7. Connections between "flyback_diode" and "ESP32"

Functionflyback_diodeESP32
digitalK → 3 V Coin Vibration Motor M+EXT
digitalA → AO3400A Logic-level N-channel MOSFET DEXT

8. Connections between "usb_c" and "ESP32"

Functionusb_cESP32
powerVBUS → TI BQ24074RGTR 1-cell LiPo Power-Path Charger INEXT
groundGND → USB groundGND
groundCC1 → 5.1 kΩ USB-C CC1 Resistor 1EXT
groundCC2 → 5.1 kΩ USB-C CC2 Resistor 1EXT

9. Connections between "usb_esd" and "ESP32"

Functionusb_esdESP32
groundGND → ESD returnGND
dataD+ → USB-C Receptacle, USB 2.0 Sink D+EXT
dataD- → USB-C Receptacle, USB 2.0 Sink D-EXT

10. Connections between "r_cc1" and "ESP32"

Functionr_cc1ESP32
ground2 → CC1 pull-downGND

11. Connections between "r_cc2" and "ESP32"

Functionr_cc2ESP32
ground2 → CC2 pull-downGND

12. Connections between "charger_bq24074" and "ESP32"

Functioncharger_bq24074ESP32
powerOUT → TI TPS63070RTER 3.3 V Buck-Boost Regulator VINEXT
powerBAT → DW01A + FS8205A 1S LiPo Protection Circuit P+EXT
analogTS → JST-GH 3-pin LiPo Battery Connector NTCEXT
groundGND → charger groundGND

13. Connections between "battery_jst" and "ESP32"

Functionbattery_jstESP32
powerBAT+ → DW01A + FS8205A 1S LiPo Protection Circuit B+EXT
groundBAT- → DW01A + FS8205A 1S LiPo Protection Circuit B-EXT

14. Connections between "battery_protection" and "ESP32"

Functionbattery_protectionESP32
groundP- → protected battery negativeGND

15. Connections between "reg_tps63070" and "ESP32"

Functionreg_tps63070ESP32
powerVOUT → regulated logic rail3V3
groundGND → regulator groundGND

16. Connections between "r_gate" and "ESP32"

Functionr_gateESP32
digital1 → motor control outputGPIO 42

17. Connections between "r_gate_pd" and "ESP32"

Functionr_gate_pdESP32
digital1 → AO3400A Logic-level N-channel MOSFET GEXT
ground2 → gate pulldown groundGND

18. Connections between "r_bat_top" and "ESP32"

Functionr_bat_topESP32
analog1 → DW01A + FS8205A 1S LiPo Protection Circuit P+EXT
analog2 → battery ADC divider nodeGPIO 3

19. Connections between "r_bat_bottom" and "ESP32"

Functionr_bat_bottomESP32
ground2 → divider groundGND
analog1 → 1.0 MΩ Battery Divider Top Resistor 2EXT

20. Connections between "r_i2c_sda" and "ESP32"

Functionr_i2c_sdaESP32
power2 → I2C pull-up supply3V3
i2c1 → Pololu 3417 VL53L5CX 8×8 ToF Carrier SDAEXT

21. Connections between "r_i2c_scl" and "ESP32"

Functionr_i2c_sclESP32
power2 → I2C pull-up supply3V3
i2c1 → Pololu 3417 VL53L5CX 8×8 ToF Carrier SCLEXT

Deploy the firmware

#include <Arduino.h>
#include <Wire.h>

constexpr int I2C_SDA_PIN = 1;
constexpr int I2C_SCL_PIN = 2;
constexpr int LIDAR_INT_PIN = 18;
constexpr int IMU_INT_PIN = 21;
constexpr int BATTERY_ADC_PIN = 3;
constexpr int AMP_SD_PIN = 41;
constexpr int MOTOR_PIN = 42;

uint32_t lastReportMs = 0;

void setup() {
  Serial.begin(115200);
  delay(200);

  pinMode(AMP_SD_PIN, OUTPUT);
  digitalWrite(AMP_SD_PIN, LOW);  // Keep the speaker quiet during board bring-up.
  pinMode(MOTOR_PIN, OUTPUT);
  digitalWrite(MOTOR_PIN, LOW);   // Keep the motor off during board bring-up.

  pinMode(LIDAR_INT_PIN, INPUT);
  pinMode(IMU_INT_PIN, INPUT);
  analogReadResolution(12);
  Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN, 400000);

  Serial.println("DUNE VISION Ω hardware bring-up");
}

void loop() {
  const uint32_t now = millis();
  if (now - lastReportMs >= 1000) {
    lastReportMs = now;
    const uint16_t rawBattery = analogRead(BATTERY_ADC_PIN);
    const float adcVoltage = (3.3f * rawBattery) / 4095.0f;
    const float batteryVoltage = adcVoltage * ((1000000.0f + 330000.0f) / 330000.0f);

    Serial.print("Battery divider estimate: ");
    Serial.print(batteryVoltage, 2);
    Serial.println(" V");
  }
  delay(10);
}

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace, diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik