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
}
-
To use a different channel you'd change ADMUX. See the datasheet to determine what it should be.Delta_G– Delta_G2018年01月31日 05:17:05 +00:00Commented Jan 31, 2018 at 5:17
1 Answer 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:
- Save the value that has just been read
- switch the multiplexer to the other channel
- 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;