SIMPLE ADC

21 posts / 0 new
Last post
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi

Thanks everyone for answering my question earlier regarding simple push button, I'd like to fire away my second question.

I'm using the following code to test ADC. I'm using ATTINY13 for this simple project and using the following diagram for input to the ADC0.

(+5V)
-------
|
620 ohm
|
Var Resistor(20 kOhm) ---> into ADC0
|
620 ohm
|
(GND)

Currently, LED2 turns, on while the LED1 off, when the input to the ADC0 is below 2.5V and vice versa. However, I am experiencing LED2 going off if I keep turning the pot below 2.18 V. The LED2 stays on between 2.5V to 2.18V but not below 2.18V.

// Source: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=56429

#include 
#include 

int main(void)
{
	DDRB |= (1 << 2); // Set LED1 as output 
   	DDRB |= (1 << 0); // Set LED2 as output 

	ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Set ADC prescaler to 128 - 125KHz sample rate @ 16MHz 
	
	//ADMUX |= (1 << REFS0); // Set ADC reference to AVCC 
	ADMUX &= ~(1 << REFS0); // Set ADC reference to VCC 
	ADMUX |= (1 << ADLAR); // Left adjust ADC result to allow easy 8 bit reading 

	// No MUX values needed to be changed to use ADC0 

	
	ADCSRA |= (1 << ADEN);  // Enable ADC 

	ADCSRA |= (1 << ADIE);  // Enable ADC Interrupt 
	sei();   // Enable Global Interrupts 

	ADCSRA |= (1 << ADSC);  // Start A2D Conversions 
	//ADCSRA |= (1 << ADFR);  // Set ADC to Free-Running Mode 
	ADCSRA |= (1 << ADATE);
	for(;;)  // Loop Forever 
	{ 
	} 
}

ISR(ADC_vect) 
{ 
	// Code to be executed when ISR fires 
 	if(ADCH < 128)
    {
    	PORTB |= (1 << 2); // Turn on LED1
        PORTB &= ~(1 << 0); // Turn off LED2 		
    }
	else
    {
    	PORTB &= ~(1 << 2); // Turn off LED1 
        PORTB |= (1 << 0); // Turn on LED2 
		
	}
}

What am I doing wrong? Any suggestions?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there something wrong with my question format? I need help on this. I don't have debugger tool to debug where the logic error is coming from.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Suggest you wire up the UART (or perhaps an LCD) and actually print out the raw ADCH readings to see what's going on.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Currently, LED2 turns, on while the LED1 off, when the input to the ADC0 is below 2.5V and vice versa. However, I am experiencing LED2 going off if I keep turning the pot below 2.18 V. The LED2 stays on between 2.5V to 2.18V but not below 2.18V.

Check reference voltage pin

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for your replies.

I'm using VCC as my reference voltage, am I not?
ADMUX &= ~(1 << REFS0); // Set ADC reference to VCC

I think by observing that the transition of LED occur at around 2.5V, VCC is being used for reference voltage . Comment on this?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I'm using VCC as my reference voltage, am I not?
ADMUX &= ~(1 << REFS0); // Set ADC reference to VCC

Yes you are.
I'm not that much expert but it is look like issue with reference voltage, try to vary reference voltage using potentiometer and check the results.

Nilesh

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try variations of the program. For example, do a single conversion (instead of free running) 50 times a second.

What is the VCC of the Tiny13 when the pot goes below 2.18V? What is the resistor value on the LED?

Try removing the LEDs and see if the logic on PortB 0 and 2 works correctly. Does VCC voltage stay on PortB2 when the pot is less than +2.1 when the LED is removed?

In a simple situation like this the first troubleshooting approach is to determine if the problem is in the program or in the hardware wiring.

Are you using a crystal on the Tiny13? Your code says ADPS2_0 is 125KHz from a 16MHz system clock. The Tiny13 can not use a crystal and can only get a 16MHz system clock from an external clock source. Try changing the fuses for the internal 9.6MHz or 4.8MHz clock.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

With the Tiny13, a debug method might be to setup a PWM and feed the ADC to it. This is very simple to do. A scope can then be used to read the ADC value via a duty-cycle measurement. If a scope is not available used a led and resistor and view intensity.

It all starts with a mental vision.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Or if you can find one, hook up one of those old-fashioned, mechanical meters and let its inertia integrate the pulse train for you. Or create an RC filter and substitute a DVM.

---------------------
John Firestone

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Quote:
I'm using VCC as my reference voltage, am I not?
ADMUX &= ~(1 << REFS0); // Set ADC reference to VCC

Yes you are.


Well, assuming that the value of REFS1 is immaterial.

I >>always<< fail to see the fascination with bit-fiddling ADMUX. Just build it ans set it. It is more efficient in terms of cycles and code space, avoids any RMW situations, and makes most of the discussion in this thread moot.

Here is one link to a prior spouting of my opinion on this, that links to another thread which has 3 more links...
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=95716&highlight=admux+rmw
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=95310&highlight=admux+rebuild

You can put lipstick on a pig, but it is still a pig.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Well, assuming that the value of REFS1 is immaterial.
Since the tiny13 doesn't have a REFS1, I would say that it is immaterial.

Regards,
Steve A.

The Board helps those that help themselves.

Pages