Sensor Min-Max values

I have an anemometer successfully up and running utilizing a very nice (at least to me) sketch provided by ForceTronics. I have added simple LCD print lines and now,

I want to add a maximum wind speed value to the LCD and ultimately, SD data logger.

The problem is, I'm stumped as to the correct way to do this in my situation. I have searched all over and the methods I have tried have at best populated the max value on the display, but it does not "save" it. I am using an Uno and the circuit includes a debounce circuit for the reed switch.

If anyone can point me in the right direction, I'd sure appreciate it!

The sketch I have so far is attached - Thanks !

const byte interruptPin = 3; //anemomter input to digital pin (must be D2 or D3 in Uno)
volatile unsigned long sTime = 0; //stores start time for wind speed calculation
unsigned long dataTimer = 0; //used to track how often to communicate data
volatile float pulseTime = 0; //stores time between one anemomter relay closing and the next
volatile float culPulseTime = 0; //stores cumulative pulsetimes for averaging
volatile bool start = true; //tracks when a new anemometer measurement starts
volatile unsigned int avgWindCount = 0; //stores anemometer relay counts for doing average wind speed
float aSetting = 60.0; //wind speed setting to signal alarm

#include <LiquidCrystal.h>  //Include LCD library
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // initialize the library with the numbers of the interface pins

//======================================================================================

void setup() {
  lcd.begin(20, 4); // set up the LCD's number of columns and rows

  pinMode(13, OUTPUT); //setup LED pin to signal high wind alarm condition
  pinMode(interruptPin, INPUT_PULLUP); //set interrupt pin to input pullup
  attachInterrupt(interruptPin, anemometerISR, RISING); //setup interrupt on anemometer input pin, interrupt will occur whenever falling edge is detected
  dataTimer = millis(); //reset loop timer
}

//======================================================================================


void loop() {

  unsigned long rTime = millis();
  if ((rTime - sTime) > 2500) pulseTime = 0; //if the wind speed has dropped below 1MPH than set it to zero

  if ((rTime - dataTimer) > 1800) { //See if it is time to transmit

    detachInterrupt(interruptPin); //shut off wind speed measurement interrupt until done communication
    float aWSpeed = getAvgWindSpeed(culPulseTime, avgWindCount); //calculate average wind speed
    if (aWSpeed >= aSetting) digitalWrite(13, HIGH);  // high speed wind detected so turn the LED on
    else digitalWrite(13, LOW);   //no alarm so ensure LED is off
    culPulseTime = 0; //reset cumulative pulse counter
    avgWindCount = 0; //reset average wind count

    float aFreq = 0; //set to zero initially
    if (pulseTime > 0.0) aFreq = getAnemometerFreq(pulseTime); //calculate frequency in Hz of anemometer, only if pulsetime is non-zero
    float wSpeedMPH = getWindMPH(aFreq); //calculate wind speed in MPH, note that the 2.5 comes from anemometer data sheet



    Serial.begin(57600); //start serial monitor to communicate wind data
    Serial.println();
    Serial.println("...................................");
    Serial.print("Anemometer speed in Hz ");
    Serial.println(aFreq);
    Serial.print("Current wind speed is ");
    Serial.println(wSpeedMPH);
    Serial.print("Current average wind speed is ");
    Serial.println(aWSpeed);

   
    lcd.clear();
    lcd.print("Average Wind Speed: ");
    lcd.print(aWSpeed);
    lcd.print(" MPH   ");
    


    Serial.end(); //serial uses interrupts so we want to turn it off before we turn the wind measurement interrupts back on


    start = true; //reset start variable in case we missed wind data while communicating current data out
    attachInterrupt(digitalPinToInterrupt(interruptPin), anemometerISR, RISING); //turn interrupt back on
    dataTimer = millis(); //reset loop timer
  }
}

//using time between anemometer pulses calculate frequency of anemometer
float getAnemometerFreq(float pTime) {
  return (1 / pTime);
}
//Use anemometer frequency to calculate wind speed in MPH, note 2.5 comes from anemometer data sheet
float getWindMPH(float freq) {
  return (freq * 2.5);
}
//uses wind MPH value to calculate KPH
float getWindKPH(float wMPH) {
  return (wMPH * 1.61);
}
//Calculates average wind speed over given time period
float getAvgWindSpeed(float cPulse, int per) {
  if (per) return getWindMPH(getAnemometerFreq((float)(cPulse / per)));
  else return 0; //average wind speed is zero and we can't divide by zero
}

//This is the interrupt service routine (ISR) for the anemometer input pin
//it is called whenever a falling edge is detected
void anemometerISR() {
  unsigned long cTime = millis(); //get current time
  if (!start) { //This is not the first pulse and we are not at 0 MPH so calculate time between pulses
    // test = cTime - sTime;
    pulseTime = (float)(cTime - sTime) / 1000;
    culPulseTime += pulseTime; //add up pulse time measurements for averaging
    avgWindCount++; //anemomter went around so record for calculating average wind speed
  }
  sTime = cTime; //store current time for next pulse time calculation
  start = false; //we have our starting point for a wind speed measurement
}

Would it be too simple to save the min/max values of wSpeedMPH? The general plan for a maximum is to replace it if the current value is larger.

To "save" the maximum wind speed you need a line something like this:

if (wind_speed > max_wind_speed) max_wind_speed = wind_speed;

Of course, you will need to reset max_wind_speed to zero from time to time.

Thank you both !
I got it!

OK.... next issue: I am getting seemingly random super high Max values in very low wind conditions such as 50 MPH, 2500 MPH and... inf MPH. The incorrect Max values appear to progressively increase over hours.

Did I not implement the "if" statement correctly?

