ADS1115 Interrupt Not Working

Hello,

I am trying to use an interrupt to read an ADS1115 using an Arduino Uno board. The ADS1115 is connected to a single potentiometer and reads one value. I am using the Adafruit_ADS1x15 library.

I can read the ADS1115 using the library's single ended example:

#include <Adafruit_ADS1X15.h>

Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */

void setup(void)
{
  Serial.begin(9600);
  Serial.println("Getting single-ended readings from AIN0..3");
  Serial.println("ADC Range: +/- 6.144V (1 bit = 3mV/ADS1015, 0.1875mV/ADS1115)");

  if (!ads.begin()) {
    Serial.println("Failed to initialize ADS.");
    while (1);
  }
}

void loop(void)
{
  int16_t adc0;
  float volts0;

  adc0 = ads.readADC_SingleEnded(0);
  volts0 = ads.computeVolts(adc0);
  Serial.println(volts0);

  delay(1000);
}

However, when I copy the code from the loop into the interrupt, it does not output anything into the serial monitor anymore.

#include <Adafruit_ADS1X15.h>

Adafruit_ADS1115 ads;

int16_t adc0;
float volts0;

// counter and compare values
const uint16_t tl_load = 0;
const uint16_t tl_comp = 31250;

void setup(void) {
  Serial.begin(9600);

  // reset timer 1 control reg A
  TCCR1A = 0;

  // set prescaler of 256
  TCCR1B |= (1 << CS12);
  TCCR1B &= ~(1 << CS11);
  TCCR1B &= ~(1 << CS10);

  // reset timer 1 and set compare value
  TCNT1 = tl_load;
  OCR1A = tl_comp;

  // enable timer compare interrupt
  TIMSK1 = (1 << OCIE1A);

  // enable global interrupts
  sei();

  if (!ads.begin()) {
    Serial.println("Failed to initialize ADS.");
    while (1);
  }

}
                                                   
void loop(void) {
  delay(1000); // main code, waits when interrupt is not called
}

// interrupt
ISR(TIMER1_COMPA_vect) {

  adc0 = ads.readADC_SingleEnded(0);
  volts0 = ads.computeVolts(adc0);
  Serial.println(volts0);

  TCNT1 = tl_load; // sets timer to 0
}

I'm assuming that single ended mode is not compatible with my interrupt setup, but I don't understand the ADS1115's modes.

Thanks for any help! This is my first time working with embedded code and external ADCs so I'm not really knowledgeable on the microcontroller or the ADS1115.

That breaks all the rules for interrupts. Never attempt to do serial I/O of any sort in an interrupt.

Instead, set a flag, declared volatile, and in loop() check that flag, then do all the required work.

// interrupt
volatile bool interrupt_flag = false;

ISR(TIMER1_COMPA_vect) {

 interrupt_flag = true;
  TCNT1 = tl_load; // sets timer to 0
}
...
// in loop:

if (interrupt_flag) {
interrupt_flag = false;
process_data();
}
...
1 Like

Yout loop has only a delay. When you fix that, remove all delays, they don't help and can only hurt as when in a delay you don't receive the interrupts.
You must be an advanced coder as I don't understand the hieroglyphics.

You need to, so study the data sheet carefully.

It should go without saying that you can't collect data faster than the ADS1115 can produce it, but there appears to be nothing in the code that checks.

Thanks for your response!

I was planning on adding a check. I am still reading about how to do so using the data sheet (again, I am very new to embedded coding).

Hopefully it won't be an issue in this early test? Currently the interrupt only occurs every 0.5s.

Why hope? Look up how to set the data sampling rate: 8 to 860 samples per second.

You might also look up how to use the built in data ready interrupt output.

Finally, consider studying Adafruit's getting started tutorial.

1 Like