Ohm meter strange outputs

I am trying to create an ohmmeter I have attached the serial output and the schematic. i have used a 1 mega ohm resistor as my unknown however the voltage drop is the largest for the 220 ohms resistor and the ohm predictions are all way off.

#define vin 5

long R1[] = {220,470,670,1000,10000,22000,47000,74000,100000,470000};
int pins[] = {40,42,44,46,48,50,52,51,49,47};
static const uint8_t analog_R = A12;

void setup() {
  //analog pin
  pinMode(analog_R, INPUT);

  //digital pins
  pinMode(40, OUTPUT);
  pinMode(42, OUTPUT);
  pinMode(44, OUTPUT);
  pinMode(46, OUTPUT);
  pinMode(48, OUTPUT);
  pinMode(50, OUTPUT);
  pinMode(52, OUTPUT);
  pinMode(51, OUTPUT);
  pinMode(49, OUTPUT);
  pinMode(47, OUTPUT);
  
  Serial.begin(115200); 
  
}

void loop() {
  while(1){
    unsigned long sensorValue;
    
    for(int i = 0;i<10;i++){  
      digitalWrite(pins[i],HIGH);
      delay(100);
      sensorValue = 0;
      for(int j=0;j<10;j++){
        sensorValue+=analogRead(analog_R);
      }
      sensorValue/=10;
      digitalWrite(pins[i],LOW);
      Serial.println(" ");
      Serial.print("Sensor value = ");
      Serial.println(sensorValue);
      Serial.print("Known Resistor value = ");
      Serial.println(R1[i]);
      float voltage=(sensorValue*5.0)/1023.0;
      Serial.print("voltage = ");
      Serial.println(voltage);
      screen(String(resistance(5.0-voltage,i)));
    }
    while(1){}
  }
}

int resistance(float vout,int i){
  return R1[i]*(1/(vin/vout-1));
}

void screen(String text){
    Serial.print("Estimate resistor value = ");
    Serial.print(text);
    Serial.println(" ohm");
}

Please learn how to cut and paste text instead of posting images of it.

Amongst the obvious blunders in your code are the use of

 while(1){

and setting all your pins to OUTPUT.

If you wish to compare a resistor to the "unknown", then you set only that single pin to OUTPUT and all others to INPUT.

And you probably should be able to perform the calculations using long integers rather than floats, as the ADC output is just an integer.

The voltage output by a digital pin when HIGH, which is the voltage source for your resistive dividers, is lower than the Arduino supply voltage, or the ADC reference voltage.

Your formula to calculate the unknown resistance assumes that they are all the same.

Except for the one you are currently testing with, surely you should set all the reference resitor drive pins to be high impedance (i.e. as inputs) . Only the reference you are currently using needs to be set to high after first setting it to be an output.

P.S. there is no need to know the actual voltage measured.

:slight_smile: Seems I was a bit too slow in responding.

jremington:
The voltage output by a digital pin when HIGH, which is the voltage source for your resistive dividers, is not the same as the Arduino supply voltage, or the ADC reference voltage.

I'm not quite sure what you are getting at there. :cold_sweat: Maybe just not how I would have explained it. :astonished:

If what you mean is that the ~50 Ohm internal resistance of the output driver is added to the resistance in question, that is indeed the case and significant for all of the resistor values up to 1k. But not the major problem with the code as first quoted.

This can be compensated by connecting the reference resistors for these low values as a series chain with the "free" end connected to a second analog pin.

I'm not quite sure what you are getting at there.

The equation used to determine resistance assumes that vin is 5 V.

vin is not 5 V, and and it is not equal to the ADC reference voltage, which is used to determine vout.

So, the formula is wrong.

Does that help?

I don't see how this would actually matter. :cold_sweat:

The ADC readings are ratiometric, so whether the actual Vcc is 5 V or not, the resistance calculation - if correctly formulated - will be determined and expressed as if it was in fact 5 V.

You do however need the modification - and new code to match - that I pointed out in #5.

I dont have enough analog pins to set for each resistor in circuit. if digital out is not 5V what is it?

flintloque:
I dont have enough analog pins to set for each resistor in circuit. if digital out is not 5V what is it?

You only need the one ADC which reads the value of the voltage at the junction of all the resistors. All the reference resistors need to go to digital pins. When a resistor is not active the pin needs to set to be a digital input so that it is high impedance and does not load the circuit. The pin on the active reference resistor needs to be set to be a digital output and initialised to HIGH to set it to Vcc (Approx 5V).

You don't need to change your circuit diagram. Just your code!

I don't see how this would actually matter.

Don't worry about it -- not your project!

Could i do that using diodes and change VCC to 4.3 to account for diode voltage drop?

Before worrying about the solutions to the various problems, define the goal.

What accuracy do you want from the measurement? Why did you choose this approach? Will you consider another approach?

If it is just a learning experiment, then "close enough" is probably OK.

This a small piece of a masters project so I don't want to invest too much into this part however I would like to get it more accurate than it is currently.

Thanks for all the advice it has been very helpful I am actually getting meaningful returns from the analogue read.

output with a 10k unknown resistor:

Sensor value = 493
Known Resistor value = 10000
voltage = 2.41
Estimate resistor value = 10770 ohm

#define vin 5.0

long R1[] = {220,470,670,1000,10000,22000,47000,74000,100000,470000};
int pins[] = {40,42,44,46,48,50,52,51,49,47};
static const uint8_t analog_R = A14;

void setup() {
  //analog pin
  pinMode(analog_R, INPUT);

  //digital pins
  for(int i = 0;i<10;i++){  
    pinMode(pins[i], INPUT);
  }
  
  Serial.begin(115200); 
  
}

void loop() {
  while(1){
    unsigned long sensorValue;
    
    for(int i = 0;i<10;i++){  
      pinMode(pins[i], OUTPUT);
      digitalWrite(pins[i],HIGH);
      for(int j = 0;j<2;j++){
        sensorValue=analogRead(analog_R);
      }
      digitalWrite(pins[i],LOW);
      pinMode(pins[i], INPUT);
      
      Serial.println(" ");
      Serial.print("Sensor value = ");
      Serial.println(sensorValue);
      Serial.print("Known Resistor value = ");
      Serial.println(R1[i]);
      float voltage=(sensorValue*vin)/1024.0;
      Serial.print("voltage = ");
      Serial.println(voltage);
      
      screen(String(resistance(vin-voltage,i)));
    }
    while(1){}
  }
}

unsigned long resistance(float vout,int i){
  return R1[i]*(1/(vin/vout-1));
}

void screen(String text){
    Serial.print("Estimate resistor value = ");
    Serial.print(text);
    Serial.println(" ohm");
}

flintloque:
Could i do that using diodes and change VCC to 4.3 to account for diode voltage drop?

How would that help? Your have been given the solution to your problem at least three times. What don't you undestaand?

I don't see any further point in posting to this topic until you implement the solution.

Have you had statistics and propagation of errors in your educational program? This is usually taught to first or second year science majors in college, and should be a given for a masters program. If so, time to apply that learning! If not, back to the books.

What are the specified accuracies of the resistor values in your setup? What is the overall accuracy of a voltage divider, given the individual resistor specifications (use propagation of errors)?

What is are the ACTUAL voltages involved? Measure them with your multimeter.

How accurate is your multimeter?

jremington:
Don't worry about it -- not your project!

And not yours either. :cold_sweat:

OK, here is the circuit to compensate for the driver resistance - albeit with a slight blunder that I can't be bothered to re-do given the time limit on CircuitLab. :astonished:


R1 should be 4k7 or some other desired value, and there are of course, further values after R8.

The point is, when the lower resistances - comparable to the 50 Ohm approximate value of the output driver - are selected, Analog 1 measures the actual voltage driving the selected resistor, and can be used as the basis of the ratio on Analog 0 which is used to calculate the unknown resistor value using the correct formula. By the time you get to 4k7 or 10k, 50 Ohm is only 1% or less of the value so there is no need to compensate for it.

Note of course that the low value reference resistances are now the sum of the values except for the very first, the one here on D44. :grinning: