ESP32 Basics
The ESP32 is a low-cost microcontroller with integrated WiFi and Bluetooth, made by Espressif Systems. It's the heart of this telemetry project.
Key Specifications
| Spec | Value |
|---|---|
| CPU | Dual-core Xtensa LX6, up to 240 MHz |
| RAM | 520 KB SRAM |
| Flash | 4 MB (typical) |
| WiFi | 802.11 b/g/n, 2.4 GHz |
| Bluetooth | BLE 4.2 and Classic |
| GPIO | 34 pins |
| ADC | 12-bit, 18 channels |
| Operating Voltage | 3.3V |
Power Consumption
This is important for car applications where the ESP32 runs on OBD port power (12V stepped down).
| Mode | Current Draw | Notes |
|---|---|---|
| Active (WiFi + BLE) | 160-260 mA | During driving, full operation |
| WiFi only | 80-120 mA | If BLE disabled after connection |
| Modem sleep | 20 mA | WiFi connected, CPU idle |
| Light sleep | 0.8 mA | Wake on interrupt/timer |
| Deep sleep | 10 µA | Only RTC running |
| Hibernation | 2.5 µA | Minimal, wake on RTC/external |
Power Modes Explained
Active Mode: CPU running, radios active. Use this while driving.
Modem Sleep: WiFi maintains connection but radio sleeps between beacons. Good for reducing power while staying connected.
Light Sleep: CPU paused, RAM retained. Can wake on GPIO/timer. Good between transmissions.
Deep Sleep: Only RTC memory preserved (8KB). Everything else powered off. Wake on timer or external signal. Good when car is parked.
In Our Project
While driving: ~200mA at 3.3V = 0.66W Car OBD provides 12V, so with a buck converter: 0.66W / 12V = 55mA from car
This is negligible - car alternator produces 50-150A.
Dual-Core Architecture
ESP32 has two CPU cores:
- Core 0 (PRO_CPU): Usually handles WiFi/BLE stack
- Core 1 (APP_CPU): User application code
The Arduino framework runs your code on Core 1 by default. You can pin tasks to specific cores:
xTaskCreatePinnedToCore(
taskFunction, // Function
"TaskName", // Name
10000, // Stack size
NULL, // Parameters
1, // Priority
NULL, // Task handle
0 // Core (0 or 1)
);
Memory Layout
┌─────────────────────────────┐
│ Flash (4MB) │
│ ├── Bootloader │
│ ├── Partition table │
│ ├── Application (your code)│
│ └── SPIFFS/LittleFS (files)│
├─────────────────────────────┤
│ SRAM (520KB) │
│ ├── .data (globals) │
│ ├── .bss (zero-init) │
│ ├── Heap (malloc) │
│ └── Stack │
├─────────────────────────────┤
│ RTC Memory (8KB) │
│ └── Survives deep sleep │
└─────────────────────────────┘
BLE on ESP32
The ESP32's BLE stack is based on the Bluedroid stack (or NimBLE as alternative).
Key concepts:
- GATT: Generic Attribute Profile - how data is structured
- Service: A collection of characteristics (like a class)
- Characteristic: A data point (like a property)
- UUID: Unique identifier for services/characteristics
In our project, the ELM327 adapter exposes:
- Service UUID:
0000fff0-0000-1000-8000-00805f9b34fb - TX Characteristic:
0000fff2-...(we write commands here) - RX Characteristic:
0000fff1-...(we receive responses here)
WiFi on ESP32
#include <WiFi.h>
void setup() {
WiFi.begin("SSID", "password");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
Serial.println(WiFi.localIP());
}
The ESP32 supports:
- Station mode (connect to AP)
- Access Point mode (be an AP)
- Both simultaneously
Arduino vs ESP-IDF
| Aspect | Arduino | ESP-IDF |
|---|---|---|
| Learning curve | Easy | Steep |
| Abstraction | High | Low |
| Control | Limited | Full |
| Performance | Good | Optimal |
| Libraries | Many | Fewer |
We use Arduino framework for simplicity. ESP-IDF is Espressif's official SDK with FreeRTOS.
Common Pitfalls
-
Watchdog Timer: Long blocking operations trigger watchdog reset. Use
yield()ordelay(1)in loops. -
Stack Overflow: Default task stack is small. Increase if using recursion or large local variables.
-
WiFi + BLE: Using both simultaneously increases power and memory. BLE stack alone uses ~70KB RAM.
-
String fragmentation: Using Arduino
Stringclass can fragment heap. Preferchar[]for embedded.