Skip to the content
2 layers87 × 22.3 mmPanel, the printed circuit board in 3D

An rp2040-based acquisition board for pulse-echo ultrasound

Size
87 × 22.3 mm
Copper layers
2
Thickness
1.6 mm
Parts
46
Nets
34
Pads
162
Tracks, vias
547, 154
Pours
4
Routed
Yes
KiCad
KiCad 8.0 (file 20240108)
Created
31 Mar 2024
Updated
24 Oct 2026

Overview

Panel is an open-source printed circuit board by kelu124, from the kelu124/pic0rick repository on GitHub. It is a 2-layer board of 87 × 22.3 mm with 46 parts on 34 nets, routed with 547 tracks and 154 vias.

It is built around the R2D-0524/P-R, MD1213K6-G and TC6320TG-G, with the BAV99, ILSB1206ER6R8K and 150080GS75000 among its other parts. Its parts include 16 capacitors, 7 connectors, 6 ICs, 4 resistors and 3 diodes. It belongs with the RP2040 boards of this library.

Main components

6

README

README.md

GitHub repo size GitHub language count GitHub top language GitHub last commit

Slack replacement made-with-Markdown

the pic0rick project

Patreon Kofi

The pic0rick is a very central board for an ultrasound pulse-echo system. It is composed of a main board, based on the RP2040 (or RP2350) and easy to solder SMD, to which a single, and a double PMOD connector can connect to addons:

  • The main board is equipped with a 60Msps, 10bit ADC. Front end is protected against high-voltage pulses, and features a proven time-gain compensation system consisting in a AD8331 (7.5 dB to 55.5dB) with a controlling (MCP4812) SPI DAC.
  • The single PMOD connector can plug to the Pulser board, which can be equipped with a simple +-25V generation board. Together, they generate the pulse on behalf of the pic0rick main board. The setup can generate three-level pulses ( with a pair of MD1210 + TC6320 ).
  • The double PMOD connector can be used for virtually anything. The current code allows for a VGA to be connected, which displays acquisitions from the board.

The current system uses both PIOs (one for the acquisition, the other for the VGA) which leaves the other resources of the rp2040 relatively free to use for your own priorities.

Published documents include:

  • KiCad design files for the main board
  • KiCad design files for the pulser + hv boards
  • KiCad design files for the MUX
  • KiCad design files for other boards =)
  • rp2040/rp2350 firmware for the microcontroller.

I know the PMODs aren't strictly speaking PMODs, I needed to have 5V facility on the header =)

And if you want to discuss the project - meet us on our chat.

Repository layout

PathContents
firmware/The unified RP2040/RP2350 firmware (CMake project adc-pulse). One source tree with -DMUX / -DDSP build options. hw/ = shared acquisition + pulser + spi1 DAC; dsp/ = RP2350 DSP (CMSIS-DSP Hilbert envelope + binary protocol); max/ = MAX14866 mux. version.yaml + CHANGELOG.md track the firmware version; build.sh builds all 6 variants into dist/.
python/Host stack (pic0rick package): device.py (serial driver), dsp.py (binary frame protocol), ndt_acquisition.py (echo/thickness analysis + HDF5), and the example_*.ipynb notebooks.
hardware/KiCad design files and build.sh fabrication outputs — main board (adc/), pulser + HV (pulser/), MUX (mux/), VGA (vga/), PSRAM (psram/).
docs/Documentation: dsp_output_formats.md, dsp_test_guide.md, images/, data/, fw_history/ (maintainer-curated reference .uf2 baselines), and claude/ (cross-session engineering notes).
.github/workflows/CI: builds all firmware variants and publishes a release on push to main.

Getting Started

Prerequisites

  • pic0rick main board + pulser board + HV board (assembled)
  • USB-C cable
  • Python 3.9+
  • A piezoelectric transducer (e.g. 5 MHz single-element contact probe)

Building the firmware

The firmware is a single source tree (firmware/) with build options:

  • -DMUX (default on) — MAX14866 HV multiplexer support.
  • -DDSP (RP2350/pico2 only) — on-board Hilbert-envelope DSP + binary protocol (see DSP build below).
