Recently, when I started to research the topic of Logic Analyzers, I found the incredible PulseView Project. However, I did not want to invest in additional hardware but just use one of my favorite microprocessors (ESP32, Raspberry Pico) as capturing device.

There are quite a few logic analyzer projects with a similar goal:

However all of them are geared for one specific architecture and therefore are not portable.

I wanted to come up with a better design and provide a basic C++ Library that implements the SUMP protocol and clearly separates the generic functionality from the processor specific in order to support an easy rollout to new architectures: The only common precondition is the Arduino API.

I am currently supporting

  • AVR Processors
  • ESP32
  • ESP8266
  • Raspberry Pico

The Arduino Sketch

The basic Arduino Sketch for the logic-analyzer is quite simple. We just need to call the begin method on a LogicAnalyzer object and add the command handler in the loop(). The provided implementation just uses the default values which are defined in the config:

#include "Arduino.h"
#include "logic_analyzer.h"

using namespace logic_analyzer;  

int pinStart=START_PIN;
int numberOfPins=PIN_COUNT;
LogicAnalyzer logicAnalyzer;

void setup() {
    logicAnalyzer.begin(Serial, &capture, MAX_CAPTURE_SIZE, pinStart, numberOfPins);

void loop() {
    if (Serial) logicAnalyzer.processCommand();


You can actvate the logging by assigning a Stream to the LogicAnalyzer object by calling logicAnalyzer.setLogger():

// setup logger
Serial1.begin(115200, SERIAL_8N1, 16, 17);

Adding Additional Functionality

An easy way to extend the functionality is by adding an event handler. The following acts on a status change event by activating the LED dependent on the actual status:

// Use Event handler to control the LED
void onEvent(Event event) {
    if (event == STATUS) {
        switch (logicAnalyzer.status()) {
            case ARMED:
                digitalWrite(LED_BUILTIN, LOW);
            case STOPPED:
                digitalWrite(LED_BUILTIN, LOW);

and we can just activate it by calling:


Custom Capturing

I am providing a default implementation for the capturing with the Capture class. It’s main goal is portability because it should work on all Arduino Boards. To come up with a dedicated improved capturing is easy. Just implement your own class:

class YourFastCapture : public AbstractCapture {
        /// Default Constructor
        YourFastCapture() : AbstractCapture(){

        /// starts the capturing of the data
        virtual void capture(){
            /// your implementation

Supporting new Architectures

In order to support a new architecture, you need to implement a specific config file, that contains the following information:

  • Defines for the processor specific (resource) settings (e.g. MAX_CAPTURE_SIZE, SERIAL_SPEED …)
  • A typedef for PinBitArray which defines the recorded data size
  • An implementation of the class PinReader which reads all pins in one shot

Here is the config_esp32.h which serves as an example.

Class Documentation

The complete generated class documentation can be found on Github.

Connecting to Pulseview

  • Start the Arduino “logic-analyzer” Sketch
  • Start Pulseview
  • Select “Connect to a Device”:
    • Choose the Driver: Openbench Logic Sniffer & SUMP Compatibles
    • Choose the Interface: Select Serial Port with the Port to your Arduino Device and the frequency defined in the config.h (e.g. the ESP32 uses 921600)
    • Click on “Scan for Devices using driver above” button
    • Select the Device – “Arduino” which should be available and confirm with OK


You can download the library as zip and call include Library -> zip library. Or you can git clone this project into the Arduino libraries folder e.g. with

cd  ~/Documents/Arduino/libraries
git clone pschatzmann/logic-analyzer.git

Supported Boards

I have tested the functionality with the following processors:

Processor Max Freq Max Samples Pins
ESP32 2463700 100000 8
ESP8266 1038680 50000 4
AVR Processors (Nano) 109170 500 8
Raspberry Pico 2203225 100000 8


The basic implementation is only using a single core. While capturing is in process we do not support any cancellation triggered from Pulseview. In order to support this, we would just need to extend the functionality in a specific sketch to run the capturing on one core and the command handling on the second core. And this is exactly the purpose of this library: to be able to build a custom optimized logic analyzer implementation with minimal effort!

You can find my project on Github.


Leave a Reply

Avatar placeholder

Your email address will not be published.