Interrupts

Does the use of interrupts affect the internal clock of the Arduino? I am using an interrupt signal generated as a hole in a rotating disc passes between an IR LED and a Photo-diode. I get the time when rotation starts and then when rotation ends and subtract the two to give a measure of running time. I find that that over 1 minute of running time, I get a consistent 54 seconds indicated. When I measure the time without using interrupts I get an accurate 60 seconds indicated for 1 minute. Any idea what's going on?

Glynne: Does the use of interrupts affect the internal clock of the Arduino?

It certainly might, but it rather depends on just how bad your code looks. Unless you post it for examination (using the "code" tags - the [ # ] icon), no-one here can tell you.

This would be an excellent example of why you should not try to use interrupts where they are not needed or appropriate, and your description of an optical interrupter on a shaft is a classic example where an interrupt is inappropriate. :D

Glynne: Any idea what's going on?

Could be that your interrupt handler is taking so long to complete that it is causing the timer interrupt to overflow? If you published your code and hardware circuit diagram, you might get more than wild guesses.

I’m new to writing sketches for the Arduino Uno so would appreciate any comments as to how I should do this. The Skech I use is as follows:-

/*
The circuit:

  • LCD RS pin to digital pin 12

  • LCD Enable pin to digital pin 11

  • LCD D4 pin to digital pin 5

  • LCD D5 pin to digital pin 4

  • LCD D6 pin to digital pin 9

  • LCD D7 pin to digital pin 2

  • LCD R/W pin to ground

  • 10K variable resistor:

  • ends to +5V and ground

  • wiper to LCD VO pin (pin 9)

  • Pin 3 connects to IR PhotoDiode

  • Pin 13 connects to status LED
    */

#include <LiquidCrystal.h>
int revs=0; // number of revolutions
int counter = 0;
unsigned long stime = 0; //start time variable
unsigned long ttime = 0; // time into the run variable
LiquidCrystal lcd(12, 11, 5, 4, 9, 2);

void setup() {

attachInterrupt(1, count, RISING);
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(“Ready”); //ready to run motor
}

void loop() {
}
void count() {
switch (counter) {
case 1:
counter = 1;
if (revs == 0) { //if start of first revolution
stime = millis(); // get clock time at start of run
ttime=stime;
}
else {
ttime = millis(); //otherwise get clock time each revolution
}

revs++; // incremrnt number of revolutions by 1
lcd.setCursor(0, 0);
lcd.print(" “); //clear display
lcd.setCursor(0, 0);
lcd.print(revs); // Display number of revolutions
lcd.setCursor(0, 1);
lcd.print(” ");
lcd.setCursor(0, 1);
lcd.print(ttime/1000-stime/1000); // display number of seconds into run after each revolution
break;
default:
counter = 1;
break;
}
}

Take all the lcd stuff out of the interrupt routine.

...R

When posting code, please copy the code as plain text and post into your message inside CODE tags.

The ‘copy for forum’ feature in the IDE is worse than useless and you should ignore it.

How about moving the Quote button far away from the Code button ;)

LCDs are very slow, and even if they weren't you shouldn't do that much work in an ISR. That will stop the millis() tick from working.


Rob

Glynne: I'm new to writing sketches for the Arduino Uno so would appreciate any comments as to how I should do this.

As I previously said, the very first rule, especially if you are new to writing sketches is: Do not attempt to use interrupts. You clearly do not understand what an interrupt is.

Seriously. Get rid of the interrupt routine. All the working code goes in "loop".

Your code in "loop" should have two modes, one for acquiring data (counting), and one for displaying. Tempting as it may seem, it is not possible to do both at the same time unless you have a deep understanding of how to use interrupts, but then only if there is any need to do so. It is extremely rare that there is.

So, write code to do the counting, which is to say code that alternately polls the opto-interrupter and the millis() timer, performing debouncing of the interrupter as it goes (depending on how much tendency there is for "bounce"). When you have accumulated the requisite number of counts, or the requisite time has passed - whichever way you need to do it, you switch to the display routine which due to delays, will prevent you from counting. Then of course, you switch back to counting by a "state" switch which determines which routine is executed on each pass of the loop.

If your intent is to perform a number of tasks, you need one iteration of each to be performed on each pass through the "loop"; this is the proper way to write code. If you only ever want to do this count and display, arguably you can use a primitive version where they could be two successive parts of the main "loop", the "count" part being an independent loop in itself.

And yes, please go back and fix the "quote" tags for "code".