← Back to Garden
evergreen ·
esp32 microcontroller iot bluetooth wifi

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

  1. Watchdog Timer: Long blocking operations trigger watchdog reset. Use yield() or delay(1) in loops.

  2. Stack Overflow: Default task stack is small. Increase if using recursion or large local variables.

  3. WiFi + BLE: Using both simultaneously increases power and memory. BLE stack alone uses ~70KB RAM.

  4. String fragmentation: Using Arduino String class can fragment heap. Prefer char[] for embedded.

Resources