Sketch, fonts, bitmaps, setup.h config, README, .gitignore.
USB Voltage / Current Monitor — RP2040-Zero + SSD1306 OLED
A small Arduino sketch that turns an RP2040-Zero into a USB power monitor. It measures the voltage and current of whatever is plugged into it, calculates power draw, and shows everything on a 128×64 SSD1306 OLED — complete with a cute 7-segment-style "USB score" rated on how close the supply is to an ideal 5 V.
Features
- Live readings — voltage (V), current (A), power (W) updated every 100 ms
- USB quality score (0–9) — big 48 px DSEG7 "7SEGGCHAN" digit showing how close the rail is to the ideal 5.0 V (9 = perfect, blink = out of range)
- Temperature — from the RP2040's internal ADC temperature sensor
- Uptime counter — MM:SS, wraps after 99 minutes
- Custom fonts — 7-segment-style DSEG7 fonts plus DejaVu Sans Mono for labels
- Hand-drawn icons — temperature and clock bitmaps
- Lean-build options — disable fonts / bitmaps / score to free up flash
Hardware requirements
| Part | Notes |
|---|---|
| RP2040-Zero (or any RP2040 board) | mcu_model is set in setup.h |
| SSD1306 OLED, 128×64, I2C | address 0x3C, SWITCHCAPVCC |
| Voltage divider | default ratio ÷2, connected to the voltage ADC pin |
| Current-sense shunt resistor | default 50 mΩ, on the current ADC pin |
| USB thing to measure | the whole point :) |
Wiring
Default pins (see setup.h to change):
| Signal | Pin |
|---|---|
| OLED SDA | GP28 |
| OLED SCL | GP29 |
| Voltage sense (after divider) | A0 |
| Shunt sense (across the shunt) | A1 |
Wire the OLED to 3V3 / GND and the two I2C lines. Connect the voltage
divider output to A0 and the shunt's voltage drop to A1.
The display shows "Display Error: Check Connections" on the serial monitor (115200 baud) and halts if the OLED is not found — check SDA/SCL wiring and the
0x3Caddress first.
How it measures
Readings are taken with the ADC at 12-bit resolution (analogReadResolution(12)):
voltage (V) = raw / 4095 × 3.3 × voltage_divider
current (A) = raw / 4095 × 3.3 × (1000 / shunt_resistance_mΩ)
wattage (W) = current × voltage
Both scale factors live in setup.h:
voltage_divider— by how much the input voltage is divided before the ADC (default2)shunt_resistance— shunt value in milliohms (default50)
Measurements refresh every 100 ms. Temperature comes from the RP2040's
built-in sensor (analogReadTemp()), no external sensor needed.
USB score
calculateUSBScore() grades how close the measured voltage is to an ideal
5.0 V USB rail. Higher is better:
| Score | Voltage range |
|---|---|
| 9 | 4.90 – 5.10 V |
| 8 | 4.80 – 4.90 V or 5.10 – 5.20 V |
| 7 | 4.70 – 4.80 V or 5.20 – 5.30 V |
| 6 | 4.60 – 4.70 V or 5.30 – 5.40 V |
| 5 | 4.40 – 4.60 V or 5.40 – 5.60 V |
| 4 | 4.20 – 4.40 V or 5.60 – 5.80 V |
| 3 | 4.00 – 4.20 V or 5.80 – 6.00 V |
| 2 | 3.70 – 4.00 V or 6.00 – 6.30 V |
| 1 | 3.50 – 3.70 V or 6.30 – 6.50 V |
| 0 | 3.00 – 3.50 V or 6.50 – 8.00 V |
blink (-) |
below 3.0 V or above 8.0 V (out of range) |
The score is rendered as a big 48 px digit; when out of range it toggles
between - and blank every second.
Display layout
┌─────────────────────────────────┐
│ [temp] 25.4 C° │ [clock] 05:42 │ top: temp + uptime
├─────────────────────────────────┤
│ V: 5.012 │
│ A: 0.842 │ │
│ W: 4.219 │ 9 │ big USB score
│ │ │
└─────────────────────────────────┘
- Top row: temperature icon + value, a separator line, clock icon + uptime
- Left column:
W:/A:/V:labels (DejaVu Sans Mono) with DSEG7 7-segment values - Right side: the 48 px DSEG7 score digit behind a vertical divider
With use_default_fonts = true the same layout is drawn in the built-in
Adafruit 5×7 font (and C replaces C°).
Getting started
- Install the Raspberry Pi Pico / RP2040 board package in the Arduino IDE
(e.g. Earle Philhower's arduino-pico core,
which provides
analogReadResolution()/analogReadTemp()and the Pico SDK). - Install the libraries: Adafruit GFX Library and Adafruit SSD1306 (Library Manager).
- Copy all files from this folder into a sketch folder named
voltage_current_monitor_usbso the.hfiles sit next to the.ino. - Set your hardware values in
setup.h(shunt, divider, pins, features). - Select your board / port and upload.
Required libraries
| Library | Purpose |
|---|---|
Wire |
I2C (built in) |
Adafruit_GFX |
graphics primitives |
Adafruit_SSD1306 |
OLED driver |
<hardware/adc.h> |
Pico SDK ADC (comes with the arduino-pico core) |
Project structure
voltage_current_monitor_usb/
├── voltage_current_monitor_usb.ino main sketch (loop, display, score, uptime)
├── setup.h hardware + feature configuration
├── dseg7_7seggchan_mini_font_48p_regular.h DSEG7 "7SEGGCHAN" 48 px font (score)
├── dseg7_classic_mini_font_11p_regular.h DSEG7 Classic mini font (values)
├── DejaVu_Sans_Mono_font_12p_regular.h label font (as `DialogInput_plain_12`)
└── images.h temperature & clock bitmaps
Configuration (setup.h)
| Option | Default | What it does |
|---|---|---|
shunt_resistance |
50 |
shunt value in mΩ — set to match your hardware |
voltage_divider |
2 |
divider ratio for the voltage input |
VOLTAGE_PIN / CURRENT_PIN |
A0 / A1 |
ADC pins |
I2C_SDA / I2C_SCL |
28 / 29 |
OLED I2C pins |
use_7seggchan |
true |
draw the big 48 px score digit |
use_default_fonts |
false |
use built-in fonts instead of the custom font files (saves flash) |
use_bitmaps |
true |
draw the temperature / clock icons (saves flash when off) |
use_usbscore |
true |
compute the 0–9 USB score (requires use_7seggchan) |
use_splash / use_version_splash |
true |
reserved splash-screen toggles (no splash code in the current sketch yet) |
Saving flash: if the sketch is too big, set use_default_fonts = true
(and skip the three font #includes) and/or use_bitmaps = false
(and skip images.h).
Troubleshooting
- "Display Error: Check Connections" and it hangs — OLED not found.
Check SDA/SCL wiring,
0x3Caddress, and the pins insetup.h. - Voltage reads wrong — verify
voltage_dividermatches your divider hardware. - Current reads wrong — verify
shunt_resistance(in mΩ), e.g.50= 0.05 Ω. - Compilation fails / flash overflow — disable custom fonts and/or bitmaps
(see above) and remove the unneeded
#includes. - Serial monitor — set the baud rate to
115200.
Credits
- DSEG7 fonts (7SEGGCHAN and Classic variants) by Keshikan — https://www.keshikan.net/fonts-e.html
- DejaVu Sans Mono font family
- Custom fonts converted to Adafruit GFX format with the converter at https://oleddisplay.squix.ch/
- Temperature & clock icons drawn by hand in Piskel