This shows you the differences between two versions of the page.
|
pm:prj2026:florin.stancu:cconstantinescu2705 [2026/05/09 19:12] cconstantinescu2705 |
pm:prj2026:florin.stancu:cconstantinescu2705 [2026/05/25 05:25] (current) cconstantinescu2705 |
||
|---|---|---|---|
| Line 3: | Line 3: | ||
| ===== Introduction ===== | ===== 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. | + | This 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 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 local test signals. The sampled waveform can also be streamed over USB CDC as comma-separated sample values for optional logging on a PC. |
| - | 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. | + | The goal of the project is to build a compact embedded measurement tool and to exercise several microcontroller peripherals at the same time: ADC, SPI, DMA-driven display transfers, PWM, GPIO input handling, multicore execution and USB serial communication. |
| ===== General Description ===== | ===== 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. | + | The oscilloscope is centered around the Raspberry Pi Pico. The analog input signal first passes through a protection and scaling circuit before reaching ADC0 on GP26. The trigger threshold is read from a potentiometer connected to ADC1 on GP27. |
| Core 0 handles the oscilloscope user interface and acquisition pipeline: | Core 0 handles the oscilloscope user interface and acquisition pipeline: | ||
| - | * ADC sampling using DMA | + | * ADC sampling |
| - | * trigger level reading from a potentiometer on ADC1 | + | * trigger level reading from a potentiometer |
| * trigger edge detection | * trigger edge detection | ||
| * waveform rendering on the ILI9341 TFT display | * waveform rendering on the ILI9341 TFT display | ||
| Line 22: | Line 22: | ||
| * USB CDC sample streaming | * 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. | + | Core 1 runs independently as a simple PWM-based signal generator on GP14. During testing, this output can be routed through an RC low-pass filter and connected back to the oscilloscope input. |
| Signal flow: | Signal flow: | ||
| Line 41: | Line 41: | ||
| [GP27 / ADC1] <- potentiometer for trigger level | [GP27 / ADC1] <- potentiometer for trigger level | ||
| [GP2-GP5] <- buttons for user control | [GP2-GP5] <- buttons for user control | ||
| - | [GP12 PWM] -> display backlight brightness | + | [GP22 GPIO] -> display backlight enable |
| [USB CDC] -> sample export to PC | [USB CDC] -> sample export to PC | ||
| - | [GP22 PWM] -> optional function generator output | + | [GP14 PWM] -> optional function generator output |
| </code> | </code> | ||
| Line 54: | Line 54: | ||
| ^ Component ^ Role ^ | ^ Component ^ Role ^ | ||
| | Raspberry Pi Pico | Main controller, ADC acquisition, display rendering, USB communication and PWM generation | | | 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 | | + | | ILI9341 2.4 inch TFT display | Waveform and UI display, connected through SPI0 | |
| | 10k potentiometer | Trigger threshold adjustment, read by ADC1 | | | 10k potentiometer | Trigger threshold adjustment, read by ADC1 | | ||
| | 2 x 100k resistors | Input voltage divider, divides the probe input by 2 | | | 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 | | | 2 x 100 ohm resistors | ADC input series protection and PWM output series resistor | | ||
| - | | 1nF capacitor | ADC input filtering | | + | | Small capacitor, about 100pF to 1nF | Optional ADC input noise filtering | |
| - | | 4 x 100nF capacitors | Pico supply decoupling, display supply decoupling, PWM output filtering and ADC_VREF decoupling | | + | | 100nF capacitors | Supply, display and ADC reference decoupling | |
| | 4 x tactile push buttons | Timebase, trigger edge and display mode controls | | | 4 x tactile push buttons | Timebase, trigger edge and display mode controls | | ||
| | Probe/header input | External signal input and ground reference | | | Probe/header input | External signal input and ground reference | | ||
| Line 68: | Line 68: | ||
| ^ Display Pin ^ Pico Pin ^ Notes ^ | ^ Display Pin ^ Pico Pin ^ Notes ^ | ||
| - | | VCC | 3.3V, pin 36 | Display supply | | + | | GND | GND | Common ground | |
| - | | GND | GND, pin 38 | Common ground | | + | | VCC | 3.3V | Display supply | |
| - | | CS | GP13, pin 17 | SPI1 chip select | | + | | CLK | GP18, pin 24 | SPI0 clock | |
| - | | RESET | GP14, pin 19 | Active low reset | | + | | MOSI / SDA | GP19, pin 25 | SPI0 TX | |
| - | | DC | GP15, pin 20 | Data/command select | | + | | RESET / RES | GP20, pin 26 | Active low reset | |
| - | | MOSI / SDA | GP11, pin 15 | SPI1 TX | | + | | DC | GP21, pin 27 | Data/command select | |
| - | | SCK / CLK | GP10, pin 14 | SPI1 clock | | + | | LED / BLK | GP22, pin 29 | Backlight enable | |
| - | | LED | GP12, pin 16 | PWM backlight control | | + | | MISO / SDO | Not connected | Not used by the firmware | |
| - | Touch controller pins, if present on the display module, are not used. | + | The display module used for the final implementation does not expose a chip-select pin. The firmware therefore uses the display as the only SPI device and does not drive a display CS line. Touch controller pins, if present on other display modules, are not used. |
| === ADC Input === | === ADC Input === | ||
| Line 95: | Line 95: | ||
| </code> | </code> | ||
| - | 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. | + | The optional ADC filter capacitor should be small. In the final circuit, a 100pF capacitor was used because a larger capacitor visibly rounded fast square waves. |
| === Potentiometer === | === Potentiometer === | ||
| Line 117: | Line 117: | ||
| ^ Signal ^ Connection ^ | ^ Signal ^ Connection ^ | ||
| - | | PWM source | Pico GP22, pin 29 | | + | | PWM source | Pico GP14, pin 19 | |
| - | | Series resistor | R5, 100 ohm | | + | | Series resistor | 100 ohm | |
| | Output terminal | GEN_OUT | | | Output terminal | GEN_OUT | | ||
| - | | Output filter capacitor | C4, 100nF from GEN_OUT to GND | | + | | Optional filter capacitor | 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. | 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. | ||
| Line 126: | Line 126: | ||
| === Decoupling === | === 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. | + | 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 is placed between ADC_VREF and AGND to decouple the ADC voltage reference. |
| ==== Electrical Schematic ==== | ==== Electrical Schematic ==== | ||
| Line 136: | Line 136: | ||
| The firmware is organized around the two RP2040 cores. | 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. | + | Core 0 performs the oscilloscope acquisition and display tasks. The ADC is sampled into a RAM buffer. 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 display is updated over SPI0. The frame buffer is transferred to the display using DMA, which reduces the time spent waiting for SPI transfers and keeps the interface more responsive. The display backlight is enabled from GP22. |
| 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. | 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. | + | Core 1 runs the signal generator. It configures PWM on GP14 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. | 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. | ||
| Line 148: | Line 148: | ||
| Main software modules: | Main software modules: | ||
| - | * ADC and DMA acquisition | + | * ADC acquisition |
| * trigger detection | * trigger detection | ||
| * waveform scaling and rendering | * waveform scaling and rendering | ||
| * SPI display driver | * SPI display driver | ||
| + | * DMA display transfer | ||
| * button and potentiometer input | * button and potentiometer input | ||
| * PWM function generator | * PWM function generator | ||
| * USB CDC sample streaming | * USB CDC sample streaming | ||
| - | ===== Results ===== | + | ===== Source Code ===== |
| - | 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 firmware is implemented in a single C source file for the Raspberry Pi Pico SDK: |
| - | 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. | + | * {{pm:prj2026:florin.stancu:pico_oscilloscope.zip|pico_oscilloscope.zip}} |
| - | + | ||
| - | ===== 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. | + | The code contains the ILI9341 display driver, ADC acquisition, trigger detection, waveform rendering, button handling, potentiometer reading, USB CDC sample streaming and the second-core PWM function generator. |