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.

Interfacing#

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…? ↩︎