Using internal VRef on ATmega 328

For Flowcode users to discuss projects, flowcharts, and any other issues related to Flowcode 6.

Moderator: Benj

Post Reply
Niro
Posts: 77
Joined: Mon Jan 03, 2011 8:58 pm
Has thanked: 29 times
Been thanked: 10 times

Using internal VRef on ATmega 328

Post by Niro »

Hi All,

I know, there has been a post regarding attiny for FC V5 here, but it seems to me this is different in V6.
http://wwww.matrixmultimedia.com/mmforu ... 5ce#p52772

Can anybody help using the internal ref (1.1V) of the ATmega 328?

Many thanks,
Niro

Niro
Posts: 77
Joined: Mon Jan 03, 2011 8:58 pm
Has thanked: 29 times
Been thanked: 10 times

Re: Using internal VRef on ATmega 328

Post by Niro »

I tried it the way of the thread mentioned above, but unfortunately it does not work.
ADC is still using Vref=VDD

For the use of the internal Vref (1,1V) this should be added for ATmega328:
ADMUX |= (1 << REFS0); (Bit 6)
ADMUX |= (1 << REFS1); (Bit 7)

So I looked through the AVR_CAL_ADC and found out, MX_ADC_TYPE_2 is used

So I modified AVR_CAL_ADC.c like this;

Code: Select all

#ifdef MX_ADC_TYPE_2
	void FC_CAL_ADC_Enable (MX_UINT8 Channel, MX_UINT8 Conv_Speed, MX_UINT8 Vref, MX_UINT8 T_Charge)
	{
		Vref = 1 - Vref;

		tris_reg = (MX_UINT8*) &DDRC;
		old_tris = *tris_reg;

		*tris_reg &= ~(1 << Channel);							//turn selected ADC on
		ADCSRA = (1 << ADEN) | Conv_Speed;
		// ADDED 4 lines
		#ifdef MY_CUSTOM_ADC
			ADMUX |= (1 << REFS0); 
			ADMUX |= (1 << REFS1);
		#else
			// Original line follows:
			ADMUX = (Vref << REFS0) | (1 << ADLAR) | Channel;
			// ADDED next line
		#endif

		delay_us(T_Charge);										//wait the acquisition time

		ADCSRA |= (1 << ADSC);									//begin next conversion
	}

	MX_UINT16 FC_CAL_ADC_Sample (MX_UINT8 Sample_Mode)
	{
		MX_UINT16 iRetVal;

		while(ADCSRA & (1 << ADSC));

		if (Sample_Mode)
		{
			iRetVal = (ADCL >> 6);								//10-bit ADC
			iRetVal |= (ADCH << 2);
		}
		else
			iRetVal = ADCH;										//8-bit ADC

		ADCSRA |= (1 << ADSC);									//begin next conversion

		return (iRetVal);
	}

	void FC_CAL_ADC_Disable ()
	{
		*tris_reg = old_tris;									//restore old tris value, and reset adc registers
		ADCSRA &= ~(1 << ADEN);
	}
I also added "#define MY_CUSTOM_ADC" to the supplementary code.

In the panel properties there still is only VDD and Vref+ Pin selectable.
But that wouldn't matter if it woulf work....

As I'm really no expert in C and don't really know how ADCs get managed by FlowCode, could anybody please check the code and help to get it work.

Many thanks,
Niro
Attachments
ADC_01.jpg
ADC_01.jpg (47.01 KiB) Viewed 5257 times

kersing
Valued Contributor
Valued Contributor
Posts: 2045
Joined: Wed Aug 27, 2008 10:31 pm
Location: Netherlands
Has thanked: 553 times
Been thanked: 1081 times

Re: Using internal VRef on ATmega 328

Post by kersing »

The supplementary code is included after the component code in the generated C code if I recall correctly.

A work around would be to try adding a define in the global variables pane (at the top) set to any value. Now generate the C code and check for a define named like the one you just added prefixed FC... As a last step, change your ifdef in AVR_CAL_ADC.C to check for the name you just found in stead of MY_CUSTOM_ADC.
“Integrity is doing the right thing, even when no one is watching.”

― C.S. Lewis

Niro
Posts: 77
Joined: Mon Jan 03, 2011 8:58 pm
Has thanked: 29 times
Been thanked: 10 times

Re: Using internal VRef on ATmega 328

Post by Niro »

Thanks kersing, for this workaround.
The idea sound good, but unfortunately it doesn't work either.

Maybe I applied it the wrong way....

I added a global that shows up in the C-code under 'variable declarations' as:
#define FCVsz_ADC_VREF_INTERN 1
Now I changed the name in the AVR_CAL_ADC this way, but nothing different happens.

Next I tired someting different and replaced the original lines in the AVR_CAL_ADC with the ones that should enable internal Vref (selecting VDD in the panel properties):

Code: Select all

#ifdef MX_ADC_TYPE_2
	void FC_CAL_ADC_Enable (MX_UINT8 Channel, MX_UINT8 Conv_Speed, MX_UINT8 Vref, MX_UINT8 T_Charge)
	{
		Vref = 1 - Vref;

		tris_reg = (MX_UINT8*) &DDRC;
		old_tris = *tris_reg;

		*tris_reg &= ~(1 << Channel);							//turn selected ADC on
		ADCSRA = (1 << ADEN) | Conv_Speed;
		// modified lines
			ADMUX = (1 << ADLAR) | Channel;
		// setting ADC to Vref intern	
			ADMUX |= (1 << REFS0); 
			ADMUX |= (1 << REFS1);		
		// end of modification	
		

		delay_us(T_Charge);										//wait the acquisition time

		ADCSRA |= (1 << ADSC);									//begin next conversion
	}

	MX_UINT16 FC_CAL_ADC_Sample (MX_UINT8 Sample_Mode)
	{
		MX_UINT16 iRetVal;

		while(ADCSRA & (1 << ADSC));

		if (Sample_Mode)
		{
			iRetVal = (ADCL >> 6);								//10-bit ADC
			iRetVal |= (ADCH << 2);
		}
		else
			iRetVal = ADCH;										//8-bit ADC

		ADCSRA |= (1 << ADSC);									//begin next conversion

		return (iRetVal);
	}

	void FC_CAL_ADC_Disable ()
	{
		*tris_reg = old_tris;									//restore old tris value, and reset adc registers
		ADCSRA &= ~(1 << ADEN);
	}
Now the value measured at the ADC changes to a different value, but still not the correct one expected.

As it is really confusing for me how FlowCode handles the ADCs, can't anybody of the matrix staff help???
I need this very urgent for a customer project....

Many thanks,
Niro

Niro
Posts: 77
Joined: Mon Jan 03, 2011 8:58 pm
Has thanked: 29 times
Been thanked: 10 times

Re: Using internal VRef on ATmega 328

Post by Niro »

OK.... done!
I wrote my own C-code for accessing the ADC. Much easier than modifing FlowCode.
But I hope that gets fixed in an update.
Using FlowCode for professional applications needs really some better support for special functions, and especially for AVR at all....

Regards,
Niro

Post Reply