0

I am using an ATMega2560 with a resistance touch screen (uses the ADC with analogRead commands) – I also use other ADC pins with analogRead (NTC temp sensor). This all works fine.

I have recently added a function that requires me to get ADC readings at known intervals and decided that using the automatic sampling was best – I found the code to do this online and it works well for the function it is required for.

My issue is, after I do the continuous sampling, I cannot get the ADC analogRead values to return the same as they where before the continuous sample.

I have checked the datasheet and it says the initial value for the ADCSRA, ADCSRB & ADMUX = 0 – I have tried this and quite a few other things with no success.

I have attached some code that does the same as my program – i.e. analogRead returns a different value after the continuous sample.

byte samplesADC[100];
int samplesADCCount = 0;
bool ADCEnd = false;

void startADCAcquire(){
  int dacChan = 14;
  Serial.println("Start ADC Aquire: ");
  
  cli();//diable interrupts
  
  //set up continuous sampling of analog pin 0
  //clear ADCSRA and ADCSRB registers
  ADCSRA = 0;
  ADCSRB = 0;
  
  ADMUX |= dacChan&0x07;
  if (dacChan >= 8) 
      ADCSRB |= _BV(MUX5);
  else
      ADCSRB &= ~_BV(MUX5);
  ADMUX |= (1 << REFS0); //set reference voltage
  ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only

  ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
  ADCSRA |= (1 << ADATE); //enabble auto trigger
  ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
  ADCSRA |= (1 << ADEN); //enable ADC
  ADCSRA |= (1 << ADSC); //start ADC measurements
  sei();//enable interrupts
}

void stopADCAcquire(){
  Serial.println("");
  Serial.println("Stop ADC Acquire");
  cli();//diable interrupts
  
  //set up continuous sampling of analog pin 0
  //clear ADCSRA and ADCSRB registers
  ADCSRA = 0;
 ADCSRB = 0;
  ADMUX = 0;
//  ADCSRB &= ~_BV(MUX5);
//  ADMUX &= ~(1 << ADLAR); 
//   ADCSRA &= ~(1 << ADSC);       // disable adc interrupt
  sei();//enable interrupts 
}

void setup(){
  
  Serial.begin(9600);
  Serial.println("");
  Serial.println("START");
  Serial.print("Pin A2 (1): ");
  Serial.println(analogRead(A2));
  startADCAcquire();
  int i;
  while(ADCEnd == false){
    i++;
  }
  while ((UCSR0A & _BV (TXC0)) == 0)
    {} 
  Serial.print("Pin A2 (2): ");
  Serial.println(analogRead(A2));
  Serial.println("END");
}

ISR(ADC_vect) {//when new ADC value ready
  samplesADC[samplesADCCount] = ADCH;
  Serial.print(samplesADC[samplesADCCount]);
  Serial.print(", ");
  samplesADCCount++;
  if(samplesADCCount == 100){
   
   stopADCAcquire();
    ADCEnd = true;
  }
}

void loop(){
}

Output:

START
Pin A2 (1): 0
Start ADC Aquire: 
127, 127, 127...... (x100) 
Stop ADC Acquire
Pin A2 (2): 510
END
1
  • Read Nick Gammon on interrupt. Commented Oct 21, 2021 at 23:53

1 Answer 1

0

Thanks @hcheung...

So I'm not sure if you pointed me to the interrupt page, with reference to the code issues around my interrupt handlers - I think I have sorted these by using volatile variables and removing excess code/print statements from the ISR handler. So thanks for the link - it was a helpful reminder.

However this did nothing to resolve my issue and the output remained the same! On the interrupt page I noticed some code where registers are copied to a buffer and then reassigned later. I decided to try this and copied the ADCSRA, ADCSRB & ADMUX registers on program load and reassigned them after the AD scan. This also failed - Then as last ditch I copied the registers just before the call to start the AD scan (i.e afer analogRead had been called) and it worked. I am now able to use the analogRead command after my continuous read.

I attach updated code that works - i.e analogRead works after being in continuous mode.

volatile byte samplesADC[100];
volatile int samplesADCCount = 0;
volatile bool ADCEnd = false;
uint8_t  ADCSRASave;
uint8_t  ADCSRBSave;
uint8_t  ADMUXSave;


void startADCAcquire(){
  int dacChan = 14;

  ADCSRASave = ADCSRA;
  ADCSRBSave = ADCSRB;
  ADMUXSave = ADMUX;

  cli();//diable interrupts
  
  //set up continuous sampling of analog pin 0
  //clear ADCSRA and ADCSRB registers
  ADCSRA = 0;
  ADCSRB = 0;
  ADMUX |= dacChan&0x07;
  if (dacChan >= 8) 
     ADCSRB |= _BV(MUX5);
  else
    ADCSRB &= ~_BV(MUX5);
  ADMUX |= (1 << REFS0); //set reference voltage
  ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
  ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
  ADCSRA |= (1 << ADATE); //enabble auto trigger
  ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
  ADCSRA |= (1 << ADEN); //enable ADC
  ADCSRA |= (1 << ADSC); //start ADC measurements
  sei();//enable interrupts
}

void stopADCAcquire(){
  cli();//diable interrupts
  ADCSRA = ADCSRASave; //0;
  ADCSRB = ADCSRBSave; //0;
  ADMUX = ADMUXSave; //;
  sei();//enable interrupts 
}

void setup(){
  Serial.begin(9600);
  Serial.println("");
  Serial.println("START");
  Serial.print("Pin A2 (1): ");
  Serial.println(analogRead(A14));
  Serial.println("Start ADC Aquire: ");
  while ((UCSR0A & _BV (TXC0)) == 0){} 
  startADCAcquire();
   while(ADCEnd == false){  }
  stopADCAcquire();
  for(int x = 0; x < 100; x++){
     Serial.print(samplesADC[x]);
    Serial.print(", ");
  }
  Serial.println("");
  Serial.println("Stop ADC Acquire");
  Serial.print("Pin A2 (2): ");
  Serial.println(analogRead(A14));
  Serial.println("END");
}

ISR(ADC_vect) {//when new ADC value ready
  samplesADC[samplesADCCount] = ADCH;
// Serial.print("p");
  samplesADCCount++;
  if(samplesADCCount == 100){
       ADCEnd = true;
  }
}

void loop(){
}

Output:

START
Pin A2 (1): 511
Start ADC Aquire: 
127, 127, 127, 127 <<< x 100
Stop ADC Acquire
Pin A2 (2): 511    <<< value now same as first
END
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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.