Skip to the content
2 layers139 × 190 mmProgrammable precision resistor, the printed circuit board in 3D

Programmable precision resistor

sbstnh/programmable_precision_resistor65

A SCPI programmable precision resistor

Size
139 × 190 mm
Copper layers
2
Thickness
1.6 mm
Parts
253
Nets
321
Pads
901
Tracks, vias
1,447, 103
Pours
13
Routed
Yes
KiCad
KiCad 9.0 (file 20241229)
Created
18 Aug 2023
Updated
2 Nov 2025

Overview

Programmable precision resistor is an open-source printed circuit board by sbstnh, from the sbstnh/programmable_precision_resistor repository on GitHub, published under the BSD-3-Clause licence. It is a 2-layer board of 139 × 190 mm with 253 parts on 321 nets, routed with 1,447 tracks and 103 vias.

It is built around the STM32G441KBT6, STP16CP05T and 24C32, with the 74HC14, USBLC6-2SC6 and BAV99 among its other parts. Its parts include 80 diodes, 72 resistors, 41 switches, 19 capacitors and 7 ICs. It belongs with the STM32 boards of this library.

Main components

8

README

README.md

Programmable Precision Resistor

A SCPI programmable precision resistor

Programmable Precision Resistor

WARNING: The programmable power resistor presented is mains powered. On the power supply board there will be mains/line voltage. Working with/on such devices can lead to damage, injury or death. Don't do it if you're not qualified or authorized to do so. You use the circuits described at you own risk. You have to make sure that the circuit is safe and adheres to the applicable standards in your location. You might operate the mainboard and ui board more safely with a bench or external power supply.

WARNING: I abandoned the AC/DC converter of the initial design mostly due to EMI issues. I ended up using a EI-core (isolation) transformer, bridge rectifier, capacitor two tiny DC/DC converters. Some of the documentation does not reflect this change.

Background and motivation

In 2021/2022 I designed a DC electronic load that would be more capable, but also much more complex than the usual DIY solutions. However, after building a working breadboard prototype of the analog circuitry with 12 ICs including multiple precision and dual opamps, I thought that it might be better to start with a smaller project that would allow me to gain a lot of experience and write much of the non-application specific code that I could use later on for the digital part. Also, at the time I was looking for a decade resistor box to add to my lab. And this is how I started working on a programmable decade resistor, a pretty specialized tool for niche applications.

Introduction

A programmable resistor is a electronic device whose electrical resistance can be adjusted typically through digital signals. Programmable resistors are available in form of integrated circuits (often referred to as digital potentiometers) as well as stand-alone devices/expansion cards. There are many different applications, each with their own set of requirements e. g.:

programmable gain amplifiers sensor emulation, e. g. for integration tests with hardware-in-the-loop simulators automated testing calibrators prototyping Basic concept The programmable resistor closely follows the main principle of resistor decade boxes: connecting multiple devices (“decades”) in series, with each of the devices having a settable resistance of 0 Ω, 1 ⋅ 10^n Ω, 2 ⋅ 10^n Ω, 9 ⋅ 10^n Ω, where n specifies the decade in question.

Those devices are simple resistor networks complemented by one (multi-throw) or more (single- or multi-throw) switches. While the actual topology and resistor values vary vastly, the switch(es) will always either short out or connect certain resistors or simply tap certain nodes of the resistor network. A simple implementation uses a 10-throw rotary switch to tap the nodes of a series resistor network of nine resistors.

Features

