Pages: [1]   Go Down
 Author Topic: Using Digital I/O as analog input (working!)  (Read 3175 times) 0 Members and 1 Guest are viewing this topic.
0
Offline
Jr. Member
Karma: 0
Posts: 78
Arduino rocks
 « on: January 31, 2011, 09:37:56 pm » Bigger Smaller Reset

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:
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);
timeStart = micros();

while(digitalRead(digitalPin) == LOW){}//wait for the pin to go HIGH

timeEnd = micros();
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)    );

}
 « Last Edit: February 02, 2011, 04:38:43 am by thefatmoop » Logged

UK
Offline
God Member
Karma: 10
Posts: 903
 « Reply #1 on: February 03, 2011, 11:52:36 am » Bigger Smaller Reset

A good example of lateral thinking.

Could come in handy some day.
 Logged

--
My New Arduino Book: http://www.arduinobook.com

Central MN, USA
Offline
Tesla Member
Karma: 64
Posts: 6889
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
 « Reply #2 on: February 03, 2011, 11:57:37 am » Bigger Smaller Reset

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.
 Logged

Left Coast, CA (USA)
Online
Brattain Member
Karma: 331
Posts: 16478
Measurement changes behavior
 « Reply #3 on: February 03, 2011, 12:02:20 pm » Bigger Smaller Reset

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

 Logged

Dallas
Offline
Sr. Member
Karma: 2
Posts: 337
nephew as a kittens
 « Reply #4 on: February 03, 2011, 01:21:43 pm » Bigger Smaller Reset

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.
 Logged

Manchester (England England)
Offline
Brattain Member
Karma: 506
Posts: 31345
Solder is electric glue
 « Reply #5 on: February 03, 2011, 04:04:41 pm » Bigger Smaller Reset

Quote