Interrupts and delay to read a rotary encoder

hello. I Have a question. for save the data RPM with Hall sensor and Arduino UNO in under code I add the codes of SD-card but it doesn’t work Correctly while the code of read rpm alone works correctly. in second code display RPM & frequency in serial monitor just 25 number not more. why this occur? what can I do to it is work Correctly?
fist code that work correctly :
// read RPM

int half_revolutions = 0;
int rpm = 0;
unsigned long lastmillis = 0;

void setup(){

Serial.begin(9600);
attachInterrupt(0, rpm_fan, FALLING);
}

void loop(){

while (millis() - lastmillis == 1000){ //Uptade every one second, this will be equal to reading frecuency (Hz).

detachInterrupt(0);//Disable interrupt when calculating

rpm = half_revolutions * 60; // Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use half_revolutions * 30.

Serial.print(“RPM =\t”); //print the word “RPM” and tab.
Serial.print(rpm); // print the rpm value.
Serial.print("\t Hz=\t"); //print the word “Hz”.
Serial.println(half_revolutions); //print revolutions per second or Hz. And print new line or enter.

half_revolutions = 0; // Restart the RPM counter
lastmillis = millis(); // Uptade lasmillis
attachInterrupt(0, rpm_fan, FALLING); //enable interrupt
}

}

// this code will be executed every time the interrupt 0 (pin2) gets low.
void rpm_fan(){
half_revolutions++;
}

second code with the code Sd-card :
// read RPM
#include <SPI.h>
#include <SD.h>
// for Due/Mega/Leonardo use the hardware SPI pins (which are different)
#define _sclk 13
#define _miso 12
#define _mosi 11
const int chipSelect = 4; //number of pin cs of sd-card
// read RPM

int half_revolutions = 0;

int rpm = 0;

unsigned long lastmillis = 0;

void setup(){
Serial.begin(9600);
attachInterrupt(0, rpm_fan, FALLING);

if (!SD.begin(chipSelect)) {
Serial.println(“Card failed, or not present”);
// don’t do anything more:
return;}
Serial.println(“card initialized.”);
SD.remove(“datalog.txt”);
File dataFile = SD.open(“datalog.txt”, FILE_WRITE);
dataFile.print(“بسمه تعالی “);dataFile.print(”\n”);
dataFile.print(“RPM \tFrequence(Hz)\n”);
dataFile.print("-------\t--------------\n");
dataFile.close();
}

void loop(){

if (millis() - lastmillis == 1000){ //Uptade every one second, this will be equal to reading frecuency (Hz).

detachInterrupt(0);//Disable interrupt when calculating

rpm = half_revolutions * 60; // Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use half_revolutions * 30.

Serial.print(“RPM =\t”); //print the word “RPM” and tab.
Serial.print(rpm); // print the rpm value.
Serial.print("\t Hz=\t"); //print the word “Hz”.
Serial.println(half_revolutions); //print revolutions per second or Hz. And print new line or enter.

File dataFile = SD.open(“datalog.txt”, FILE_WRITE);
if (dataFile) { // if the file is available, write to it:
dataFile.print(rpm);dataFile.print("\t");dataFile.print(half_revolutions);
dataFile.print("\n");
dataFile.close();
}
else { // if the file isn’t open, pop up an error:
Serial.println(“error opening datalog.txt”);
}

half_revolutions = 0; // Restart the RPM counter
lastmillis = millis(); // Uptade lasmillis
attachInterrupt(0, rpm_fan, FALLING); //enable interrupt
}
}
void rpm_fan(){
half_revolutions++;
}

if (millis() - lastmillis == 1000)

Lucky you if this get a hit. Use >=

millis() does not return consecutive values in general, it will skip occasionally since 1024us is not 1ms

You should never be detaching an interrupt, that will cause several problems (missed interrupts, false triggering on re-enabling).

To read/write volatile variables that are more than 1 byte, simply bracket the code in noInterrupts(); and interrupts();. That way you simply defer any interrupt till after you're done - you won't lose any unless you are insanely slow in copying the values!