ParameterValue / Description
Rangeshort circuit, 1 Ω … 999.999 kΩ, open circuit
Setpoint resolution1 Ω
Short-term setpoint accuracy estimate<=±0.1% of value + 0.15 Ω (2W and 4W). The estimate is based on measurements for a limited number of calibration and validation resistance setpoints. The measurements were performed with an older Agilent 34401A 6.5 digit multimeter for a single DUT. This is NOT a valid strategy to get reliable/reproducible results in the sense of a specification. It's just a more or less plausible envelope based on measurements I took for my prototype.
Display value resolution6.5 digits, 5.5 digits, 4.5 digits, 3.5 digits, but not better than 1 mΩ
Short-term display accuracy estimate<=±0.01% + 0.025 Ω (2W and 4W). This figure is meant to show how much the displayed resistance value (that is based on a calibration) deviates from the value shown on the DMM, the calibration has been performed with.
Thermal drift (estimate based on design)<<50 ppm/K
Power rating>=0.2W for decade 0 (0..9Ω),
>=0.5W else
Exact value depends on setpoint (display)
Bandwidthunspecified
Calibration modes- Uncalibrated: Switches are activated according to entered setpoint, display shows setpoint
- Two-wire (2W), Four-wire (4W): An internal setpoint is calculated based on the calibration values to reduce the error (effects changes for higher resistance values only)
Operating modesFixed: On trigger no change
Step: On trigger step to trigger setpoint value
Up: On trigger increase setpoint (linearly, 1-2-3-4-5-6-7-8-9, 1-2-5, 1-3)
Down: On trigger increase setpoint (linearly, 1-2-3-4-5-6-7-8-9, 1-2-5, 1-3)
List: See list mode
List modeUp to 100 values with individual dwell times
- Start: on trigger; or immediately after mode selection
- Step:
- Auto: Advance index automatically, solely based on dwell time
- Trigger: Advance index on each trigger event, ignoring the dwell time
- Once: Advance index on each trigger event, only after dwell time elapsed
Switchingfast (default), break-before-make
TriggerSource: Bus, External (Rising, Falling, Either), Immediate, Manual, Timer;
Mode: Continuous, Single
Parameter: Delay, Holdoff, Time (Source: Timer)
InhibitInhibit the input
- Latching: Latch input on/off on inhibit input change
- Live: Switch input on/off according to present inhibit input state
Command and trigger execution10ms loops
User interface- 18 digit alphanumeric display:
- Primary display: Resistance setpoint
- Secondary display: Input state, max. current at setpoint, max. voltage at setpoint, max. power at setpoint, hardware setpoint
- Menu-based
- 6 dual color LEDs
- Rotary encoder with push button
- 23 additional push buttons
User presets0-9; 0 is loaded on power-up
Interface- USB
- Two digital inputs, settable polarity (positive, negative) and function (trigger, inhibit, readout)
Power supplySwitch mode

System design

System block diagram

The block diagram provides an overview of the different circuit groups of each functional block, their internal connections and external interfaces. The Programmable Decade Resistor consists of three main functional blocks:

  1. Power supply (Power Supply Board), an external EMI filter is required.
  2. Programmable decades, control and driver circuits (Mainboard)
  3. User Interface (User Interface Board)

The power supply board uses an off-the-shelve AC/DC converter to provide a +15V rail. The +15V rail powers the relays on the mainboard as well as a DC/DC converter. A single DC/DC converter generates a +3.3V supply for both the mainboard and the UI board, including the LED display. The power rails are earth-referenced. (Nevertheless, the inputs of the Programmable Decade Resistor are floating thanks to the isolation of the relays.)

The mainboard’s main controller contains the business logic to control the relays, read the external inputs and run the USB and user interfaces. The main controller communicates with the User Interface Board over I2C which handles the multiplexing of the alphanumeric LED display, scans the switch matrix, decodes the signals of the rotary encoder and drives the buzzer.

Note that these pictures DO NOT represent the final design of the Programmable Precision Resistor and the power supply circuit in particular. Programmable Precision Resistor Programmable Precision Resistor

Results

After the final calibration the results are in. The first diagram shows the absolute value of the deviation between the setpoint and the value indicated by the Agilent 34401A multimeter. Connecting lines between data points for visual purposes only.

Absolute error

The second diagram shows the absolute value of the deviation between the calculated resistance (estimate based on calibration values) and the value indicated by the Agilent 34401A multimeter. Connecting lines between data points for visual purposes only

Absolute error of indicated value

About this repository

This repository contains the PCB design files used in this project. If you'd like to have a look at the interactive bom files you can do so here:

Further information

More details are available at https://hackaday.io/project/191969-programmable-precision-resistor and on my personal site https://sebastianharnisch.de.

Firmware and License

The firmware was created with STM32CubeIDE and uses code auto-generated by or provided with the IDE, including

  • the HAL library, code related to the USB device and other code
  • FreeRTOS

