DPS50V5A and a DPS3005

The DPS5005, and related DPS3005, DPS5015, DP50V5A, are variable 'bench' power supply modules. It contains a STM32F100 microprocessor and a 1.44" TFT color LCD display.

The more recent versions of DP50V5A and the DPS5005 are virtually identical except for the difference in firmware. The DP50V5A has an inferior firmware which makes the interface laggy along with a slight difference in how the M1/M2 buttons are mapped. Despite these differences, OpenDPS can be installed and the button mappings can be made to work in the same manner.


The firmware can be overwritten with an open source project called OpenDPS.

Additional features that OpenDPS features include not available from the stock firmware:

  • Serial/Wi-Fi control
  • A function generator
  • A countdown timer
  • A watt-hour meter (useful for checking how much power a battery took to charge)


STLink DPS Pinout.jpg

You will need the following to get OpenDPS running on your power supply:

  • A STLink or STLink clone
  • A computer with OpenOCD, ARM cross compiler (gcc-arm-none-eabi)

To begin, connect your STLink to the DPS power supply as per the pinout in the picture. Connect the STLink to your computer and then apply power to the DPS power supply. OpenOCD should be able to detect the device.

pi@raspberrypi:~/opendps$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v17 API v2 SWIM v4 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.236988
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : accepting 'telnet' connection on tcp/4444

In case your device is unique and has no support, use the bundled ocd-client.py script to generate a log file with all registers, hardware peripherals including ADC and DACs, timers, GPIOs, etc. If you are working on a supported device (ie. the dps-models.h file has mention of your model), you should be safe to skip this step. Create a few dumps of the device in different states (Off / On and set to different voltages) in order to make it easier to identify which GPIO pins and ADC/DACs are in use and for what purpose. The stock firmware will freeze when OpenOCD is used. The only work-around is to configure the device with the STLink disconnected and the re-connect the STLink when you are ready to create a dump.

Dumps are created with ocd-client.py script like this:

$ python ocd-client.py all > dump.txt

To compile and flash OpenOCD on your device, clone the OpenOCD repository.

$ git clone https://github.com/kanflo/opendps

On the project root directory, start OpenOCD and compile the project.

## Open a OpenOCD if not done already
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg

## In another window, you should be able to `telnet localhost 4444`

## Compile OpenDPS and then flash it on the device:

## Flash the boot loader:
$ make -C dpsboot flash

It is normal for the device to have a blank screen after the OpenDPS flash. It should boot up after flashing the dpsboot bootloader. This is a bug with the build system and you will always have to flash both OpenDPS and the DPSBoot bootloader for the device to function.

