ESP8266 ADC Detailed Description

Overview

The ADC (Analog-to-Digital Converter) in the ESP8266 allows the microcontroller to read analog signals and convert them into digital values for processing. Essential for interfacing with sensors and analog devices.

Specifications

  • Resolution: 10 bits (0–1023)
  • Input Voltage Range: 0 to 1.0 V (max)
  • Channel: Single channel (ADC0)
  • Reference Voltage: Internal 1.0 V

How It Works

The ADC samples the input voltage on ADC0. The voltage is compared to the internal reference and mapped to a digital value within the 10-bit resolution. The digital value can then be read in code.

Pin Configuration

Accessible via GPIO0 (A0). Connect sensors ensuring voltage does not exceed 1.0 V to protect the ADC.

Reading ADC Values

Example using Arduino IDE:

 
void setup() {
    Serial.begin(115200); // Initialize serial communication
}

void loop() {
    int adcValue = analogRead(A0); // Read ADC value
    float voltage = adcValue * (1.0 / 1023.0); // Convert to 0-1V
    
    Serial.print("ADC Value: ");
    Serial.print(adcValue);
    Serial.print(" | Voltage: ");
    Serial.println(voltage);
    
    delay(1000); // Wait 1 second
}
        

Calibration and Considerations

  • Use a stable power supply and minimize circuit noise.
  • Calibrate ADC for precise measurements.
  • Average multiple readings to improve accuracy.

Conclusion

The ESP8266 ADC is a versatile feature for sensor monitoring and data acquisition. Its integration with the microcontroller makes it a key tool for IoT and embedded applications.

ESP8266 I2C Master Mode Detailed Description

Overview

The I2C (Inter-Integrated Circuit) protocol allows multiple slave devices to communicate with a single master using two wires: SDA and SCL. The ESP8266 can act as an I2C master to control peripherals like sensors and displays.

The ESP8266 does not have hardware I2C, it is entirely software based and does not support slave mode.

Specifications

  • Protocol: I2C
  • Max Clock Speed: 100 kHz (Standard), 400 kHz (Fast)
  • Data Format: 7-bit or 10-bit addressing
  • Pull-up Resistors: Required on SDA and SCL

How It Works

The ESP8266 initiates communication by sending a start condition followed by the slave address, reads or writes data, and ends with a stop condition. The master controls the clock line for synchronized communication.

Pin Configuration

  • SDA: GPIO 4 (D2)
  • SCL: GPIO 5 (D1)

Master Mode Example

Example code using Arduino IDE:

 
#include <Wire.h>

#define SENSOR_ADDRESS 0x50 // Replace with your sensor's I2C address

void setup() {
    Wire.begin(); // Join I2C bus as master
    Serial.begin(115200); // Initialize serial communication
}

void loop() {
    Wire.beginTransmission(SENSOR_ADDRESS); // Start communication
    Wire.write(0x00); // Send command
    Wire.endTransmission(); // End transmission

    delay(100);

    Wire.requestFrom(SENSOR_ADDRESS, 2); // Request 2 bytes
    while (Wire.available()) {
        int data = Wire.read();
        Serial.println(data);
    }

    delay(1000); // Wait 1 second
}
        

Considerations

  • Use pull-up resistors on SDA and SCL to maintain proper levels.
  • Verify device address and commands from datasheet.
  • Ensure bus speed is compatible with all devices.

Conclusion

Operating the ESP8266 as an I2C master enables reliable communication with various peripherals, making it ideal for sensor interfacing and IoT applications.

ESP8266 I2S Interface

The ESP8266 features a basic I2S interface for audio output. It supports transmit (TX) only in master mode. I2S input (RX) is not supported. Commonly used for sending audio to an I2S DAC or amplifier.

GPIO Mapping

  • GPIO3 (RX) – I2S Data Out (DOUT)
  • GPIO0 – I2S Word Select (WS / LRCLK)
  • GPIO2 – I2S Clock (SCK / BCLK)

Example: Generate a 1 kHz Sine Wave (I2S Audio TX)


#include <Arduino.h>
extern "C" {
  #include "i2s_reg.h"
  #include "i2s.h"
}

#define SAMPLE_RATE 44100
#define PI 3.14159265
uint16_t sineWave[256];

void setupI2S() {
  i2s_begin();
  i2s_set_rate(SAMPLE_RATE);
}

void generateSineWave() {
  for (int i = 0; i < 256; i++) {
    sineWave[i] = 0x8000 + 0x7FFF * sin(2 * PI * i / 256);
  }
}

