Go Down

Topic: Using the analog comperator for interrupts (Read 25467 times) previous topic - next topic

signout

I'm currently polling one of the analog inputs and when the value is above 200 it sends a midi signal. The problem being that it misses some beats probably due to the polling being too slow, hence I want to make it interrupt based instead.

void loop() {
      sensorValue = analogRead(sensorPin);
      if (sensorValue > 100) {
        noteOn(0x90, bassdrum, 0x40);
        blink(1);
      }
      while(analogRead(sensorPin) > 100){
        delay(5);
      }
}

I think I want to generate a interrupt by putting a reference voltage on pin AIN0 (Arduino Digital 6) and when the voltage on AIN1 (Arduino Digital 7) rises above the voltage of AIN0 then generate a interrupt.

I'm having trouble figuring out the built in comperator.
As far as I can see from the data sheet I need to set ACIS1 and ACIS0 and enable it by setting ACSR bit 3 (ACIE).
But how do I set that up in my sketch, and how do i make the interrupt routine?
Does someone have a code example I can see? Can it even be done this way?

Thank you in advance.

Coding Badly

#1
May 04, 2010, 04:22 am Last Edit: May 04, 2010, 04:23 am by bcook Reason: 1
Quote
As far as I can see from the data sheet I need to set ACIS1 and ACIS0 and enable it by setting ACSR bit 3 (ACIE).
But how do I set that up in my sketch


This should set ACSR...

ACSR =
 (0<<ACD) |   // Analog Comparator: Enabled
 (0<<ACBG) |   // Analog Comparator Bandgap Select: AIN0 is applied to the positive input
 (0<<ACO) |   // Analog Comparator Output: Off
 (1<<ACI) |   // Analog Comparator Interrupt Flag: Clear Pending Interrupt
 (1<<ACIE) |   // Analog Comparator Interrupt: Enabled
 (0<<ACIC) |   // Analog Comparator Input Capture: Disabled
 (1<<ACIS1) | (1<ACIS0);   // Analog Comparator Interrupt Mode: Comparator Interrupt on Rising Output Edge

Quote
how do i make the interrupt routine?

ISR(ANALOG_COMP_vect )
{
 // Put your code here
}

You may need to include <avr/interrupt.h> at the top of your Sketch.

I've not used the analog comparator so any or all of above could be wrong.

GrooveFlotilla

Quote
problem being that it misses some beats probably due to the polling being too slow,

Another approach would be to separate the initiation of an analogue read from the read itself, so on one cycle you would initiate the read, and on the next actually perform it.
If you look at the source of "analogRead" in "wiring_analog.c", you'll see that there's a setup where the mux and reference are set, a start conversion, then a wait for the conversion to finish.
If you split the routine just before the wait loop, you can start a conversion, go off and do something else, then come back to the read the result of the conversion.
You still need the "while" loop, but it will waste less time.
Some people are like Slinkies.

Not really good for anything, but they bring a smile to your face when pushed down the stairs.

signout

Thank you for your help.

Just to follow up on this. I ended up with this code:

const int LEDpin = 13;     // Indicator LED
const int kickdrum = 36;   // MIDI note of the kick drum
int kick = 0;              // Just a variable for setting kick detected

void setup() {
  ACSR =
  (0<<ACD) |   // Analog Comparator: Enabled
  (0<<ACBG) |   // Analog Comparator Bandgap Select: AIN0 is applied to the positive input
  (0<<ACO) |   // Analog Comparator Output: Off
  (1<<ACI) |   // Analog Comparator Interrupt Flag: Clear Pending Interrupt
  (1<<ACIE) |   // Analog Comparator Interrupt: Enabled
  (0<<ACIC) |   // Analog Comparator Input Capture: Disabled
  (1<<ACIS1) | (1<ACIS0);   // Analog Comparator Interrupt Mode: Comparator Interrupt on Rising Output Edge

  pinMode(LEDpin, OUTPUT); //  Set the state of the LED I/O pin
  Serial.begin(31250); //  Set MIDI bitrate
  blink(3);
}

void loop() {
 if(kick){
   noteOn(0x90, kickdrum, 0x40); // Send the MIDI note to the guitar hero drum set
   blink(1); // Flash the LED if a kick is detected
   delay(50); // Debounce - just in case
   kick=0; // Reset the kick detected
 }
}

ISR(ANALOG_COMP_vect)
{
         kick=1; // Kick detected
}

//  plays a MIDI note.  Doesn't check to see that
//  cmd is greater than 127, or that data values are  less than 127:
void noteOn(byte cmd, byte data1, byte  data2) {
  Serial.print(cmd, BYTE);
  Serial.print(data1, BYTE);
  Serial.print(data2, BYTE);
}

void blink(int howManyTimes) {
  int i;
  for (i=0; i< howManyTimes; i++) {
    digitalWrite(LEDpin, HIGH);
    delay(10);
    digitalWrite(LEDpin, LOW);
  }
}

It seems to work fine with a Guitar Hero drum set, a Roland KD-8 electric drum trigger and a 4.7V zener, a voltage divider (2*390k) for the comperator reference and a 220 ohm for the MIDI output.

Go Up