Programmable Precision Resistor

A SCPI programmable precision resistor

Public Chat
Similar projects worth following
In this project I build a SCPI programmable precision resistor - if you will a glorified decade resistance box. At first glance it's as simple as connecting a few relays and resistors with each other. Let me tell you: Not quite. I will share my thought process designing the device.

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.


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
  • hardware-in-the-loop simulation (detailed explanation below)
  • 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 ⋅ 10n Ω, 2 ⋅ 10n Ω, 9 ⋅ 10n Ω, where n specifies the decade in question.

A manually operated Siemens B2086 Decade Resistor

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.

Schematic of a simple resistor decade with a 10-throw rotary switch


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. Measurements performed with an Agilent 34401A 6.5 DMM for a single DUT.

Note: 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.

The initial goal was achieved: (much) better than ±0.5% of value + 0.3 Ω
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 (shown on 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, decrease 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...
Read more »

  • Power supply

    Sebastian5 days ago 0 comments

    Just a quick follow-up on this project. Today I switched the unit on and after a briefly turning on it shut off again, completely dead. I checked the fuses - all fine. So I had to open the case and I was presented with the smell of burnt components - but nothing really visible.

    The only logical explanation: Either the DC/DC converter or the inrush current limiting resistor must have gone (or both, obviously). My money was on the inrush current limiting resistor and sure enough it reads >2 MOhms. No burn marks though. At closer inspection I found that I used an unsuitable resistor: It has a flame-proof coating, but the datasheet does not mention that it is surge/pulse rated. Oops! 

    Also, the schematics showed a 33 Ohm resistor, which is a copy & paste error. I actually used a more appropriate 12 Ohm resistor - with 33 Ohms the power dissipation is needlessly high, especially at 120V. Now I have to order a more appropriate replacement...

  • Project costs

    Sebastian09/11/2023 at 15:27 0 comments

    I didn't really think about the BOM cost of my programmable decade resistor until I was asked. Then I also wanted to know. It is fairly difficult to put a number to what I paid, since I had a lot of components left from other projects that I could use. This includes not only cheap chip resistors and MLCCs, but also connectors, the microcontrollers etc.

    Normally, I order my parts from mouser and digikey. For some of the industry-standard components, connectors etc. I also use local distributors (cheaper!). This is why I'll only give a very rough estimate for the per unit costs including taxes (and not including any shipping costs). For some of the parts like the PCBs there is a minimum order quantity that will increase the cost in most DIY scenarios.

    Mechanical parts

    #Description€ (est.)
    1ELMA Stylebox 15 Standard (not new)50,00
    2Front & Rear panels (Aluminum PCBs)5,00
    3Rotary encoder knobs and key caps10,00
    4IEC power connector + Fuse3,00
    54mm banana sockets8,00
    6Connectors, cables etc.2,00
    7Mounting hardware2,00


    #Description€ (est.)
    1Mainboard PCB3,50
    3EC2-12NU relays (or similar)73,50
    4Precision resistors63,00
    5Other components30,00

    UI Board

    #Description€ (est.)
    1UI PCB2,50
    3STP16CP05 constant current LED drivers10,00
    4LED displays15,00
    5Rotary encoder and switches37,00
    6Other components12,00

    Power supply board

    #Description€ (est.)
    1Power supply PCB1,00
    1TRACO TMPW 10-11519,50
    1NE-18 series power switch8,50
    1Other components5,00


    According to this calculation the total cost of the unit would be about 369 €. Quite a lot, actually. This doesn’t necessarily reflect what I paid for it though. One example: I bought 5 NE-18 type switches on ebay for about 2 € each. These are not necessarily the same as the ones provided by mouser, but both variants could be used.

  • Panels

    Sebastian09/05/2023 at 17:17 0 comments

    I was asked a few times how I did the front and rear panels, so this is what I’d like to talk about in this blog. There are different ways to achieve a similar result. For me, the easiest and most cost-effective solution was to just design another PCB – I know how KiCAD works and it does everything I need it to do.

    The basics

    Depending on the actual use case you can use a regular FR-4 board. For this project, however, I chose an aluminum PCB. Those only have one copper layer and the prototyping service might (and probably will) specify different limits/process parameters. But other than that it is very similar to designing a regular PCB.

    The first question might be which side of the PCB shall be visible. For this I chose the top side, i. e. the side where the copper layer would be. This allows me to remove the solder mask from the bottom, exposing the bare aluminum (again: This is a one layer PCB). Now the aluminum part makes good electrical contact with the case, so that it can be grounded properly (safety) and work as a shield.

    "Bottom" side of the panel: Bare aluminum

    Then I removed the copper layer (almost) completely, because I didn’t want to risk having a large floating conductor anywhere*. The solder mask, however, stays in place, giving the front panel its white color. The (black) silk screen is perfectly suitable to group and label the controls, connectors etc. In theory you could remove the solder mask partially on the front panel as well, exposing the aluminum to give you a fourth color. If you decide not to completely remove the copper, but expose it instead, you have the option for a fifth color. Whether this is a good idea is up to you.

    Rear panel

    *) At this point it probably wouldn’t really matter which side you use for the solder mask and silk screen I think

    A few tips

    If you plan to use certain components over and over again, maybe for different projects or maybe just because you have 20 switches of the same type on your UI board, it might be really handy to create a footprint for the cutout, labels, graphics etc. The same is also true for the outline of the panel itself. Most of my projects use the same cases, switches, power connectors etc. over and over again – so creating the footprints is what I did.

    In some use cases you might find helpful to place symbols on a schematic and import the footprints based on the schematic. In most cases this would be overkill though – simply adding the footprints to the PCB (in Pcbnew) does the job equally well.

    A simple 3d model of the programmable resistor. Some components are missing. Nevertheless it was very helpful to avoid mistakes during the design phase

    Many case and component manufacturers provide 3D models on their websites that can be combined into an assembly with all the panels and PCBs to catch errors early on. Unfortunately, there is no 3D model available for the switches I used and I couldn’t be bothered to create them myself. Still, this approach helped me to avoid some issues with the front panel that would have required a second revision otherwise – now the first revisions of both the front and rear panels worked perfectly.

    The design

    The layout of the user interface etc. depends on the application and is completely up to you – obviously. The labeling, the fonts, additional graphics and so on can improve or hurt the usability significantly. So it’s usually a good idea to spend quite a bit of time thinking about how you and more importantly any other operator should or would likely use the device and make it as easy to work with as possible. It can be helpful to go through a few iteration on paper (or any suitable program) before even starting the implementation in your PCB software.

    Also it’s really helpful to take some inspiration from the designs of big TME manufacturers like HP/Agilent/Keysight, Keithley, Tektronix & co. You don’t have to copy them, but adopting some of the general concepts they use might get you started...

    Read more »

  • Mechanical Parts

    Sebastian08/31/2023 at 20:02 0 comments

    After being asked about some aspects of the mechanical design and components used a few times, I'd like to address those questions. I have to admit that I'm neither very good at the mechanical design, nor do I have a 3d printer (yet) or a shop where I can do metal work myself. That being said, I was still able to design a reasonably professional looking device and bring it to life with the help of modern prototyping services.

    The new 3D printed knob for the rotary encoder.

    CaseELMA, Stylebox 15 Standard; 2 RU, 42HP (half 19")Very expensive for a typical DIY project, although I don't know the exact pricing
    Front and Rear panels1.6mm Aluminium PCB with white solder mask and black silk screenSee next post for details
    PCB mountingStand-offs (M3)Stand-offs are connected to chassis (earth).

    However, the circuit is earth referenced via cable (connected to the power connector).
    New Rotary knob3d printed (MJF)Most pictures were taken with the old temporary knob
    Push buttonsC&K/littlefuse PVA series switches with matching capsDifferent force ratings available
    Line switchC&K NE18 series switchCan be a pain to design and print a connecting rod if the switch is located far back in the unit.

    I just used a thin wood rod and some tiny shaft coupling to connect the rod with the switch. Seems to work just fine.

    A 3d printed part would be more professional, no doubt about it
    Red filter for displayColor filter, Red foil, 0.3mm; random amazon product; glued to the back of the front panelWorks surprisingly well, however it's obviously not as strong as acrylic glas.

    Reminds me of the HP/Agilent 66xx series power supplies (and other products) with the thin foil covering their LCD displays.

    Wouldn't like that for commercial use at all ;) 

    Next steps

    There will be a separate post where I explain the fairly straight forward process of designing the front and rear panels.

  • Final calibration results

    Sebastian08/28/2023 at 16:05 0 comments

    After the modification described in the previous log I let the “adjustment” and calibration procedure run again. 5 days later I repeated the calibration (without doing the adjustment). As before, all measurements are performed with an Agilent 34401A 6.5 digit multimeter.

    Accuracy of the resistance

    First up is a diagram that shows the absolute value of the deviation of the measurement from the setpoint. The tested values are grouped as follows:

    • Calibration points: There are 55 calibration points (0 Ω, 1 Ω, 2 Ω, .., 9 Ω; 10 Ω, 20 Ω, .., 90 Ω; 100 Ω, 200 Ω, .., 900 Ω; 1 kΩ, 2 kΩ, .., 9 kΩ; 10 kΩ, 20 kΩ, .., 90 kΩ; 100 kΩ, 200 kΩ, .., 900 kΩ). In the diagram, all calibration points are connected via lines for visual purposes only. This does NOT imply that we can estimate the deviation for setpoints between two calibration points by looking at this line.
    • Validation points: These are 9 randomly selected values per decade for the upper five decades. All values of the first decade are already included in the calibration points. This results in 45 additional points. Validation points are not connected by a line.

    The diagram includes curves for the following scenarios:

    • UNCAL@4W: The programmable resistor is used in its uncalibrated mode, where the user selectable setpoint equals the hardware setpoint. If, for example, the user enters 130 kΩ, the 6th decade would be in the 100kΩ, the 5th decade in the 30kΩ and all other decades in the shorted position. Also, the display logic ignores the calibration constants and shows 130.000 kΩ. (The input LED switches to red in order to indicate the uncalibrated mode.) For the diagram shown, the measurement was performed using a four-wire resistance measurement
    • 2W: In the calibrated two-wire mode, the programmable resistor uses the two-wire calibration constants to optimize the hardware setpoint so that the actual resistance value is as close to the setpoint as possible. The calibration in this scenario is also performed using two-wire measurements
    • 4W: In the calibrated four-wire mode, the programmable resistor uses the four-wire calibration constants to optimize the hardware setpoint so that the actual resistance value is as close to the setpoint as possible. The calibration in this scenario is also performed using four-wire measurements

    There are two curves to assess whether/which specifications can be fulfilled:

    • In order to compare the results with the requirements defined in the project description, the diagram shows a curve where the absolute value of the deviation would be equal to 0.5% of value + 0.3 Ω
    • A second curve narrows the spec down to 0.1% of value + 0.15 Ω

    The programmable decade resistor is not perfect. Neither is my test setup. I use an Agilent 34401A 6.5 digit multimeter for my measurements. The calibration string of the unit used for this particular calibration shows "9 NOV 2001 23.9C". I have done a plausibility check with a 1 kΩ Vishay 0.005% 2ppm/K precision resistor and it measured surprisingly close to spot on (yeah, it's only one range). Also, I have a second 34401A that shows generally very similar values, so I'm confident that the Agilent 34401A has no obvious defect. But let's be clear: That's just the best I can do right now in terms of absolute accuracy. But even if the meter had a recent successful calibration, the DMM is not perfect. Therefore the diagram includes three curves that characterize the accuracy we can expect from the Agilent 34401A multimeter (absolute value; measured values could deviate in positive as well as negative direction by the amount indicated). These are based on a Keysight datasheet ("published in USA, July 8, 2022"). With all these things out of the way, here is the diagram:

    Absolute value of the deviation between the setpoint...

    Read more »

  • A quick Optimization

    Sebastian08/25/2023 at 15:01 0 comments

    I went into this project with the thought that it will be a rather small one. This certainly influenced some decisions I made along the way. Now that the project had evolved into a much larger thing than initially anticipated it’s reasonable to have another look at possible optimizations, albiet the calibration results were already pretty satifactory. A small modification - seen in the following picture - can make quite a difference, so why not do it?

    A green 20 kΩ resistor soldered on top of the 20 Ω resistor in order to improve accuracy for low resistance values. Note the similarities of the PCB layout and the second schematic shown below.

    The contact resistance again

    From the start it was clear that the relays’ contact resistances will reduce the accuracy of the programmable decade resistor, especially in the lower two decades.

    To mitigate this issue I used high quality relays and paralleled their two poles. To further improve accuracy I added bypass relays for the lower three decades that bypass effectively shorted higher decades. What I did not do though: Adding footprints to improve accuracy by measuring the actual resistance and connect a matching resistor in parallel to the "main" resistors. Again, this was intentional to reduce complexity and the required board space. Also, the contact resistance is not constant, so there will always be some deviation caused by the relays. And with the topology I selected it’s not quite so easy to compensate for the contact resistances, because the contact resistance varies between odd and even resistance values. These problems are a byproduct of reducing the number of relays required.

    And of course, shorted decades (nominal resistance of 0 Ω) will always have a residual resistance, bypass relays present or not. Shall we compensate for those as well to get better accuracy for the lower decades at the cost of the higher decades where the bypass relays are not available? One could argue that it would be preferable to do so, because a few milliohms do not matter for larger values.


    That being said, improvements can be achieved even if the result will be far from perfect even after the optimization. Let’s take a look at the schematic of the first decade:

    Simplified decade resistor topology

    There are two variants I’d like to discuss that improve the situation:

    • Variant 1: We connect resistors in parallel with R4 and R6 respectively that reduce each resistance by about one relay’s contact resistance (as per calibration results about 25 mΩ).
    • Variant 2: We only use one resistor, parallel to R6, so that the resistance is reduced by two times the contact resistance (50 mΩ)
    Nominal resistance


    Relays in
    signal path
    Contact resistance (ca.)


    Expected offset with variant 1 (ca.)


    Expected offset with variant 2 (ca.)


    0SW3, SW4, bypass relays0.0750.0750.075
    1SW4, bypass relay0.0500.0250.050
    2; 4; 6; 8SW3 and (SW7 or SW10 or SW13 or SW15) and bypass relay0.0750.0500.025
    3; 5; 7; 9(SW7 or SW10 or SW13 or SW15) and bypass relay0.0500.0000.000
    Demonstration of the effect of the two modification variants for the first decade

    We can clearly see that both solutions are not perfect. I prefer variant 2, because this improves the situation significantly for all resistance values greater than 1. In contrast, with variant 1 we have a large offset of about two times the contact resistance for all even values, whereas for odd values we have reduced the offset to ~0: The error varies significantly between consecutive resistance values.

    But how would we calculate the resistance required for variant 2? The calculation is very simple. With Rp as the resistance of a parallel connection and Rp1 and Rp2 as the branch resistances we get:

    Let's say we want to decrease R6 by 50 mΩ, then we calculate the value of the resistor Rp1 to be connected in parallel as follows:


    In reality, we...

    Read more »

  • First calibration test

    Sebastian08/22/2023 at 16:02 0 comments

    In one of the previous logs I covered in depth, how I use the term “calibration” in the context of the programmable decade resistor and how the calibration procedure works. Now it's time for an initial test of the calibration procedure. To automate the calibration I wrote a little Python script that interfaces with the programmable resistor as well as the multimeter (Agilent 34401A) via PyVISA and SCPI commands.

    Automated calibration procedure using SCPI commands

    Adjustment/calibration results

    The result table shows a selection of calibration points for the 4 wire mode. It has the following columns:

    • Applied value: Value applied to the input for checking the calibration
    • Calculated value: Estimation of the actual resistance, based on the previous “adjustment” procedure
    • Ind. value: Indicated value/Measurement taken with an Agilent 34401A 6.5 digit multimeter
    • Min: Minimum value according to initial accuracy goals
    • Max: Maximum value according to initial accuracy goals
    • Dev.: Deviation between indicated value and applied value in percent
    • Dev. Calc. to Ind.: Deviation between calculated value based on the calibration constants and the indicated value
    Applied value (Ω)Calculated value (Ω)Ind. value (Ω)Min (Ω)Max (Ω)Dev. (%)Dev. Calc. to Ind. (%)
    Excerpt of the calibration results for four-wire measurement

    As expected, the programmable decade resistor stays well within the initial goal of << 0.5% of value + 0.3 Ω. That, however, was a pretty low bar. At the upper end, the performance is fairly impressive and showed how well the algorithm described in this post actually works. Also, the estimation of the actual resistance (that is also shown on the display) is very close to the measured value.

    At the lower end, however, there is some significant deviation, mostly caused by the relay contact resistances, trace resistance and so on. 

    Next steps

    Before doing a proper full calibration and presenting the final results in a more user-friendly form, let's do a small hardware optimization of the design.

  • Status Update: GitHub repository

    Sebastian08/19/2023 at 12:10 0 comments

    I was asked whether I'd be willing to share the design files. Yeah, why not... If you're interested in having a look at the different PCBs - including the panels - head over to my GitHub repository linked on the project page. Those were designed in KiCAD v7.

    I generated the interactive BOM html files with an absolutely awesome KiCAD plugin written by qu1ck:

    I plan to release relevant parts of the code as well, same repo.

    You're under no obligation to do so, but if you actually consider building this or a similar device, I would be happy to see what you did with it and maybe how you made it better.

    Also, if there are aspects that you'd like more information about, please let me know.

  • Warm-up curve

    Sebastian08/17/2023 at 16:41 0 comments

    Generally, test and measurement equipment needs a certain period of warm-up time to reach a thermal equilibrium that allows for low thermal drift. That is also true for the programmable decade resistor. I’m especially interested in the warm-up time with all relays off as well as with many relays on. I chose a value of 100 kΩ for the latter.

    (For simplicity I decided against using latching relays, however that would have been a better choice performance-wise as mentioned before. Due to the additional power dissipation in the relay coils the curves will look different.)

    The programmable resistor decade mainboard has two temperature sensors that can be read remotely via SCPI. To have a more complete picture I’ll also use the SCPI thermometer (previous project, to sample the ambient temperature. So let’s collect some datapoints and plot a few curves.

    Input off

    Temperature rise with all relays disabled (input off). Temperatures on the primary y-axis also in °C

    Unfortunately, I had to correct a simple error in the test program so the unit was already on for a few moments, explaining parts of the gap between the internal and the ambient temperature. Also, the internal temperature sensors are not nearly as precise as the sensor used in the SCPI thermometer, so a certain deviation/offset between both sensors is expected. The temperature rise is fairly limited and it takes about one hour to see most of the temperature rise. According to the measurement it would likely take more than two hours for the unit to reach a thermal equilibrium. That being said, the steadily rising ambient temperature limits my confidence in the measurement, but hey, it's good enough.

    Note: The small (positive) temperature peaks likely came from the laptop fan that switched on intermittently, although the ambient temp sensor was about 1 m away from the laptop and not (directly) in the airflow. Also, I did the measurement on a day with significant solar radiation that heated up the room. 

    Input on

    I tried to optimize the measurement protocol for the second more interestingly scenario with 100 kΩ at the input (only partially successful, I guess). Here it is:

    Temperature rise with input enabled and set to 100 kΩ. Temperatures on the primary y-axis also in °C

    As expected the power dissipation of the relays and the power supply, 2 W or thereabouts, increases the internal temperature significantly. Compared with the previous scenario, the final temperature increase has roughly trippled, and is now at about 8°C. After 30 min, the internal temperature rise is already at ~80% of and after one hour effectively at the final temperature. The dip in the ambient temperature was likely caused by temporarily opening a door.

    Next steps

    My conclusion is: Wait at least 1 hour with the input enabled and at something like 10 or 100 kΩ before going through the calibration procedure. And this is what we'll do in the next log.

  • Mainboard

    Sebastian08/14/2023 at 15:51 0 comments

    The mainboard features the main controller paired with an EEPROM, the resistor decades (precision resistors, signal relays) including two temperature sensors, relay drivers and signal conditioning for the two external digital inputs.

    Rendering of the mainboard PCB generated with KiCad

    Main controller

    The main controller is a STM32G441KBT6 microcontroller (170MHz Cortex M4, 128kB Flash, 32kB RAM). The microcontroller features a USB 2.0 device peripheral.

    The main controller contains the business logic required to control the relays and provide a user interface. It handles the processing of user user inputs, originating from either the mentioned user interface board, from SCPI messages sent over USB (virtual COM port) or from the external digital inputs.

    Voltage, current and power limits are calculated based on a given resistance setpoint. Resistance setpoints are translated into switching sequences and sent to the relay drivers via SPI. Also, the main microcontroller manages all required calibration data and user settings.

    An I2C-EEPROM (32kBits) is used to store different data related to the operation of the programmable resistor. Data integrity is validated with a CRC checksum. The data stored include the following:

    • Calibration data (2W CAL, 4W CAL, CAL information)
    • Instrument settings (e. g. Buzzer on/off)
    • User settings (presets)

    Relay driving circuit

    To drive a total of 39 non-latching relays, three low voltage 16-bit constant current LED sink drivers are used. They essentially operate as a 48-bit shift register controlled over SPI by the main microcontroller.

    Admittedly, the choice of a constant current LED driver as a relay driver is a bit odd. However, the operating conditions of the part allow for it and the part was chosen to drive the LED display on the UI Board, hence available. Care must be taken to select a constant current that is well above the minimum current to operate the relay properly.

    A visual feedback for prototyping was achieved by adding a LED in series with every relay. As a side-effect the LED reduces any potential power dissipation in the constant current driver when operating a 12V relay on the +15V rail. That being said, this design might reduce the reliability of the unit: A defective LED would cause the relay to not operate. Not a big deal for my hobby applications, but if I had to build a unit for commercial use I would use a different driving circuit and not populate the LEDs. (I would use latching relays and therefore use a completely different drive circuit anyway. But that would be a discussion for another log.)

    Temperature sensor

    The mainboard features two KTY81-210 temperature sensors (PTC). The analog voltages of the voltage divider used are digitized with two of the 12-Bit ADC channels built into the main controller. The converted readings can be accessed through both the SCPI and the user interface. During calibration the temperature is recorded and saved to the EEPROM after completion.

    External inputs

    Two external, earth-referenced inputs can be used as either a simple digital input (that can be read through SCPI), a trigger input (positive, negative, either) or an inhibit signal (latching, live). Both are Schmitt-Trigger inputs and feature a resistor/diode protection circuit that allows for voltages exceeding the internal supply voltage of +3.3V.

View all 18 project logs

Enjoy this project?



bfsmith07 wrote 09/13/2023 at 16:08 point

This is an amazing project, very cool!

  Are you sure? yes | no

Sebastian wrote 09/13/2023 at 16:32 point

Thank you!

  Are you sure? yes | no

han.zhang wrote 09/07/2023 at 15:16 point

Thank you so much, Sebastian. I've been really struggling with automating IO testing lately because the constant resistance mode of electronic loads couldn't quite mimic resistors perfectly. Your project has been a great source of inspiration for me.

  Are you sure? yes | no

Sebastian wrote 09/08/2023 at 15:02 point

Glad to hear that! Depending on what you want to achieve, the control loops of some DC loads might not be fast enough or maybe become unstable.

  Are you sure? yes | no

Ray Kampmeier wrote 08/20/2023 at 04:13 point

Hey Sebastian, what a very well executed project 👏  I’m admiring the enclosure you used.  Do you mind sharing what part/mfg that is? 🙏

  Are you sure? yes | no

Sebastian wrote 08/20/2023 at 06:44 point

Thank you! The case is made by Elma Electronic, model name Stylebox 15 Standard. Very good quality, very configurable, but made for industrial applications, hence too expensive for most diy projects if you have to buy it new. The case might be as expensive as or even more expensive than the project itself. I don’t have the exact price though and I don’t think it’s available from any of the usual distributors. So you might have to contact the company directly. 

  Are you sure? yes | no

Ray Kampmeier wrote 08/21/2023 at 16:38 point

Thank you, Sebastian! 

  Are you sure? yes | no

hebel23 wrote 08/18/2023 at 15:20 point

Well done!

  Are you sure? yes | no

Sebastian wrote 08/19/2023 at 07:27 point


  Are you sure? yes | no

Phil wrote 08/18/2023 at 09:00 point

Could you add more detail and write-up of the front panel design. It looks very nice and I would like to learn how to make such a great looking front panel for my own projects!

  Are you sure? yes | no

Sebastian wrote 08/18/2023 at 11:44 point

Yes, I put this on my list. Spoiler: It's not that hard :)

  Are you sure? yes | no

Sebastian wrote 09/05/2023 at 17:19 point

The latest post covers the panels in more detail. You can head over to my github repository and download the KiCAD 7 files/clone the repo if you like.

  Are you sure? yes | no

Phil wrote 09/06/2023 at 18:17 point

Wow. Thanks! It's so simple, I feel silly for having never thought about it before! Just use the same PCB manufacturers to make it! 

  Are you sure? yes | no

Phil wrote 09/15/2023 at 18:38 point

Could you also add a little bit about how you space/attach the front panel with the board behind it? I see the buttons poking out at uniform height and also LEDs peeking out just right.

  Are you sure? yes | no

Sebastian wrote 09/15/2023 at 19:45 point

I used simple standoffs for this, in my case metric thread M2.5 and something like 18-20 mm, don't remember. The standoffs are pushed against the front panel by the aluminum "shield" (actually a front panel PCB too) behind the front panel and the PCB. Lateral movement of the PCB is somewhat limited by the outline of the board itself and further restricted by the LEDs (three leads, power LED with horizontal orientation, all other vertical). The mounting of the aluminum shield itself was more like a quick test that worked well enough that I didn't bother implementing a proper solution like drilling a few holes and using some sort of a bracket. (Same with the wooden rod that I wanted to replace with a 3d printed part initially.)

Edit: That being said, it's important to have enough holes in the UI PCB and to mount the "aluminum shield" rigid enough to avoid bending stress in the PCB and to withstand the forces exterted on the switches by the user. Otherwise you might end up with something as poorly designed as my old ThinkPad T400 keyboard (or rather keyboard support). I accidentally ordered the 3.5 N variant which already requires quite a large force and you can obviously push much harder than that...

I measured the required distance from the board to the LEDs and just soldered the LEDs accordingly. If you take a closer look you might see that didn't work out perfectly, but good enough in my opinion. A better solution might be to design a little plastic spacer that would make the soldering easier and more consistent. With the LEDs located far enough apart my LEDs show relatively little light bleeding, but properly formed spacers or heat shrink tubing could help if that became a problem in a certain design. You can buy spacers, but I haven't found one that matches my requirements (support for three leads for the bi-color LEDs I used, length etc.).

I'm not really interested in the mechanical side at all, not only because I don't have a proper workshop for these kind of things. With a bit more effort one could implement a more professional/improved solution quite easily, even with my capabilities I guess...

  Are you sure? yes | no

Alysson Rowan wrote 08/18/2023 at 08:30 point

An extremely professional looking instrument - one that would happily grace the pages of any of the major instrument makers' catalogues.

I am curious about what influenced your choice of relay. Having worked with multiple generations of controls, I wonder whether the choice of relay may reduce the contact resistance issue further.

  Are you sure? yes | no

Sebastian wrote 08/18/2023 at 11:41 point

Hey Alysson, appreciate it! There are multiple aspects to this:

- I chose signal relays because of their relatively small footprint, I can't really comment on the influence of the relays on the bandwidth of the programmable decade resistor, leakage (would that be even a thing, realistically?)

- They were pretty cheap at the time (EC2-12NJ, different lead style than the NH variant, not recommended for new designs, ~1,60 Euro I think) and I didn't want to spend a lot of money on this "small" project. Many higher quality relays are much, much more expensive. (Keysight, Keithley etc. like to use signal relays like the EE2/EC2 in the switching cards for data acquisition units (latching). The application is different though - the contact resistance is less critical and instead the EMF might be of more concern. Still I think these are reasonable choices, but not necessarily perfect for the lower decades ;) )

- There is the next point: It started as a rather simple project where I (intentionally) didn't plan everything down to a T. It then got a bit out of hand :D

- I was more interested in the highe resistance values, like 10kOhms and up, where the algorithm described can actually do something. There the contact resistance doesn't matter

- From the datasheets alone it's hard to tell with which contact resistance you'll end up with (and it will depend on the current etc.). They usually spec a max. resistance which isn't really all that helpful in this case. I'd do some tests with different relays, although there might be other aspects to it, e. g. related to the bandwidth.

- When doing a Rev B I would likely change certain things and put more emphasis on relay selection. I would rather have latching relays, especially because this case has no vents at all and even the 140mW signal relays can increase the temperature inside significantly. This would likely be worse with many non-latching relays with a potentially lower contact resistance, but higher power requirements for the coils.

If you want to share some insight, maybe recommend different relay types feel free to do so!

  Are you sure? yes | no

Dan Julio wrote 08/17/2023 at 19:34 point

This is a profession piece of kit!  And useful.  Would you consider documenting and sharing the design itself so that others may build it?  Even selling any excess PCBs that you might have had to buy on the tindie fleamarket?

  Are you sure? yes | no

Sebastian wrote 08/17/2023 at 20:53 point

Thank you for the kind words! As a matter of fact, you are the first person to ask for the design files. I would consider making the design or at least the relevant parts of it public if I get a few more requests, since this would require some rework. (Or at least I feel that way.) I'm not quite sure how useful the UI board actually would be, because I used 7 segment displays that are not that readily available, certainly not from the big distributors. I don't plan to sell excess PCBs, because this doesn't make much sense financially, compared with ordering a bunch from prototyping companies (shipping etc.)

If there is something in particular that you are interested in, please let me know :)

  Are you sure? yes | no

Sebastian wrote 08/18/2023 at 10:46 point

Ok, I set up a github repo with KiCAD files of the mainboad. I might add other resources at a later point in time.

  Are you sure? yes | no

Dan Julio wrote 08/18/2023 at 14:09 point

Thank you Sebastian.  That seems very helpful and useful for those of us who might try to build our own.  Perhaps if you are willing, you might share the code for the main processor, or at least the parts related to setting resistance values and controlling the physical hardware.  We could create our own user interfaces.

  Are you sure? yes | no

Sebastian wrote 08/19/2023 at 07:27 point

I'll see what I can do. Please give me a little time.

  Are you sure? yes | no

Sebastian wrote 09/19/2023 at 17:16 point

Code added :)

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates