Author Topic: reading multiple analong input atmega328p  (Read 2279 times)

0 Members and 1 Guest are viewing this topic.

Offline altruan23Topic starter

  • Contributor
  • Posts: 17
  • Country: si
reading multiple analong input atmega328p
« on: November 20, 2021, 08:22:17 am »
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.pdf
Code: [Select]
#include "Arduino.h"

// Global Variables

unsigned 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 ==> volatile
volatile unsigned long int millisekunden; // milli seconds timer
unsigned long int last_msg;               //
char buffer[256];
unsigned int c;
unsigned int adc2;
unsigned int adc5;



void setup() {

  // Timer 0
  TCCR0A = (1 << WGM01);               // CTC Mode
  TCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler 64
 
  OCR0A = 250;

  // Compare Interrupt
  TIMSK0 |= (1 << OCIE0A);

  // ADC
  ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADIE);
  ADMUX |= (1 << REFS0) | (1 << MUX1); // avcc and ADC2
  ADCSRA |= 1 << ADSC; // start cconversion

  Serial.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-Routine
ISR(TIMER0_COMPA_vect) {
  millisekunden++;
}

ISR(ADC_vect) {

 
  adc2 = ADC;
  ADCSRA |= 1 << ADSC;
}

 

Offline ledtester

  • Super Contributor
  • ***
  • Posts: 3036
  • Country: us
Re: reading multiple analong input atmega328p
« Reply #1 on: November 20, 2021, 08:36:27 am »
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

 

Offline altruan23Topic starter

  • Contributor
  • Posts: 17
  • Country: si
Re: reading multiple analong input atmega328p
« Reply #2 on: November 20, 2021, 08:51:43 am »
Im not allowed to use arduino functions... im just using the platform but our teacher doesnt allow us to use that.
 

Online Psi

  • Super Contributor
  • ***
  • Posts: 9953
  • Country: nz
Re: reading multiple analong input atmega328p
« Reply #3 on: November 20, 2021, 08:58:44 am »
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
« Last Edit: November 20, 2021, 09:07:42 am by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline altruan23Topic starter

  • Contributor
  • Posts: 17
  • Country: si
Re: reading multiple analong input atmega328p
« Reply #4 on: November 20, 2021, 09:01:59 am »
i only know this way to read 1 value. how can i read another one and print them both out?
 

Offline altruan23Topic starter

  • Contributor
  • Posts: 17
  • Country: si
Re: reading multiple analong input atmega328p
« Reply #5 on: November 20, 2021, 09:23:31 am »
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: [Select]
#include "Arduino.h"

// Global Variables

unsigned 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 ==> volatile
volatile unsigned long int millisekunden; // milli seconds timer
unsigned long int last_msg;               //
char buffer[256];
unsigned int c;
unsigned int adc2;
unsigned int adc5;
unsigned int anVal[2];
volatile unsigned int adc_curr_ch = 0;

void setup() {

  // Timer 0
  TCCR0A |= (1 << WGM01);               // CTC Mode
  TCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler 64

  OCR0A = 250;

  // Compare Interrupt
  TIMSK0 |= (1 << OCIE0A);

  // ADC
  ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADIE);
  ADMUX |= (1 << REFS0); // avcc
  ADCSRA |= 1 << ADSC; // start cconversion

  Serial.begin(9600);
}

void loop() {

  if (millisekunden - last_msg >= 1000) {

    sprintf(buffer, "\nt=[%lu] ADC0=%d ADC1=%d ",
            millisekunden, anVal[0], anVal[1]);

    last_msg = millisekunden;
    Serial.println(buffer);
  }

}

// Timer-Interrupt-Routine
ISR(TIMER0_COMPA_vect) {
  millisekunden++;
}

ISR(ADC_vect) {

  anVal[adc_curr_ch] = ADC;
// save to adc2
  if (adc_curr_ch == 0) {
    ADMUX |= (1 << MUX1);
    adc_curr_ch = 1;
  }
// save to adc5
  else if (adc_curr_ch == 1) {
    ADMUX |= (1 << MUX2) | (1 << MUX0);
    ADMUX &= ~(1 << MUX1);
    adc_curr_ch = 0;
  }

  ADCSRA |= 1 << ADSC;
}
 

Online Psi

  • Super Contributor
  • ***
  • Posts: 9953
  • Country: nz
Re: reading multiple analong input atmega328p
« Reply #6 on: November 20, 2021, 10:04:35 am »
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
« Last Edit: November 20, 2021, 10:11:46 am by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline altruan23Topic starter

  • Contributor
  • Posts: 17
  • Country: si
Re: reading multiple analong input atmega328p
« Reply #7 on: November 20, 2021, 10:30:12 am »
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: [Select]
[code]ISR(ADC_vect) {

  anVal[adc_curr_ch] = ADC;
  // save to adc2
  if (adc_curr_ch == 0) {
    ADMUX |= (1 << MUX1);
    ADMUX &= ~(1 << MUX2) | ( 1 << MUX0);
    adc_curr_ch = 1;
  }
  // save to adc5
  else if (adc_curr_ch == 1) {
    ADMUX |= (1 << MUX2) | (1 << MUX0);
    ADMUX &= ~(1 << MUX1);
    adc_curr_ch = 0;
   
  }

  ADCSRA |= 1 << ADSC;
}
[/code]
 

Online Psi

  • Super Contributor
  • ***
  • Posts: 9953
  • Country: nz
Re: reading multiple analong input atmega328p
« Reply #8 on: November 20, 2021, 11:06:00 am »
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.



Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline altruan23Topic starter

  • Contributor
  • Posts: 17
  • Country: si
Re: reading multiple analong input atmega328p
« Reply #9 on: November 20, 2021, 11:35:38 am »
i fixed it but still isnt working.
Code: [Select]
#include "Arduino.h"

// Global Variables

unsigned 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 ==> volatile
volatile unsigned long int millisekunden; // milli seconds timer
unsigned long int last_msg;               //
char buffer[256];
unsigned int c;
unsigned int adc2;
unsigned int adc5;
volatile unsigned int anVal[2];
volatile unsigned int adc_curr_ch = 0;

void setup() {

  // Timer 0
  TCCR0A |= (1 << WGM01);               // CTC Mode
  TCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler 64

  OCR0A = 250;

  // Compare Interrupt
  TIMSK0 |= (1 << OCIE0A);

  // ADC
  ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADIE);
  ADMUX |= (1 << REFS0); // avcc
  ADCSRA |= 1 << ADSC; // start cconversion

  Serial.begin(9600);
}

void loop() {

  if (millisekunden - last_msg >= 1000) {

    sprintf(buffer, "\nt=[%lu] ADC0=%d ADC1=%d ",
            millisekunden, anVal[0], anVal[1]);

    last_msg = millisekunden;
    Serial.println(buffer);
  }

}

// Timer-Interrupt-Routine
ISR(TIMER0_COMPA_vect) {
  millisekunden++;
}

ISR(ADC_vect) {

  anVal[adc_curr_ch] = ADC;
  // save to adc2
  if (adc_curr_ch == 0) {
    ADMUX |= (1 << MUX1);
    ADMUX &= ~(1 << MUX2);
    ADMUX &= ~( 1 << MUX0);
    adc_curr_ch = 1;
  }
  // save to adc5
  else if (adc_curr_ch == 1) {
    ADMUX |= (1 << MUX2) | (1 << MUX0);
    ADMUX &= ~(1 << MUX1);
    adc_curr_ch = 0;
   
  }

  ADCSRA |= 1 << ADSC;
}
 

Offline HB9EVI

  • Frequent Contributor
  • **
  • Posts: 722
  • Country: ch
Re: reading multiple analong input atmega328p
« Reply #10 on: November 20, 2021, 11:54:38 am »
hmm, did you enable the global interrupt with sei() ?
 

Offline altruan23Topic starter

  • Contributor
  • Posts: 17
  • Country: si
Re: reading multiple analong input atmega328p
« Reply #11 on: November 20, 2021, 01:03:07 pm »
unfortunately. thats not the problem
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf