Go Down

### Topic: Using Digital I/O as analog input (working!) (Read 6528 times)previous topic - next topic

#### thefatmoop

##### Feb 01, 2011, 03:37 amLast Edit: Feb 02, 2011, 10:38 am by thefatmoop Reason: 1
Here's a program that will measure an analog value (currently set up as measuring resistance) that can measure an extremely wide range of resistances from around 300ohms to 2.2meg ohms tested so far. Expect about +-4% accuracy (usually 4% too high on resistance). With my setup the measurements were very stable. This is great for getting analog input that will blow the 10bit onboard ADC away.

Here's a picture of circuit and equation. the unlabeled resistor is the one you want to measure

Anyway you can remove all the analog pin usage ( they're just there to measure voltage before and after the pin goes high). Call measureOhms(digitalPin) with digitalPin as the pin that the circuit is on, so you can easily use this for multiple pins. As for timings the larger the capacitor, the longer it will take to measure resistance. You can fix this by using a smaller capacitor, and if your resistance is too low then use larger capacitors for the timing to be large enough for the arduino to measure

Here's how it works

The capacitor gets discharged by the arduino, then the blue line's rising edge means that the digital pin has been set to input. The falling edge on the blue line is when the digital input triggers as HIGH. the arduino then compares the uptime before and after the capacitor started to charge. Resistor calculations can be done knowing initial volts (0v), final volts (2.55v), and the difference in time.

Code: [Select]
`double arduinoVoltage = 4.94; int Vpin = A0; int digitalPin = 12; int analogValuePrior = 0; int analogValueAfter = 0;void setup() {                    Serial.begin(9600);  delay(100);  Serial.print("on");  }void loop() {      Serial.print("resistance: ");  Serial.println(measureOhms(digitalPin));  Serial.print("ohms");    Serial.print("voltage prior: ");  Serial.println(analogValuePrior/1023.*arduinoVoltage);  Serial.print("voltage after: ");  Serial.println(analogValueAfter/1023.*arduinoVoltage);  Serial.print("\n\n");  delay(500);  }double measureOhms(int pinNum){ //pinNum is the digital i/o pin double timeStart = 0; double timeEnd = 0; double timeMicroSec = 0;  timeMicroSec = 0;  pinMode(digitalPin, OUTPUT);  digitalWrite(digitalPin,LOW);  delay(2); //discharge the cap    pinMode(digitalPin,INPUT);  //timeMicroSec = pulseIn(digitalPin, LOW);                                                      analogValuePrior = analogRead(Vpin);  timeStart = micros();     while(digitalRead(digitalPin) == LOW){}//wait for the pin to go HIGH    timeEnd = micros();                                                      analogValueAfter = analogRead(Vpin);  timeMicroSec = timeEnd - timeStart;    return convertToResist(timeMicroSec);}double convertToResist(double timeMicroSec){  double voltageTrigger = 2.55;  //double Vin = 4.94;  double capacitorUF = .1; // value of capacitor in micro farads (larger cap means you can measure lower resistance resistors)    return (  pow( -log(-voltageTrigger/arduinoVoltage + 1)*capacitorUF/(timeMicroSec),-1)    );}`

#### simon.monk

#1
##### Feb 03, 2011, 05:52 pm
A good example of lateral thinking.

Could come in handy some day.
--
I write books about Arduino and Electronics: http://simonmonk.org

#### liuzengqiang

#2
##### Feb 03, 2011, 05:57 pm
Good work!
I was always told that a voltage between digital HIGH and LOW will be giving indeterminate digital levels. So does your digital pin always turns LOW/HIGH at the same voltage and won't flip in the undefined voltage range? I'm curious.
Serial LCD keypad panel,phi_prompt user interface library,SDI-12 USB Adapter

#### retrolefty

#3
##### Feb 03, 2011, 06:02 pm
Quote
So does your digital pin always turns LOW/HIGH at the same voltage and won't flip in the undefined voltage range? I'm curious.

It will vary a little with the specific Vcc voltage on the chip and with temperature changes. It's normally not a recommended method to read a digital input, but working 'outside' the box sometimes gives decent results even if not the established method.

Lefty

#### BetterSense

#4
##### Feb 03, 2011, 07:21 pm
This is kind of like an integrating ADC, which can be very accurate but slow.

The ATMEGA chips have built-in voltage comparators that can be used for things like this more precisely, but I don't know how to access them using strictly arduino code.

#### Grumpy_Mike

#5
##### Feb 03, 2011, 10:04 pm
Quote
This is great for getting analog input that will blow the 10bit onboard ADC away.

Hard to see how that is justified. The resolution is poorer, it takes longer to read a sample and it ties up the CPU while you are doing it. But well done anyway.

Go Up