Interrupts on Analog Input Pins

Is there a way to generate interrupts from changes on analog inputs? This would mean recognising a change from any value in the range 0 to 1023 and using it to generate an ISR. If no means exists already, I'm sure this could be done in machine code. Maybe someone out there already has code for it.

Hoping someone can help here!

Dave.

ATmega328 (Uno et.al.) and ATmega2560 have an analog comparator built in, pins AIN0 (positive) and AIN1 (negative), which can be linked to an interrupt.

ATmega328 pin PD6 and PD7, Arduino Uno/Nano pins D6 and D7. ATmega2560 pin PE2 and PE3, on an Arduino Mega PE3 is pin 5, but PE2 is not broken out (so you can only compare to the internal references).

For details on this built-in comparator, see ATmega2560 data sheet, page 265, or ATmega328 data sheet page 234.

Alternative in hardware: you could use an external comparator (OpAmp wired as such) connected to an analog pin.

An alternative technique, but with more overhead, is to have the ADC in free running mode firing an interrupt whenever a conversion is done (almost 10k sps on a 16 MHz processor), then in the ISR you read the relevant register, and see whether the value is above or below a threshold.

But analog inputs always change. There's always noise on the analog inputs. Even with a very simple circuit that gives an analog reading of 512, sometimes you will see 511 or 513.

Usually you would just read the analog input at a specific rate, apply some digital filtering and thresholding to remove those tiny bits of noise and then do something with the output. All done in conventional code, not in interrupts.

What are you really trying to do?

Thanks for the responses. I'm polling this particular analog input, and it's slowing things down. It would improve matters if I could use an interrupt instead.

I understand the point about analog inputs varying due to noise. An ISR could cope with that by only processing changes above a certain value - say 20, or 30. Any further suggestions welcome.

Dave.

What is producing the signal on the analog pins? Could you convert it to work with digital pins and digital interrupts?

...R

The DUE has a comparison window feature for ADC conversions:

Extracts from Sam3x datasheet:

The ADC Controller features automatic comparison functions. It compares converted values to a low threshold or a high threshold or both…
Moreover a filtering option can be set by writing the number of consecutive comparisons needed to raise the flag …
The flag can be read …. and can trigger an interrupt.

Thanks for the replies. The input is a 10k potentiometer, and its value has to be monitored continuously in this application. So the digital interrupts (which I'm using for other purposes in the project anyway) is unsuitable. For the same reason the DUE would be unsuitable as it's not much better than a digital interrupt - only a limited range of values produce an interrupt. Just for clarification, I'm using the Arduino UNO. Dave.

arryman:
Thanks for the replies. The input is a 10k potentiometer, and its value has to be monitored continuously in this application.

What changes in the potentiometer do you want to detect with the interrupts?

If you just want to monitor a specific threshold you can probably organize the circuit so it can trigger a digital interrupt.

If you just want to monitor changes in the position of the potentiometer then I can't see them changing so often that polling would be a problem.

Post the code you have and which is not performing as you would like.

...R

arryman:
Thanks for the replies. The input is a 10k potentiometer, and its value has to be monitored continuously in this application. So the digital interrupts (which I'm using for other purposes in the project anyway) is unsuitable. For the same reason the DUE would be unsuitable as it's not much better than a digital interrupt - only a limited range of values produce an interrupt. Just for clarification, I'm using the Arduino UNO. Dave.

First of all, every pin has interrupts: the pin change interrupts. So that would be an avenue for you to use more digital pin interrupts.

Furthermore, you can still use the free running mode as I mentioned in #1, and get almost 10,000 measurements a second. For most practical purposes that would qualify as "continuous". Then every time that interrupt is run you check the register directly (don't use analogRead() as that's indeed slow).

Is this 'mechanical pot' controlled by a human?
Do you think you can change it's position faster than 10x per second?

Give us all the information, including the sketch.
Leo..

But if monitoring only 10 times a second you miss all the noise! :slight_smile:

You can easily write a non-blocking analogRead by splitting the existing analogRead into two functions. The one does the setup of the read and the second one simply checks if the conversion is completed and returns e.g. -1 if not and the usual result if completed.

I wrote it a while ago, but never really tested. Will see if I can find it.

arryman:
Thanks for the responses. I'm polling this particular analog input, and it's slowing things down. It would improve matters if I could use an interrupt instead.

I severely doubt that. A potentiometer controlled by hand (because it is not going to be controlled by anything else :roll_eyes: ) would as others have said, need to be polled no more than ten times per second, requiring less than a millisecond on each occasion.

Thanks, but I disagree. In the program I'm developing, the polling takes place in a loop which runs every 12 mS. When an alarm is sounding (using the tone instruction), this causes a noticable "scratchy" sound to be superimposed on the alarm beep. If I stop polling the input, the scratchy sound goes away.

Thank you to all who have responded. Opinion seems to be along the lines that I don't need to do this, or that it should work all right. What I originally asked is if there is any way to use an interrupt on an analog input to look for ANY change. So I'm going to go away now and delve into the code behind this at machine code level if necessary, and write my own routine. I would prefer to do this than to change the specification of the system I have been asked to develop.

Thanks again, one and all, and kind regards,

Dave.

In the program I'm developing, the polling takes place in a loop which runs every 12 mS.

What is slowing it down so much ?

The Due hardware will do exactly what you asked for, even though you have not yet understood all the implications of what you asked for.

But you don't need that hardware. If you post the code which makes the scratchy sound, it can be fixed easily.

Here's the code that's causing the problem.

while (modeSelect == 6) {
modeWaitTune(modeSelect + 6);
tone(beep, pitch);
pitch = 200 + analogRead(2) * 2;
}

I need the tone to respond to the pitch input instantaneously in this application. It works as shown, but every so often the generated tone wavers and sound "scratchy." Deleting the pitch input cures the problem but prevents the program doing what it's supposed to do. An analog-triggered ISR could handle this.

Do post your full code, using code tags.
Most likely the problem is in the part you didn't post.

while (modeSelect == 6) {
    modeWaitTune(modeSelect + 6);
    tone(beep, pitch);
    pitch = 200 + analogRead(2) * 2;
  }

Judging from its name the modeWaitTune() function waits for something. Is that correct ?

If only you had posted your full code ...