NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » MicroView and ADC conversion

June 14, 2017
by scootergarrett
scootergarrett's Avatar

So I'm using the MicroView that I bootloaded discussed here, everything seemed to be working correctly but now I'm am trying to use the analog to digital converter. When I load the program on a simple DIP 328p it works as expected (numbers print to my computer screen change with voltage). But when I load the exact same program on the MicroView the analog to digital converter only outputs 1023 no matter the voltage. Dose anyone have experience with boot loading an Arduino and needing to do something special to get the ADC working?

Code:

// PIN DEFINITIONS:
//
// PC0 -- temperature sensor analog input

void adc_init() {
    // set analog to digital converter
    // for external reference (5v), single ended input ADC0
    ADMUX = 0;

    // set analog to digital converter
    // to be enabled, with a clock prescale of 1/128
    // so that the ADC clock runs at 115.2kHz.
    ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);

    // fire a conversion just to get the ADC warmed up
    ADCSRA |= (1<<ADSC);
}

uint16_t adc_read()
{
    // read from ADC, waiting for conversion to finish
    // (assumes someone else asked for a conversion.)
    // wait for it to be cleared
    while(ADCSRA & (1<<ADSC))
    {
        // do nothing... just hold your breath.
    }
    // bit is cleared, so we have a result.

    // read from the ADCL/ADCH registers, and combine the result
    // Note: ADCL must be read first (datasheet pp. 259)
    uint16_t result = ADCL;
    uint16_t temp = ADCH;
    result = result + (temp<<8);

    // set ADSC bit to get the *next* conversion started
    ADCSRA |= (1<<ADSC);

    return result;
}

int main()
{
    uint16_t ADCVal;

    // start up the Analog to Digital Converter
    adc_init();

    // start up the serial port
    uart_init();
    FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
    stdin = stdout = &uart_stream;

    while(true)
    {
        ADCVal = adc_read();

        printf_P(PSTR("ADC:%i\r\n"), ADCVal);
        delay_ms(100);
    }

    return 0;
}
June 14, 2017
by scootergarrett
scootergarrett's Avatar

Solved my own problem but am unsure of the reason. From this post I found this line:

ADMUX |= ( 1 << REFS0 );

When added to the adc_init() function it works as expected. I'm not sure what the initial difference was between the MCU where they were defaulting to different states.

June 19, 2017
by BobaMosfet
BobaMosfet's Avatar

ADMUX contains which of N channels of the ADC you're using. Set it to 1 (or whichever channel you want to use: ADMUX = 1 If you OR it, you're turning on more than one channel.

Don't OR it. Do a warm-up conversion every time you change the channel.

BM

Post a Reply

Please log in to post a reply.

Did you know that hobby servos are controlled through a particular kind of PWM (Pulse Width Modulation) signal? Learn more...