Interference using two Interrupt

Hi ¡¡ … I’m new to Arduino and i’m having probles trying to measure speed and cadence of a bicycle using the respective sensors ( wheel & crank ) and interrupts ( on a MEGA )
Here is the code i´m using

volatile unsigned long start1=0;
volatile unsigned long end1=0;
volatile unsigned int vel1=0;
volatile unsigned int vel2=0;
volatile unsigned long  const=60000;
volatile float factor = 0.0006;
volatile unsigned int const perimeter = 209; // [cm]
volatile unsigned long start2=0;
volatile unsigned long end2=0;
volatile unsigned int rpm1=0;
volatile unsigned int rpm2=0;


void setup() {
   Serial.begin(9600);
   attachInterrupt(digitalPinToInterrupt(2), rpm, RISING);
   attachInterrupt(digitalPinToInterrupt(3), vel, RISING);

}

void loop() {
 
  if(vel1 != vel2){
  Serial.println(vel1);
  vel2=vel1;}


 if(rpm1 != rpm2){
  Serial.print("\t");
  Serial.print("\t");
  Serial.println(rpm1);
  rpm2=rpm1;}

}

void vel() {
 
  start1 = millis();
  if((start1 - end1) >140) {
    vel1 = perimeter *(factor/(start1 - end1))* const;
    end1 = start1;  }
}

void rpm() {
 
  start2 = millis();
  if((start2 - end2) >300) {
    rpm1=const/(start2-fin2);
    end2 = start2;  }
}

Basicaly i´m printing speed and cadence everytime it changes; and the Interrupts only measure the difference of time between the current and last time triggered … make the calculations … save the value ( the “if” part is a debounce thing dependent on the maximun speed and rpm )
Now, void rpm() and void vel() works fine separately, but together they do this …

vel            rpm

2
		15
4
		33
6
7
		42
		69   <--------- error, 
		140 <--------- error
8
		48
		46
		47
		48
		49
		50
		52
9
10
		57
		58
		186 <--------- error
		90   <--------- error
		59
		58
		59
		62
11
10
		60
		61
		62
		61
		60
9                    <--------- stop pedaling, wheel inertia
8
7
6
5
		5    <--------- error, cero cadence
		36   <--------- error, cero cadence
4
3
2
		5    <--------- pedaling backwards, wheel doesn´t move, only crank
		62
		68
		69
		71
		70
		72
		70
		68
0
		67
		66
4                    <--------- error, wheel doesn´t move
		70
		69

The problem seems to be a kind interference between the Interrupts, i´ve try to use detachInterrupt() on the code whit no results ( the code stop working sometimes ) … maybe i´m using it wrong … don´t know
Can anyone tell me whats happening ? I feel like something is missing…

Your code doesn't compile. const is a keyword and can't be used as a variable name. fin2 isn't declared and it doesn't make sense to use it there anyway. It should presumably be end2.

Pete

Oh and in the code that you have noy posted which does compile it's println that is giving the problem.

Mark

What type of sensor are you using which is providing input to pin 2 and 3?

el_supremo:
Your code doesn't compile. const is a keyword and can't be used as a variable name. fin2 isn't declared and it doesn't make sense to use it there anyway. It should presumably be end2.

Pete

Yes; should say constant and end2 .. sorry

i copy the code from another place … this is the one corresponding to the data

volatile unsigned long start1=0;
volatile unsigned long end1=0;

volatile unsigned int vel1=0;
volatile unsigned int vel2=0;

volatile unsigned long  constant=60000;
volatile float factor = 0.0006; 
volatile unsigned int const perimeter = 209; // [cm]


volatile unsigned long start2=0;
volatile unsigned long end2=0;

volatile unsigned int rpm1=0;
volatile unsigned int rpm2=0;


void setup() {
   Serial.begin(9600); 
   attachInterrupt(digitalPinToInterrupt(2), rpm, RISING);
   attachInterrupt(digitalPinToInterrupt(3), vel, RISING);

}

void loop() {
  
  if(vel1 != vel2){
  Serial.println(vel1);
  vel2=vel1;
  //EIFR = (1 << INTF0);
  //EIFR = bit (INTF0);
  //EIFR = 0x01;
  
  //attachInterrupt(digitalPinToInterrupt(3), rpm, RISING);}
  
}

 if(rpm1 != rpm2){
  Serial.print("\t");
  Serial.print("\t");
  Serial.println(rpm1);
  rpm2=rpm1;
  //EIFR = (1 << INTF0);
  //EIFR = bit (INTF0);
  //EIFR = 0x01;
  
  //attachInterrupt(digitalPinToInterrupt(2), rpm, RISING);}
  
}



}

void vel() {
  
  start1 = millis();
  if((start1 - end1) >140) {
    vel1 = perimeter *(factor/(start1 - end1))* constant;
    end1 = start1;
    
    //detachInterrupt(digitalPinToInterrupt(3));
  }
}

void rpm() {
  
  start2 = millis();
  if((start2 - end2) >300) {
    rpm1=constant/(start2-end2);
    end2 = start2;
    
    //detachInterrupt(digitalPinToInterrupt(2));
  }
}

the annotations ( detachs / clear flag ) it’s what I’ve try

i´m using reed sensors ( is what cycling computers use, i think)

and your is of println is still your error

Mark

Can you provide a quick sketch of how you have the reed switch wired to the arduno and to power or ground. Is the reed switch opened or closed by the magnet? I think the input to the arduino may be floating when the reed switch is open depending on how it is wired.

Always explicitly declare your pin modes. Even though every pin defaults to INPUT on startup, it's not good practice to rely on that. (And it's pretty rare not to use INPUT_PULLUP.)

You also never take a local copy of the volatile variables. What if vel2!=vel1 when you checked it but later on (a few microsecond later) vel1 changes? Then you save that changed value to vel2, without ever looking at it. At the top of the loop, call noInterrupts() grab a stable copy of the volatiles and then re-enable interrupts with interrupts(). This way you get a consistent set of values.

The worst case when you don't use clean local copies is the interrupt can change the value between the main program reading the first and second byte of the 2-byte integer. That gets weird random results that look totally crazy.

MorganS:
Always explicitly declare your pin modes. Even though every pin defaults to INPUT on startup, it’s not good practice to rely on that. (And it’s pretty rare not to use INPUT_PULLUP.)

You also never take a local copy of the volatile variables. What if vel2!=vel1 when you checked it but later on (a few microsecond later) vel1 changes? Then you save that changed value to vel2, without ever looking at it. At the top of the loop, call noInterrupts() grab a stable copy of the volatiles and then re-enable interrupts with interrupts(). This way you get a consistent set of values.

The worst case when you don’t use clean local copies is the interrupt can change the value between the main program reading the first and second byte of the 2-byte integer. That gets weird random results that look totally crazy.

i´ll give it a try to se what happen … also im going to upload the sketch later, if it’s of any help.