Pinscope on the Raspberry Pi Pico 2 W

Remote access, logs, metrics, crash reports and firmware updates for the Pico 2 W with the Pico SDK. One line in CMake, one line of code.

With an AI assistant. Copy the instructions and paste them into Claude, Cursor, Copilot or ChatGPT in your project: it adds Pinscope the way this page says, and asks you for the project key instead of writing it into your code. Or give it the link: pico.md.

Try the sample first

You need CMake, Ninja and the Arm GCC (arm-none-eabi-gcc). Without PICO_SDK_PATH, the Pico SDK and the FreeRTOS kernel are downloaded the first time:

git clone https://github.com/pinscope-dev/pinscope-pico && cd pinscope-pico
PINSCOPE_KEY=psk_... WIFI_SSID=... WIFI_PASSWORD=... cmake -S sample -B build -G Ninja
cmake --build build

Hold BOOTSEL while plugging the board in and copy build/pinscope_pico.uf2 to it.

1. Connect

Add it to the build

Clone pinscope-pico next to your project (or add it as a git submodule). In your CMakeLists.txt, after pico_sdk_init():

include(pinscope-pico/pinscope.cmake)

target_link_libraries(app
    pinscope
    pico_cyw43_arch_lwip_sys_freertos
    FreeRTOS-Kernel-Heap4
    pico_stdlib)

Pinscope runs in a FreeRTOS task of its own and uses lwIP's sockets, so the project uses the SDK's FreeRTOS WiFi architecture, pico_cyw43_arch_lwip_sys_freertos. In your lwipopts.h:

#define NO_SYS                  0
#define LWIP_SOCKET             1
#define LWIP_NETIF_LOOPBACK     1
#define MEMP_NUM_NETCONN        12

The build stops with the setting to change if one is missing.

Start it

In the dashboard, open your project and the tab Connect a device and copy the project key. Then, once WiFi is connected:

#include "pinscope.h"

pinscope_start(&(pinscope_config_t){
    .project_key = "psk_...",
    .firmware_version = "1.0.0",   // shown in the dashboard
});

Call it once. It reconnects by itself. The device needs to reach connect.pinscope.dev on TCP port 443, outbound only. Flash the UF2 and the device appears under Devices.

2. Reach the device

Whatever listens on port 80 of the Pico is served at the device's own HTTPS address, exactly as on ESP32: pages, JSON APIs and WebSockets, share links, public pages and your own address. See Reach the device.

3. Logs and metrics

Everything the firmware prints with printf reaches the Logs tab, a line at a time. The USB or UART output is unchanged.

MetricMeaning
heap_free, heap_minFree FreeRTOS heap now, and the lowest it has been
stack/pinscopeStack the Pinscope task has never used
rssiWiFi signal
chip_temp_c, uptime_sThe RP2350's temperature sensor, and time since boot
pinscope_metric("water_level_cm", 42.5);

4. Crashes

On a HardFault, the program counter, the return address and the code addresses found on the stack are kept in RAM across the reset and sent on the next connection, under the Crashes tab. Upload the .elf of that build under Firmware to read function names and line numbers; builds are matched by their GNU build ID. Pinscope provides isr_hardfault; an application that defines its own replaces it.

5. Firmware updates

Updates use the RP2350's own A/B partitions: the new firmware is written to the partition not in use, and the bootrom boots it on trial. Once per board, load a partition table with two partitions for the application:

picotool partition create partitions.json pt.uf2
picotool load pt.uf2 && picotool reboot -u

with a partitions.json like the one in ports/pico/sample. Then flash your firmware as usual. To update it, upload the build's .uf2 under Firmware and press Update firmware on the device.

The new firmware is confirmed when it reaches Pinscope; if it does not within five minutes, the device restarts and the bootrom goes back to the previous one. Without the partition table the device simply shows no Update firmware button. Pinscope keeps its device credential in the last 4 KB sector of flash, outside both partitions.

Memory

About 9 KB of RAM: 4.2 KB of frame buffers, queue and state, as on ESP32, a 3 KB task stack, and the task, lock and socket. No TLS library: the connection uses the Noise protocol, with keys from the RP2350's hardware random generator.

If it does not work

Pinscope's lines carry pinscope:; a device that connected says online at https://….

What you seeWhat to check
The build stops: Pinscope needs lwIP socketsSet NO_SYS 0 and LWIP_SOCKET 1 in lwipopts.h, and link pico_cyw43_arch_lwip_sys_freertos
The build stops: LWIP_NETIF_LOOPBACKSet it to 1: Pinscope reaches the Pico's own web server through it
No online at line, no errorWiFi is not connected yet, or the network does not let the Pico reach connect.pinscope.dev on TCP port 443
There is no Update firmware buttonThe board has no A/B partition table yet

Still stuck? Write to support@pinscope.dev with the lines that carry pinscope:.