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
}
1
  • To use a different channel you'd change ADMUX. See the datasheet to determine what it should be.
    – Delta_G
    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;

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.