bash
cd firmware && ./build.sh          # builds all 6 variants into firmware/dist/:
#   rp2040-{mux,nomux}, rp2350-{mux,nomux}, rp2350-{mux,nomux}-dsp

Prebuilt firmware/rp2040.uf2 / firmware/rp2350.uf2 are the default (mux, non-DSP) builds. CI publishes all variants as release assets.

Flashing the firmware

  1. Hold the BOOTSEL button on the RP2040/RP2350 while connecting USB — the board mounts as a USB mass-storage device. (After the first flash you can instead send the reboot-dfu command over serial to re-enter the bootloader without the button.)
  2. Copy the compiled .uf2 file into the drive. The board reboots automatically.
  3. Verify: open a serial terminal at 115,200 baud. You should see the run> prompt (stdio build). Send version to confirm the firmware version, board and options.

Installing the Python library

bash
pip install pyserial numpy h5py scipy matplotlib

Clone this repo and add python/ to your path, or run notebooks from the python/ directory.

Quick start

The examples below target the DSP build (-DDSP, RP2350) — the recommended firmware, which streams CRC-checked binary frames. For the plain stdio build see Serial commands.

python
from pic0rick.device import Pic0rick
from pic0rick.ndt_acquisition import UltrasonicAcquisition

probe = Pic0rick()           # auto-detects the USB serial port
print(probe.version()['raw'])

# Set TGC gain (raw DAC value 0–1023; higher = more gain)
probe.set_gain(300)

# Configure and arm the pulser so the capture transmits
probe.configure_pulse(negative_ns=200, damp_ns=2000, positive_ns=200,
                      order="pos-first")
probe.arm_pulser()

frame = probe.read_raw()     # 8000-sample raw ADC frame (CRC-checked)
signal = frame.samples()     # numpy uint16, 0..1023
# envelope = probe.read_fft().samples()   # 4096-sample Hilbert envelope
probe.disarm_pulser()

On the stdio (non-DSP) build instead use probe.dac(gain), probe.pulse_adc_trigger(pon, poff, damp), probe.read().

Or use the higher-level acquisition wrapper (drives the DSP build for you):

python
acq = UltrasonicAcquisition.from_probe(
    Fech=60e6,
    pon=70,        # pulse-on duration [ns]
    poff=70,       # pulse-off duration [ns]
    damp=6000,     # damping duration [ns]
    gain=300,      # raw DAC value (0–1023)
    target="1018 steel 25 mm",
    h5_path="my_scan.h5",
)
acq.plot()

Serial commands (stdio / non-DSP build)

The stdio build exposes a text protocol at 115,200 baud (USB CDC), with a run> prompt:

CommandArgumentsDescription
start acq <pon> <poff> <damp>nanosecondsFire pulse, DMA-capture 8000 samples
write dac <N>0–1023Set TGC gain (MCP4812 10-bit DAC)
read—Return last captured buffer (hex, comma-separated 10-bit values)
write mux <hex>hex wordWrite the MAX14866 shift register (MUX builds)
set mux / clear mux—Pulse the MAX14866 SET / CLR line (MUX builds)
version—Print firmware version, board/chip, options, git hash, release URL
reboot-dfu—Reboot into the USB bootloader (BOOTSEL) for reflashing

The DSP build uses different commands (dac write, read_raw, read_fft, …) and a binary protocol — see DSP build.

Parameter details

pon / poff / damp — expressed in nanoseconds from Python. The firmware converts them to 125 MHz clock cycles internally (divides by 8).

gain — raw 10-bit DAC value (0–1023) controlling the VGAIN pin of the AD8331 TGC amplifier (7.5 dB to 55.5 dB range). The example notebook uses values in the 0–500 range.

DSP build (RP2350)

Building with -DDSP=ON (RP2350/pico2) adds an on-board DSP path: a float32 CMSIS-DSP Hilbert envelope. Instead of the text REPL it speaks a binary framed protocol (64-byte header + CRC32) with two capture modes:

  • read_raw — 8000 raw ADC samples (no FFT).
  • read_fft — 4096-sample Hilbert envelope.

plus acq raw|envelope|alaw, stream start|stop, dsp scale|selftest, dac write <0..1023>, pulse config <neg_ns> <damp_ns> <pos_ns> <neg-first|pos-first>, pulser arm|disarm, status, help, version, reboot-dfu.

Drive it from Python with pic0rick.dsp and these Pic0rick methods: version(), status(), set_gain(n), configure_pulse(...), arm_pulser()/disarm_pulser(), read_raw(), read_fft(), capture(payload). The frame and status formats are documented in docs/dsp_output_formats.md; see docs/dsp_test_guide.md and the python/example_dsp.ipynb / python/example_simple.ipynb notebooks.

Signal chain

text
Transducer
   │
   ├──► TX path: PIO pulser GPIO11/12 (P+/P-) + GPIO16/17 (PDAMP/OE) → MD1213 + TC6320 → ±25V three-level pulse
   │
   └──► RX path: T/R protection → AD8331 TGC (gain set by MCP4812 DAC)
                  → 60 Msps 10-bit ADC (PIO + DMA, 8000 samples/acquisition)
                  → USB CDC → Python

The ADC samples are 10-bit unsigned (0–1023, mid-scale = 512). The ndt_acquisition wrapper normalises them to float32 in the range ≈ [−1, 1]:

python
signal = (adc_count - 512) / 512.0

Setup

The three boards assemble look like this

Example of acquisitions

Demo of output to VGA

Beware. This is not a standard development, more of a proof of concept. It lives on a separate branch here.

Only using the pico to setup gain and trigger acquisitions. The screen displays the gain value (0 to 9, with a 100x divider). Displays raw buffer of acquisition.

Example of a compact assembly

Within a game card footprint

Along with the other boards

Assembly

What you get :

Before assembly

You will need to get a few headers, a raspberry pico, and SMA connectors

Focus on the Pulser connector

Once assembled

Top view

Bottom view

License

This work is based on three previous TAPR projects, the echOmods project, the un0rick project, and the lit3rick project - their boards are open hardware and software, developped with open-source elements as much as possible.

Copyright Luc Jonveaux (kelu124@gmail.com) 2024

  • The hardware is licensed under TAPR Open Hardware License (<www.tapr.org/OHL>)
  • The software components are free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
  • The docs is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

Disclaimer

This project is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE.

Parts

46
QtyValueFootprintReferences
7100nFCapacitor_SMD:C_1206_3216MetricC1, C3, C7, C8, C14, C15, C16
41uFCapacitor_SMD:C_1206_3216MetricC2, C6, C12, C13
310KResistor_SMD:R_1206_3216MetricR2, R3, R4
310nFCapacitor_SMD:C_1206_3216MetricC4, C5, C9
2120Ohm 3 AInductor_SMD:L_1206_3216MetricFB1, FB2
24.7uFCapacitor_SMD:C_1206_3216MetricC10, C11
2BAV99Package_TO_SOT_SMD:SOT-23D1, D2
2LOGOICTAMKY_V8:qr_pic0rickG***, G***
2MD1213K6-GPMOD_PULSER:MD1213IC2, IC5
2SN74LVC2G04DBVTPMOD_PULSER:SN74LVC2G04DBVIC1, IC4
2TC6320TG-GPMOD_PULSER:SOIC127P600X175-8NIC3, IC6
11KResistor_SMD:R_1206_3216MetricR1
16.8uHInductor_SMD:L_1206_3216MetricL1
161300611021Connector_PinHeader_2.54mm:PinHeader_1x06_P2.54mm_HorizontalJ3
1AMPHENOL_132357-11PMOD_PULSER:AMPHENOL_132357-11J1
1Conn_01x02Connector_PinHeader_2.54mm:PinHeader_2x01_P2.54mm_HorizontalJ2
1Conn_01x02_PinConnector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_VerticalJ6
1Conn_01x02_SocketConnector_PinSocket_2.54mm:PinSocket_1x02_P2.54mm_VerticalJ7
1Conn_01x03_PinConnector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_VerticalJ4
1Conn_01x03_SocketConnector_PinSocket_2.54mm:PinSocket_1x03_P2.54mm_VerticalJ5
1Green LEDDiode_SMD:D_0805_2012MetricD3
1LOGOICTAMKY_V8:OSHW_mask_1G***
1R2D-0524_PSamacSys_Parts:R2D0524PPS1
1TC74VHC08F_EL,K,F_PMOD_PULSER:SOIC127P780X190-14NH1
1VAL**Panelization:mouse-bite-3mm-slotmouse-bite-3mm-slot

