Detecting all possible states of an input pin

Having a spare Arduino Nano and a small OLED screen laying around I thought that I would make a simple logic probe to detect the state of a pin in a project circuit. Nothing fancy, just detect the state and display it on the OLED

Given a common GND, then detecting HIGH and LOW is, of course, easy but can I detect and differentiate between those states and a pin whose state is floating or high impedance in order to report all 4 states ?

I don't want the circuit to get too complex, but adding an op-amp or two would be acceptable if needed. Adding software is, of course, acceptable.

Any ideas ?

To detect floating... Use an I/O with a serial diode and serial resistor to apply a "soft" HIGH to the tested pin, and an I/O input to detect.
Do the similiar to apply a "soft" LOW.

Resistor in series with the pin. Set it to output and write it low, set to input and see if it is still low. Set to output and write high, input, see if still high. If it stays where you put it then it’s probably floating. Needs some experimentation.

Is the output drive transistor still active when the pin is redirected to input mode?

Railroader:
Is the output drive transistor still active when the pin is redirected to input mode?

No, how could it be?

On a PIC the register that controls whether the pin is input or output is called TRIS for tristate. Set it to input and the output drive becomes tristate, so effectively disconnected.

If you can use two pins, you connect a high value resistor (47 or 100k) from the test pin to the "puller" pin. If the test pin always follows the "puller" pin even after the "puller" is disabled (INPUT), it is floating.

Possibly simpler, 220k from pin to ground, switch between INPUT and INPUT_PULLUP. If it reads LOW in the first case and HIGH in the second, it is floating or at least a higher impedance.

220k from pin to ground, switch between INPUT and INPUT_PULLUP. If it reads LOW in the first case and HIGH in the second, it is floating or at least a higher impedance.

After a quick experiment that seems to be OK using a 100K resistor to GND. Using 200K causes false HIGHs to be reported when the input is floating

A valid signal source should override a 100k (50µA) signal source. Input leakage current is specified max. 1µA.

UKHeliBob:
After a quick experiment that seems to be OK using a 100K resistor to GND. Using 200K causes false HIGHs to be reported when the input is floating

Your code is running too fast! Slow it down a little. :grinning:

I specified that value in order to make the voltage divider effect with the effective 47k of INPUT_PULLUP more positive. With a 100k resistor, you should get the pin to 2/3 Vcc which should certainly be a clear HIGH though this also could be delayed on switching by wiring capacitance.

For the ATmega328P, the I/O pin pull-up resistor is 20-50k. On the Nano, if you connect a 47K resistor from 3.3V to A0, then you could use A0 as your probe by connecting to any digital with a jumper.

Using analogRead, you should get:

[b]I/O MODE        VOLTS     READING[/b]
[color=teal]INPUT           3.3       675
INPUT_PULLUP    4.1-4.5   839-921
OUTPUT HIGH     5         1023
OUTPUT LOW      0         0[/color]

Pseudocode:

if (probeVal > 970) {
  // Output High
} else if (probeVal > 760) {
  // Input Pullup
} else if (probeVal > 600) {
  // Input
} else {
  //Output Low
}

Your code is running too fast! Slow it down a little.

Any suggestions as to the frequency that the two readings should be made at ?

The breadboard prototype ,complete with OLED output, seems to be working OK with a 100K resistor running at full speed. The OLED is only being updated when the output changes so it not slowing things down unduly

On the Nano, if you connect a 47K resistor from 3.3V to A0, then you could use A0 as your probe by connecting to any digital with a jumper.

Something else to try

UKHeliBob:
Any suggestions as to the frequency that the two readings should be made at ?

Not as such, but giving the circuit capacitance time to settle should allow 200k to work. A millisecond should be way more than adequate. :grinning:

Hello,

Electrically your proposal to add an opamp is a very good idea. If you use the non inverting input of the opamp as probe and you make a feedback loop 1:1 (simple non inverting amplifier), you will get a very high impedance.

Then connect the output of the opamp to an analog input of your test board and you are done.
If you want to regulate the sensitivity you can use a pot meter to connect the + input to GND and regulate the sensitivity (M ohms range). You can even amplify the signal to adapt the range if you want it.

If you have an input resistance of your measuring device that is in the same range of the voltage at the input you want to read, you create a voltage divider. Hence you measurement will influence your measured value so much that it risks not to be relevant any more and you have false conclusions.

So actually what you do this way is to make an impedance transforming circuit.

Best Regards,
Johi

With an analog input it's sufficient to attach a 1:2 voltage divider (2 100k resistors from Vcc to Gnd) to that input. Then the idle (tristate, broken...) reading is 512 (Vcc/2), HIGH near 1023 and LOW near 0. An INPUT_PULLUP reads about 700-800.

Thanks for the suggestions

The breadboard prototype seems to work OK with a digital input to GND via 200K with a 1 millisecond delay between INPUT and INPUT_PULLUP readings, so I am going to stick to that as it also works when reading the pins of an ESP32 (3.3V outputs)

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.