SIMPLE ADC

Last post
21 posts / 0 new
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.

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

LOL. [Yet another reason I use the Tiny25, I guess.]

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

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

Simonetta wrote:
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.

VCC of Tiny13 stays at 5.1 V regardless of whether I have LEDs or not. I am using internal clock (Int. RC OSc. 9.6 MHz; Start-up time: 14 CK + 64 ms) but I see CKDIV8 bit checked. Does this mean the actual clock I will be using is 9.6 Mhz divided by 8 and the final clock will be that number divided by prescaler?

I haven't tried using single conversion technique and would like to leave it till I ran out of possible solution.

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

Quote:

but I see CKDIV8 bit checked. Does this mean the actual clock I will be using is 9.6 Mhz divided by 8

Yes 1.2MHz

 

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

KitCarlson wrote:
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.

Just read manual regarding debug wire. I've check off DWEN and when I clicked program, AVR Studio warned me about losing ISP. Does this mean, after clicking OK, I will not be able to program the ATTINY13?

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

Quote:

OK, I will not be able to program the ATTINY13?

If all you have is ISP then yes you have lost the chip. If you buy a debugWire interface (Dragon, JTAGICEmkII, AVR One!) then you will be able to contact it via dW and while in that mode get it switched back to ISP.

Only thing is those debuggers cost respectively:

$50
$299
one kidney or your grandmother

 

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

clawson wrote:
Quote:

but I see CKDIV8 bit checked. Does this mean the actual clock I will be using is 9.6 Mhz divided by 8

Yes 1.2MHz

I've changed the prescaler to 4 so that my clock speed will be 300 KHz. Nonetheless, I still have the same issue.

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

Quote:

I've changed the prescaler to 4 so that my clock speed will be 300 KHz.

Which prescaler? Are you talking about CLKPR. When the CKDIV8 fuse is set it just arranges for that register to default to /8 and 9.6MHz becomes 1.2MHz. If you have changed that to /4 you have changed the CPU frequency to 2.4MHz

 

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

Quote:
Which prescaler? Are you talking about CLKPR. When the CKDIV8 fuse is set it just arranges for that register to default to /8 and 9.6MHz becomes 1.2MHz. If you have changed that to /4 you have changed the CPU frequency to 2.4MHz

I mean the prescaler that i set with the following code

ADCSRA |= (1 << ADPS1); 
ADCSRA &= ~((1 << ADPS2) | (1 << ADPS0));

Will it not be 300 KHz after all this? /8 from CKDIV8 and /4 from ADPS bits? so 9600 Khz / 32 = 300 kHz

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

I've moved the ADC input port to ADC2. I am not sure why it did not work with ADC0 but I think it has something to do with RESET. Can you guys please explain why this is happening?

This is where I've got the idea:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=65484&highlight=adc+attiny13

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

Quote:

I've moved the ADC input port to ADC2. I am not sure why it did not work with ADC0 but I think it has something to do with RESET. Can you guys please explain why this is happening?

The _RESET pin cannot be used for anything but resetting the micro UNTIL you change the state of the RSTDISBL fuse bit.

However do NOT rush to do this because as soon as you do you will no longer be able to reprogram the chip (by ISP). If you have a high voltage serial programmer (ne that applies +12V to _RESET) then you will be able to reprogram it - but you then need to consider whether the analog circuity connected to pin1 might be destroyed when 12V is applied - so for HVSP it's best to have the chip socketed so you can remove it and plug it into the separate programmer when you need to.

This is one of the penalties you pay for using a chip with so few pins. In the short term - if you don't need to use all th other pins the easy answer is to move the ADC input as you have.