reading multiple analong input atmega328p - Page 1
Forum section: electronics / general

author: altruan23
author_rank: Contributor
timestamp: November 20, 2021, 08:22:17 am
content: Hello.I want to read 2 analog inputs and print them out every second, but i dont know how to do that. Can anyone help me?the datasheet can be found here:https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdfCode:#include "Arduino.h"// Global Variablesunsigned long int t_ref; // Reference time// whenever a variable is used by both, Interrupt and main programm we// need to tell the compiler about it ==> volatilevolatile unsigned long int millisekunden; // milli seconds timerunsigned long int last_msg; //char buffer;unsigned int c;unsigned int adc2;unsigned int adc5;void setup() {// Timer 0TCCR0A = (1 << WGM01); // CTC ModeTCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler 64OCR0A = 250;// Compare InterruptTIMSK0 |= (1 << OCIE0A);// ADCADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADIE);ADMUX |= (1 << REFS0) | (1 << MUX1); // avcc and ADC2ADCSRA |= 1 << ADSC; // start cconversionSerial.begin(9600);}void loop() {if (millisekunden - last_msg >= 1000) {sprintf(buffer, "\nt=[%lu] adc2=%d, adc5=%d",millisekunden, adc2, adc5);Serial.println(buffer);last_msg = millisekunden;}}// Timer-Interrupt-RoutineISR(TIMER0_COMPA_vect) {millisekunden++;}ISR(ADC_vect) {adc2 = ADC;ADCSRA |= 1 << ADSC;}

author: ledtester
author_rank: Super Contributor
timestamp: November 20, 2021, 08:36:27 am
content: It looks like you are using the Arduino libraries, so you what about using analogRead():https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/The Arduino library also keeps track of milliseconds for you:https://www.arduino.cc/reference/en/language/functions/time/millis/Otherwise, here's a tutorial on performing low-level ADC reads by manipulating the ADC control registers:https://maker.pro/custom/tutorial/how-to-take-analog-readings-with-an-avr-microcontroller

author: altruan23
author_rank: Contributor
timestamp: November 20, 2021, 08:51:43 am
content: Im not allowed to use arduino functions... im just using the platform but our teacher doesnt allow us to use that.

author: Psi
author_rank: Super Contributor
timestamp: November 20, 2021, 08:58:44 am
content: You don't need to use use any interrupts or timers (unless the teachers says you must use interrupts).Setup- Configure the ADC reference to what you want to use, probably AVCC pin.Loop- Set the ADC channel to the correct channel for the first ADC input you want to read- Start an ADC conversion by writing 1 to the correct bit of the ADC control registers- Wait in a loop for the ADC conversion complete bit to become set- Read the ADC data register value and print it or whatever- Set the ADC channel to the correct channel for the second ADC input you want to read- Start an ADC conversion by writing 1 to the correct bit of the ADC control registers- Wait in a loop for the ADC conversion complete bit to become set- Read the ADC data register value and print it or whatever

author: altruan23
author_rank: Contributor
timestamp: November 20, 2021, 09:01:59 am
content: i only know this way to read 1 value. how can i read another one and print them both out?

author: altruan23
author_rank: Contributor
timestamp: November 20, 2021, 09:23:31 am
content: So i tried to solve it with an array but it doesnt want to work. it saves just 1 value in both array places.Code:#include "Arduino.h"// Global Variablesunsigned long int t_ref; // Reference time// whenever a variable is used by both, Interrupt and main programm we// need to tell the compiler about it ==> volatilevolatile unsigned long int millisekunden; // milli seconds timerunsigned long int last_msg; //char buffer;unsigned int c;unsigned int adc2;unsigned int adc5;unsigned int anVal;volatile unsigned int adc_curr_ch = 0;void setup() {// Timer 0TCCR0A |= (1 << WGM01); // CTC ModeTCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler 64OCR0A = 250;// Compare InterruptTIMSK0 |= (1 << OCIE0A);// ADCADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADIE);ADMUX |= (1 << REFS0); // avccADCSRA |= 1 << ADSC; // start cconversionSerial.begin(9600);}void loop() {if (millisekunden - last_msg >= 1000) {sprintf(buffer, "\nt=[%lu] ADC0=%d ADC1=%d ",millisekunden, anVal, anVal);last_msg = millisekunden;Serial.println(buffer);}}// Timer-Interrupt-RoutineISR(TIMER0_COMPA_vect) {millisekunden++;}ISR(ADC_vect) {anVal = ADC;// save to adc2if (adc_curr_ch == 0) {ADMUX |= (1 << MUX1);adc_curr_ch = 1;}// save to adc5else if (adc_curr_ch == 1) {ADMUX |= (1 << MUX2) | (1 << MUX0);ADMUX &= ~(1 << MUX1);adc_curr_ch = 0;}ADCSRA |= 1 << ADSC;}

author: Psi
author_rank: Super Contributor
timestamp: November 20, 2021, 10:04:35 am
content: Your anVal array needs to be made volatile.Also, check your MUX settings are correct. Looks like you are starting on ADC2 but then switching between ADC5 and ADC7 because MUX2 and MUX0 are never cleared. So it's switching between 101 and 111

author: altruan23
author_rank: Contributor
timestamp: November 20, 2021, 10:30:12 am
content: still isnt working. can u just pls check my code and repair it? i really dont have time i waster already 4hourse today and im writing the exam in 2 days.Code:ISR(ADC_vect) {anVal = ADC;// save to adc2if (adc_curr_ch == 0) {ADMUX |= (1 << MUX1);ADMUX &= ~(1 << MUX2) | ( 1 << MUX0);adc_curr_ch = 1;}// save to adc5else if (adc_curr_ch == 1) {ADMUX |= (1 << MUX2) | (1 << MUX0);ADMUX &= ~(1 << MUX1);adc_curr_ch = 0;}ADCSRA |= 1 << ADSC;}

author: Psi
author_rank: Super Contributor
timestamp: November 20, 2021, 11:06:00 am
content: I'm happy to point out errors, but I'm not writing your homework for you.You're missing a ~ for the (1 << MUX0) when you clear ADMUX.

author: altruan23
author_rank: Contributor
timestamp: November 20, 2021, 11:35:38 am
content: i fixed it but still isnt working.Code:#include "Arduino.h"// Global Variablesunsigned long int t_ref; // Reference time// whenever a variable is used by both, Interrupt and main programm we// need to tell the compiler about it ==> volatilevolatile unsigned long int millisekunden; // milli seconds timerunsigned long int last_msg; //char buffer;unsigned int c;unsigned int adc2;unsigned int adc5;volatile unsigned int anVal;volatile unsigned int adc_curr_ch = 0;void setup() {// Timer 0TCCR0A |= (1 << WGM01); // CTC ModeTCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler 64OCR0A = 250;// Compare InterruptTIMSK0 |= (1 << OCIE0A);// ADCADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADIE);ADMUX |= (1 << REFS0); // avccADCSRA |= 1 << ADSC; // start cconversionSerial.begin(9600);}void loop() {if (millisekunden - last_msg >= 1000) {sprintf(buffer, "\nt=[%lu] ADC0=%d ADC1=%d ",millisekunden, anVal, anVal);last_msg = millisekunden;Serial.println(buffer);}}// Timer-Interrupt-RoutineISR(TIMER0_COMPA_vect) {millisekunden++;}ISR(ADC_vect) {anVal = ADC;// save to adc2if (adc_curr_ch == 0) {ADMUX |= (1 << MUX1);ADMUX &= ~(1 << MUX2);ADMUX &= ~( 1 << MUX0);adc_curr_ch = 1;}// save to adc5else if (adc_curr_ch == 1) {ADMUX |= (1 << MUX2) | (1 << MUX0);ADMUX &= ~(1 << MUX1);adc_curr_ch = 0;}ADCSRA |= 1 << ADSC;}

author: HB9EVI
author_rank: Frequent Contributor
timestamp: November 20, 2021, 11:54:38 am
content: hmm, did you enable the global interrupt with sei() ?

author: altruan23
author_rank: Contributor
timestamp: November 20, 2021, 01:03:07 pm
content: unfortunately. thats not the problem