Hardware Requirements
- ESP32 Development Board (ESP32-WROOM-32 recommended)
- VL53L0X ToF Laser Sensor (I2C interface)
- RGB LED (Common Anode) for visual feedback
- Resistors: 3x 220Ω (for LED current limiting)
- Jumper Wires and breadboard
- Micro USB Cable for programming
Wiring Diagram
| Component | ESP32 Pin | Notes |
|---|---|---|
| VL53L0X SDA | GPIO 21 | I2C Data |
| VL53L0X SCL | GPIO 22 | I2C Clock |
| VL53L0X VIN | 3.3V | Power |
| VL53L0X GND | GND | Ground |
| LED Red | GPIO 13 | Via 220Ω resistor |
| LED Green | GPIO 12 | Via 220Ω resistor |
| LED Blue | GPIO 14 | Via 220Ω resistor |
| LED Common | 3.3V | Common Anode |
Setup Development Environment
Option 1: Arduino IDE (Recommended for Beginners)
Install Arduino IDE
Download from arduino.cc
- Version 2.0+ recommended
Add ESP32 Board Support
- Open File → Preferences
- Add to Additional Board Manager URLs:
- Go to Tools → Board → Board Manager
- Search for “esp32” and install esp32 by Espressif Systems
Install Required Libraries
Go to Sketch → Include Library → Manage Libraries and install:
- Adafruit VL53L0X (by Adafruit)
- ArduinoJson (by Benoit Blanchon) - Version 6.x
- Adafruit BusIO
- Adafruit Unified Sensor
Option 2: PlatformIO (Advanced Users)
Install PlatformIO
- VS Code Extension: Search for “PlatformIO IDE” in Extensions
- Standalone: platformio.org
Configure Firmware
1. Create Secrets File
Copy the example secrets template:2. Edit Configuration
Openarduino_secrets.h and configure:
arduino_secrets.h
Configuration Parameters
| Parameter | Description | Example |
|---|---|---|
SECRET_SSID | WiFi network name | "ParkingLot_WiFi" |
SECRET_PASS | WiFi password | "SecurePass123" |
SECRET_GCP_URL_INGEST | Cloud Run ingest endpoint | https://ingest-[hash].run.app |
SECRET_GCP_URL_GET | Cloud Run status endpoint | https://get-status-[hash].run.app |
SECRET_SPOT_ID | Unique spot identifier | "A-01", "B-12", etc. |
Spot ID Naming Convention: Use format
[ZONE]-[NUMBER] (e.g., A-01, B-12, VIPA-03). This must match the spot IDs created in the dashboard.3. Calibrate Sensor Threshold
The default detection threshold is 400mm (line 78 inS-Parking.ino):
- Ceiling-mounted (2.5m): 400-500mm
- Pole-mounted (1.5m): 300-400mm
- Ground-level test: 200-300mm
Upload Firmware
Connect ESP32
- Plug ESP32 into computer via USB
- Install drivers if needed: silabs.com/developers/usb-to-uart-bridge-vcp-drivers
Select Port
Arduino IDE: Tools → Port → Select COM port (Windows) or /dev/ttyUSB0 (Linux)PlatformIO: Auto-detects port
Firmware Behavior
The S-Parking firmware implements intelligent self-healing logic:Polling Intervals
- Sensor reading: 500ms (fast response to vehicle arrival/departure)
- Cloud sync: 15s (periodic validation of reservation status)
LED Status Indicators
| LED Color | Status | Description |
|---|---|---|
| 🟢 Green | Available | No vehicle, no reservation |
| 🟡 Amber (Red+Green) | Reserved | No vehicle, but reserved in system |
| 🔴 Red | Occupied | Vehicle detected (priority over reservation) |
Self-Healing Logic
The firmware auto-corrects desynchronization (lines 120-136): Scenario A: Sensor shows Available (Green), Cloud shows Occupied- Cause: Network packet loss when vehicle departed
- Action: Force-send “Available” status to cloud
- Cause: Network packet loss when vehicle arrived
- Action: Force-send “Occupied” status to cloud
The physical sensor reading always takes priority over cloud state. This ensures visual LED feedback is accurate for drivers on-site.
Test Firmware
1. Verify WiFi Connection
Serial Monitor output should show:2. Test Sensor Detection
Place an object (or hand) under the sensor:3. Verify Cloud Sync
Every 15 seconds:4. Check Dashboard
Open S-Parking web dashboard and verify:- Spot appears with correct ID
- Status updates in real-time (under 2s latency)
- LED color matches dashboard indicator
Troubleshooting
Issue: “Error al iniciar VL53L0X”
Cause: Sensor not detected on I2C bus Solution:- Verify wiring (SDA → GPIO 21, SCL → GPIO 22)
- Check sensor power (3.3V, not 5V!)
- Test I2C scanner:
Issue: “Fallo al conectar WiFi. Reiniciando…”
Cause: Incorrect SSID/password or weak signal Solution:- Verify credentials in
arduino_secrets.h - Move ESP32 closer to router during testing
- Check WiFi is 2.4GHz (ESP32 doesn’t support 5GHz)
Issue: HTTP Response Code 404/500
Cause: Incorrect Cloud Run URL or service not deployed Solution:Issue: LED not lighting up
Cause: Incorrect LED type (Common Cathode vs. Common Anode) Solution: Invert logic insetColor() function:
Issue: Sensor reads 8190mm constantly
Cause: VL53L0X out of range or measurement error Solution:- Check
measure.RangeStatus(should be 0 for valid reading) - Ensure target is within 0-1200mm range
- Adjust sensor angle (perpendicular to ground)
Issue: High latency (>5s) in status updates
Cause: Network congestion or Cloud Run cold start Solution:- Reduce
cloudPollIntervalto 10000ms for critical spots - Set Cloud Run minimum instances to 1:
Production Deployment Tips
Unique Spot IDs
Use a consistent naming scheme:
A-01toA-20(Zone A)B-01toB-15(Zone B)VIP-01toVIP-05(VIP section)
Weatherproofing
For outdoor installations:
- IP65-rated enclosures
- Silicone seal around sensor
- Waterproof USB connectors
Firmware Update Over-The-Air (Future)
S-Parking roadmap includes OTA updates via ESP32’s built-in OTA capabilities:Next Steps
Environment Configuration
Manage secrets and API endpoints across all system components
Deploy Cloud Run
Set up backend services for IoT data ingestion
Firebase Hosting
Deploy the web dashboard to production