1

How could the same code be used with different ADC channels?

const byte adcPin = 0; // A0
const int MAX_RESULTS = 100;
volatile int resultsV [MAX_RESULTS];
volatile int resultsI [MAX_RESULTS];
volatile int resultNumber;
void setup ()
{
 Serial.begin (115200);
 Serial.println ();
 // reset Timer 1
 TCCR1A = 0;
 TCCR1B = 0;
 TCNT1 = 0;
 TCCR1B = bit (CS11) | bit (WGM12); // CTC, prescaler of 8
 TIMSK1 = bit (OCIE1B);
 OCR1A = 338;
 OCR1B = 338; // 39 = 20 uS - sampling frequency 50 kHz
 ADCSRA = bit (ADEN) | bit (ADIE) | bit (ADIF); // turn ADC on, want interrupt on completion
 ADCSRA |= bit (ADPS2); // Prescaler of 16
 // ADCSRA |= (1 << ADPS1) | (1 << ADPS0); // 8 prescaler for 153.8 KHz
 ADMUX = bit (REFS0) | (adcPin & 7);
 ADCSRB = bit (ADTS0) | bit (ADTS2); // Timer/Counter1 Compare Match B
 ADCSRA |= bit (ADATE); // turn on automatic triggering
}
// ADC complete ISR
ISR (ADC_vect)
{
 resultsV[resultNumber++] = ADC;
 //resultsI[resultNumber++] = ADC;
 if (resultNumber == MAX_RESULTS)
 {
 ADCSRA = 0; // turn off ADC
 }
}
EMPTY_INTERRUPT (TIMER1_COMPB_vect);
void loop () {
 while (resultNumber < MAX_RESULTS)
 { }
 for (int i = 0; i < MAX_RESULTS; i++)
 {
 Serial.print( resultsV);
 Serial.print(" ");
 Serial.print( resultsI);
 Serial.println();
 }
 resultNumber = 0;
 ADCSRA = bit (ADEN) | bit (ADIE) | bit (ADIF) | bit (ADPS2) | bit (ADATE);
 // turn ADC back on
}
per1234
4,2782 gold badges23 silver badges43 bronze badges
asked Jan 31, 2018 at 2:32
1
  • To use a different channel you'd change ADMUX. See the datasheet to determine what it should be. Commented Jan 31, 2018 at 5:17

1 Answer 1

1

From what I understand, you want to read two ADC channels simultaneously. First, you have to understand that you cannot read them exactly at the same time, as you have a single ADC. What you can do, however, is read them one after the other: you read the V channel, then the I channel, then the V channel again, etc. This means you will have to change the multiplexer setting (the ADMUX register) in between the readings. The most convenient place to do this is within the ADC ISR, the logic of which becomes:

  1. Save the value that has just been read
  2. switch the multiplexer to the other channel
  3. turn off the ADC if you are done.

Example code (not tested):

const byte PIN_V = 0; // A0
const byte PIN_I = 1; // A1
// ADC complete ISR.
ISR(ADC_vect)
{
 if (ADMUX & 7 == PIN_V) {
 // We have just read the V channel.
 // Save the value and switch to the I channel.
 resultsV[resultNumber] = ADC;
 ADMUX = bit(REFS0) | PIN_I;
 } else {
 // Otherwise we completed a (V, I) pair, we can increment
 // resultNumber.
 resultsI[resultNumber++] = ADC;
 ADMUX = bit(REFS0) | PIN_V;
 }
 // Turn off the ADC when done.
 if (resultNumber == MAX_RESULTS)
 ADCSRA = 0;
}

Note that this example assumes you do the readings in the (V, I) order. Thus, within setup(), you have to initialize the multiplexer for the V channel, as in

ADMUX = bit(REFS0) | PIN_V;
answered Jan 31, 2018 at 9:31

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.