how to set lower adc precision value on Atmega16?

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

Hi, i'm new to programming and micro-controllers and i would like to get a 6 bit adc precision in my Atmega16 project, to get values from 0 to 64 instead of 0 to 255.

 

here's my code for now :

 

int adc(uchar channel)
{
    // AD conversion:
    ADMUX = channel & 0x07;            // single ended channel 0..7
    ADMUX |= (0 << REFS1) | (0 << REFS0);            // AVCC as reference
    ADMUX |= (0<<ADLAR);            // left adjust result
    
    ADCSRA |= (1<<ADSC);            // start conversion
    while (ADCSRA & (1<<ADSC));        // wait for ADC ready
    
    return ADCH;                // 8 bit precision and i need 6 bit

 

Thank you in advance!

This topic has a solution.

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

Hi, i'm new to programming and micro-controllers and i would like to get a 6 bit adc precision in my Atmega16 project, to get values from 0 to 64 instead of 0 to 255.

 

??? Do you mean 0-63?

 

Did you mean 0-1023 from a 10 bit result?

 

The obvious answer to your question is "divide by 4" (or equivalently shift two places), isn't it?

 

Tell why you "need 6 bit"?  Now, your derived control signal may be desired in a different range.  So you gather a full ADC result, filtering/averaging as needed.  Then you apply a transfer function to relate the ADC reading (e.g. speed) into the units you desire (e.g. furlongs per fortnight, 0-63).  And that transfer function is /4.

 

In the real world it usually isn't quite that cut-and-dried.  The "/4" is often a multiply and divide with calibration factors, perhaps with an offset.  (Can you say "y = (rise/run)*x + b" ?)

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

yes 0-63

 

why? i making a midi controller for a program that cant recive CC values higher than 64 (or 63).

/4 does it mean return ADCH/4 ;? can you give me an exemple? (i know that 255/4 is 63.75 but i thought that making something like ADMUX |= (ADLAR>>2) would be better;
 

according to http://maxembedded.com/2011/06/t... if you have 10 bit adc precision it gives you max value of 2^10 = 1024 so i think if i will use 6 bit precision i will get max value of 64 2^6 = 64.

Last Edited: Tue. May 19, 2015 - 03:31 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

uint16_t adc_result;

uint16_t control value;

...

// I guess 8-bit (ADLAR) or 10-bit is up to you.

//  Many of us would take multiple readings and average or otherwise filter to minimize noise.

 

// Get the reading

adc_result = read_adc(my_channel);

 

// (average, filter as needed)

 

// Convert to control signal by applying transfer function

control_value = adc_result/4;

 

// Now use the control_value in the desired units

...

 

With the above approach, you keep read_adc() "pure" to be able to use with other signal ranges.

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

ADMUX |= (0 << REFS1) | (0 << REFS0);            // AVCC as reference
    ADMUX |= (0<<ADLAR);            // left adjust result
  

???  Where in the world did you get this routine?  ORing anything with zero does nothing.  There are many discussions here on re-building ADMUX each time, rather than doing any bit fussing.

 

AVcc as reference is >>not<< 0-0 for the bits, is it?

Mega48 app code fragment below; similar to Mega16 but the internal reference is a different value:

// VREF
// ====
//	Note that in ADMUX, bit 7 is REFS1; bit 6 is REFS0

//	REFS1:0		ADMUX Mask		Description
//	------- 	----------		-----------
//	0 			0x00			External AREF
//	1			0x40			Use Vcc as Aref
//	3			0xc0			Internal 1.1V bandgap
#define	ADC_VREF_VCC	0x40
#define	ADC_VREF_AREF	0x00
#define	ADC_VREF_BG		0xC0


#define ADC_VREF_TYPE ADC_VREF_VCC

...

Then your read_adc() becomes something like:

 

uint16_t read_adc(uchar channel)
{
    // AD conversion:
    ADMUX = ADC_VREF_TYPE | (1<<ADLAR) | (channel & 0x07);            // single ended channel 0..7
    
    ADCSRA |= (1<<ADSC);            // start conversion
    while (ADCSRA & (1<<ADSC));        // wait for ADC ready
    
    return ADCH;                // 8 bit precision 
}

 

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.

Last Edited: Tue. May 19, 2015 - 03:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you ! it worked !