looking for good RPM sketch for wind turbine monitoring

I don't see why interrupts never seem to start. no millis.

// EBRC temperature sensor application 11/2015 tmw
int sensorTemp1Pin = A0;    // select the input pin for temp1
int sensorTemp2Pin = A1;    // select the input pin for temp2
int sensorTempAmbPin = A2;  // select the input pin for temp_ambient
int sensorExtVrefPin = A3;  // select the input pin to measure external AD780, 3.00v half value, 2x 1k
int sensorExt5vPin = A4;  // select the input pin to measure 5v rail 40% value via 1.5k and 1k Resistors
int ledPin = 13;      // select the pin for the LED
#define ARRAY_LENGTH 96             
#define ARRAY_LENGTH_RPM 2880  //  elements of RPM array
                              
#define VoltsPerBit 0.002930     //  external Vref, AD780,3.00v 
                                
#define Adj 0.9                 // adjustment factor for temperature reading accuracy  0014650
#define LoadResistor 4870  // Load resistor for temp sensor AD594, 1ua/deg K, 4870 ohms
#define NumberOneSecBetweenReadings 1 
#define NumberRPMBetweenTemps 3  //  20   5 min = 300sec = 300/NumberOneSecBetweenRPM
#define NumberOneSecBetweenRPM 1   // 15
int sensorValueTemp1[ARRAY_LENGTH];    // temperature(degF) coming from the sensor
int sensorValueTemp2[ARRAY_LENGTH] ;    // temperature(degF) coming from the sensor
int sensorValueTempAmb[ARRAY_LENGTH] ;  // temperature(degF) coming from the sensor
unsigned int sensorRPM[ARRAY_LENGTH_RPM] ; // RPM values  coming from 3ph voltage
unsigned int temp_RPM = 0;
unsigned int NumberOfBlips = 0;
long int RPMsubArray[60 * NumberOneSecBetweenReadings+1];   //average before report array
long int RPMAverager = 0;
#define NumTurbinePoles 42
#define ABS_MAX_RPM 4000

//int sensorValueCircularTest[ARRAY_LENGTH];  // test
int sensorBitsTemp1 = 0;  //ADC conversion bits
int sensorBitsTemp2 = 0;
int sensorBitsTempAmb = 0;
int ExtVrefBits = 0;
int Ext5vBits = 0;

float MicroAmps = 0;           // temp variable for temperature calculation
float temp7 = 0;
int temp_index = 0;
int temp_out_index = 0;
int array_index = 0;
int last_index = 0;  //
int temp_cntr = 0;
int temp_Temp_cntr = 0;
short Temp_flag = 0;

int DelayTime = 0;
int idx = 0;
int temp_val = 0; 

int temp_index_RPM = 0;
int temp_out_index_RPM = 0;
int array_index_RPM = 0;
int last_index_RPM = 0;
int temp_RPM_cntr = 0;
short RPM_flag = 0;

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEE
};
IPAddress ip(192, 168, 1, 19);

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
const int chipSelect = 4;

//setup for RPM measurement
// period of pulse accumulation and serial output, milliseconds
#define MainPeriod 100
long previousMillis = 0; // will store last time of the cycle end
unsigned long currentMillis = millis();
volatile unsigned long duration=0; // accumulates pulse width
volatile unsigned int pulsecount=0;
volatile unsigned long previousMicros=0;