void setup() {
  generateSineWave();
  setupI2S();
}

void loop() {
  for (int i = 0; i < 256; i++) {
    while (!i2s_available()) delayMicroseconds(10);
    i2s_write_sample(sineWave[i]);
  }
}
        

Note: Use the i2s library available in ESP8266 Arduino core. Output is 16-bit mono, typically connected to an I2S DAC or class D amplifier.

Resources: ESP8266Audio, esp8266/Arduino

ESP8266 SPI Detailed Description

The SPI (Serial Peripheral Interface) is a synchronous serial communication protocol used for short-distance communication in embedded systems. The ESP8266 supports SPI in master and slave modes to interface with peripherals such as sensors, displays, and memory devices.

  • Max Clock Speed: Up to 80 MHz
  • Data Format: 8 bits per transmission
  • Supported Modes: Master and Slave
  • Chip Select: GPIO pins control slave devices

Master Mode

In master mode, the ESP8266 initiates communication and controls the clock line (SCK). It reads and writes data to one or multiple slaves and manages data flow effectively.

Pin Configuration

  • MOSI: GPIO 13 (D7)
  • MISO: GPIO 12 (D6)
  • SCK: GPIO 14 (D5)
  • CS: GPIO 15 (D8, configurable)

Master Mode Example


#include <SPI.h>

void setup() {
    SPI.begin(); // Initialize SPI as master
    pinMode(15, OUTPUT); // Set CS pin as output
    digitalWrite(15, HIGH); // Deselect the slave
}

void loop() {
    digitalWrite(15, LOW); // Select the slave
    byte response = SPI.transfer(0x01); // Send a byte and receive response
    digitalWrite(15, HIGH); // Deselect the slave

    Serial.print("Response: ");
    Serial.println(response, HEX); // Print response in hex

    delay(1000); // Wait 1 second
}
        

Slave Mode

In slave mode, the ESP8266 responds to commands from the master device and can send data back. The slave must wait for the master to initiate communication.

Pin Configuration

  • MOSI: GPIO 13 (D7)
  • MISO: GPIO 12 (D6)
  • SCK: GPIO 14 (D5)
  • CS: GPIO 15 (D8, configurable)

Slave Mode Example


#include <SPI.h>

volatile byte dataReceived = 0;

void setup() {
    SPI.begin(); // Initialize SPI
    pinMode(15, INPUT); // CS pin as input
    SPCR |= _BV(SPE); // Enable SPI in slave mode
}

ISR(SPI_STC_vect) {
    dataReceived = SPDR; // Read received data
    SPDR = dataReceived; // Echo back
}

void loop() {
    if (dataReceived) {
        Serial.print("Data received: ");
        Serial.println(dataReceived, HEX); // Print received data
        dataReceived = 0;
    }
}
        

Considerations

  • Ensure proper connection of MOSI, MISO, SCK, and CS lines.
  • Adjust SPI speed according to the connected devices.
  • Pay attention to timing in slave mode to ensure reliable data transfer.

Conclusion

The ESP8266's SPI support in master and slave modes provides flexible, high-speed communication with various peripherals, essential for sensors, displays, and other fast data applications.

Understanding Timers in ESP8266

The ESP8266 features simple hardware timers used for scheduling tasks, handling delays, and generating PWM signals. Efficient use is critical due to limited timer resources.

Types of Timers

  • Software Timers: Implemented in software using interrupts for general timekeeping and regular intervals.
  • Hardware Timer: Single hardware timer for precise delays and time-dependent events.

Timer Registers

  • LOAD_REG: Initial value when timer starts.
  • COUNT_REG: Current timer counter value.
  • ALARM_REG: Time to trigger interrupt.

Timer Modes

  • One-Shot Mode: Counts once, then stops for single events.
  • Periodic Mode: Continuously resets, generating periodic interrupts.

Prescaler & Clock Source

Internal clock divided using a prescaler to control counting frequency, adjusting event timing.

Interrupts & Events

Alarm triggers an interrupt, allowing time-critical tasks to be executed. Limited hardware makes these interrupts essential for precise operations.

Conclusion

ESP8266’s single hardware timer is essential for precise timing. Software timers can extend functionality but rely on interrupts, which may impact performance under heavy load.

1. Frequency Generator

Generate a 1kHz signal by toggling a pin using the hardware timer.


void setup() {
  pinMode(2, OUTPUT);
  timer1_attachInterrupt(togglePin);
  timer1_enable(TIM_DIV1, TIM_EDGE, TIM_LOOP);
  timer1_write(80000000 / (2 * 1000));
}