const byte interruptPin = 3; //anemomter input to digital pin (must be D2 or D3 in Uno)
volatile unsigned long sTime = 0; //stores start time for wind speed calculation
unsigned long dataTimer = 0; //used to track how often to communicate data
volatile float pulseTime = 0; //stores time between one anemomter relay closing and the next
volatile float culPulseTime = 0; //stores cumulative pulsetimes for averaging
volatile bool start = true; //tracks when a new anemometer measurement starts
volatile unsigned int avgWindCount = 0; //stores anemometer relay counts for doing average wind speed
float aSetting = 60.0; //wind speed setting to signal alarm
float max_aWSpeed = 0;
#include <LiquidCrystal.h>  //Include LCD library

LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // initialize the library with the numbers of the interface pins

//======================================================================================

void setup() {
  lcd.begin(20, 4); // set up the LCD's number of columns and rows

  pinMode(13, OUTPUT); //setup LED pin to signal high wind alarm condition
  pinMode(interruptPin, INPUT_PULLUP); //set interrupt pin to input pullup
  attachInterrupt(interruptPin, anemometerISR, RISING); //setup interrupt on anemometer input pin, interrupt will occur whenever falling edge is detected
  dataTimer = millis(); //reset loop timer
}

//======================================================================================


void loop() {

  unsigned long rTime = millis();
  if ((rTime - sTime) > 2500) pulseTime = 0; //if the wind speed has dropped below 1MPH than set it to zero

  if ((rTime - dataTimer) > 1800) { //See if it is time to transmit

    detachInterrupt(interruptPin); //shut off wind speed measurement interrupt until done communication
    float aWSpeed = getAvgWindSpeed(culPulseTime, avgWindCount); //calculate average wind speed
    if (aWSpeed >= aSetting) digitalWrite(13, HIGH);  // high speed wind detected so turn the LED on
    else digitalWrite(13, LOW);   //no alarm so ensure LED is off
    culPulseTime = 0; //reset cumulative pulse counter
    avgWindCount = 0; //reset average wind count

    float aFreq = 0; //set to zero initially
    if (pulseTime > 0.0) aFreq = getAnemometerFreq(pulseTime); //calculate frequency in Hz of anemometer, only if pulsetime is non-zero
    float wSpeedMPH = getWindMPH(aFreq); //calculate wind speed in MPH, note that the 2.5 comes from anemometer data sheet

    if (aWSpeed > max_aWSpeed) max_aWSpeed = aWSpeed;


    Serial.begin(57600); //start serial monitor to communicate wind data
    Serial.println();
    Serial.println("...................................");
    Serial.print("Anemometer speed in Hz ");
    Serial.println(aFreq);
    Serial.print("Current wind speed is ");
    Serial.println(wSpeedMPH);
    Serial.print("Current average wind speed is ");
    Serial.println(aWSpeed);

   
    lcd.clear();
    lcd.print("Average Wind Speed: ");
    lcd.print(aWSpeed);
    lcd.print(" MPH ");
    lcd.print(max_aWSpeed);
    lcd.print(" Max");
    


    Serial.end(); //serial uses interrupts so we want to turn it off before we turn the wind measurement interrupts back on


    start = true; //reset start variable in case we missed wind data while communicating current data out
    attachInterrupt(digitalPinToInterrupt(interruptPin), anemometerISR, RISING); //turn interrupt back on
    dataTimer = millis(); //reset loop timer
  }
}

//using time between anemometer pulses calculate frequency of anemometer
float getAnemometerFreq(float pTime) {
  return (1 / pTime);
}
//Use anemometer frequency to calculate wind speed in MPH, note 2.5 comes from anemometer data sheet
float getWindMPH(float freq) {
  return (freq * 2.5);
}
//uses wind MPH value to calculate KPH
float getWindKPH(float wMPH) {
  return (wMPH * 1.61);
}
//Calculates average wind speed over given time period
float getAvgWindSpeed(float cPulse, int per) {
  if (per) return getWindMPH(getAnemometerFreq((float)(cPulse / per)));
  else return 0; //average wind speed is zero and we can't divide by zero
}

//This is the interrupt service routine (ISR) for the anemometer input pin
//it is called whenever a falling edge is detected
void anemometerISR() {
  unsigned long cTime = millis(); //get current time
  if (!start) { //This is not the first pulse and we are not at 0 MPH so calculate time between pulses
    // test = cTime - sTime;
    pulseTime = (float)(cTime - sTime) / 1000;
    culPulseTime += pulseTime; //add up pulse time measurements for averaging
    avgWindCount++; //anemomter went around so record for calculating average wind speed
  }
  sTime = cTime; //store current time for next pulse time calculation
  start = false; //we have our starting point for a wind speed measurement
}

photon_trap:
OK.... next issue: I am getting seemingly random super high Max values in very low wind conditions such as

first, how useful is the max wind speed unless you know the period? Since the beginning of Time? Since your Arduino started up? the last hour, day, week, month?

Second, and this is just a personal preference, the author goes through a lot of unnecessary machinations in loop, turning on/off interrupts & Serial and such. This whole thing can be managed much simpler than the code you inherited.

I know the period exactly because I am the one to hit the reset button and I have a memory.

As for the second point, while you may very well be correct, your statement is of very little use to me at this point as I am still pretty low on the learning curve

photon_trap:
I know the period exactly because I am the one to hit the reset button and I have a memory.

I guess my point was, why not include some time references?

My other point was that (and in consideration of "am still pretty low on the learning curve") you are unfortunately dealing with more complexity than necessary, and it will serve to only make it harder for you (and harder for others) to modify it to suit your unique preferences (and elephant-like memory capability :wink: ).