The 45 most common of 46 parts.

More from kelu124/pic0rick

7
  • 4 layers87.1 × 78.2 mm3 in 1 Panel, the printed circuit board in 3D

    3 in 1 Panel

    kelu124/pic0rick

    An rp2040-based acquisition board for pulse-echo ultrasound

    115 parts116
  • 4 layers85 × 54 mmPICO ADC Test, the printed circuit board in 3D

    PICO ADC Test

    kelu124/pic0rick

    An rp2040-based acquisition board for pulse-echo ultrasound

    66 parts116
  • 2 layers63.3 × 22.3 mmPMOD Pulser update, the printed circuit board in 3D

    PMOD Pulser update

    kelu124/pic0rick

    An rp2040-based acquisition board for pulse-echo ultrasound

    33 parts116
  • 2 layers63 × 23.5 mmMAX14866 PMOD, the printed circuit board in 3D

    MAX14866 PMOD

    kelu124/pic0rick

    An rp2040-based acquisition board for pulse-echo ultrasound

    17 parts116
  • 2 layers20.7 × 22.3 mmHV BOARD, the printed circuit board in 3D

    HV BOARD

    kelu124/pic0rick

    An rp2040-based acquisition board for pulse-echo ultrasound

    8 parts116
  • 2 layers47.3 × 16.3 mmPMOD2VGA, the printed circuit board in 3D

    PMOD2VGA

    kelu124/pic0rick

    An rp2040-based acquisition board for pulse-echo ultrasound

    8 parts116
  • 2 layers18.8 × 16.3 mmPMOD2PSRAM, the printed circuit board in 3D

    PMOD2PSRAM

    kelu124/pic0rick

    An rp2040-based acquisition board for pulse-echo ultrasound

    4 parts116

Similar boards

  • 4 layers120 × 80 mmUltr4rick, the printed circuit board in 3D

    Ultr4rick

    kelu124/ultr4rick

    High-end version of the pic0rick

    269 parts4
  • 4 layers200 × 100 mmMinUS, the printed circuit board in 3D

    MinUS

    kelu124/minus

    Minimal ultrasound platform

    222 parts3
  • 2 layers47 × 52.1 mmDB pulser v3, the printed circuit board in 3D

    DB pulser v3

    echopen/PRJ-medtec_kit

    17 parts19
  • 2 layers79.5 × 79.5 mmEsp32-energymeter V2, the printed circuit board in 3D

    Esp32-energymeter V2

    ElektorLabs/esp32-energymeter

    The Elektor ESP32 Energy Meter project, featuring schematics, PCB designs, and ESPHome integration for advanced energy monitoring

    116 parts48MIT
  • 2 layers40 × 50 mmWired sculpt, the printed circuit board in 3D

    Wired sculpt

    chadaustin/wired-sculpt-pcb

    KiCad design files for the Wired Sculpt conversion mod

    39 parts35
  • 4 layers127 × 76.2 mmPayload pcb, the printed circuit board in 3D

    Payload pcb

    austindriggs/urc-payload-pcb

    All-purpose control and interface board designed to manage mission-critical sensors and electronics for University Rover Challenge at WVU.

    114 partsMIT
  • 2 layers50 × 70 mmProjet, the printed circuit board in 3D

    Projet

    Barberousse-le-bon/conception_pcb

    28 parts
  • 2 layers152.1 × 70.1 mmFLP PCB set, the printed circuit board in 3D

    FLP PCB set

    DSM-Interrupt/FLP

    Overall Embedded segment of Project FLP

    118 parts

Questions

How big is the Panel PCB?

It measures 87 × 22.3 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Panel use?

46 parts, built around the R2D-0524/P-R, MD1213K6-G, TC6320TG-G and BAV99. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Panel KiCad files?

From the kelu124/pic0rick repository on GitHub, at the commit this page was made from: the board is hardware/pulser_panel/panel.kicad_pcb and its schematic hardware/adc/PICO_ADC_Test.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Panel design in my own project?

Its repository states no licence, so its author keeps all rights: ask kelu124 before reusing the design.