0
votes

I am using an Arduino uno to measure the speed of a dc motor. I have a opto sensor that gives a pulse when the motor has made a full turn. The problem I've got starts when the motor has a speed > 90Hz. As soon as I reach 90Hz, the Arduino doesn't enter the interrupt function.

My code:

int pin = 13;
volatile int state = LOW;
volatile unsigned long startTijd = 0;
volatile unsigned long eindTijd = 0;
unsigned int frequentie = 0;
volatile int count = 0;

void setup()
{
  pinMode(pin, OUTPUT);
  attachInterrupt(0, blink, FALLING); //LOW, HIGH, FALLING, RISING, CHANGE

  Serial.begin(19200);
}

void loop()
{
  noInterrupts();
  digitalWrite(pin, state);
  interrupts();
}

void blink()
{
  if (count == 0) {
    startTijd = micros();
  }
  count++;
  if (count == 31) {
    count = 0;
    eindTijd = micros();
    eindTijd -= startTijd;
    Serial.print(eindTijd);
    Serial.print(" ms. - ");

    frequentie = 30 * 1000000 / eindTijd;
    Serial.print(frequentie);
    Serial.println(" Hz.");

  }
  state = !state;

}

My question is : When the Arduino receives interrupts at 90Hz, it doesn't execute the code in the interrupt. When the motor goes below 90Hz after that, the code works again. What am I doing wrong ?

2
What is your question exactly ? - Aleph0
When the Arduino receives interrupts at 90Hz, it doesn't execute the code in the interrupt. When the motor goes below 90Hz after that, the code works again. What am I doing wrong ? - Nick Raeven
@NickRaeven Are you certain the opto sensor handles a frequency of > 90Hz ? or - how long does it assert the signal you're measuring ? - nos
What's the real resolution of micros()? Are you certain it's not being called, or do you just no longer see output on the serial port? Can you toggle a GPIO port and set an oscope to trigger on a level change? - Brian Cain
perhaps you should ask this on the Arduino site: arduino.stackexchange.com - Peter M

2 Answers

3
votes

It looks as though blink is your ISR. If that's the case, you shouldn't be doing debug I/O within that routine for 2 reasons. The first is that you are calling a process that could block. The second is that ISRs should do their thing and finish (should be highly efficient). My guess is that if you remove the debug I/O from your ISR and pass info back to the interrupted task instead (safely, of course) you will be able to service interrupts at greater than 90 hz.

2
votes

Just to add to @Bruce answer. You are using serial IO in the interrupt. Each time you are printing around 15-20 characters (depending on the values calculated). Each character is encoded by 8 bit data + 1 start bit + 1 stop bit = 10 bits. So, say 20*10=200 bits. The baud rate is 19200bps, so time required to transmit 200 bits is 200/19200 sec, or in terms of frequency 19200/200=96Hz. So this is the maximum frequency achievable for transmission of 20 characters, which is close to your measured 90Hz (take in account that I am not considering any time spacing overhead between the transmits).