Use of sei() and cli()

Hi!
I've found a code for reading RPM of a fan.
I see that in code, after the counter of RPM was reset, there are that snippet of code

sei()
delay()
cli()

Ok, it works either with or without sei/cli..so my question is: is necessary using those functions?

Here the test code.

void readFan() {
    nTick = 0;
    //sei();
    delay(1000);
    //cli();
    Calc = (nTick* 60);
    Serial.print (Calc);
}

void loop () 
{ 
    for (int i = 255; i >= 80; i -= 10) {
      //sei();
      analogWrite(fanPin, i);      
      delay(1000); // Wait for stabilize RPM
      readFan();
      //cli();
    }

Another question. I'm trying to read the RPM for some range of PWM value.
The actual code is working perfectly, but if inside readFan() I decomment sei/cli, the program stops and the loop doesn't continue (I hear the fan always the same speed).
Instead, if I decomment the sei/cli inside main "loop" routine it works..

I'm a bit confused about that..for reading the fan RPM and setting the PWM value, I should use those interrupt flag??

Ps:- sorry for my awful English..
Thanks a lot

There is some code that you are not showing. That is the interrupt registration and the interrupt service routine (ISR).

Enabling and disabling interrupts twice has the same effect as enabling and disabling them once.

Not enabling or disabling interrupts at all does affect whether the ISR gets called.

Yes, in the link below you found the code that I've copied with a bit modify :smiley:

The code works perfecly, but I want to know why use that or not..

Ps:- I'm trying to do the same thing (calculate the reading RPM without using Interrupt) just for learn..

Here the snippet:

void readFan(int pwmValue) {          //Set NbTops to 0 ready for calculations
    NbTopsFan = 0;

    int val2 = 0;
    while (true) {
      val2 = digitalRead(hallsensor);
      if (val2 == 1)  NbTopsFan +=1;    
      
      if (NbTopsFan >= 20) {
         //Update RPM every 20 counts, increase this for better RPM resolution,
         //decrease for faster update
         rpm = 30*1000/(millis() - timeold)*NbTopsFan;
         timeold = millis();
         break;
      }
    }
    
    Serial.print ("rpm : ");
    Serial.print (rpm * 5);
    Serial.print ("\r\n");

It works, but I need to learn the formula: rpm = 30*1000/(millis() - timeold)*NbTopsFan;

30*1000 ?! Obviously just to study a bit :smiley:

The formula assumes that NbTopsFan is counting up during exactly one second. They use sei() and cli() to ensure that NbTopsFan does not keep counting after that second of time is finished.

(I'd add a "volatile" to the declaration of the NbTopsFan variable since it is modified in an interrupt and read from the main loop)

(I also prefer using interrupts() and noInterrupts() instead of cli/sei because in the first assembly language I learned, 6502, the SEI and CLI instructions were also used to enable/disable interrupts, but with the opposite meaning of what they have on Atmel chips...)

Mmm ok for the meaning of SEI and CLI..but if I enable/disable interrupt in readFan() routine, all program stop...Why I can enable/disable only in the main loop?

For the formula, SEI - delay CLI is simple to learn, but the second formula:

rpm = 30*1000/(millis() - timeold)*NbTopsFan;

is another attempt to calc the RPM. That formula work also with interrupt (see the original example) but if I put in a polling function it won't work..
I think it's a maths problem ::slight_smile:
That why I didn't understand that formula, why 30? The original formula for speed is (in the example is obviously adapted):

    // WHEELCIRC = 2 * PI * radius (in meters)
    // speed = rpmilli * WHEELCIRC * "milliseconds per hour" / "meters per kilometer"

    // simplify the equation to reduce the number of floating point operations
    // speed = rpmilli * WHEELCIRC * 3600000 / 1000
    // speed = rpmilli * WHEELCIRC * 3600


via - http://chiphacker.com/questions/89/how-do-i-use-a-hall-effect-sensor-to-measure-the-rpm-of-a-wheel

but a computer software (like speed fan) cannot know the exactly size of a fan, so where is the equation for getting the value of 30?

I try to modify the question in a more comprensive English :smiley:

How I can measure the RPM of a fan using polling instead interrupt?

Why I want to use a more complex method if the interrupt method is more easy and accurate? Because on Arduino I have only 2 or 4 interrupt PIN (Arduino Mini/Mega).

What is generating the interrupts now? The interrupt handler is triggered on a rising edge, a falling edge, or both. That is a transition from LOW to HIGH, from HIGH to LOW, or from HIGH to LOW and from LOW to HIGH.

Connect those signals to digital pins and use digitalRead to determine the state (HIGH or LOW) of the pin. You then need to keep track of the previous state, and compare that to the current state, to detect when an edge has been encountered. You then decide whether to to do anything about that edge, depending on it's type (rising or falling).

If all you are doing is measuring the speed of a fan, why does it matter if it uses all the external interrupts?

Infact, in my previous post I put the code for reading that info, but the value is wrong..
I think that the formula for calculating the RPM is wrong...but I'm not sure if I don't know exactly if I can calculate the RPM using a polling on digitalRead

void readFan(int pwmValue) {          
    NbTopsFan = 0;

    int val2 = 0;
    while (true) {
      val2 = digitalRead(pinOfFanRPM);
      if (val2 == 1)  NbTopsFan +=1;

      if (NbTopsFan >= 20) {
         rpm = 30*1000/(millis() - timeold)*NbTopsFan;
         timeold = millis();
         break;
      }
    }

I need to use the digital pins because I need to know the fan speed of 8 or more fans.