Dealing with AnalogRead jitter

Ok I'm having an issue with analogRead and jitter on the values, in particular I need to monitor the voltage on a capacitor until it reaches the 5 volts and then log the discharge time through a pot, and blink an led to indicate the discharge time.

Something is not working correctly, I see that the voltage bounces around +/-3 units or there about. I imagine I'm going to have the same issue on checking voltage as it drops. The code seems ok, but the led just stays solid as far as I can tell.

I was trying is like this:

/* Capacitor Algorithm

 setup pins
 - discharge to input (High impedence)
 - charge pin to output


 ** Calculate Capacitance **
 record start by micros(econds)
 set charge to output to high
 check voltage until (loop) voltage reaches max
 current time - start time
 Serial print Capacitance? (time/resistance)

 ** Calculate discharge time **
 Discharge
 - charge pin to input (high impedence)
 - record start by micros(econds)
 - discharge to low output
 - check voltage until at RC
 - current time - start time

 ** Set Blink Rate **


 End Algorithm
 */

int pinAnalog = A0;
int pinDischarge = 2;
int pinCharge = 5;
int outLed = 9;

unsigned long startTime;
unsigned long chargeTime;
unsigned long endTime;
unsigned long blinkDuration;

void setup() {
	pinMode(pinCharge, OUTPUT);     // set pinCharge to output
	digitalWrite(pinCharge, LOW);   // set pinCharge to low
}

void loop() {
	digitalWrite(pinCharge, HIGH);  // set pinCharge HIGH and capacitor charging

	while (analogRead(pinAnalog) < 1024) {       // When analog pin voltage reaches, 647 is 63.2% of 1023, 1 TC
	}											// 0V - 5V => 0 to 1023
	startTime = micros();           // record start time in milliseconds

	/* dicharge the capacitor  */
	digitalWrite(pinCharge, LOW);	// set charge pin to  LOW
	pinMode(pinDischarge, OUTPUT);	// set discharge pin to output
	digitalWrite(pinDischarge, LOW);	// set discharge pin LOW
	while (analogRead(pinAnalog) > 0) {// wait until capacitor discharges 0V

	}
	endTime = micros() - startTime; //record time it took to dischare
	pinMode(pinDischarge, INPUT); //set discharge pin back to input, (high impedence)

	blinkDuration = computeBlinkDuration(endTime) / 2;

	while (micros() - endTime < 20000) { //blink the led for duration
		if (abs(endTime / blinkDuration) % 2 != 1)
			digitalWrite(outLed, HIGH);
		else
			digitalWrite(outLed, LOW);
	}
}

unsigned long computeBlinkDuration(unsigned long result) {
	unsigned long high = 1000000; //1 second or 1 million microseconds
	unsigned long low = 100000; //0.1 seconds, or 100,000 microseconds
	unsigned long delta = high - low;
	
        return delta * result / 100000 + low;
}

I see that the voltage bounces around +/-3 units or there about.

Only to be expected this is because you are measuring in microseconds and the analogue read takes about 10 microseconds to compleat so you are never going to get the same figure.

Blinking an led to show a variable quantity is not a very sensitive tool. Also without trying it the code you use to do this is not terribly convincing, it looks obscure.mhave you tried just the blink bit and feeding it diffrent data?

Hi, first when you are going to charge the capacitor, you output 5 high to charge the cap.
What is the other side of the capactitor doing??
A0 will not measure the charge on the cap.
You need to re evaluate the circuit.

It should be .

One end of capacitor to gnd, the other end of the capacitor to A0.
D5 through your potentiometer to A0,

When D5 is LOW the cap is discharging, when D5 is HIGH it is charging.
A0 is monitoring the charge voltage on the capacitor.
If you want a different charge and discharge rate then you will have to use two digital outputs and some diodes.
As the arduino is only rated at 40mA output current then the value of your charge resistor should be,

5/0.04=125 Ohms minimum, to limit peak current.

I would suggest higher value of resistance, say 1K, depending on capacitor values you are aiming to measure.

Hope this helps.
Tom..... :slight_smile:

and the analogue read takes about 10 microseconds

More like 100 microseconds.

Isn't putting D2 to an input before charging the capacitor a way to prevent it from discharging the capacitor. I thought it would be high impedance?
Won't grounding one terminal cause it to drain out into ground and not charge?

Normally I would ground it, but was unsure how to handle this:

I think you want to have your Cap in parallel to ground, not series. You might also want to consider using a transistor to charge up the cap, rather than a pin. Otherwise you'll have to switch it from output to Hi-Z input to deal with that factor.

             / --- 5V
  D5 ->  |  (P-Type or PNP)
            \ ---- | ----- | --- A0
                      |           >  
                  ===C1    <  (R1, Pot?)
                      |           >
  GND  ------|------|---

This should let you measure the time constant assuming it is slow enough for the ADC on the arduino to read it. You may also want to try looking at a comparator and once it crosses a known threshold from High, record that time.

Your going to get some jitter on the ADC readings that's just the real world. You could repeat the experiment 100 times and the average your data, may be?. It would be best if you gave us more background.

Mark

To be honest this is a Circuits Lab, they are all using Basic Parallax stamps and it to be working.

Course I being the odd one pull out my arduino and try the same, "blink an led to indicated the discharge time of a capacitor depending on the position of the pot" My understanding is that the pot limits the rate that capacitor discharges depending on the value its set at.

Not sure I'm right BUT 5V is absolute max for the ADC you may be better limiting the voltage to say 4.8 (a voltage divider) and look for anything over that as your end condition. Allowing for losses in the wiring I'm not convinced you will consistently get a 5V reading from the ADC. With ideal components, in theory Yes, but in the real word NO.

Mark

Hi, if you use the circuit in reply #7, A0 will read zero all the time, because it is at ground.
A0 should be connected to the junction of the resistor and capacitor, that way you are measuring the voltage across the capacitor.

Tom.... :slight_smile:

Oh kk, I see that. Guess Ill play around with blink rates for now and determine if its the code or the limitation of analogRead. I knew there was some delay but wasn't expecting a 100 millisecond delay.

but wasn't expecting a 100 millisecond delay.

Where?
An analogRead takes about 100 microseconds.

holmes4:
Not sure I'm right BUT 5V is absolute max for the ADC you may be better limiting the voltage to say 4.8 (a voltage divider) and look for anything over that as your end condition. Allowing for losses in the wiring I'm not convinced you will consistently get a 5V reading from the ADC. With ideal components, in theory Yes, but in the real word NO.

Mark

Absolute maxs are -0.5V and Vcc+0.5V, and losses in the wiring won't affect an ADC reading
as the input resistance is something like 10^10 ohms or higher.