Testing tri-state pin - erroneous results with internal pullup
The internal pull-up is around 50k. So, install an external pull-down (to ground) of a somewhat higher value, like 1M.

Now:

Go to input mode, no pull-up. Get a reading. Turn on the internal pull-up. This should overpower the pull-down. If the reading changes, it was tri-state. Otherwise, if the reading doesn't change the external device is overpowering both pull-up and pull-down and you have the actual reading.

You may need a slight delay to allow the low-value pull-down to change the pin state.



Amended code to demonstrate:

 

// PART (2) Code to determine state of tri-state pin
Serial.print(stateCh);     // Shows what it *should* be

pinMode(pinTest, INPUT);
delayMicroseconds (100);
byte firstReading = digitalRead(pinTest);
pinMode(pinTest, INPUT_PULLUP);
delayMicroseconds (10);
byte secondReading =  digitalRead(pinTest);

if (firstReading != secondReading)
  Serial.println(" - HiZ");
else if (secondReading == HIGH)
  Serial.println(" - HIGH");
else
  Serial.println(" - LOW");


(Only showing the part that detects the pin state, the rest is the same).

Output:

 

H - HIGH
L - LOW
Z - HiZ
Z - HiZ
Z - HiZ
H - HIGH
H - HIGH
H - HIGH
H - HIGH
H - HIGH
H - HIGH
H - HIGH
L - LOW
Z - HiZ
Z - HiZ
Z - HiZ
H - HIGH
H - HIGH
H - HIGH
H - HIGH
H - HIGH
H - HIGH
H - HIGH
L - LOW
Z - HiZ
Z - HiZ
Z - HiZ
H - HIGH
H - HIGH
H - HIGH


As you can see, working perfectly. I needed a longer delay after turning the internal pullup off because the fall time was around 100 µs. This actually sounds reasonable, because the 1 megohm resistor will take time to discharge the capacitance on the pin.

So:


10 µs delay after turning the internal pull-up on
100 µs delay after turning the internal pull-up off




Theory for the delays

The Atmega328 pin is specified as having a maximum capacitance of 10 pF (10e-12). It is considered charged/discharged after 5 time-constants, where T = R.C.

Thus for an internal pull-up resistance of 50k and a capacitance of 10 pF, charging should take:

50e3 * 10e-12 * 5 = 2.5e-006 (0.0000025) -&gt; 2.5 µs


And to discharge through 1M (1e6) ohms, discharging should take:

1e6 * 10e-12 * 5 = 5e-005 (0.00005) -&gt; 50 µs


My observed results were about 2.5 µS for the charge, but more like 100 µs for the discharge, however I probably had considerable stray capacitance in the wires used in the test circuit.