How can I differentiate between multiple circuits?
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++) {
if (digitalRead(pins[j]) == LOW) {
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.
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