Reading two sensors values without affecting each others

Hi,
I am using arduino UNO to calculate my bike speed and direction. I uses Hall effect sensor to calculate the speed, and Compass sensor to read the bike angular direction. I use both of them nicely, but i have problem when migrating them in the same board/system. the compass calculations affects the speed calculations inside interrupts.

Here's the code in loop function:

void loop()
{
if (millis()-lastMillis == 1000) // check speed every second or above
  {
      detachInterrupt(0); // deattaching interrupt to calculate speed
      rpm = rpmcount * 3.75; // rpm is counter * (60 second / number of ma8nateeses)
      wSpeed = ((Circ * rpm) / time_scale); // speed = rpm *   mo7eet el kawet4
      wSpeed_precision = (wSpeed - (int)wSpeed)*100;
      rpmcount = 0; // re-init
      lastMillis = millis();  // updating millis
      attachInterrupt(0, rpm_fan, CHANGE);   // attach interrupt again
  }
if (millis() - lastMillis_Angle == 10)
  {
   detachInterrupt(0);
   // Calculate angle
   angleCalculation();
   lastMillis_Angle = millis();
   attachInterrupt(0, rpm_fan, CHANGE);
  }
}

void rpm_fan()
{
  ++rpmcount;
}

void angleCalculation() {
// angle calculations is performed here ..
}

The Question is how to use both of senors simultaneously without allowing the compass calculations to affect the speed calculations/interrupt ???

thanks.

Hi, welcome to the forum.

It is not okay to check with millis for a certain amount of milliseconds, you could miss one. Always check with ">=".
When you update the variable with millis(), the millis() could have been incremented, and you miss another millisecond.

// Keep timing without delay, never miss one.
if (millis() - prevMillis >= 100)
{
  prevMillis += 100;
}

To disable interrupts, use noInterrups() and interrupts(). The attach and detach are not ment to be used this way.

There might be a few other problems with your sketch (float versus integer and use of 'volatile'). Please show the whole sketch.

Peter_n:
Hi, welcome to the forum.

It is not okay to check with millis for a certain amount of milliseconds, you could miss one. Always check with ">=".
When you update the variable with millis(), the millis() could have been incremented, and you miss another millisecond.

// Keep timing without delay, never miss one.

if (millis() - prevMillis >= 100)
{
  prevMillis += 100;
}




To disable interrupts, use noInterrups() and interrupts(). The attach and detach are not ment to be used this way.

There might be a few other problems with your sketch (float versus integer and use of 'volatile'). Please show the whole sketch.

Thanks for your advice, I already use volatile variables inside the interrupts and float variables not updated inside interrupts. But the core problem for me now. how to make the I2C Compass Sensor triggered in an interrupt like the hall effect sensor. So as to calculate the speed very accurate and to be just read compass when changed.

thanks a lot.

Why not request the compass data 10 or 20 times a second ?

Peter_n:
Why not request the compass data 10 or 20 times a second ?

I do that here:

if (millis() - lastMillis_Angle >= 10)
  {
   detachInterrupt(0);
   // Calculate angle
   angleCalculation(); // this function is responsible for compass sensor read and serial send
   lastMillis_Angle += 10;
   attachInterrupt(0, rpm_fan, CHANGE);
  }

but every time I call it. I have to disable interrupt that calculate the speed.

MostafaKhattab:
but every time I call it. I have to disable interrupt that calculate the speed.

Why ? I don't understand.
Can you show the whole sketch, I'm pretty much in the dark now and have no idea what is going on.

Since we haven't seen the whole sketch, I am just assuming here. Looks like he is using pin 2 (Interrupt 0? Right?) for both sensors.

And yeah, no need to use an interrupt for compass poling.

Peter_n:
Why ? I don’t understand.
Can you show the whole sketch, I’m pretty much in the dark now and have no idea what is going on.

void loop()
{
if (millis()-lastMillis == 1000) // check speed every second or above
  {
      detachInterrupt(0); // deattaching interrupt to calculate speed
      rpm = rpmcount * 3.75; // rpm is counter * (60 second / number of ma8nateeses)
      wSpeed = ((Circ * rpm) / time_scale); // speed = rpm *   mo7eet el kawet4
      wSpeed_precision = (wSpeed - (int)wSpeed)*100;
      rpmcount = 0; // re-init
      lastMillis = millis();  // updating millis
      attachInterrupt(0, rpm_fan, CHANGE);   // attach interrupt again
  }
if (millis() - lastMillis_Angle == 10)
  {
   detachInterrupt(0);
   // Calculate angle
   angleCalculation();
   lastMillis_Angle = millis();
   attachInterrupt(0, rpm_fan, CHANGE);
  }
}

void rpm_fan()
{
  ++rpmcount;
}

void angleCalculation() {
// angle calculations is performed here ..
}

do you mean that every time i call angleCalculation() function, i don’t need to call detachInterrupt(0) - pin2 - and the enable it again after angleCalculation() … You mean that i don’t need to do that ??

i hadn’t tried yet. But is that what you really mean ??

thanks

You might need to do that if the interrupt is causing problems with the serial comm. Looks like you are checking the compass 100x per second...

But we still haven't seen the WHOLE sketch. And that == in

(millis()-lastMillis == 1000)

still bothers me.

MostafaKhattab:
do you mean that every time i call angleCalculation() function, i don't need to call detachInterrupt(0) - pin2 - and the enable it again after angleCalculation() .. You mean that i don't need to do that ??

Yes this IS what peter means.

What on earth ever made you think you needed to detach your RPM ISR when manipulating data that has nothing to do with that routine.

Paulcet:

(millis()-lastMillis == 1000)

still bothers me.

If the rest of the code is written fairly efficiently, this shouldn't be a problem. (the whole loop should be executed many times per millisecond). but >= would be better.