Further more, this project uses a SCPI parser library that can be found here: https://github.com/j123b567/scpi-parser

Most of the auto-generated code as well as the libraries are not included here. Therefore it is recommended to use STM32CubeIDE to create a project for the target device, with the USB device software and FreeRTOS enabled, add the required SCPI library and adapt the code according to the requirements.

For the code not included in this repository the respective licenses will apply instead of the license specified in this repository.

I DO NOT guarantee that the code provided is free of bugs (see LICENSE file for more details).

Parts

253
QtyValueFootprintReferences
41BAV99Package_TO_SOT_SMD:SOT-23D1, D2, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31, D32 +25
39EC2-12NU01_Sebastian:Relay_DPDT_Kemet_EC2K1, K2, K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K20, K21, K22, K23 +23
39LEDLED_SMD:LED_0805_2012MetricD3, D4, D10, D11, D12, D13, D14, D15, D16, D38, D39, D40, D41, D42, D43, D44 +23
11100n01_Sebastian:C_0805_2012Metric_BoxC3, C4, C5, C6, C9, C12, C13, C14, C17, C18, C19
9201_Sebastian:R_1206_3216Metric_BoxR16, R17, R18, R19, R20, R21, R22, R23, R24
92001_Sebastian:R_1206_3216Metric_BoxR25, R26, R27, R28, R29, R30, R31, R32, R33
920001_Sebastian:R_1206_3216Metric_BoxR34, R35, R36, R37, R38, R39, R40, R41, R42
9200k01_Sebastian:R_1206_3216Metric_BoxR61, R62, R63, R64, R65, R66, R67, R68, R69
920k01_Sebastian:R_1206_3216Metric_BoxR52, R53, R54, R55, R56, R57, R58, R59, R60
92k01_Sebastian:R_1206_3216Metric_BoxR43, R44, R45, R46, R47, R48, R49, R50, R51
8M3MountingHole:MountingHole_3.2mm_M3_DIN965_PadH1, H2, H3, H4, H5, H6, H7, H8
62.2k01_Sebastian:R_0805_2012Metric_BoxR1, R2, R8, R9, R14, R15
4100k01_Sebastian:R_0805_2012Metric_BoxR3, R4, R6, R7
31.5k01_Sebastian:R_0805_2012Metric_BoxR70, R71, R72
3STP16CP05Package_SO:TSSOP-24_4.4x7.8mm_P0.65mmU5, U6, U7
210k01_Sebastian:R_0805_2012Metric_BoxR10, R11
227p01_Sebastian:C_0805_2012Metric_BoxC7, C8
23301_Sebastian:R_0805_2012Metric_BoxR12, R13
2GNDTestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP1, TP2
2JTP123601_Sebastian:JTP1236SW1, SW2
2KTY82Package_TO_SOT_SMD:SOT-23TH1, TH2
1+15V INTestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP3
1+15V SWTestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP10
1+3.3VTestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP4
1100uCapacitor_Tantalum_SMD:CP_EIA-7343-31_Kemet-D_Pad2.25x2.55mm_HandSolderC1
110n01_Sebastian:C_0805_2012Metric_BoxC15
110u01_Sebastian:C_0805_2012Metric_BoxC2
116MHzCrystal:Crystal_HC49-4H_VerticalY1
11k01_Sebastian:R_0805_2012Metric_BoxR5
11u01_Sebastian:C_0805_2012Metric_BoxC16
124C32Package_SO:SO-8_3.9x4.9mm_P1.27mmU3
14.7u01_Sebastian:C_0805_2012Metric_BoxC10
174HC14Package_SO:SOIC-14_3.9x8.7mm_P1.27mmU2
1BSS138Package_TO_SOT_SMD:SOT-23Q1
1Conn_01x03_MaleConnector_Phoenix_MSTB:PhoenixContact_MSTBA_2,5_3-G_1x03_P5.00mm_HorizontalJ2
1Conn_02x03_Odd_EvenConnector_IDC:IDC-Header_2x03_P2.54mm_VerticalJ5
1DISP_RESETTestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP7
1EXT_IN1TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP5
1EXT_IN2TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP6
1INT_UITestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP9
1MOSITestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP12
1NSSTestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP14
1PWRConnector_Molex:Molex_KK-254_AE-6410-03A_1x03_P2.54mm_VerticalJ1
1RES1Connector_Molex:Molex_KK-396_A-41791-0005_1x05_P3.96mm_VerticalJ6
1SCKTestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP13
1SCLTestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP8
1SDATestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP11
1STM32G441KBPackage_QFP:LQFP-32_7x7mm_P0.8mmU4
1TSM3401Package_TO_SOT_SMD:SOT-23Q2
1UIConnector_IDC:IDC-Header_2x03_P2.54mm_VerticalJ4
1USBLC6-2SC6Package_TO_SOT_SMD:SOT-23-6U1
1USB_BConnector_USB:USB_B_Lumberg_2411_02_HorizontalJ3
1dnp01_Sebastian:C_0805_2012Metric_BoxC11
1~{OE}TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_BeadedTP15

