Arduino Forum

Using Arduino => Networking, Protocols, and Devices => Topic started by: ebarash on Jan 09, 2019, 12:30 pm

Title: Arduino Interrupt pins problem
Post by: ebarash on Jan 09, 2019, 12:30 pm
Dear All,

it seems a problem with my interrupt pin 2. I want to calculate the RPM of a motor. The simple code is quite well through int pin 3, but when I change it to int pin 2 the result is not correct. What should be the problem?
I check it on two arduino uno boards, same problem.

thanks




int ir_sensor = 2;                                   
unsigned int ir_rpm = 0;                           
unsigned int numOfRotations = 0;                   
int pulsesPerTurn = 1;                             
unsigned long lastTime = 0;                         

void counter(){                                     
    numOfRotations++;
}

void setup() {
                             
    Serial.begin(115200);                           
                                     
    pinMode(ir_sensor,INPUT);                       

    attachInterrupt(digitalPinToInterrupt(ir_sensor), counter, FALLING);         
           
}

void loop()  {     
    stop_ir_Interrupt();                   
                                 
           Serial.print("  "); Serial.println(ir_rpm);                                 

}

void stop_ir_Interrupt(){
                   
     if(millis() - lastTime >= 1000){                                         
        detachInterrupt(digitalPinToInterrupt(ir_sensor));                   
        ir_rpm = (numOfRotations * 60) / pulsesPerTurn;                       
        lastTime = millis();
        numOfRotations = 0;                                                   
        attachInterrupt(digitalPinToInterrupt(ir_sensor), counter, FALLING);
    }

   
}
Title: Re: Arduino Interrupt pins problem
Post by: KASSIMSAMJI on Jan 09, 2019, 12:44 pm
you should  declare your numOfRotations as ' volatile unsigned int ' as it appears in both main thread and the ISR routine

you can google what 'volatile ' means
Title: Re: Arduino Interrupt pins problem
Post by: ebarash on Jan 09, 2019, 01:03 pm
you should  declare your numOfRotations as ' volatile unsigned int ' as it appears in both main thread and the ISR routine

you can google what 'volatile ' means
well it is recommended to use variables as volatile inside interrupts. but It doesn't influence on your result generally.
I tried all of them and got same results.

the problem is, the result from pin2 and pin 3 are not same with same conditions!
Title: Re: Arduino Interrupt pins problem
Post by: KASSIMSAMJI on Jan 09, 2019, 01:09 pm
well it is recommended to use variables as volatile inside interrupts. but It doesn't influence on your result generally.
I tried all of them and got same results.

the problem is, the result from pin2 and pin 3 are not same with same conditions!
try  INPUT_PULLUP in pinMode

CHANGE over FALLING in attachInterrupt()
Title: Re: Arduino Interrupt pins problem
Post by: ebarash on Jan 09, 2019, 01:22 pm
try  INPUT_PULLUP in pinMode

CHANGE over FALLING in attachInterrupt()
I tried all of them. I have different results!
Title: Re: Arduino Interrupt pins problem
Post by: Robin2 on Jan 09, 2019, 02:33 pm
I use the program in this link (https://forum.arduino.cc/index.php?topic=564223.msg3844595#msg3844595) to detect the speed of a small motor. Note how simple the ISR code is and how there is no need for detachInterrupt()

...R
Title: Re: Arduino Interrupt pins problem
Post by: ebarash on Jan 09, 2019, 03:23 pm
I use the program in this link (https://forum.arduino.cc/index.php?topic=564223.msg3844595#msg3844595) to detect the speed of a small motor. Note how simple the ISR code is and how there is no need for detachInterrupt()

...R
Thanks for your answare. The problem is with interrupt 0(pin2). I don't know why, but it does not give me the right answare. interrupt 1 (pin 3) is good and I don't have any problem with my code.
Title: Re: Arduino Interrupt pins problem
Post by: Robin2 on Jan 09, 2019, 04:37 pm
Thanks for your answare. The problem is with interrupt 0(pin2). I don't know why, but it does not give me the right answare. interrupt 1 (pin 3) is good and I don't have any problem with my code.
Is that true with my program ?

...R
Title: Re: Arduino Interrupt pins problem
Post by: ebarash on Jan 11, 2019, 12:44 pm
Is that true with my program ?

...R
I used your code. It is working well on both of pins 2,3. Also my simple code is working well when I use a delay() (at leats with 100ms) in my void loop().

The problem comes when I don't use any delay in void loop. I am wondering about this result. What should be the problem?

The number of pulses per second should be counted inside interrupt function and finally the value will be printed in main loop! why this miskate happens without delay?
Title: Re: Arduino Interrupt pins problem
Post by: Robin2 on Jan 11, 2019, 12:54 pm
I used your code. It is working well on both of pins 2,3.
So why not use it?

...R
Title: Re: Arduino Interrupt pins problem
Post by: ebarash on Jan 11, 2019, 01:03 pm
So why not use it?

...R
The reason is that I have some other datas which should be save in an array together with rpm and they are comming in several milliseconds, so I  cannot wait one second to save them.Your code has also one second delay to write pulses and without that is not working.
Title: Re: Arduino Interrupt pins problem
Post by: Robin2 on Jan 11, 2019, 02:36 pm
Your code has also one second delay to write pulses and without that is not working.
That is not an important part of my program. I just did it like that so the info appears at a rate that makes sense for the human viewing the screen. There is no need to display the data and you can update things every time there is a pulse if you wish.

I don't know what you mean by "without that is not working"

...R
Title: Re: Arduino Interrupt pins problem
Post by: ebarash on Jan 11, 2019, 03:49 pm
I don't know what you mean by "without that is not working"

...R
this is oart of your code.
I mean what if you remove the one second waiting time to show data?


void loop() {
    getIsrData();
//    (millis() - prevDisplayMillis >= 1000) {
//     prevDisplayMillis += 1000;
        showData();
//     }
}

pulses per second will not be true if you unable those lines!
Title: Re: Arduino Interrupt pins problem
Post by: Robin2 on Jan 11, 2019, 04:27 pm
pulses per second will not be true if you unable those lines!
You don't need a 1 second interval to know the pulse rate. All you need to know is the interval between two pulses (or the interval between a larger number if you want an average.

And even if you do want to show the data once per second the rest of your program does not have to be limited to once per second.

Rather than pick small holes in specific pieces of code that were just prepared as a typical example why not tell us exactly what you want to achieve?

...R
Title: Re: Arduino Interrupt pins problem
Post by: ebarash on Jan 15, 2019, 11:18 am
You don't need a 1 second interval to know the pulse rate. All you need to know is the interval between two pulses (or the interval between a larger number if you want an average.


Rather than pick small holes in specific pieces of code that were just prepared as a typical example why not tell us exactly what you want to achieve?

...R
Thanks for your advices but the problem is I am very curious about pin 2 which is not stable as pin 3. It seems there is a problem with timing. With 1 second intervals to show data it works well( or with baud rate of lower than 9600), but without that delay only pin 3 gives me the right results. Pin 2 is not stable and gives the higher rpm. even with your nice code it will happens.

At all, I don't have any problem with my code because I am using pin3.

Just to know if someone had same problem or knows the reason. Because it happens even with a very simple code.
Title: Re: Arduino Interrupt pins problem
Post by: Robin2 on Jan 15, 2019, 12:06 pm
Pin 2 is not stable and gives the higher rpm. even with your nice code it will happens.
When you said (in Reply #8) "I used your code. It is working well on both of pins 2,3" I had assumed there were no problems.

Please post the version of my code that is giving rise to the incorrect readings when using pin2 and working properly when using pin3.

Also please post some samples of the output in each case.

...R

Title: Re: Arduino Interrupt pins problem
Post by: ebarash on Jan 15, 2019, 01:21 pm
Also please post some samples of the output in each case.

...R


well, this is your code and I just added marked line with #### to show the number of pulses in 1 second


const byte fwdPin = 9;
const byte revPin = 10;
const byte potPin = A1;

int potVal;
int pwmVal;

unsigned long revMicros;
unsigned long prevRevMicros;
unsigned long revDuration;
unsigned long revCount;


unsigned long prevDisplayMillis;
unsigned long  displayInterval = 1000;

    // variables for the ISR
volatile unsigned long isrMicros;
volatile unsigned long isrCount;
volatile bool newIsrMicros = false;



void setup() {
    Serial.begin(115200);
    Serial.println("SimpleISRdemo.ino");
    pinMode (fwdPin, OUTPUT);
    pinMode (revPin, OUTPUT);

    isrCount = 0;
    attachInterrupt(1, revDetectorISR, RISING);
}

//==========

void loop() {
    getIsrData();
    if (millis() - prevDisplayMillis >= displayInterval) {
        prevDisplayMillis += displayInterval;
        showData();
        isrCount=0;                                       //#### 
        readPot();
        updateMotorSpeed();
    }
}

//===========

 void readPot() {
    potVal = analogRead(potPin);
}

//===========

void updateMotorSpeed() {
    pwmVal = potVal >> 2;

    digitalWrite(revPin,LOW);
    analogWrite(fwdPin, pwmVal);
 }

//===========

void getIsrData() {
    if (newIsrMicros == true) {
        prevRevMicros = revMicros; // save the previous value
        noInterrupts();
            revMicros = isrMicros;
            revCount = isrCount;
            newIsrMicros = false;
        interrupts();
        revDuration = revMicros - prevRevMicros;
    }
}

//===========

void showData() {
    Serial.println();
    Serial.println("===============");
    Serial.print("PWM Val "); Serial.println(pwmVal);
    Serial.print("  Rev Duration ");
    Serial.print(revDuration);
    Serial.print("  Rev Count ");
    Serial.print(revCount);
    Serial.println();
}

//===========

void revDetectorISR() {
    isrMicros = micros();
    isrCount ++;
    newIsrMicros = true;

}

--------------------------------------------------------------------------------------------------

and this the result with both pins 2 and 3

Rev Duration 44644  Rev Count 22

**********************************************************************
**********************************************************************

Now I changed it just a little:

changes marked with //####




const byte fwdPin = 9;
const byte revPin = 10;
const byte potPin = A1;

int potVal;
int pwmVal;

unsigned long revMicros;
unsigned long prevRevMicros;
unsigned long revDuration;
unsigned long revCount;
unsigned long lastMillis=0;                          //####

unsigned long prevDisplayMillis;
unsigned long  displayInterval = 1000;

    // variables for the ISR
volatile unsigned long isrMicros;
volatile unsigned long isrCount;
volatile bool newIsrMicros = false;



void setup() {
    Serial.begin(115200);
    Serial.println("SimpleISRdemo.ino");
    pinMode (fwdPin, OUTPUT);
    pinMode (revPin, OUTPUT);

    isrCount = 0;
    attachInterrupt(1, revDetectorISR, RISING);
}

//==========

void loop() {
    getIsrData();
 //   if (millis() - prevDisplayMillis >= displayInterval) {  //####
        prevDisplayMillis += displayInterval;
        showData();
        readPot();
        updateMotorSpeed();
  //  }                                                                       //####
}

//===========

 void readPot() {
    potVal = analogRead(potPin);
}

//===========

void updateMotorSpeed() {
    pwmVal = potVal >> 2;

    digitalWrite(revPin,LOW);
    analogWrite(fwdPin, pwmVal);
 }

//===========

void getIsrData() {
    if (newIsrMicros == true) {
        prevRevMicros = revMicros; // save the previous value
        noInterrupts();
            revMicros = isrMicros;
           if(millis() - lastMillis>=1000){     //####
            revCount = isrCount;                //####
            lastMillis += 1000;                   //####
            isrCount=0;                             //####
           }                                             //####
            newIsrMicros = false;
        interrupts();
        revDuration = revMicros - prevRevMicros;
    }
}

//===========

void showData() {
    Serial.println();
    Serial.println("===============");
    Serial.print("PWM Val "); Serial.println(pwmVal);
    Serial.print("  Rev Duration ");
    Serial.print(revDuration);
    Serial.print("  Rev Count ");
    Serial.print(revCount);
    Serial.println();
}

//===========

void revDetectorISR() {
    isrMicros = micros();
    isrCount ++;
    newIsrMicros = true;

}
------------------------------------------------------------------------------------

this is the result with arduino pin 3


Rev Duration 44660  Rev Count 22


but for pin 2

Rev Duration 44684  Rev Count 37

************************************************************
************************************************************

You can see by same code I have defferent results.

But if I apply delay(1000) in void loop, or unmark this line

//   if (millis() - prevDisplayMillis >= displayInterval) {  //####

the result will be same again.
Title: Re: Arduino Interrupt pins problem
Post by: Robin2 on Jan 15, 2019, 01:43 pm
To make it easy for people to help you please modify your post and use the code button </>
Code: [Select]
so your code looks like this and is easy to copy to a text editor. See How to use the Forum (http://forum.arduino.cc/index.php?topic=149014.0)

Your code is too long for me to study quickly without copying to my text editor. The text editor shows line numbers, identifies matching brackets and allows me to search for things like all instances of a particular variable or function.

Also please use the AutoFormat tool to indent your code for easier reading.

...R
Title: Re: Arduino Interrupt pins problem
Post by: ebarash on Jan 15, 2019, 02:18 pm
Quote
To make it easy for people to help you please modify your post and use the code button </>

Sorry if I wrote like that, I am new.

this is your code and I just added marked line with #### to show the number of pulses in 1 second

and this the result with both pins 2 and 3

Rev Duration 44644  Rev Count 22



Code: [Select]

const byte fwdPin = 9;
const byte revPin = 10;
const byte potPin = A1;

int potVal;
int pwmVal;

unsigned long revMicros;
unsigned long prevRevMicros;
unsigned long revDuration;
unsigned long revCount;


unsigned long prevDisplayMillis;
unsigned long  displayInterval = 1000;

    // variables for the ISR
volatile unsigned long isrMicros;
volatile unsigned long isrCount;
volatile bool newIsrMicros = false;



void setup() {
    Serial.begin(115200);
    Serial.println("SimpleISRdemo.ino");
    pinMode (fwdPin, OUTPUT);
    pinMode (revPin, OUTPUT);

    isrCount = 0;
    attachInterrupt(1, revDetectorISR, RISING);
}

//==========

void loop() {
    getIsrData();
    if (millis() - prevDisplayMillis >= displayInterval) {
        prevDisplayMillis += displayInterval;
        showData();
        isrCount=0;                                       //#### 
        readPot();
        updateMotorSpeed();
    }
}

//===========

 void readPot() {
    potVal = analogRead(potPin);
}

//===========

void updateMotorSpeed() {
    pwmVal = potVal >> 2;

    digitalWrite(revPin,LOW);
    analogWrite(fwdPin, pwmVal);
 }

//===========

void getIsrData() {
    if (newIsrMicros == true) {
        prevRevMicros = revMicros; // save the previous value
        noInterrupts();
            revMicros = isrMicros;
            revCount = isrCount;
            newIsrMicros = false;
        interrupts();
        revDuration = revMicros - prevRevMicros;
    }
}

//===========

void showData() {
    Serial.println();
    Serial.println("===============");
    Serial.print("PWM Val "); Serial.println(pwmVal);
    Serial.print("  Rev Duration ");
    Serial.print(revDuration);
    Serial.print("  Rev Count ");
    Serial.print(revCount);
    Serial.println();
}

//===========

void revDetectorISR() {
    isrMicros = micros();
    isrCount ++;
    newIsrMicros = true;

}

Title: Re: Arduino Interrupt pins problem
Post by: ebarash on Jan 15, 2019, 02:24 pm
and this is with a little change:

changes marked with //####

this is the result with arduino pin 3


Rev Duration 44660  Rev Count 22


but for pin 2

Rev Duration 44684  Rev Count 37

You can see by same code I have defferent results.

But if I apply delay(1000) in void loop, or unmark this line

//   if (millis() - prevDisplayMillis >= displayInterval) {  //####

the result will be same again.

Code: [Select]

const byte fwdPin = 9;
const byte revPin = 10;
const byte potPin = A1;

int potVal;
int pwmVal;

unsigned long revMicros;
unsigned long prevRevMicros;
unsigned long revDuration;
unsigned long revCount;
unsigned long lastMillis=0;                          //####

unsigned long prevDisplayMillis;
unsigned long  displayInterval = 1000;

    // variables for the ISR
volatile unsigned long isrMicros;
volatile unsigned long isrCount;
volatile bool newIsrMicros = false;



void setup() {
    Serial.begin(115200);
    Serial.println("SimpleISRdemo.ino");
    pinMode (fwdPin, OUTPUT);
    pinMode (revPin, OUTPUT);

    isrCount = 0;
    attachInterrupt(1, revDetectorISR, RISING);
}

//==========

void loop() {
    getIsrData();
 //   if (millis() - prevDisplayMillis >= displayInterval) {  //####
        prevDisplayMillis += displayInterval;
        showData();
        readPot();
        updateMotorSpeed();
  //  }                                                                       //####
}

//===========

 void readPot() {
    potVal = analogRead(potPin);
}

//===========

void updateMotorSpeed() {
    pwmVal = potVal >> 2;

    digitalWrite(revPin,LOW);
    analogWrite(fwdPin, pwmVal);
 }

//===========

void getIsrData() {
    if (newIsrMicros == true) {
        prevRevMicros = revMicros; // save the previous value
        noInterrupts();
            revMicros = isrMicros;
           if(millis() - lastMillis>=1000){     //####
            revCount = isrCount;                //####
            lastMillis += 1000;                   //####
            isrCount=0;                             //####
           }                                             //####
            newIsrMicros = false;
        interrupts();
        revDuration = revMicros - prevRevMicros;
    }
}

//===========

void showData() {
    Serial.println();
    Serial.println("===============");
    Serial.print("PWM Val "); Serial.println(pwmVal);
    Serial.print("  Rev Duration ");
    Serial.print(revDuration);
    Serial.print("  Rev Count ");
    Serial.print(revCount);
    Serial.println();
}

//===========

void revDetectorISR() {
    isrMicros = micros();
    isrCount ++;
    newIsrMicros = true;

}
Title: Re: Arduino Interrupt pins problem
Post by: Robin2 on Jan 15, 2019, 08:20 pm
Two things occur to me regarding the programs in Reply #18

in your first program this line is bad practice
Code: [Select]
        isrCount=0;                                       //#### 
Because isrCount is a 4-byte variable there is a risk that one of the bytes will be changed by the ISR while you are trying to set it to 0. You should update it with interrupts supended - like this

Code: [Select]
    noInterrupts();
       isrCount = 0;
    interrupts();


However, IMHO, there is nothing to be gained by setting the number back to 0.


And in the second program I would not have this line
Code: [Select]
          if(millis() - lastMillis>=1000){
inside the section of code where interrupts are disabled. You should ensure the interrupts are disabled for the shortest possible time.

Without trying your program (which I don't have time to do) I can't understand why it makes a difference which interrupt pin is used, although I assume the two pins have different priorities if you study the Atmega 328 datasheet closely. (It's a good read at bedtime :) )

...R
Title: Re: Arduino Interrupt pins problem
Post by: ebarash on Jan 16, 2019, 09:41 am
Quote
I assume the two pins have different priorities
Dear Robin,

I am very thankful for your time and advices. Maybe this is the answare of my question. I just wondered about the difference between two pins with the same code. I will read closely the datasheet later to know more about it.

And yes, you are right about those two lines. However, it was a sample to show the difference.

regards