Industrial control systems often rely on SCADA (Supervisory Control and Data Acquisition) to monitor and control field devices. In this project, I recreated a miniature SCADA-like console on the Raspberry Pi Pico, entirely in C++, with no external sensors required. The Pico appears as a USB serial device, accepts commands, and responds with telemetryβjust like a field unit in an industrial network.
π― Project Goal
- Simulate a SCADA field device with minimal hardware.
- Build an interactive command console over USB-CDC.
- Show telemetry (internal temperature sensor), device control (LED), and logging.
- Learn how to integrate command parsing, ADC reads, and serial communication on bare-metal Pico.
β¨ Features Implemented
-
USB-CDC console (appears as COM port on Windows,
/dev/ttyACM0on Linux). -
Commands:
-
helpβ list available commands -
idβ show device identifier -
statusβ print current status (temperature, LED state, logging period) -
tempβ one-shot temperature read -
led on|off|toggleβ control onboard LED -
rate <ms>β set periodic status reporting interval -
log on|offβ enable/disable periodic logging
-
Periodic logging of temperature and LED state.
Built-in LED feedback for visibility.
π§ Technical Breakdown
1. USB-CDC Communication
The Pico is configured to use USB-CDC (serial over USB) as its standard I/O channel. With:
pico_enable_stdio_usb(scada_console 1)
pico_enable_stdio_uart(scada_console 0)
all printf and getchar calls redirect to USB. On Windows, the board enumerates as USB Serial Device (COMx).
I used PuTTY to connect at 115200 baud, with Flow Control = None. This gave me a direct SCADA-like console experience.
2. Command Parser
Instead of building a full protocol stack, I implemented a lightweight line-based command parser in C++. Every command line is read from getchar_timeout_us(), buffered, and passed to a handler function that maps text commands to actions.
This approach makes it easy to extend with new commands (e.g., alarm, reset, profile save).
3. Telemetry (Temperature via ADC)
The RP2040 has a built-in temperature sensor accessible on ADC4. Using hardware/adc.h, I read raw ADC values, converted them to volts, and applied the datasheet formula:
float read_internal_temp_c() {
uint16_t raw = adc_read();
float volts = raw * (3.3f / 4095.0f);
return 27.0f - (volts - 0.706f) / 0.001721f;
}
This gives a rough internal temperature (not highly accurate, but perfect for telemetry demo).
4. Status Logging
I implemented periodic logging using absolute_time_t and make_timeout_time_ms(). When log on is enabled, the Pico automatically prints status every rate <ms> milliseconds.
This simulates how industrial field devices send periodic reports to SCADA masters.
5. Project Structure
mini-scada-pico/
ββ main.cpp # Application entry point
ββ utils.hpp / utils.cpp # Command parser + helpers
ββ CMakeLists.txt
ββ pico_sdk_import.cmake
ββ assets/demo.gif
π₯οΈ Example Session
== Mini SCADA Console ==
Device: PICO-FIELD-01
Commands:
help
id
status
log on|off
rate <ms>
led on|off|toggle
temp
> id
PICO-FIELD-01
> status
id=PICO-FIELD-01 temp=28.75C led=OFF period=1000ms
> led on
OK
> temp
28.70
> log on
OK log on
[STATUS] id=PICO-FIELD-01 temp=28.77C led=ON period=1000ms
π What I Learned
- How to use USB-CDC on Pico as the main I/O channel.
- Building a command console on bare-metal hardware is simpler than it looks when using C++ and Pico SDK.
- The internal temperature sensor (ADC4) is a handy built-in telemetry source.
- Industrial-style periodic logging can be simulated with
absolute_time_ttimers. - Debugging USB-CDC on Windows sometimes requires driver fixes (usbser/Zadig) and patience.
π Source Code
The full code is available on GitHub:
π Mini SCADA Console Repository
Top comments (0)