void togglePin() {
  digitalWrite(2, !digitalRead(2));
}

void loop() {}
        

2. PWM Generator at 25kHz

Generate a 25kHz PWM signal with 50% duty cycle on GPIO5.


void setup() {
  pinMode(5, OUTPUT);
  analogWriteFreq(25000);
  analogWrite(5, 128);
}

void loop() {}
        

3. One-Shot Pulse Generation

Generate a single pulse on a GPIO pin using one-shot timer mode.


void setup() {
  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);
  timer1_attachInterrupt(generatePulse);
  timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE);
  timer1_write(50000);
}

void generatePulse() {
  digitalWrite(4, HIGH);
  delayMicroseconds(100);
  digitalWrite(4, LOW);
}

void loop() {}
        

4. Frequency Measurement

Measure input signal frequency on GPIO12 using interrupts.


volatile unsigned long pulseCount = 0;
unsigned long prevMillis = 0;
unsigned long frequency = 0;

void IRAM_ATTR countPulse() {
  pulseCount++;
}

void setup() {
  pinMode(12, INPUT);
  attachInterrupt(digitalPinToInterrupt(12), countPulse, RISING);
  prevMillis = millis();
}

void loop() {
  if (millis() - prevMillis >= 1000) {
    frequency = pulseCount;
    pulseCount = 0;
    prevMillis = millis();
    Serial.print("Frequency: ");
    Serial.println(frequency);
  }
}
        

5. Timer Interrupt Example

Trigger an interrupt every 5 seconds using the hardware timer.


volatile bool timerFlag = false;

void IRAM_ATTR onTimer() {
  timerFlag = true;
}

void setup() {
  Serial.begin(115200);
  timer1_attachInterrupt(onTimer);
  timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
  timer1_write(5000000);
}

void loop() {
  if (timerFlag) {
    Serial.println("Timer interrupt triggered");
    timerFlag = false;
  }
}
        
ESP RTC (Real-Time Clock) Detailed Description

The ESP8266 microcontroller does not include a hardware Real-Time Clock (RTC). However, ESPConfig by Peter Dunne can provide real-time functionality by using NTP (Network Time Protocol) over Wi-Fi to synchronize time.

While NTP allows the ESP8266 to maintain accurate time when connected to the network, it has limitations: it requires Wi-Fi connectivity and periodic updates, and cannot maintain time during power loss or extended offline periods.

For applications where reliable timekeeping is a system requirement, you have two additional options:

  • External RTC Modules: I²C or SPI RTC modules like DS3231 or PCF8523 provide accurate timekeeping even when the ESP8266 is powered off, often with a backup battery.
  • ESP32 Devices: Many ESP32 variants include an integrated RTC subsystem that supports low-power sleep modes and more accurate internal timing, making them a suitable alternative if hardware RTC is required.
ESP8266 Interrupts Detailed Description

Interrupts are a powerful feature in microcontrollers that allow the processor to respond to events without polling. The ESP8266 supports various types of interrupts that can enhance the responsiveness and efficiency of applications.

External Interrupts

External interrupts can be triggered by changes in the state of a GPIO pin, such as rising or falling edges. The ESP8266 can respond to these changes to perform actions quickly.

Example:

 
#define BUTTON_PIN 4 // GPIO pin for button

void ICACHE_RAM_ATTR handleButtonPress() {
    // Code to execute when button is pressed
}

void setup() {
    pinMode(BUTTON_PIN, INPUT_PULLUP); // Set button pin as input
    attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), handleButtonPress, FALLING);
}

void loop() {
    // Main loop does other tasks
}
      
Serial Interrupts

Serial interrupts can be used to respond to incoming data on the serial interface. This is useful for processing data as it arrives.

Example:

 
volatile bool dataReady = false;

void ICACHE_RAM_ATTR onReceive() {
    dataReady = true; // Flag that data has been received
}

void setup() {
    Serial.begin(115200);
    Serial.setTimeout(100); // Set a timeout for Serial read
    attachInterrupt(digitalPinToInterrupt(0), onReceive, RISING);
}

void loop() {
    if (dataReady) {
        String input = Serial.readString();
        Serial.println("Received: " + input);
        dataReady = false; // Clear the flag
    }
}
      
Timer Interrupts

Timer interrupts allow code to execute at defined intervals, enabling precise timing for tasks such as periodic sensor readings.

Example:

 
volatile bool timerFlag = false;

void IRAM_ATTR onTimer() {
    timerFlag = true; // Set flag for main loop
}

void setup() {
    Timer1.attachInterrupt(onTimer); // Attach interrupt
    Timer1.enable(TIMER1); // Start timer
}

void loop() {
    if (timerFlag) {
        // Execute periodic task
        timerFlag = false; // Reset flag
    }
}
      
SPI Interrupts

SPI interrupts are typically managed through callback functions when using libraries. However, you can still handle events by checking the SPI buffer in a regular loop or using an external interrupt to signal when data is ready.

Example:

 
#define SPI_CS_PIN 15

void ICACHE_RAM_ATTR handleSPI() {
    // Handle SPI data reception
}

void setup() {
    pinMode(SPI_CS_PIN, OUTPUT);
    attachInterrupt(digitalPinToInterrupt(SPI_CS_PIN), handleSPI, FALLING);
}

void loop() {
    // Main loop can perform other tasks
}
      
WiFi Interrupts

WiFi events can trigger interrupts when the ESP8266 connects to a network or receives data. You can use callback functions to handle these events.

Example:

 
void onWiFiEvent(WiFiEvent_t event) {
    switch (event) {
        case SYSTEM_EVENT_STA_START:
            Serial.println("WiFi started");
            break;
        case SYSTEM_EVENT_STA_CONNECTED:
            Serial.println("Connected to WiFi");
            break;
        // Handle other events
    }
}

void setup() {
    WiFi.onEvent(onWiFiEvent); // Attach WiFi event handler
    WiFi.begin("yourSSID", "yourPASSWORD"); // Start WiFi connection
}

void loop() {
    // Main loop can perform other tasks
}
      

The ESP8266 offers versatile interrupt capabilities across various functionalities, enabling efficient and responsive applications. By leveraging these interrupts, developers can create responsive and efficient systems that interact seamlessly with external events.

ESP8266 DMA Support

Unlike some modern microcontrollers, the ESP8266 does not provide true Direct Memory Access (DMA) support. While certain peripherals like UART and SPI have internal FIFOs that can handle small buffers autonomously, these are not full DMA engines. All larger data transfers still require CPU intervention, limiting high-speed or low-latency operations.

Implications:

  • High-speed data transfers for audio, video, or large sensor buffers are CPU-bound.
  • Interrupts or timer-driven routines must be used for precise control.
  • Applications requiring hardware-level DMA, such as zero-CPU PWM resets or peripheral-triggered memory transfers, cannot be achieved on the ESP8266.

Compare with ESP32 DMA capabilities

ESP8266 Configuration using ESPconfig

The ESPconfig library by Peter Dunne simplifies configuration of ESP8266 and ESP32 devices. It supports WiFi setup, OTA updates, and web-based management. The library allows operation in WiFi client, access point, and relay modes.

  • WiFi Client Mode (Connect to WiFi)
  • Access Point (AP) Mode (Configuration Portal)
  • Relay Mode (Extends WiFi coverage)

Source Code: ESPconfig GitHub

Example Code: ESPconfig Setup
 
#include "sysconfig8266.h";

void setup() {
  Serial.begin(115200);
  sysConfig.init();
  Serial.println("Ready.");  
}

void loop() {
  sysConfig.run();
}
        

The ESPconfig library initializes WiFi, OTA, NTP, and optional Bluetooth (ESP32 only). It runs a web-based configuration portal if WiFi credentials are missing or connection fails.

The Admin Page uses Unicode glyphs as icons to reduce overhead.

ESP Config Admin Page screenshot

The Information page shows device overview and details.

ESP 8266 information page screenshot
WiFi Client Mode

// Connect ESP8266 to an existing WiFi network
#include <ESP8266WiFi.h>

const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("Connecting to WiFi...");
  while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); }
  Serial.println("\nWiFi connected.");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
}

void loop() { }
        

Connects ESP8266 to a WiFi network and prints its IP address.

WiFi Station Mode (Access Point)

// ESP8266 as WiFi Access Point with web server
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

const char* ssid = "ESP8266_Access_Point";
const char* password = "12345678";
ESP8266WebServer server(80);

void handleRoot() { server.send(200, "text/plain", "Hello from ESP8266!"); }

void setup() {
  Serial.begin(115200);
  WiFi.softAP(ssid, password);
  Serial.print("Access Point IP: "); Serial.println(WiFi.softAPIP());
  server.on("/", handleRoot);
  server.begin();
  Serial.println("Web server started.");
}

void loop() { server.handleClient(); }
        

ESP8266 creates a WiFi network and runs a basic web server.

WiFi Relay Mode

// ESP8266 as Client and AP simultaneously
#include <ESP8266WiFi.h>

