problem with attiny24 adc

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys.

I'm working on a project with attiny24a. avr should read 2 adc channels in a timer ISR and convert the adc value to a voltage value.

At first I read adc0 , convert it and compare with a constant value, it works. Then I read just adc1 same as adc0 and it's ok. But the problem is when I read two adc channels immediately after each other!!

 

see codes below:

ISR (TIM0_OVF_vect)
{
	// Produce almost 1mSec
	if (++Timer0Counter0==mSec_1) 
	{		
		Timer0Counter0=0;
		ADC1=read_adc(1);
		ADC0=read_adc(0);
		
		//V1=(ADC1*5*(R12+R11))/(1023*R12);
		V0=(ADC0*5*(R02+R01))/(1023*R02);
		
		if (V0>10)	{Led_On;}
		else		{Led_Off;}
			
	}
}

 

According to the codes when V0 is bigger than 10v, led goes on, other wise it's off. but it doesn't work as it designed to. It doesn't change in 10.. when I reduce V1 about 6.5, led goes on and off...

this is my schematic:

 

what should I do?

This topic has a solution.

...

Last Edited: Sun. Dec 24, 2017 - 05:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I should add that this code works in main while loop correctly:

 

while(1)
{
    ADC1=read_adc(1);
    ADC0=read_adc(0);
    
    V1=(ADC1*5*(R12+R11))/(1023*R12);
    V0=(ADC0*5*(R02+R01))/(1023*R02);
    
    if (V0>10 && V1>10)	
    {
        Led_On;
    }
    else		
    {
        Led_Off;
        
    }
}

 

...

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

My first guess is ADC0/ADC1 have not been defined as "volatile"? 

Any variable shared between main() and an ISR() should be declared volatile.

 

If this has been done, then please post a small complete program that demos the problem.

 

Jim

 

Mission: Improving the readiness of hams world wide : flinthillsradioinc.com

Interests: Ham Radio, Solar power, futures & currency trading - whats yours?

 

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

ki0bk wrote:
My first guess is ADC0/ADC1 have not been defined as "volatile"? 

 

I tested both situation! non-volatile and volatile variable! got the same resault!  This kind of code works as I expect in main while:

sasan.riahi wrote:
while(1) { ADC1=read_adc(1); ADC0=read_adc(0); V1=(ADC1*5*(R12+R11))/(1023*R12); V0=(ADC0*5*(R02+R01))/(1023*R02); if (V0>10 && V1>10) { Led_On; } else { Led_Off; } }

 

but any other conditions like below, does not work:

 

- read adc pins in ISR and change led in main while

- read adc pins and change led in ISR!! 

 

The strange thing is that I check V0 voltage to be 10v and then I change led on/off! but led changed when V1 is about 6.5v!!

 

please post a small complete program that demos the problem.

theres nothing else in this code right now!! just check two voltage inputs and change a led on/off!! 

...

Last Edited: Tue. Dec 19, 2017 - 05:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think I found the problem.. 

 

if V0=10      =>     V0_ADC=424

if V1=6.5     =>     V1_ADC=426

////

if V1=10      =>     V1_ADC=655

if V0=15.5   =>     V0_ADC=657

 

I think when I want to read adc in ISR, the adc channel does not selected correctly!!

what whould cause this problem???indecision

...

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

sasan.riahi wrote:
what whould cause this problem???
ki0bk wrote:
please post a small complete program that demos the problem

In particular, ADC setup and the ADC read routine.  Do we know AVR's clock speed? 

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

I've never met a pig I didn't like, as long as you have some salt and pepper.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I fixed the problem!

 

in my read_adc function I read the adc channel 3 times in a for loop to ensure the right channel is selected.

 

unsigned int read_adc(unsigned char adc_input)
{
	char i=0;
	ADMUX=adc_input;
	_delay_us(10);
	for (i = 0; i < 3; i++)
	{
		ADCSRA|=(1<<ADSC);
		while ((ADCSRA & (1<<ADIF))==0);
		ADCSRA|=(1<<ADIF);
	}
	return ADCW;
}

 

...