user47960: 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.

user19409: 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

user7508: 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.

47960: <p>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).</p>

<p>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.</p>

<p>I currently have no resistors in the circuits.</p>

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

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

<p>My questions boil down to two:</p>

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

<p>I'm a software engineer, but a complete noob when it comes to <em>real</em> electronics and Arduino, so please feel free to assume I know nothing.</p>
 19409: <p>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.</p>

<p>I personally would add a <a href="https://en.wikipedia.org/wiki/Low-pass_filter" rel="nofollow noreferrer">RC Low pass filter</a> to the output of the PWMs. <a href="https://www.electronics-tutorials.ws/filter/filter_2.html" rel="nofollow noreferrer">More information here.</a> 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.</p>

<p><a href="https://i.stack.imgur.com/Eeiko.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Eeiko.png" alt="Basic RC filter"></a></p>

<p>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.</p>

<p>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.</p>

<p>To calculate the value of the resistor and capacitor you need:
There is a very good article over at <a href="https://www.allaboutcircuits.com/technical-articles/low-pass-filter-a-pwm-signal-into-an-analog-voltage/" rel="nofollow noreferrer">All About Circuits that goes into this subject in detail</a>.</p>

<p>To calculate the value we need to know the frequency:</p>

<blockquote>
  <p>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. <a href="https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/" rel="nofollow noreferrer">- Arduino Analog Write</a></p>
</blockquote>

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

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

<p>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.</p>

<hr>

<p><strong>EDIT:</strong><br>
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:</p>



<p><img src="https://i.stack.imgur.com/SJhtb.png" alt="schematic"></p>



<p><sup><a href="/plugins/schematics?image=http%3a%2f%2fi.stack.imgur.com%2fSJhtb.png">simulate this circuit</a> &ndash; Schematic created using <a href="https://www.circuitlab.com/" rel="nofollow">CircuitLab</a></sup></p>

<hr>

<p><strong>Edit #2:</strong>  </p>

<blockquote>
  <p>Jonathan Wrote:<br>
  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, <strong>making it hard to give the user incremental feedback</strong> on how many wires are correctly connected.</p>
</blockquote>

<p>This can easily be solved by providing 6 individual voltage divider networks, as shown below. Notice how each voltage divider has a different ratio.</p>



<p><img src="https://i.stack.imgur.com/M6viA.png" alt="schematic"></p>



<p><sup><a href="/plugins/schematics?image=http%3a%2f%2fi.stack.imgur.com%2fM6viA.png">simulate this circuit</a></sup></p>
 7508: <p>First, let's consider the logic of your program. You have two groups of
pins: 6&nbsp;pins connected to the wires and 6&nbsp;pins connected to
the terminals. The first thing I would do is forget that these are two
different groups. Consider you just have 12&nbsp;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&nbsp;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.</p>

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

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

<pre class="lang-c++ prettyprint-override"><code>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 &lt; 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 &lt; PIN_COUNT - 1; i++) {
        pinMode(pins[i], OUTPUT);
        digitalWrite(pins[i], LOW);
        for (int j = i+1; j &lt; 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);
    }
}
</code></pre>

<p>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&nbsp;kΩ resistor in series with each pin, but then all the
pins that are not actively being tested should be set to <code>INPUT</code> rather
than <code>INPUT_PULLUP</code>, otherwise multiple pullups in parallel may start to
compete with the series resistor.</p>
