OpenDPS replaces the DPS5005 display with a real ESP32 interface
Give your DPS5005 the upgrade it deserves
At a glance
- What is it?
- OpenDPS is an open source replacement firmware for the DPS5005 bench power supply, and the fork documented here adds a native ESPHome component on ESP32 in place of the original ESP8266 proxy. It suits hobbyists who want a real screen, datalogging and network control of a cheap supply, and it is not a drop in upgrade for someone who only wants accurate readings.
- Who is it for?
- Adopt OpenDPS if you own a DPS5005 or DPS5015 and want open firmware, headless Home Assistant control, datalogging and over the air upgrades rather than the original two button interface, and stay on the stock firmware if a working display and no flashing effort matter more than network integration.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 51 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What OpenDPS actually replaces on the DPS5005
The DPS5005 is a cheap programmable bench power supply whose front panel is a small display and a rotary encoder, driven by an STM32. OpenDPS is an open source replacement firmware for that controller, and the repository description puts it bluntly: give your DPS5005 the upgrade it deserves. The primary language is C, and the project builds on libopencm3, the open source bare metal library for STM32, with a Makefile that compiles three separate pieces.
The Makefile shows the structure plainly. The default target initialises and updates the git submodules if libopencm3 is missing, then builds libopencm3 with TARGETS=stm32/f1, then opendps, then dpsboot, then esp8266-proxy. The flash target builds opendps and dpsboot, so a user who has never touched the hardware can get a working image from a single make invocation.
The bootloader matters more than it first appears. The README states that reflashing the bootloader requires JTAG or SWD access, while the main application firmware can be upgraded over UART at any time by the ESPHome device, and that the original dpsboot bootloader must be intact for that path to work. So there is a one time hardware access requirement, and then a wireless upgrade path for the rest of the life of the device.
The fork documented in this README adds an ESPHome component that talks to the DPS over UART from any ESP32, replacing the separate ESP8266 Wi-Fi proxy that the original project used.
Flashing the DPS: submodule, libopencm3, dpsboot, opendps
The getting started section is unusually concrete. Step one is to follow the original project's flashing guide, either the Wiki file in the repository or the upstream blog post by the original author, to unlock and flash the device. The recommended path is the firmware from this fork, because it includes baud rate switching, improved ADC accuracy and calibration fixes.
The build and flash sequence is five commands:
git clone --recursive https://github.com/p1ngb4ck/opendps.git
cd opendps
make -C libopencm3
make -C dpsboot flash # only needed for a fresh device or to update the bootloader
make -C opendps flashThe recursive clone flag matters because libopencm3 is a git submodule, and the dpsboot flash line is marked as only needed for a fresh device or to update the bootloader. If you are running upstream OpenDPS already, the README says the ESPHome component is backwards compatible with any OpenDPS version that has a working bootloader, and you can upgrade the main firmware later directly from the ESPHome device UI with no PC and no JTAG required.
A detail that will bite people: the clone URL in the README points at the p1ngb4ck fork, not at the kanflo repository, so follow the URL your own README gives you rather than assuming the upstream one carries the same firmware changes.
The ESP32 side: a native ESPHome component instead of the ESP8266 proxy
The original architecture had the DPS talking to a separate ESP8266 acting as a Wi-Fi proxy, which then reached Home Assistant. This fork replaces that proxy with a native ESPHome component named opendps that talks directly to the DPS over UART from any ESP32. The repository still contains an esp8266-proxy directory and the Makefile still builds it, so the old path remains in the tree alongside the new one.
The component is installed without a manual step, because the config uses external_components to pull the opendps component from the project's companion ESPHome repository. The documented installation is:
# Install ESPHome (if needed)
pip install esphome
# Compile and flash (USB connected)
esphome run esphome-config/esphome_config_opendps_JC1060P470_I_W_Y.yamlA web installer and the ESPHome dashboard are offered as GUI alternatives to the command line. The component itself has no display dependency, which is the important architectural fact: the UI is purely additive. Strip the display, lvgl and touchscreen sections out of the YAML and you keep only the opendps component with your sensors and automations, and all control and monitoring still works headlessly via Home Assistant or MQTT.
The feature list for the component covers real-time V_in, V_out, I_out, power and temperature sensors, output enable and disable, voltage and current set, function selection, lock, brightness, and OTA. That is the whole surface of the power supply exposed over the network, which is what makes it useful as a Home Assistant device rather than a curiosity.
Wiring TX to RX and the 3.3V question
Step three is the physical connection, and the wiring table in the README is minimal on purpose:
| DPS pin | ESP32 pin |
|---------|-----------|
| TX | RX (see config) |
| RX | TX (see config) |
| GND | GND |Two cautions are attached. Exact GPIO assignments are defined in the ESPHome config file rather than hardcoded in the docs, so you read them out of the YAML rather than guessing. And the logic level is 3.3V on the ESP32 side, so you must check your DPS model's serial voltage before connecting. That is the sentence to take seriously, because connecting a 5V serial line to an ESP32 pin is the kind of mistake that kills a board.
The three wire names in the table are also the whole protocol surface. The DPS speaks a serial protocol over TX and RX, and the component handles the framing, which is why the ESP8266 proxy was needed in the first place and why replacing it with a component is possible now.
Hardware changes in the firmware: baud rate, ADC averaging and calibration
The fork's firmware changes are the part that affects the numbers you read, not just the interface. They are listed with commit hashes, which is helpful when you want to see the diff.
The configurable UART baud rate is the one with the most reach. Runtime baud rate switching is supported and the default changed to 115200 for faster host communication, which matters because a UART link at the old rate is the bottleneck when you are pulling readings continuously. The CLI gained dpsctl --set-baud and --upgrade-baud for baud rate management and baud-rate-aware firmware upgrades.
The measurement changes are more substantive. ADC oversampling averages 420 ADC samples per reading, giving an update rate of about 50 Hz and an ADC rate of about 21 kHz, and the README describes the result as significantly smoother voltage and current readings. The current noise floor clamp holds output current at zero below the 10 mA noise floor, which removes false micro-amp readings at idle, a specific complaint that anyone who has used a DPS5005 in Home Assistant will recognise.
Then there is the calibration work: ADC_CHA_IOUT_GOLDEN_VALUE corrected for the DPS5005, a double-offset bug in current averaging fixed, and the input voltage now displayed with two decimal places. The bootloader got link-time optimisation with hw_set_baudrate_boot trimmed to fit the 5 KB flash budget, and a status response code handling fix landed alongside.
None of these are documented as new hardware features. They are accuracy and responsiveness fixes, which is exactly what a supply that has to be trustworthy in an automation is short of.
The Python side: dpsctl and what the repository contains
There is a command line tool in the tree, dpsctl, and it is packaged with setup.py as a console script entry point named dpsctl mapping to dpsctl.dpsctl:main, with a version of 0.1 and an MIT licence. The only runtime dependency is pyserial, and requirements.txt pins pyserial at 3.4. The package also ships a uhej subpackage that lives under the dpsctl directory, mapped with package_dir.
Beyond that, the repository layout shows the project's full scope. There is dpsboot for the bootloader, opendps for the main application, esp8266-proxy for the original wireless bridge, emu for an emulator, hardware for board files, openocd and ocd-client.py for JTAG debugging, docker for a containerised build, build_binaries.sh, pastdump.sh, and a .gitmodules file that declares the libopencm3 dependency. The top level also holds a Wiki.md, which is the flashing guide the README points at, and a requirements.txt pinning pyserial.
The emu directory deserves a note because it changes how you can work on the firmware. An emulator lets you develop and test without a physical supply, which is the difference between a project you can iterate on and one that needs the bench in front of you.
Where this fork stops: hardcoded UI and a display sized target
The honest limitation is in the display path. The provided config targets the Guition JC1060P470_I_W_Y, an ESP32-P4 tablet with a 10.6 inch MIPI DSI display and IP101 Ethernet, and the README warns that the UI currently has hardcoded sizes and positions throughout the LVGL config, so another display resolution requires manual layout adjustments. The intended target is 1024x600 or larger, for example 10.1 inches.
Auto-sizing is on the ToDo list, not implemented. The rest of the planned work is BLE remote and keyboard support, USB-HID support for a local keyboard or gamepad on the ESP32, and ongoing minor UI fixes. The fact that the fork relies on a custom LVGL 9.5 component that overrides the ESPHome bundled LVGL version, credited to a third party, is another dependency to be aware of when you plan a build.
There is also a release record oddity. The listed releases are untagged snapshots dated March 2021 and February 2021, which is a long way behind the last push on 2026-09-02 and behind the state described in the README. The repository is not archived, so work continues, but the release list is not a reliable guide to what is current. Use the master branch and build from source.
Editorial conclusion
Adopt OpenDPS if you own a DPS5005 or DPS5015 and want open firmware, headless Home Assistant control, datalogging and over the air upgrades rather than the original two button interface, and stay on the stock firmware if a working display and no flashing effort matter more than network integration. Before you start, confirm your model is reverse engineerable, get JTAG access sorted because reflashing dpsboot needs JTAG or SWD, and check the serial voltage of your unit because the ESP32 side runs at 3.3V. The firmware build uses libopencm3 and the upstream flashing guide, and the last push was on 2026-09-02.
Frequently asked questions
What does OpenDPS do for a DPS5005 power supply?
OpenDPS is open source replacement firmware for the DPS5005 and DPS5015 bench power supply controllers, written in C and built on libopencm3 for STM32. It replaces the original minimal display interface and adds a UART link to an ESP32.
Do I need JTAG to flash OpenDPS onto a DPS5005?
Reflashing the dpsboot bootloader requires JTAG or SWD access. The main application firmware can be upgraded over UART at any time from the ESPHome device UI, as long as the original dpsboot bootloader is intact.
What does the opendps ESPHome component add?
It replaces the original separate ESP8266 Wi-Fi proxy with a native ESPHome component that talks to the DPS over UART from any ESP32. It exposes V_in, V_out, I_out, power and temperature sensors, output enable, voltage and current set, function selection, lock, brightness and OTA.
Can I use OpenDPS with a headless ESP32 and no screen?
Yes. The opendps component has no display dependency, so you can remove the display, lvgl and touchscreen sections from the YAML and keep the component with your sensors and automations. Control and monitoring then work headlessly via Home Assistant or MQTT.
What accuracy improvements does the forked OpenDPS firmware make?
The firmware adds ADC oversampling that averages 420 samples per reading, clamps output current to zero below the 10 mA noise floor, corrects ADC_CHA_IOUT_GOLDEN_VALUE for the DPS5005, and fixes a double-offset bug in current averaging. The UART default baud rate is also 115200 for faster host communication.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kanflo-opendps)Was this useful?