Using pin change interrupt for analog input PCINT8

Hi Folks,

I’m currently playing around with “pin change interrupts” but the sketch I’ve written, doesn’t work as expected.
Maybe there’s someone out there, who can help me.

So, what is my intention: I’ve a temperature sensor LM35 connected to A0 (analog in 0) on my Arduino Uno.
Everytime, when there is a change in temperature, I want to throw an interrupt and do something - e.g. print
out the temperature. I know, that task could be done very easy - but I want to play around with pin change interrupts.

When I remove the OUT pin of the LM35 sensor from the breadboard - some values are printed, but nothing
gets printed while the sensor is connected =(

volatile const uint8_t sensPin = 0;
volatile uint8_t analog_reference = DEFAULT;

volatile unsigned long IRQ8PrevTime;
volatile int prevVal = 0;
volatile uint8_t irqFlag = 0;

void setup() {
  Serial.begin(9600);
  
  PCICR |= (1 << PCIE1);      // enable pin change interrupt for PCINT14..8
  PCMSK1 |= (1 << PCINT8);    // Enable Pin Change interrupt for ADC0 (analog PIN 0) INT8
  IRQ8PrevTime = millis();    // Hold current time
  
  Serial.println("Waiting interrupt...");
  interrupts();
}

void loop() {
  if (irqFlag == 1) {
    Serial.println (prevVal);   // Print value
    irqFlag=0;                  // Reset IRQ flag
  } 
}

ISR(PCINT1_vect) {
  int curVal;
  
  long unsigned IRQ8ActTime = millis();
  
  if (IRQ8ActTime - IRQ8PrevTime > 1) {
    ADMUX = (analog_reference << 6) | (sensPin & 0x07);  // ADMUX - ADC Mulitplexer Selection Register
    ADCSRA |= (1<<ADSC);                                 // ADCSRA: Bit 6 – ADC Start Conversion
    while (bit_is_set(ADCSRA, ADSC));                    // While conversion in progress loop
    uint8_t low = ADCL;                                  // read low value
    uint8_t high = ADCH;                                 // read high value
    curVal = (high << 8) | low;                          // combine low + high
    
    if (curVal != prevVal) {
      IRQ8PrevTime = IRQ8ActTime;
      prevVal = curVal;
      irqFlag = 1;
    }
  }
}

Thanks for any help or suggestions

Richard

Interrupts are digital beasts. Pin change interrupts occur when a pin changes from a high logic level to a low logic level, or vice versa. They won't work well at all with an analog signal as output by an LM35.

OK, thank you for this useful information.
Maybe that'll explain why the interrupt happens whe I disconnect the OUT signal from the sensor.

Is there any other efficient way to catch changes in sensor data without polling them?

Using timers?

A timer could be used to cause an interrupt, which could then cause the sensor to be read. That seems to me to just be a fancy way of polling, though.

One question to ask would be what constitutes a change in sensor data. In the case of an analog sensor (and probably a lot of digital sensors too), it has to be read to detect a change, the detecting being a task for software.

A comparator to compare the signal to a threshold voltage? Hang on - doesn't the ATMega328p have one of those built in...?

Polling could be made much less time consuming by splitting the analogRead(). I did this as an experiment see - Experiment - split up analog read in 3 steps - Libraries - Arduino Forum -