
Ui board
sbstnh/programmable_precision_resistor
A SCPI programmable precision resistor

A SCPI programmable precision resistor
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.
A SCPI 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.
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.
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.
| Parameter | Value / Description |
|---|---|
| Range | short circuit, 1 Ω … 999.999 kΩ, open circuit |
| Setpoint resolution | 1 Ω |
| 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 resolution | 6.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) |
| Bandwidth | unspecified |
| 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 modes | Fixed: 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 mode | Up 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 |
| Switching | fast (default), break-before-make |
| Trigger | Source: Bus, External (Rising, Falling, Either), Immediate, Manual, Timer; Mode: Continuous, Single Parameter: Delay, Holdoff, Time (Source: Timer) |
| Inhibit | Inhibit 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 execution | 10ms 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 presets | 0-9; 0 is loaded on power-up |
| Interface | - USB - Two digital inputs, settable polarity (positive, negative) and function (trigger, inhibit, readout) |
| Power supply | Switch mode |
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:
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.

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.

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

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:
More details are available at https://hackaday.io/project/191969-programmable-precision-resistor and on my personal site https://sebastianharnisch.de.
The firmware was created with STM32CubeIDE and uses code auto-generated by or provided with the IDE, including
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).
| Qty | Value | Footprint | References |
|---|---|---|---|
| 41 | BAV99 | Package_TO_SOT_SMD:SOT-23 | D1, D2, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31, D32 +25 |
| 39 | EC2-12NU | 01_Sebastian:Relay_DPDT_Kemet_EC2 | K1, K2, K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K20, K21, K22, K23 +23 |
| 39 | LED | LED_SMD:LED_0805_2012Metric | D3, D4, D10, D11, D12, D13, D14, D15, D16, D38, D39, D40, D41, D42, D43, D44 +23 |
| 11 | 100n | 01_Sebastian:C_0805_2012Metric_Box | C3, C4, C5, C6, C9, C12, C13, C14, C17, C18, C19 |
| 9 | 2 | 01_Sebastian:R_1206_3216Metric_Box | R16, R17, R18, R19, R20, R21, R22, R23, R24 |
| 9 | 20 | 01_Sebastian:R_1206_3216Metric_Box | R25, R26, R27, R28, R29, R30, R31, R32, R33 |
| 9 | 200 | 01_Sebastian:R_1206_3216Metric_Box | R34, R35, R36, R37, R38, R39, R40, R41, R42 |
| 9 | 200k | 01_Sebastian:R_1206_3216Metric_Box | R61, R62, R63, R64, R65, R66, R67, R68, R69 |
| 9 | 20k | 01_Sebastian:R_1206_3216Metric_Box | R52, R53, R54, R55, R56, R57, R58, R59, R60 |
| 9 | 2k | 01_Sebastian:R_1206_3216Metric_Box | R43, R44, R45, R46, R47, R48, R49, R50, R51 |
| 8 | M3 | MountingHole:MountingHole_3.2mm_M3_DIN965_Pad | H1, H2, H3, H4, H5, H6, H7, H8 |
| 6 | 2.2k | 01_Sebastian:R_0805_2012Metric_Box | R1, R2, R8, R9, R14, R15 |
| 4 | 100k | 01_Sebastian:R_0805_2012Metric_Box | R3, R4, R6, R7 |
| 3 | 1.5k | 01_Sebastian:R_0805_2012Metric_Box | R70, R71, R72 |
| 3 | STP16CP05 | Package_SO:TSSOP-24_4.4x7.8mm_P0.65mm | U5, U6, U7 |
| 2 | 10k | 01_Sebastian:R_0805_2012Metric_Box | R10, R11 |
| 2 | 27p | 01_Sebastian:C_0805_2012Metric_Box | C7, C8 |
| 2 | 33 | 01_Sebastian:R_0805_2012Metric_Box | R12, R13 |
| 2 | GND | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP1, TP2 |
| 2 | JTP1236 | 01_Sebastian:JTP1236 | SW1, SW2 |
| 2 | KTY82 | Package_TO_SOT_SMD:SOT-23 | TH1, TH2 |
| 1 | +15V IN | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP3 |
| 1 | +15V SW | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP10 |
| 1 | +3.3V | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP4 |
| 1 | 100u | Capacitor_Tantalum_SMD:CP_EIA-7343-31_Kemet-D_Pad2.25x2.55mm_HandSolder | C1 |
| 1 | 10n | 01_Sebastian:C_0805_2012Metric_Box | C15 |
| 1 | 10u | 01_Sebastian:C_0805_2012Metric_Box | C2 |
| 1 | 16MHz | Crystal:Crystal_HC49-4H_Vertical | Y1 |
| 1 | 1k | 01_Sebastian:R_0805_2012Metric_Box | R5 |
| 1 | 1u | 01_Sebastian:C_0805_2012Metric_Box | C16 |
| 1 | 24C32 | Package_SO:SO-8_3.9x4.9mm_P1.27mm | U3 |
| 1 | 4.7u | 01_Sebastian:C_0805_2012Metric_Box | C10 |
| 1 | 74HC14 | Package_SO:SOIC-14_3.9x8.7mm_P1.27mm | U2 |
| 1 | BSS138 | Package_TO_SOT_SMD:SOT-23 | Q1 |
| 1 | Conn_01x03_Male | Connector_Phoenix_MSTB:PhoenixContact_MSTBA_2,5_3-G_1x03_P5.00mm_Horizontal | J2 |
| 1 | Conn_02x03_Odd_Even | Connector_IDC:IDC-Header_2x03_P2.54mm_Vertical | J5 |
| 1 | DISP_RESET | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP7 |
| 1 | EXT_IN1 | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP5 |
| 1 | EXT_IN2 | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP6 |
| 1 | INT_UI | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP9 |
| 1 | MOSI | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP12 |
| 1 | NSS | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP14 |
| 1 | PWR | Connector_Molex:Molex_KK-254_AE-6410-03A_1x03_P2.54mm_Vertical | J1 |
| 1 | RES1 | Connector_Molex:Molex_KK-396_A-41791-0005_1x05_P3.96mm_Vertical | J6 |
| 1 | SCK | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP13 |
| 1 | SCL | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP8 |
| 1 | SDA | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP11 |
| 1 | STM32G441KB | Package_QFP:LQFP-32_7x7mm_P0.8mm | U4 |
| 1 | TSM3401 | Package_TO_SOT_SMD:SOT-23 | Q2 |
| 1 | UI | Connector_IDC:IDC-Header_2x03_P2.54mm_Vertical | J4 |
| 1 | USBLC6-2SC6 | Package_TO_SOT_SMD:SOT-23-6 | U1 |
| 1 | USB_B | Connector_USB:USB_B_Lumberg_2411_02_Horizontal | J3 |
| 1 | dnp | 01_Sebastian:C_0805_2012Metric_Box | C11 |
| 1 | ~{OE} | TestPoint:TestPoint_Loop_D1.80mm_Drill1.0mm_Beaded | TP15 |

sbstnh/programmable_precision_resistor
A SCPI programmable precision resistor

sbstnh/programmable_precision_resistor
A SCPI programmable precision resistor


Reemuson/MENG4210-Project
Data Recording and Electrophysiological Acquisition Module

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.


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

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.

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

It measures 139 × 190 mm and has 2 copper layers, 1.6 mm thick.
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.
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.
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).