A simple SPI controlled voltage window comparator

Circuit Diagram

Best described as “functional enough to be useful, but trivial enough to understand.”, this - largely symetrical - circuit is composed of three distinct stages:

  1. Two MCP41010 digital potentiometers1 are used as voltage/potential dividers, creating reference voltages for our comparisons;
  2. a dual-op-amp (LM358) is used to provide both high and low voltage comparisons;
  3. output is inverted via a 2N222 NPN BJT - pulling the output pin low when either of the op-amps detects an out-of-range voltage.

Additional components are simply decoupling capacitors on the digital potentiometers, diodes to prevent any backfeeding on the op-amp outputs, and resistors to control the output transistor.

The MCP41010 accepts input at a width of 8-bits, providing 256 different possible wiper positions - or a resolution of around .4%. This would - I think - provide an accuracy of around ~0.02V given an input voltage of 5V.2

A higher resolution PDF of the schematic is here.


The real advantage of this circuit is that the MCP41010 digital potentiometers can be controlled via SPI, and can therefore be dynamically configured during runtime - allowing monitoring parameters to change based upon external events/input.

My own potential use case is as part of an array, monitoring multiple circuits that all have different operating ranges; using a simple module that can be reconfigured on-the-fly solves a lot of the pain-points with manually implementing set reference voltages or requiring physical manipulation of an analog potentiometer.

I’ve yet to actually put this to use yet though! I’ll be sure to throw a quick Arduino library on Github when I do though; but it will essentially only require:

  1. The ability to send values via SPI to the two pots; and
  2. the ability to read the status of a digital pin.3

  1. The MCP42xxxx packages contain two digital potentiometers in one IC, so this is an option for further reducing the component count. ↩︎

  2. Theoretically that’s the case - 256 distinct values provide a resolution of ~0.4%, which is around 0.02V when running against 5V. Practically I’ve yet to actually try. ↩︎

  3. This digital pin will trigger an interrupt in my case; but I’m not entirely sure whether that’s an anti-pattern to implement in a reusable library…? ↩︎