Logic Analyzer: See What Really Happens on the Pins
A cheap 8-channel analyzer shows GPIO signals over time. We compare a software square wave made with digitalWrite and hardware PWM, and learn to measure period and duty.
About the project
A multimeter shows the average voltage, and when a signal changes thousands of times a second it is helpless. A logic analyzer records the state of several digital lines over time and draws them as a timing diagram. It is the best way to understand why I2C does not work, how long your delay(1) really takes, or whether PWM is configured correctly.
A popular cheap option is an 8-channel, 24 MHz Saleae clone that works with the free PulseView software (the sigrok project).
What you need
- ESP32 DevKit
- 8-channel / 24 MHz USB logic analyzer
- PulseView
Wiring
| Analyzer channel | ESP32 | What we see |
|---|---|---|
| D0 | GPIO25 | a software square wave |
| D1 | GPIO26 | a slower pattern |
| D2 | GPIO27 | hardware PWM, 1 kHz, 25 % |
| GND | GND | a common ground is mandatory |
Without the GND connection the analyzer shows noise. Cheap analyzer inputs are rated for 0–5 V, so the ESP32's 3.3 V is safe for them.
What the sketch generates
- D0: every pass of
loop()toggles the pin and then callsdelay(1). That gives a square wave with a ~2 ms period, but it "breathes": each pass takes a little longer than 1 ms. - D1: bit 2 of the counter
n, a signal four times slower than D0. - D2: the LEDC hardware produces 1 kHz at 64/256 = 25 % duty. It does not depend on
loop()and stays perfectly steady even while the program is busy with something else.
Code
// Three signals for a logic analyzer
void setup() {
pinMode(25, OUTPUT);
pinMode(26, OUTPUT);
ledcAttach(27, 1000, 8); // hardware PWM: 1 kHz
ledcWrite(27, 64); // 25 % duty
}
void loop() {
static uint8_t n = 0;
digitalWrite(25, !digitalRead(25)); // toggles every ~1 ms → 2 ms period
digitalWrite(26, (n >> 2) & 1); // 4× slower
n++;
delay(1);
}
Reading the diagram
- Period is the time between two rising edges. Frequency = 1 / period.
- Duty is the share of the period the line spends HIGH.
- In PulseView, add a protocol decoder (I2C, UART, SPI, 1-Wire): it labels the bytes right above the signal.
- The sample rate should be at least 4–10 times the signal frequency. 400 kHz I2C needs 4 MHz or more.
Things to try
- Change
delay(1)todelayMicroseconds(100)and watch D0 squeeze together. - Change
ledcWrite(27, 64)to 192: the duty becomes 75 %. - In the simulator, change the "Time window" in the analyzer properties (2 ms … 5 s) to zoom in on the signal or see a long stretch.