const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";
const char* apSSID = "ESP8266_Relay";
const char* apPassword = "relay_pass";

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); }
  Serial.println("\nConnected to WiFi. IP: "); Serial.println(WiFi.localIP());
  WiFi.softAP(apSSID, apPassword);
  Serial.print("Access Point IP: "); Serial.println(WiFi.softAPIP());
}

void loop() { }
        

Extends WiFi coverage by acting as both client and access point.

ESP8266 Detailed Description

The ESP8266 is a low-cost Wi-Fi microchip with full TCP/IP stack and microcontroller capabilities. It is widely used in IoT applications due to affordability, ease of use, and robust features.

  • Microcontroller: Tensilica L106 Diamond
  • Clock Speed: Up to 80 MHz
  • RAM: 160 KB
  • Flash Memory: 4 MB (varies by module)
  • Wi-Fi Standard: 802.11 b/g/n
  • Operating Voltage: 3.0–3.6 V
  • GPIO Pins: Up to 17 I/O pins
  • Protocols: TCP, UDP, HTTP, FTP, etc.
Features
  • Low Power Consumption: Ideal for battery-operated devices.
  • Integrated Wi-Fi: Built-in Wi-Fi for easy network connection.
  • Programming Flexibility: Supports Arduino IDE, MicroPython, and native SDK.
  • Rich Peripheral Support: I2C, SPI, UART, PWM, ADC interfaces.
Common Applications
  • Home automation systems
  • Wearable technology
  • Smart agriculture
  • Remote sensors
  • IoT prototypes and products
Programming the ESP8266

The ESP8266 can be programmed using the Arduino IDE via a USB-to-serial adapter. Example code to connect to Wi-Fi:


#include <ESP8266WiFi.h>

const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";

void setup() {
    Serial.begin(115200);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("Connecting to WiFi...");
    }
    Serial.println("Connected to WiFi!");
}

void loop() {
    // Your main code
}
        

ESP8266‑01 Pinout

ESP8266‑01 module pinout diagram

Image: Sayan123Wiki / Wikimedia Commons, CC BY-SA 4.0

ESP‑8266 (ESP‑12E / NodeMCU) Pinout

ESP8266 ESP‑12E development board pinout diagram

Image: from GitHub "Googler00tGER / NodeMCU‑ESP12E‑pinouts". Check the repo for license. (GitHub repo)

Conclusion

The ESP8266 is a popular choice in the maker and IoT communities due to its low cost, simplicity, and versatility, suitable for both simple Wi-Fi devices and complex IoT systems.

ESP8266 Variants

Board CPU Speed RAM Flash Memory Peripherals Operating Voltage Other Specifications
ESP8266-01 80 MHz 64 KB 512 KB - 1 MB 2 GPIO, UART, SPI 3.3V Basic Wi-Fi module, minimal GPIO
ESP8266 NodeMCU 80/160 MHz 128 KB 4 MB 11 GPIO, UART, SPI, I2C, ADC, PWM 3.3V Popular development board, Lua-based firmware, USB interface
ESP8266 WeMos D1 Mini 80/160 MHz 128 KB 4 MB 11 GPIO, UART, SPI, I2C, ADC, PWM 3.3V Compact size, Arduino IDE compatible, widely used in IoT projects
ESP8285 ESP-M2 80/160 MHz 64 KB 1 MB 8 GPIO, UART, SPI 3.3V Built-in flash, space-constrained designs
ESP8285 ESP-01F 80/160 MHz 64 KB 1 MB 4 GPIO, UART, SPI 3.3V Miniature form factor, built-in flash
ESP8266 ESP-12E 80/160 MHz 128 KB 4 MB 17 GPIO, UART, SPI, I2C, ADC 3.3V Popular variant for IoT applications
ESP8266 ESP-12F 80/160 MHz 128 KB 4 MB 17 GPIO, UART, SPI, I2C, ADC 3.3V Improved antenna design compared to ESP-12E
ESP8266 Huzzah 80/160 MHz 128 KB 4 MB 9 GPIO, UART, SPI, I2C, ADC 3.3V Adafruit's breadboard-friendly ESP8266 version
ESP (ESP8266) – Legal & Documentation Notice

ESP8266EX® is a trademark of Espressif Systems. Visit Espressif Systems website. Download ESP8266EX Datasheet (PDF).

© 2025 Espressif Systems. All rights reserved.

ESP32 / ESP8266 Boards & Modules

Sources for ESP8266EX and various ESP32 modules (Classic, S2, C3, C6, S3). Ideal for IoT and WiFi/BLE projects.