This is an old revision of the document!


Digital Oscilloscope on Raspberry Pi Pico

Introduction

The project implements a single-channel digital oscilloscope using a Raspberry Pi Pico board based on the RP2040 microcontroller. The oscilloscope samples an external analog signal with the Pico's internal 12-bit ADC, detects a configurable trigger event, and displays the captured waveform on a 2.4 inch ILI9341 TFT display connected through SPI.

The user can adjust the timebase, trigger threshold, trigger edge and display mode using four push buttons and one potentiometer. The second RP2040 core is used as an independent PWM function generator for generating a local test signal. The sampled waveform can also be streamed over USB CDC to a PC for logging and analysis.

The goal of the project is to build a compact embedded measurement tool and to exercise several microcontroller peripherals at the same time: ADC, DMA, SPI, PWM, GPIO interrupts, multicore execution and USB serial communication.

General Description

The oscilloscope is centered around the Raspberry Pi Pico. The analog input signal first passes through a simple protection and scaling circuit before reaching ADC0 on GP26. The ADC samples the signal into a memory buffer using DMA, which reduces CPU load and allows stable periodic acquisition.

Core 0 handles the oscilloscope user interface and acquisition pipeline:

  • ADC sampling using DMA
  • trigger level reading from a potentiometer on ADC1
  • trigger edge detection
  • waveform rendering on the ILI9341 TFT display
  • button handling
  • USB CDC sample streaming

Core 1 runs independently as a simple PWM-based signal generator on GP22. During testing, this output can be routed through an RC low-pass filter and connected back to the oscilloscope input.

Signal flow:

[Probe input]
      |
[Voltage divider and ADC protection]
      |
[GP26 / ADC0]
      |
[DMA sample buffer]
      |
[Trigger detection and waveform processing]
      |
[SPI display rendering on ILI9341]

[GP27 / ADC1] <- potentiometer for trigger level
[GP2-GP5]    <- buttons for user control
[GP12 PWM]   -> display backlight brightness
[USB CDC]    -> sample export to PC
[GP22 PWM]   -> optional function generator output

Hardware Design

The hardware is built around the Raspberry Pi Pico, an SPI TFT display, a protected ADC input stage, a potentiometer, four push buttons and a PWM test output.

Main Components

Component Role
Raspberry Pi Pico Main controller, ADC acquisition, display rendering, USB communication and PWM generation
ILI9341 2.4 inch TFT display Waveform and UI display, connected through SPI1
10k potentiometer Trigger threshold adjustment, read by ADC1
2 x 100k resistors Input voltage divider, divides the probe input by 2
2 x 100 ohm resistors ADC input series protection and PWM output series resistor
1nF capacitor ADC input filtering
4 x 100nF capacitors Pico supply decoupling, display supply decoupling, PWM output filtering and ADC_VREF decoupling
4 x tactile push buttons Timebase, trigger edge and display mode controls
Probe/header input External signal input and ground reference

Pin Connections

ILI9341 Display

Display Pin Pico Pin Notes
VCC 3.3V, pin 36 Display supply
GND GND, pin 38 Common ground
CS GP13, pin 17 SPI1 chip select
RESET GP14, pin 19 Active low reset
DC GP15, pin 20 Data/command select
MOSI / SDA GP11, pin 15 SPI1 TX
SCK / CLK GP10, pin 14 SPI1 clock
LED GP12, pin 16 PWM backlight control

Touch controller pins, if present on the display module, are not used.

ADC Input

The oscilloscope input uses a 2:1 voltage divider before the Pico ADC. This allows input voltages up to about 6.6V to be mapped into the Pico ADC's 0V to 3.3V range.

INPUT SIGNAL
     |
    R1 100k
     |
     +---- node A ---- R3 100R ---- GP26 / ADC0
     |
    R2 100k
     |
    GND

The ADC filter capacitor is 1nF. A larger 100nF capacitor would create a very low cutoff frequency with the 100k/100k input divider and would visibly attenuate useful oscilloscope signals.

Potentiometer

Potentiometer Pin Connection
Left terminal 3.3V
Right terminal GND
Wiper GP27 / ADC1, pin 32

Buttons

Each button is connected between the GPIO pin and GND. Internal pull-up resistors are enabled in software.

Button Pico GPIO Pico Pin Function
Button 1 GP2 pin 4 Timebase increase
Button 2 GP3 pin 5 Timebase decrease
Button 3 GP4 pin 6 Toggle trigger edge
Button 4 GP5 pin 7 Cycle display mode

Function Generator Output

Signal Connection
PWM source Pico GP22, pin 29
Series resistor R5, 100 ohm
Output terminal GEN_OUT
Output filter capacitor C4, 100nF from GEN_OUT to GND

For testing, GEN_OUT can be connected to the oscilloscope input header. This jumper is only used during tests and is not a permanent connection in the main input circuit.

Decoupling

100nF capacitors are placed between 3.3V and GND near the Pico and near the display module. These capacitors reduce local supply noise caused by fast digital switching, especially during SPI display updates. A separate 100nF capacitor, C5, is placed between Pico pin 35, ADC_VREF, and GND to decouple the ADC voltage reference.

Electrical Schematic

Electrical schematic

Software Design

The firmware is organized around the two RP2040 cores.

Core 0 performs the oscilloscope acquisition and display tasks. The ADC is configured to sample ADC0 at a fixed rate. Samples are transferred into a RAM buffer using DMA. After a buffer is filled, the software searches for a trigger crossing based on the threshold read from the potentiometer and the selected edge direction. The selected waveform window is then converted from ADC values to display pixel coordinates and rendered on the ILI9341 display.

The display is updated over SPI1. Static UI elements such as the grid, voltage scale, time scale and trigger marker are drawn separately from the waveform when possible, reducing redraw work. The display backlight is controlled with PWM on GP12.

The four buttons are read as digital inputs with internal pull-ups. Software debouncing is used to avoid repeated false events. The buttons modify the timebase, trigger edge and display mode.

Core 1 runs the signal generator. It configures PWM on GP22 and updates the PWM output independently from the acquisition code. This makes it possible to test the oscilloscope without requiring an external signal generator.

USB CDC is used to stream sample data to a connected PC. The data can be sent as comma-separated values, allowing it to be saved or plotted with common serial tools.

Main software modules:

  • ADC and DMA acquisition
  • trigger detection
  • waveform scaling and rendering
  • SPI display driver
  • button and potentiometer input
  • PWM function generator
  • USB CDC sample streaming

Results

The expected result is a working oscilloscope interface showing a live waveform on the ILI9341 display. The user can change the horizontal scale, adjust the trigger threshold with the potentiometer, switch between rising and falling edge triggering, and freeze or change the display mode using the buttons.

The internal PWM generator output can be connected to the input stage during testing to verify acquisition, triggering and rendering without an external signal generator.

Conclusions

This project combines multiple RP2040 hardware features into one embedded measurement device. The main challenges are stable high-speed ADC acquisition, efficient display rendering, and reliable triggering. The final implementation demonstrates how DMA and multicore execution can be used to reduce CPU load and keep the user interface responsive while continuously acquiring data.

Source Code

The firmware is developed as a Raspberry Pi Pico SDK project. The repository contains the acquisition code, display driver integration, button handling, trigger logic, PWM generator and USB CDC serial export.

Bibliography / Resources

pm/prj2026/florin.stancu/cconstantinescu2705.1778343125.txt.gz · Last modified: 2026/05/09 19:12 by cconstantinescu2705
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0