More from sbstnh/programmable_precision_resistor

2
  • 2 layers212 × 67 mmUi board, the printed circuit board in 3D

    Ui board

    sbstnh/programmable_precision_resistor

    A SCPI programmable precision resistor

    133 parts65BSD-3-Clause
  • 2 layers70 × 159.5 mmPower supply, the printed circuit board in 3D

    Power supply

    sbstnh/programmable_precision_resistor

    A SCPI programmable precision resistor

    49 parts65BSD-3-Clause

Similar boards

  • 2 layers268 × 62 mmSmu front 1, the printed circuit board in 3D

    Smu front 1

    jaromir-sukuba/J-SMU

    DIY source-measure unit

    90 parts244
  • 2 layers100 × 60 mmDREAM, the printed circuit board in 3D

    DREAM

    Reemuson/MENG4210-Project

    Data Recording and Electrophysiological Acquisition Module

    137 partsMIT
  • 4 layers64.3 × 70.4 mmVETO BOX V0.0.1, the printed circuit board in 3D

    VETO BOX V0.0.1

    va-cyber-zha/VETO_BOX_V0.0.1

    Cosmic veto box - Scintillator box with SIPMs measuring cosmic radiation. Inside the box will be placed test subject, and with the PCB I designed, filter out the cosmic noise from a measurement.

    119 partsMIT
  • 2 layers61 × 61 mmJuwei17onstep, the printed circuit board in 3D

    Juwei17onstep

    xlazam01/Juwei17

    Upgrade of Juwei17 Astronomy Mount

    140 parts9MIT
  • 4 layers50 × 50 mmPicr 1 9tdi, the printed circuit board in 3D

    Picr 1 9tdi

    ducman1998/basket-ball-robot

    DeltaX Basketball Track robot (University of Tartu) | Source code, robot design and electronic schematics |🥉Won 3rd place out of 10 teams | The fastest robot in the competition

    84 parts1
  • 2 layers48.7 × 22.5 mmAirsticks pcb, the printed circuit board in 3D

    Airsticks pcb

    lizboyer/Airsticks

    Airsticks was a project by myself (Elizabeth Boyer), Christian Tchilikov, and Dearborn Plys. It uses accelerometers, a speaker, an STM32 MCU, and a board we created.

    69 parts1
  • 2 layers64.7 × 35.3 mmStm32g441kbt6 development, the printed circuit board in 3D

    Stm32g441kbt6 development

    jalikins/STM32_bazel_development

    This repository contains a hermetic Bazel build configuration for STM32 microcontrollers (specifically targeting the STM32G4 series).

    57 partsMIT
  • 4 layers75 × 25 mmIntro Board v1, the printed circuit board in 3D

    Intro Board v1

    pc-neal/MoonPCB

    Ashur, Patrick, and Matthew "Floppy Balls" Schettino

    67 parts

Questions

How big is the Programmable precision resistor PCB?

It measures 139 × 190 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Programmable precision resistor use?

253 parts, built around the STM32G441KBT6, STP16CP05T, 24C32 and 74HC14. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Programmable precision resistor KiCad files?

From the sbstnh/programmable_precision_resistor repository on GitHub, at the commit this page was made from: the board is pcb/mainboard/mainboard.kicad_pcb and its schematic mechanical/front_panel/front_panel.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Programmable precision resistor design in my own project?

Its repository publishes it under the BSD-3-Clause licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).