Problem with interrupts + serial port

I'm writing a (seemingly simple) program to read an encoder on a flow meter using interrupts, and then convert those pulses into a flow rate in L/min, and then output the flow rate number to the serial port so I can see it on my screen. I have a button to press to start this 'test' which tells the program to a) open the solenoid valve to let water flow and b) start the interrupt and start counting pulses.
Here's my code

// reading liquid flow rate using adapted program from Seeeduino and Water Flow Sensor from Seeedstudio.com

volatile int NbTopsFan; //measuring the rising edges of the signal
int Calc;                               
int hallsensor = 2;    //The pin location of the sensor
int val = 0;                //val is the value of the button (1 = on)

void rpm ()     //This is the function that the interupt calls 
{ 
  NbTopsFan++;  //This function measures the rising and falling edge of the hall effect sensors signal
} 

void setup() //
{ 
  pinMode(hallsensor, INPUT);  //connected to flow meter sensor
  Serial.begin(115200); 
  attachInterrupt(0, rpm, RISING); 
  pinMode(13, OUTPUT);                   //connected to solenoid
  pinMode(3, INPUT);                        //connected to button input
} 

void loop ()    
{
  val = digitalRead(3);                      //read the button
  cli();
  if (val == 1)                                      //if the button is pressed down, start the test
  {
    digitalWrite(13, HIGH);   //open solenoid valve
    NbTopsFan = 0;   //Set NbTops to 0 ready for calculations
    sei();      //Enables interrupts
    delay (1000);   //Wait 1 second
    cli();      //Disable interrupts
    digitalWrite(13, LOW);  //close solenoid valve
    delay(100);

  }

  if (NbTopsFan != 0)                 //if we have new data, calculate flow rate and output to serial port
  {
    Calc = (NbTopsFan *60 / 73); //(number of pules in 1 second *60 seconds /1 min) / 73L/min (calibrated by seeed), = flow rate in L/min 
    Serial.print (Calc, DEC); //Prints the flow rate in L/min
    Serial.print (" L/min \n"); 
    NbTopsFan = 0;                             //reset data for next test
    Calc = 0;                        
    delay(100);
  }
  
}

Everything is 'pretty much' working fine aside from the serial port. When i press the button once, I don't see anything written to the screen. But when I press it again, I get the flow rate from the previous 'test' (ie the flow rate calculated on the previous button press). Why is the serial data one button press behind?

  cli();

Why are you turning interrupts off? Serial printing uses interrupts.

    sei();      //Enables interrupts
    delay (1000);   //Wait 1 second
    cli();      //Disable interrupts

That is not the way to time one second.

Timers:

Thanks for the reply, Nick. I was just adapting the example code for the flow meter that I bought from seeed studio.

http://www.seeedstudio.com/wiki/G1/4"_Water_Flow_Sensor#Introduction

I'll look into doing this a different way!

Just to get you started, and to counter these weird suggestions people have about turning interrupts off, this is what I recommend:

volatile bool counting;
volatile unsigned long events;

unsigned long startTime;
const unsigned long INTERVAL = 1000;  // 1 second

void eventISR ()
  {
  if (counting)
    events++;    
  }  // end of eventISR
  
void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  attachInterrupt (0, eventISR, FALLING);
  }  // end of setup

void showResults ()
  {
  Serial.print ("I counted ");
  Serial.println (events);
  }  // end of showResults
  
void loop ()
  {
  if (counting)
    {
    // is time up?
    if (millis () - startTime < INTERVAL)
      return;  
    counting = false;
    showResults ();
    }
    
  noInterrupts ();
  events = 0;
  startTime = millis ();
  EIFR = bit (INTF0);  // clear flag for interrupt 0 (Atmega328)
  counting = true;
  interrupts ();
  }  // end of loop

You can add your own stuff about flashing LEDs etc.

In loop() here we wait for the interval (1 second in this case) to be up, otherwise we return, effectively doing nothing. You could of course do other things instead of just returning.

If the time is up we display the count.

If counting is not currently active (and presuming we want it to be active) we remember the start time, reset the counter to zero, and let it start counting up.

That code seemed to work OK up to 100 kHz, although the counts were getting a bit inaccurate. You can do more precise timings by using the hardware counters / timers. Details here: