How can I differentiate between multiple circuits?

I'm building a puzzle for an escape room. I want to give the user 6 wires and 6 terminals, then confirm that they've connected the correct wires to the correct terminals (one-to-one).

My first (successful) attempt to implement this puzzle was to connect the wires to 6 PWM analog outputs set to different levels, and connect the terminals to 6 analog input pins. By time-averaging the readings on the input pins, I was able to determine which wire(s) are connected to which terminals, if any.

I currently have no resistors in the circuits.

As the puzzle is currently designed, it's possible for the user to do weird things like:

• Connect multiple wires to the same terminal.
• Connect multiple wires together, without connecting them to any terminal.
• Touch multiple exposed wires and/or terminals.

My questions boil down to two:

• Is my current approach dangerous, either for the Arduino or my users, and are there recommended precautions I should take?
• Is there a better (safer or simpler or more robust) way to implement the puzzle?

I'm a software engineer, but a complete noob when it comes to real electronics and Arduino, so please feel free to assume I know nothing.

First, let's consider the logic of your program. You have two groups of pins: 6 pins connected to the wires and 6 pins connected to the terminals. The first thing I would do is forget that these are two different groups. Consider you just have 12 pins that the user has to connect in a specific fashion. This way most “weird things” the user could do, like connecting wires together, are not a special case anymore. They are just another invalid combination. Now what you have to do is, for every pair of pins among those 12, determine whether or not they are connected together. If any pair is connected that shouldn't be, you have an invalid combination. If any pair is not connected while it should be, it's again an invalid combination. If every pair is the expected state (either connected or not connected), then the user did solve the puzzle.

Now, for the hardware side. A simple way to know whether two pins are connected together is to set one of them to INPUT_PULLUP and the other one to OUTPUT LOW. This second pin should be the only one accessible to the user that outputs a LOW. All other exposed pins should be set as either INPUT or INPUT_PULLUP. Now, if the first pin reads LOW, you know have a connection. If it reads HIGH the two pins are not connected together.

Here is an example program demonstrating that principle. It loops over the 66 possible pairs to check whether they are connected or not. You just have to replace the inner if with your code that validates the combination.

const int PIN_COUNT = 12;
const uint8_t pins[PIN_COUNT] = {...};

void setup() {
Serial.begin(9600);

// Set all pins to INPUT_PULLUP.
for (int i = 0; i < PIN_COUNT; i++)
pinMode(pins[i], INPUT_PULLUP);
}

void loop() {
// Loop over all pin pairs (pins[i], pins[j]).
// Set pins[i] to OUTPUT LOW, then read pins[j].
for (int i = 0; i < PIN_COUNT - 1; i++) {
pinMode(pins[i], OUTPUT);
digitalWrite(pins[i], LOW);
for (int j = i+1; j < PIN_COUNT; j++) {
Serial.print("pins ");
Serial.print(pins[i]);
Serial.print(" and ");
Serial.print(pins[j]);
Serial.println(" are connected together.");
}
}
pinMode(pins[i], INPUT_PULLUP);
}
}

As for the safety, you should be fine as long as the users do not have access to any low-impedance ground or voltage source. In particular, the GND and 5V pins should not be user-accessible. For extra protection, you could put a 1 kΩ resistor in series with each pin, but then all the pins that are not actively being tested should be set to INPUT rather than INPUT_PULLUP, otherwise multiple pullups in parallel may start to compete with the series resistor.

• This is exactly the method I use for testing development boards I make. A shield is attached which links 50% of the pins to the other 50% through 100r resistors. Scanning the pins with one set low checks for both proper continuity as well as shorts to other pins.
– Majenko
Jul 10 '18 at 22:39
• Beautiful. This is the paradigm I was missing. It totally hadn't occurred to me that I could actually measure under different configurations in rapid succession. My options for building things just exploded. I'll try it out. Jul 11 '18 at 5:57
• This worked wonderfully. I much prefer it over my analog approach, as I don't need to worry about defining expected voltage ranges for each input. And of course, I didn't need to check all 12*11/2 combinations, since I really just need to know which wires are connected to each terminal (6*6 checks) - if two terminals or two wires were connected, it would necessarily result in the wrong combination of wires connected to a given terminal. It is however important to check for more than the expected 6 connections, to handle the case where the user somehow bridges all the terminals. Thanks! Jul 12 '18 at 5:04

I would also connect the terminals to the 6 analog input pins and have 6 unique voltages, one per wire. The Arduino will only provide the output when the 6 wires are placed on the correct terminals. In other words, that is when the Arduino sees the correct analog voltage on the respective pins.

I personally would add a RC Low pass filter to the output of the PWMs. More information here. Your PWM output would go into the Vin and the then the Vout would go to your wire (ie the analog input). One filter per channel. The RC filter will protect the Arduino from shorts to +ve, Gnd and the other pins as well as providing a bit of protection from static. It will also simplify your code.

At the moment you are having to implement fancy code to average out the voltage on those analog pins. The RC filter would essentially make that code not needed.

To calculate the value of the resistor and capacitor you need: There is a very good article over at All About Circuits that goes into this subject in detail.

To calculate the value we need to know the frequency:

The frequency of the PWM signal on most pins is approximately 490 Hz. On the Uno and similar boards, pins 5 and 6 have a frequency of approximately 980 Hz. - Arduino Analog Write

I used http://sim.okawa-denshi.jp/en/PWMtool.php to calculate the values of R & C needed with a very low ripple ( < 60mV ) using common values. I based my calculations around the 490Hz as the lower frequencies perform worst with low pass filters.

I suggest you use values of R = 10k and C = 4.7uF. You can play with these values until you get the output you desire.

One last thing I would consider is to put some protection on the terminals that connect to the analog pins. This could be a small resistance in series, or a 5.1V zener in parallel (the pin may already have this?) or some capacitance in parallel.

EDIT:
I have just had a brainwave - You don't need to use the PWM's to output the different analog values - you could use a voltage divider circuit instead. No RC filter needed. For example: simulate this circuit – Schematic created using CircuitLab

Edit #2:

Jonathan Wrote:
The only minor downside I'm noticing is that if the user has two wires connected to the same terminal, it affects all the voltages read across the other terminals, making it hard to give the user incremental feedback on how many wires are correctly connected.

This can easily be solved by providing 6 individual voltage divider networks, as shown below. Notice how each voltage divider has a different ratio. simulate this circuit

• @sa-leinad Cool idea on the voltage divider circuit. Jul 10 '18 at 18:45
• Cool. So the expectation is that with your second idea, I should be able to see actual different (stable) voltages on the different wires, which eliminates the need for the time averaging, right? I'll try it out. Jul 11 '18 at 5:50
• I tried it out, and this (second idea with the voltage divider circuit) seems to work fine. The only minor downside I'm noticing is that if the user has two wires connected to the same terminal, it affects all the voltages read across the other terminals, making it hard to give the user incremental feedback on how many wires are correctly connected. Thanks again! Jul 12 '18 at 4:56
• Ahhh, I was not aware of the need to provide incremental feedback. In that case you will need 6 different voltage divider networks. I will edit my answer to include this. Jul 12 '18 at 13:48