constant value with ADC on atmega64

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

hello,

i wrote a code to measure a few voltages and currents using the ADC on a atmega16, but the software got big enough that i had to upgrade the chip to an atmega64.

It seemed pretty straight forward to migrate from one to the other, but after hours and hours of trying to debug the software and hardware, i just can't find the reason why the ADC readings are always the same / or do not show the actual input voltage to the sensors... is there something different for the atmega64 ADC? i have already tried different adc channels but they seem to have the same issue, so it must be a software related problem... my code is shown below

thank you!
- Eric

#define F_CPU 7372800UL									
#define BAUDRATE 19200		
#define UBRR_VALUE ((F_CPU/(BAUDRATE*16UL)) - 1)

#include 
#include 
#include 
#include 		
#include 
#include 
#include 
#include 
#include 					
#include 

#define true 1 
#define false 0 

volatile char byte;
volatile char Rx_ready = false;

char Vw_str[3];			
char Iw_str[5];	

unsigned int Vw, Iw;
unsigned char w_API[18];
/************************************************************************************************/

void USART_init()
{	UBRR0L = UBRR_VALUE;					
	UBRR0H = (UBRR_VALUE >> 8);			
	UCSR0B |= (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);	}
/************************************************************************************************/

void initADC()
{	ADMUX |= (0 << REFS1) | (1 << REFS0);						// Set ADC reference voltage to AVCC
	ADCSRA |= (1 << ADEN);//| (1 << ADIE); 						// Enable ADC. ADIE conflicts with ADIF		
	ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);	}	// Set ADC prescaler to 128 bits
/************************************************************************************************/

// Reading an analog value
uint16_t ReadADC(uint8_t channel)		
{
	ADMUX = (ADMUX & 0xF0) | channel;

	ADCSRA |= (1 << ADSC);					// Start Single Conversion
	while(!(ADCSRA & (1 << ADIF)));			// Waiting for conversion to complete
	ADCSRA |= (1 << ADIF);					// Clear AD Interrupt Flag
	uint16_t adc_L = ADCL;				
  	uint16_t adc_H = ADCH;
  	uint16_t adc_final = adc_L + (adc_H << 8);
	return adc_final;
}
/************************************************************************************************/

void USART_TX(unsigned int byt)				
{	while(!(UCSR0A & (1 << UDRE0))){}	
	UDR0 = byt;	} 
/************************************************************************************************/

ISR(USART0_RX_vect)
{	
	byte = UDR0;
	if (byte == 'z')	// Control for reception of data
	{	Rx_ready = true;	}
}	
/************************************************************************************************/

// ADC0	Vs solar voltage
int Vwind()
{	unsigned long volt=0, V_n = 0; 
	unsigned int ADCvoltage = 0;
	ADCvoltage = ReadADC(0);						
	volt = ADCvoltage * 4.88281;					// 5000[mV]/1024=4.88281 -- (R2+R1)/R2=21
	V_n = (unsigned int)(volt * 101.0 / 1000.0);	// where R1 = 10M, R2 = 100k
	return V_n;	}
/************************************************************************************************/

/* CSNP661 - CURRENT SENSOR	*/
int Iwind()
{	long double curr=0;
	unsigned int ADCcurrent = 0;
	ADCcurrent = 0;
	ADCcurrent = ReadADC(5); 	
	curr = ADCcurrent * 0.0488281 * 1000;	// sending [mA]
// curr=Ip --> Ip/1000=Is --> Vi=ADC*5/1024 = Is*Rm --> Vi/R*1000=Ip	
return (unsigned int)curr;	}
/************************************************************************************************/

void values_API(void)
{	
	//send results via xbee pro to laptop
}
/************************************************************************************************/

int main(void)				
{
	USART_init();	
	initADC();
	sei();

	while(1)
    {	
		if (Rx_ready == true)
		{			
			Vw = 0;		Iw = 0;		
						
			Vw = Vwind();
			Iw = Iwind();
				
			values_API(); 
/* send results to laptop via wireless transceivers*/						
			
			Rx_ready = false;
		}
    }
return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is AVCC hooked up and at a proper level?
If you put a voltmeter on the AREF pin, what do you see?
Do you have a cap on the AREF pin?

Also, I'd suggest skipping the conversion during the sanity-check phase and just work with ADC counts.

Quote:

void initADC()
{ ADMUX |= (0 << REFS1) | (1 << REFS0); // Set ADC reference voltage to AVCC
ADCSRA |= (1 << ADEN);//| (1 << ADIE); // Enable ADC. ADIE conflicts with ADIF

I'd make these = and not |=.

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.

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

both avcc and aref are at 5V. I believe the chip is connected right, see picture attached - there is a cap at the aref pin.

i changed the =| for the | but it did no apparent difference.

I am always getting this reply (voltage: 61, current: 67)

w6167
when it should be w00

for some reason when i put some voltage to the voltage sensor, it goes to 504...

note i have tried adc5 for the current, and adc4 and adc0 for the voltage. I have another voltage sensor connected at adc7 and is working just fine

Attachment(s): 

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

what if you skip the formulas and spit out raw adc data ?

also you can read the adc in 1 pass using data=ADC.

another step backwards is to only start with a single channel and having a fixed volatge there. Keep debugging and stripping als long as the result is not as expected and then rebuild from there.

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

Quote:
note i have tried adc5 for the current, and adc4
They are used by the JTAG for the M64 and it MUST be turned off if you want to use them.

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

hmmm i am still getting the reply

w6767

when what i would expect is zero. I found the problem though... most port pins seem to be at a low 0.4-0.6 V...

From p. 327 of atmega64 manual -
low: -0.5 so i guess this is ok and i should account for it in software... but i don't think i had this issue when using the ADC on my atmega16...

could you tell how to bring all pins down to the GND voltage at 0V? (i guess you'll say set all pins to 0, but this will not work with the ADC pins that i do need to use?)

Thank you!
- Eric

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

Can you confirm that you actually read and understood what js posted about JTAG? This is not clear from your post above. Your post starting "hmmmm" coulde be re js's post or meslomps.

(When reporting back on the result of a test of a specific suggestion it is a good idea to quote a short passage of the suggestion so it is clear what was being tested, and to what the result pertains.)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

sorry about that!

js's mentioned:

Quote:
They are used by the JTAG for the M64 and it MUST be turned off if you want to use them.

I am confused as to what do i need to turn off. If it is just to turn off the jtag or unplug it, yes, i do not have the jtag connected when reading voltage and current. If i need to turn off a 'JTAG functionality' of the pin to be able to use the ADC, i am not doing that... could you tell me how to?

thanks,
- Eric

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

If you do not need JTAG at all you can turn it off with a fuse (named JTAGEN or some such).

If you are using JTAG eg to program the AVR then you can let your firmware turn it off. The code has been posted here many times. A Search for "disable JTAG" and similar should turn it up.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Quote:

A Search for "disable JTAG" and similar should turn it up.

Add "JTD" and you may get there quicker - or just search for "JTD" in the datasheet.

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

I got bitten by FAQ#5 :P

thank you, it's working fine now

- Eric