Using the Digital Ports as Tri State supplies

Hi,
sometime ago i had to match resistors for an amplifier. I thought that there might be a better way to do this than with a Wheatstone bridge by hand, but didn't got around to do it.

Whenever i thought of it, ran into issues with the internal resistance of fets, transistors and multiplexern.

Today i had an idea and just threw together a small prototype:

The idea is:

  • 8 Resistors get inserted into the zif socket, each is connected to one digital port on the arduino on one side and to one input of the AD623 instrumentation amplifier on the other side.

  • The other input of the amp is connected to a voltage divider resulting in approximately 1/2 Vcc

  • The amp has a reference of also 1/2 Vcc, the output is connected to Analog port 0.

  • At the beginning of the sketch digital ports 2- 9 ar set to input low, to disable the pullup. This should effectively but them into a "not connected" state.

  • Now the sketch loops over all pin combinations and turns both pins to output.
    It measures the value of A0 with one of the pins low, the other high, and the other way around. If the resistors are similiar, the value should be the same, no matter which way the current flows.

Now for my questions:

  1. Is it safe to use the digital ports in this way?
    I know that i shouldn't use resistors less than 75 Ohm, because
    33mA = 5V / (2*75 Ohm)
    But is there anything else that might damage the ports?

  2. Are the low input ports really disconnected, or will they influence the result? In my tests i didn't find a difference wether all places where filled or not, but is this also true in theory?

  3. What is the highest resistance i could test without some internal pullups / pulldowns interferring?

My small tests look promising, so if everything checks out, i would probably build myself a small shield with indicator lights to match the resistors together.

For anyone interessted here is my test code, just remeber it's an early prototype:

 #define FIRST_PIN 2
#define LAST_PIN 9
#define PROBE_PIN 0
#define NUMBER_TESTS 16


int loopCounter;
void setup(){
  Serial.begin(115200);
  int i;
  for(i = FIRST_PIN; i <= LAST_PIN; i++){
    pinMode(i, INPUT);
    // disable Pullup to not confuse the test
    digitalWrite(i, LOW);
  }
  loopCounter = 0;
}

void loop(){
  if(loopCounter < 1) {
    Serial.println("Starting Loop:");
    int outerPin, innerPin, match1, match2, i;
    signed long measureLow, measureHigh, bestValue, difference;
    
    match1 = 0;
    match2 = 0;
    bestValue = 0x1FFFFFFF;
    
    for(outerPin = FIRST_PIN; outerPin < LAST_PIN; outerPin++){
      Serial.print("\tChecking pin: ");
      Serial.println(outerPin);
      
      for(innerPin = outerPin + 1; innerPin <= LAST_PIN; innerPin++){
        pinMode(outerPin, OUTPUT);
        digitalWrite(outerPin, LOW);
        measureLow = 0;
        measureHigh = 0;
        //First measure LOW, HIGH
        pinMode(innerPin, OUTPUT);
        digitalWrite(innerPin, HIGH);
        for(i = 0; i < NUMBER_TESTS; i++) {
          measureLow += analogRead(PROBE_PIN);
        }
        
        // measure High Low
        digitalWrite(innerPin, LOW);
        digitalWrite(outerPin, HIGH);
        for(i = 0; i < NUMBER_TESTS; i++) {
          measureHigh += analogRead(PROBE_PIN);
        }
        
        difference = measureLow - measureHigh;
        difference = difference < 0 ? 0 - difference : difference;
        if (difference < bestValue) {
          bestValue = difference;;
          match1 = innerPin;
          match2 = outerPin;
        }
        
        measureLow = (measureLow / NUMBER_TESTS);
        measureHigh = (measureHigh / NUMBER_TESTS);
        
        Serial.print("\t\t");
        Serial.print(innerPin);
        Serial.print(" : "); 
        Serial.print(measureLow);
        Serial.print(" / "); 
        Serial.print(measureHigh);
        Serial.print(" - ( "); 
        Serial.print(difference);
        Serial.print(" )\n"); 
        
        // Set pin to input, no pullup again
        pinMode(innerPin, INPUT);
        digitalWrite(innerPin, LOW);
      }
      // Set pin to input, no pullup again
      pinMode(outerPin, INPUT);
      digitalWrite(outerPin, LOW);

    }

    Serial.print("\n Best match: ");
    Serial.print(match1);
    Serial.print(" / "); 
    Serial.print(match2);
    Serial.print(" : "); 
    Serial.print(bestValue);
    Serial.print("\n"); 
    loopCounter++;
  }
}
  1. Is it safe to use the digital ports in this way?

Yes

Are the low input ports really disconnected,

No they are hard to ground. To disconnect them define them as inputs and disable the internal pull up resistor.

What is the highest resistance i could test without some internal pullups / pulldowns interferring?

Just shooting from the hip I would say 200K.

Thanks, this looks promising.

No they are hard to ground. To disconnect them define them as inputs and disable the internal pull up resistor.

As far as i can tell a simple

pinMode(pin, INPUT);
digitalWrite(pin, LOW);

should do right?

Bye,
NsN

Yes that will set the pin to an input and disable the internal pull up so there is effectively no (or as small as it is possible to get) loading from the pin.