If you have issues compiling and get an error /home/pi/opendps/libopencm3/include/libopencm3/dispatch/nvic.h:8:11: fatal error: libopencm3/stm32/f1/nvic.h: No such file or directory , try running make on the root directory once (it will error on something else, but it shouldn't matter) and then try again.

If buttons aren't working, then your hardware might be using different GPIO pins. Refer to the dump made above to determine any necessary changes needed to the code.

If voltages and currents are off, you need to calibrate the device by adjusting the dps-models.h file.


OpenDPS makes use of multiple screens, each with a different set of functions. The key combinations used to switch screens are SET + Rotary.

Power is controlled using the ON / OFF switch.

To protect from accidental changes while powered on, the interface can be locked or unlocked by pressing and holding Rotary. When locked, no interface or settings can be changed.

DPS Mode Screen[edit]

The DPS Mode screen shows the voltage, current, and power output being supplied by the power supply and was designed to look and feel as close to the original DPS firmware as possible while retaining a cleaner user interface.

DSP5005 Interface

Buttons work as you would expect: V will allow editing of the maximum voltage. A will allow editing of the maximum current.

The user interface can be locked by holding the Rotary down until a padlock symbol appears near the bottom of the screen. Conversely, the interface can be unlocked by holding the Rotary down until the padlock symbol disappears.

DSP5005 Third Item Interface

The third value on the screen can be changed using the Rotary Press + Rotary Turn combination. Values that are displayed in the third row can be edited using Rotary Press, or by navigating through the interface using SET + M1 or SET + M2. The DPS Mode screen currently supports editing of:

  • Power Output / Power Limit
  • Timer (time until power off, or time since power on)
  • Brightness
  • Watt-Hour Meter (measured in milliwatt-hours).

DSP5005 Power Interface.png

When the DPS unit is turned on, you will see either CC or CV signifying whether the device is in constant current or constant voltage mode. Depending on the power output limit that is set, a power output warning may be seen when power output exceeds 80% of the power limit. Exceeding the power limit will automatically turn the output off.

DSP5005 Preset and Timer.png

The DPS screen supports up to two recall preset settings. Each preset setting saves the voltage, current limit, power limit, and timer value. Recall a preset by holding M1 or M2. Save a preset by holding SET + M1 or SET + M2.

If a timer is set prior to power on, a hourglass icon will flash signifying that a timer is set. When the timer elapses, power will automatically be shut off. If the timer is not set prior to power on, the timer will act as a clock and will show the duration since power on.


Voltage and current are controlled using a pair of DAC and ADCs. The two DACs control the output current and voltage while the two ADCs measure the current and voltage. Typically, you will need to calibrate these DACs and DACs in order to have accurate values.

Calibration involves finding the slope (K) and offset constant (C) of the DAC/ADC curve. The curve is linear and can be found by finding two points. For DACs, we want to map the input value to the DAC (0 ~ 4096) to the actual output value (voltage or current limits). For ADCs, we want to map the ADC output (0 ~ 4096) to its actual value (voltage or current).

Default values are defined in dps-model.h and any changes will need to be made to this file directly.

In either case, use the spreadsheet to calculate the DAC and ADC values.


The DAC is the simplest to calibrate. Hit M1 and M2 buttons simultaneously to enter the calibration menu. From this menu, you can set the input DAC values for both voltage and current DACs. Alternatively, you can set the voltage DAC value by writing to register DHR12R1 at address 0x40007408 and the current DAC by writing to register DHR12R2 at address 0x40007414.

We will map this voltage value to the actual voltage that is measured with a reference multimeter.

For voltage:

  1. Hit M1+M2 to enter calibration menu
  2. Assign Vout DAC a value of 50 (this is D1)
  3. Measure the voltage with a reference multimeter (V1)
  4. Assign Vout DAC a value of 500 (this is D2)
  5. Measure the voltage again. (V2).
  6. Calculate the K value: (D1 - D2) / (V1 - V2)
  7. Calculate the C value: D1 - (K * V1)
  8. Update values for K and C as V_DAC_K and V_DAC_C.

The same principle applies for the current DAC but with slightly different values.

  1. Hit M1+M2 to enter calibration menu
  2. Assign Iout DAC a value of 500 (this is D1)
  3. Connect a current sink (ideally 2+ amps). Measure the current as C1
  4. Assign Iout DAC a value of 1200 (this is D2)
  5. Measure the current as C2
  6. Calculate the K value: (D1 - D2) / (C1 - C2)
  7. Calculate the C value: D1 - (K * C1)
  8. Update values for K and C as A_DAC_K and A_DAC_C.


The ADC K/C values can be calibrated by calculating the original raw value based on the measured and actual voltage/current and then adjusting the existing K/C values to account for any drift. Use the spreadsheet to help with this calculation.

  1. Plug in the existing K and C values to the spreadsheet
  2. First column takes a lower value.
    1. Turn the power on so that the DPS is supplying power
    2. Enter the a voltage reading as displayed
    3. Enter the actual voltage by measuring the DPS voltage output
  3. Repeat for the higher-end value
  4. Enter the new K and C values

These steps apply to current as well.


DPS Mode on OpenDPS running on a DP50V5A

OpenDPS is opensource and is very easy to add new features. The project is relatively active and new features are being added all the time.


The Makefile is capable of rendering different fonts to be used in the firmware. Copy your ttf or otf font to the gfx directory and edit the Makefile. Alternatively, override the Makefile values and then run:

# make -C opendps fonts


Convert a png with the script:

% python gen_lookup.py -i gfx/png/poweroff.png -o poweroff
Converting gfx/png/poweroff.png to gfx-poweroff.c/h

STM32 Flash Information[edit]

The STM32F100 has a 64KB/(128KB?) flash. The original firmware is protected and cannot be read. You can disable readout protection by unlocking the STM32 microcontroller but this will wipe all existing data.

$ telnet localhost 4444
> flash list
{name stm32f1x base 134217728 size 131072 bus_width 0 chip_width 0}
> flash banks
#0 : stm32f1x.flash (stm32f1x) at 0x08000000, size 0x00020000, buswidth 0, chipwidth 0

> halt
target halted due to debug-request, current mode: Handler HardFault
xPSR: 0x61000003 pc: 0x080001d2 msp: 0x200007a8

> stm32f1x options_read 0
Option Byte: 0x3fffffe
Readout Protection On
Software Watchdog
Stop: No reset generated
Standby: No reset generated
User Option0: 0xff
User Option1: 0xff

Readout Protection is set to On, which can be changed by changing the Read Protection (RDP) level. There are 3 levels:

  • 0: No read protection.
  • 1: Read protection enabled.
  • 2: Debug/chip read protection disabled. Will disable JTAG, which is bad for our case.

By changing the RDP value from 1 to 0, you will erase the flash.

> stm32f1x unlock 0
Device Security Bit Set
target halted due to breakpoint, current mode: Handler HardFault
xPSR: 0x61000003 pc: 0x2000003a msp: 0x2000076c
stm32x unlocked.
INFO: a reset or power cycle is required for the new settings to take effect.

> stm32f1x options_read 0
Option Byte: 0x3fffffc
Readout Protection Off
Software Watchdog
Stop: No reset generated
Standby: No reset generated
User Option0: 0xff
User Option1: 0xff


On a DPS5005, these are the values I see:

> flash list
{name stm32f1x base 134217728 size 0 bus_width 0 chip_width 0}{name stm32f1x base 134217728 size 0 bus_width 0 chip_width 0}
> stm32f1x options_read 0
device id = 0x10016420
STM32 flash size failed, probe inaccurate - assuming 128k flash
flash size = 128kbytes
Option Byte: 0x3fffffe
Readout Protection On
Software Watchdog
Stop: No reset generated
Standby: No reset generated
User Option0: 0xff
User Option1: 0xff

See Also[edit]