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/ttyACM0
on 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_t
timers. - 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)