## Simple ADC loop returning max values [ATMega328P] [Registers] [C] [ArduinoUno]

4 posts / 0 new
Author
Message

Hi! First time posting here, but it seems like a great resource when troubleshooting, so I'm sure I'll be back!

Unfortunately I haven't been able to get a simple ADC loop to run on my Arduino Uno. I am trying to complete part of a university assignment in which we are learning to use C code to manage the registers of the ATMega328P as part of an Arduino Uno. The goal is quite simple - get the built-in LED to light up when the ADC registers a high value (above the 511 threshold), and otherwise turn off it off. I'm using a voltage divider of a 100 Ohm and 330 Ohm resistor, from the 5V to GND pin of my Arduino. The midpoint voltage is measured through wire to the A0 Arduino pin.

I've been staring at the datasheet for ages, and I just don't get what's not working with the code below. I have tried running the Arduino ADC example, which works on that pin, proving that the hardware works (I suppose?). I also started writing to the Serial port in order to see what values the ADC was picking up. An LED is connected to Arduino pin 12 in order to see when the conversion is running (depending on the ADCSRA ADSC bit value), and it seems like the ADC is indeed working...

EDIT: Forget to mention that it is continuously returning the maximum value of 1023, although I measure around 3.75V from my voltmeter.

Thankful for any guidance! :)

// Write a program that continuously converts an analogue singal on ADC0. If the value exceeds 50% turn on built-in LED, else turn off LED.

unsigned int threshold = 511; //0x01FF; // Half of nominal 10-bit max value: 1024/2-1=511

void setup() {
// For testing...
Serial.begin(9600);
Serial.print("\nThreshold is set to: ");
Serial.print(threshold, BIN);

// Regarding LED
DDRB|=0x20; //Define PB5 as output

PRR &= 0xFE; // Power Reduction ADC in PRR.PRADC (bit 0) must be 0 (enable ADC-functionality). Keep other values.

//ADMUX = (ADMUX & 0xF0)+0b00000000; // Select input channel ADC0 (Arduino A0) with bits 0-3 as 0000. First clear bits 0-3, then add correct combo. Keep bits 4-7. See datasheet pg 317 for other pin selections.
//ADMUX &= 0b00111111; // Set voltage reference to VCC by clearing bits 6 and 7, as 00 will set AREF (5V). Keeps other vals.
//ADMUX &= 0b11011111; // By default, the value is presented RIGHT ADJUSTED (here set to 0 manually as well). Left adjusted is toggled by setting ADMUX.ADLAR (bit 5) to 1. Keep other vals.

}

void loop() {

ADCSRA = 0b11000111; // Start a conversion (ADSC, bit 6) and enable ADC (ADEN, bit 7). Pre-scaler of 128 (bits 0-2: 111) to get more accurate results (pg. 308). Pg 319 in datasheet.

PORTB |=0x10; // Second LED on to show conversion is still working.
}

delay(500);
PORTB &=0xEF; //Second LED off to show conversion finished. Should be on for roughly half a sec.

// Conversion complete! Time to read result.

PORTB |= 0x20; // Turn on LED
}
else{
PORTB &= 0xDF; // Turn off LED
}

delay(500); //Delay to allow second LED time to be off (in order to see blinking effect).

}

Mechatronics student

Last Edited: Sun. Sep 17, 2017 - 04:58 PM

You've set the external reference AREF, which likely has nothing connected to it.  You'll probably want the AVCC reference instead with REFS[1:0]=0b01.

Please don't use magic numbers.  Your code is hard to read, hard to debug, hard to maintain.

And why are you reading ADCH/L separately, and in such a convoluted manner?

`ADCres = ADC;`

 "Experience is what enables you to recognise a mistake the second time you make it." "Good judgement comes from experience.  Experience comes from bad judgement." "When you hear hoofbeats, think horses, not unicorns." "Fast.  Cheap.  Good.  Pick two." "Read a lot.  Write a lot." "We see a lot of arses on handlebars around here." - [J Ekdahl]

You were completely right about the AVCC reference voltage. Apparently the professor who walked us through the basics missed that part, and I must have misunderstood the datasheet (since I did consider changing that, and actually thought I'd tried it at some point).

Reading ADC is muuuch easier than what I did - also something the professor did, and I didn't find any alternatives while reading the datasheet. Good to know for the future!

Yeah, I suppose the "magic numbers" are really bad code - but this really isn't going to be ported to any other platforms. I did initially try to use shifting of bits, but removed it as part of my troubleshooting.

Once again, thanks so much for the help - glad I wasn't too far off!

Mechatronics student

Last Edited: Sun. Sep 17, 2017 - 05:14 PM