void setup() {

  // declare the ledPin as an OUTPUT:
  pinMode(ledPin, OUTPUT);
  analogReference(EXTERNAL);

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  attachInterrupt(0, myinthandler, RISING);  // setup interrupt
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

void loop() {
delay(1000); //  1 sec

  temp_RPM_cntr++;
  if (temp_RPM_cntr >= NumberOneSecBetweenRPM)
  {
    temp_RPM_cntr = 0;   // wait till reading trigger
    RPM_flag = 1;
    array_index_RPM++;
    if (temp_Temp_cntr > NumberRPMBetweenTemps)
      {
      temp_Temp_cntr = 0;
      Temp_flag = 1;
      array_index++;
      if (array_index >= ARRAY_LENGTH)          //  make arrays circular
        array_index = 0;
      }
  }
  if (array_index_RPM >= ARRAY_LENGTH_RPM)   //  make array circular
    array_index_RPM = 0;

  Serial.print(temp_Temp_cntr);
  Serial.print(" ");
  Serial.print(temp_RPM_cntr);
  Serial.print(" ");
  Serial.print(Temp_flag);
  Serial.print(" ");
  Serial.print(RPM_flag);
  Serial.print(" ");

  Serial.print(currentMillis);
  Serial.print(" "); // separator!
  Serial.println("
");
  

//RPM stuff
if (currentMillis - previousMillis >= MainPeriod)
  {
      Serial.print(RPM_flag);
      Serial.println("
");
      //previousMillis = currentMillis;
      previousMillis += MainPeriod;
      // need to bufferize to avoid glitches
      noInterrupts();
      unsigned long _duration = duration;
      unsigned long _pulsecount = pulsecount;
      duration = 0; // clear counters
      pulsecount = 0;
      interrupts();
      float Freq = 1e6 / float(_duration);
      Freq *= _pulsecount; // calculate F
      
      if (RPM_flag)            // take a reading
      {
      sensorRPM[array_index_RPM] = Freq * 60 * 2 / NumTurbinePoles; //  external /2 in hardware compensation
      // output time and frequency data to RS232
      Serial.print(currentMillis);
      Serial.print(" "); // separator!
      Serial.print(Freq);
      Serial.print(" ");
      //Serial.print(_pulsecount);
      Serial.print(sensorRPM[array_index]);
      Serial.print(" ");
      Serial.println(_duration);
      temp_Temp_cntr++;
      RPM_flag = 0;
    }
  }

  if (Temp_flag)
  {
  // temperature code
  }


// listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
      //   client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");

  
          client.print("EBRC Field Network, Temperature Monitor Page ");
          client.println("
");

          
  
           client.print("Wind Turbine RPM ");
           temp_out_index = last_index;
           for ( temp_index_RPM = 0;  temp_index_RPM <= last_index_RPM ;  temp_index_RPM++ )
            {
            client.print(sensorRPM[temp_out_index_RPM]);
            temp_out_index_RPM = temp_out_index_RPM -1;
            client.print(", ");
            }
           temp_out_index_RPM = ARRAY_LENGTH_RPM;
           for (int temp_index_RPM = 0; temp_index_RPM < (ARRAY_LENGTH_RPM - last_index_RPM)  ; temp_index_RPM++ )
            {
            client.print(sensorRPM[temp_out_index_RPM]);
            temp_out_index_RPM = temp_out_index_RPM -1;
            client.print(", "); 
            }
          client.println("
");
          
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }
}

void myinthandler() // interrupt handler
{
  unsigned long currentMicros = micros();
  duration += currentMicros - previousMicros;
  previousMicros = currentMicros;
  pulsecount++;
}

You assign a value to current millis() at the head of the program.

unsigned long currentMillis = millis();

It is never updated in the program when used in the timer.

if (currentMillis - previousMillis >= MainPeriod)

Why not just use millis(). It will be the current value

if (millis() - previousMillis >= MainPeriod)

I see other uses of currentMillis without update

//Serial.print(currentMillis);
  Serial.println(millis());

If you want currentMillis to have the same value at several different places in the loop where timing may be delayed then just assign currentMillis() = millis() as the firs statement in loop.

Oddly, I occasionally get a corrupted web page, see attached pdf. The first is an occasional corruption footprint, but typically a page reread after corruption yields the last pic which is good expected consistent data.

This setup is on my laptop with external ethernet switch and simulated data from a 555, thus the apparent RPM stability.

int sensorTemp1Pin = A0;    // select the input pin for temp1
int sensorTemp2Pin = A1;    // select the input pin for temp2
int sensorTempAmbPin = A2;  // select the input pin for temp_ambient
int sensorExtVrefPin = A3;  // select the input pin to measure external AD780, 3.00v half value, 2x 1k
int sensorExt5vPin = A4;  // select the input pin to measure 5v rail 40% value via 1.5k and 1k Resistors
int ledPin = 13;      // select the pin for the LED
#define ARRAY_LENGTH 96     // elements of the temperature arrays, ints, 3 arrays for temp, mega has 8192 bytes memory, 8 hours
                            // read once per 1 min = 60 * 8 = 480
                            // read once per 5 min = 12 * 8 = 480
        
#define ARRAY_LENGTH_RPM 2880  //  elements of RPM array
          

#define VoltsPerBit 0.002930     //  external Vref, AD780,3.00v 
                                 
#define Adj 0.9                 // adjustment factor for temperature reading accuracy  0014650
#define LoadResistor 4870  // Load resistor for temp sensor AD594, 1ua/deg K, 4870 ohms
#define NumberOneSecBetweenReadings 1 
#define NumberRPMBetweenTemps 3  //  20   5 min = 300sec = 300/NumberOneSecBetweenRPM
#define NumberOneSecBetweenRPM 1   // 15
int sensorValueTemp1[ARRAY_LENGTH];    // temperature(degF) coming from the sensor
int sensorValueTemp2[ARRAY_LENGTH] ;    // temperature(degF) coming from the sensor
int sensorValueTempAmb[ARRAY_LENGTH] ;  // temperature(degF) coming from the sensor
unsigned int sensorRPM[ARRAY_LENGTH_RPM] ; // RPM values  coming from 3ph voltage
unsigned int temp_RPM = 0;
unsigned int NumberOfBlips = 0;
long int RPMsubArray[60 * NumberOneSecBetweenReadings+1];   //average before report array
long int RPMAverager = 0;
#define NumTurbinePoles 42
#define ABS_MAX_RPM 4000

//int sensorValueCircularTest[ARRAY_LENGTH];  // test
int sensorBitsTemp1 = 0;  //ADC conversion bits
int sensorBitsTemp2 = 0;
int sensorBitsTempAmb = 0;
int ExtVrefBits = 0;
int Ext5vBits = 0;

float MicroAmps = 0;           // temp variable for temperature calculation
float temp7 = 0;
int temp_index = 0;
int temp_out_index = 0;
int array_index = 0;
int last_index = 0;  //
int temp_cntr = 0;
int temp_Temp_cntr = 0;
short Temp_flag = 0;

int DelayTime = 0;
int idx = 0;
int temp_val = 0; 

int temp_index_RPM = 0;
int temp_out_index_RPM = 0;
int array_index_RPM = 0;
int last_index_RPM = 0;
int temp_RPM_cntr = 0;
short RPM_flag = 0;

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEE
};
IPAddress ip(192, 168, 1, 19);

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
const int chipSelect = 4;

//setup for RPM measurement
// period of pulse accumulation and serial output, milliseconds
#define MainPeriod 100
long previousMillis = 0; // will store last time of the cycle end

volatile unsigned long duration=0; // accumulates pulse width
volatile unsigned int pulsecount=0;
volatile unsigned long previousMicros=0;


void setup() {

  // declare the ledPin as an OUTPUT:
  pinMode(ledPin, OUTPUT);
  analogReference(EXTERNAL);

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  attachInterrupt(0, myinthandler, RISING);  // setup interrupt
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

void loop() {
delay(1000); //  1 sec
  unsigned long currentMillis = millis();
  temp_RPM_cntr++;
  if (temp_RPM_cntr >= NumberOneSecBetweenRPM)
  {
    temp_RPM_cntr = 0;   // wait till reading trigger
    RPM_flag = 1;
    array_index_RPM++;
    if (temp_Temp_cntr > NumberRPMBetweenTemps)
      {
      temp_Temp_cntr = 0;
      Temp_flag = 1;
      array_index++;
      if (array_index >= ARRAY_LENGTH)          //  make arrays circular
        array_index = 0;
      }
  }
  if (array_index_RPM >= ARRAY_LENGTH_RPM)   //  make array circular
    array_index_RPM = 0;



//RPM stuff
if ( millis() - previousMillis >= MainPeriod)
  {
      Serial.print(RPM_flag);
      Serial.println("
");
      //previousMillis = currentMillis;
      previousMillis += MainPeriod;
      // need to bufferize to avoid glitches
      noInterrupts();
      unsigned long _duration = duration;
      unsigned long _pulsecount = pulsecount;
      duration = 0; // clear counters
      pulsecount = 0;
      interrupts();
      float Freq = 1e6 / float(_duration);
      Freq *= _pulsecount; // calculate F
      
      if (RPM_flag)            // take a reading
      {
      sensorRPM[array_index_RPM] = Freq * 60 * 2 / NumTurbinePoles; //  external /2 in hardware compensation
    
      temp_Temp_cntr++;
      RPM_flag = 0;
    }
  }

  if (Temp_flag)
  {
  // temperature code
  }


// listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
      //   client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");

  
          client.print("EBRC Field Network, Temperature Monitor Page ");
          client.println("
");

               
  
           client.print("Wind Turbine RPM ");
           temp_out_index_RPM = last_index_RPM;
           for ( temp_index_RPM = 0;  temp_index_RPM <= last_index_RPM ;  temp_index_RPM++ )
            {
            client.print(sensorRPM[temp_out_index_RPM]);
            temp_out_index_RPM = temp_out_index_RPM -1;
            client.print(", ");
            }
           temp_out_index_RPM = ARRAY_LENGTH_RPM;
           for (int temp_index_RPM = 0; temp_index_RPM < (ARRAY_LENGTH_RPM - last_index_RPM)  ; temp_index_RPM++ )
            {
            client.print(sensorRPM[temp_out_index_RPM]);
            temp_out_index_RPM = temp_out_index_RPM -1;
            client.print(", "); 
            }
          client.println("
");
          
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }
}

void myinthandler() // interrupt handler
{
  unsigned long currentMicros = micros();
  duration += currentMicros - previousMicros;
  previousMicros = currentMicros;
  pulsecount++;
}

here is the view of corrupted page and uncorrupted page

occasional corruption.pdf (834 KB)

I really can't offer much assistance on the web page corruption issue. As general advice, you may want to transmit your data with definite start and stop markers.

You appear to be sending two data streams with different for loops. Is there any consistency to where in which stream the corruption occurs?

client.print("Wind Turbine RPM ");
           temp_out_index_RPM = last_index_RPM;
           for ( temp_index_RPM = 0;  temp_index_RPM <= last_index_RPM ;  temp_index_RPM++ )
            {
            client.print(sensorRPM[temp_out_index_RPM]);
            temp_out_index_RPM = temp_out_index_RPM -1;
            client.print(", ");
            }
           temp_out_index_RPM = ARRAY_LENGTH_RPM;
           for (int temp_index_RPM = 0; temp_index_RPM < (ARRAY_LENGTH_RPM - last_index_RPM)  ; temp_index_RPM++ )
            {
            client.print(sensorRPM[temp_out_index_RPM]);
            temp_out_index_RPM = temp_out_index_RPM -1;
            client.print(", "); 
            }

My further advice is to write a simplified sketch with just the rpm and ethernet, perhaps scaled for an Uno rather than a Mega, see if it corrupts, and then try a new posting about "intermittantly corrupted ethernet transfer".

I'm sure its a good clue that the corruption does not persist between transfers, and that after a bad page, the next one can be correct.

thanks for your continued advice and guidance.

it looks like two arrays, but it is really only one. I accumulate the data in a circular buffer, then read it out with most recent reading first.

this is the stripped down sketch.