What the hell is this?

At a high level, the Resistorganizer is a PCB that you can plug into a standard solderless breadboard and it will poll the rows and determine the resistance value of the resistor which is plugged into it (across the DIP gap). 

The board is driven by a RPi Pico, utilizing the ADC and some reference resistors to determine each resistor's value based on the voltage divider equation:

Where, in this case, the board is set up that all the resistors stored in the breadboard are R2. 

So, that's all well and good, but without some automation, it would be easier to just check the values with a multimeter. Let's expand our ADC.

Shift Happens

At the heart of this board is a handful of a cool IC, the CD74HC4051 analog multiplexer. This was a revelation to me that (of course) there's a chip out there that can act like a switch and multiplex an ADC. I'm inspired by this chip's bi-directionality. It should be noted that this chip has been replaced by TI with the MUX4051, a drop in replacement with better features. 

Since this chip isn't going to be doing hard core signal switching, it's likely an overkill solution. But, if something needs to be killed, you might as well overkill it. 

The 4051 has an 8:1 set-up, where you can poll 8 separate signals to the common terminal. Which channel is being polled is controlled with 3 address pins. The chip also has an enable pin, which effectively shuts the chip down. So, after the three address lines and the 'output' line,  each chip only requires a single pin from your microcontroller to read up to 8 signals. Hell, you could throw another generic multiplexer to handle the chip enable pins and get a whole slew of ADC input for a total of... what is that... 3 address pins, 1 ADC, 1 Clock, 1 Latch, 1 serial... so 7 pins for up to a... crap-ton of ADC goodness. I think this is very cool. 

Measuring Resistance Isn't that Straightforward... apparently.

Let's revisit the voltage divider equation again and take a look at an issue that arises from ADC precision (or lack thereof): 

Vout / Vin = R2 / R1 + R2

In theory, it should be a trivial exercise in algebra to determine R2 if Vout, Vin and R1 are known. Sure. But, in reality, there are things to consider.  The ADC is going to give you a value (in the case of the pico) between 0 and 4095 (12 bits). Where 0 = 0 volts and 4095 = ADCVref (3.3 v). Great, so if the reading is 2053 we can calculate Vout.

Yay. Based on the ratio of the max ADC value and the observed ADC value (~0.5) we can calculate that the resistance of R2 is very nearly equal to R1. Great. But, what if R1 is much, much higher or lower than R2? Well, looking at the equation at the top, as R2 gets much greater than R1, the ratio approaches 1 which would result in the output voltage being equal to the input voltage. The inverse is true as R2 is much smaller than R1, the ratio approaches zero and therefore the output voltage approaches zero. 

Resistors commonly used range in values from 220 ohm to 2,000,000 ohm. That's around 2 million values that need to be crammed into 4095 intervals. Precision isn't going to be straightforward here since one ADC interval will cover several resistance values and no one reference resistor for R1 is going to do a good job at R1. 

I should have done some research on how a standard ohmmeter does this measurement. But I didn't. I want to roll my own solution. Here's what I came up with and it involves another CD74HC4051. (edit) I did some research and found out that ohmmeters commonly use a current sensor to determine the resistance. I have an ACS712 but a look at the datasheet makes me think that it won't be handling milliamp / microamp scale very well. So... back to the original idea.

The plan to mitigate this precision problem is to select 8 resistors for reference that will range from 220Ω to 2MΩ. These will be multiplexed as R1. So, for each R2 in the breadboard, the MCU will poll each of the 8 reference resistors and determine which of them is the closest to R2. That will be the resistor used to make the calculation as it will have the greatest fidelity. There's likely a way to use the other values from the other resistors to ascertain some point on the linear range (surprise, it's not linear. I should have paid more attention in math). But I don't think that makes sense. Afterall, the farther apart R1 and R2 are, the less precise the reading. So, I would think that using less precise data will only make the result less precise. I know there's more to it than that, but I don't need this to be able to determine the value down to 1Ω. Shit, almost all my resistors are 5% anyway. Feel free to challenge my thinking on this. (edit) I realized that better accuracy can be had if R2, the unknown resistor, is polled against 2 or more (maybe all) of the reference resistors (R1). If a best fit line can be calculated, then where Y intercepts the halfway point (ADCref / 2), that is the value of the resistor. We'll see

Blinkenlights!

So, storing your resistors in a breadboard is awesome. Knowing what resistors you have stored is doubly so. Yea, having them in a breadboard makes looking at their values easier. But I don't like doing the whole  Bl,Br,Re,Or,Ye,Gr,Bl,Vi,Go,Wi memorization thing because the mnemonic taught to me back in the previous century was horrifyingly racist and misogynistic. So, of course, I can't do the decoding without it; the same way I can't alphabetize anything without singing the ABCs in my head.

The MCU needs a way to indicate which resistor on the breadboard is the value of interest. We need LEDs and we need to drive them. This time, I'm building a 48 port version of The Resistorganizer. 48 resistors will be evaluated and we'll need 48 LEDs to act as an indicator. Feels like more multiplexing is in order. 

This time we're going to use the more familiar (to me) 74HC595, a digital multiplexer. Just like we do for 7 segment displays and matrices. Hook 'em up and chain them together and driving them lights will be as easy. 

An Interface that isn't serial.Print()

So, the LEDs will indicate which resistor is being measured. But, it would be much easier to use (as in find the resistor you're looking for) if there's a logic to the lights, a way to 'scroll' through the values. In the design, I included two buttons, 'previous' and 'next'. I figure that the code can run the full scan of all the resistor values and store them in memory. Then, it displays the resistor values in order of their resistance and lights up the corresponding led. Easy.  Also, it needs a display. --- a 1602A with I2C backpack will do nicely. So the interface should work something like:

-- input / action table --

PREVIOUSNEXTAction

Pressxdisplay the next lowest value resistor in the organizer, illuminating its LED
xPressdisplay the next lowest highest resistor in the organizer, illuminating its LED
PressPressinitiate full 'scan' of all resistors

Basic? Yes. The philosophy here is that the Resistorganizer is something that can sit on your bench and you just use it. Scan, scroll, done. BUT WAIT! THERE'S MORE! Since we're utilizing a RPi Pico, why not use the 'W' variant and have it talk to NodeRed or something else to keep a database of your resistors! Then you can easily build some kind of HTML front end that shows you, at a glance, the resistors you have in the Resisorganizer. <ahem> pardon me while I get my scope creep under control. thank you.