Pages: [1]   Go Down
Author Topic: Using Digital I/O as analog input (working!)  (Read 3189 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 78
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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);
                                                      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)    );

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

UK
Offline Offline
God Member
*****
Karma: 10
Posts: 903
Twitter: @simonmonk2
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

A good example of lateral thinking.  smiley

Could come in handy some day.
Logged

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

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 65
Posts: 6938
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset 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 Online
Brattain Member
*****
Karma: 332
Posts: 16568
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Sr. Member
****
Karma: 2
Posts: 337
nephew as a kittens
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Brattain Member
*****
Karma: 515
Posts: 31567
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Pages: [1]   Go Up
Jump to: