Not the same result btw 2 codes

Hi everyone !

I don't understand how those two codes work... The first one works exactly as I want but with the Serial.available and I want an automatic check (purpose of the second code)

In the first one, the interrupt work perfectly without incressing the value of the rain falls even if I called many time RainRate()
In the second one, I check the time to execute and check RainRate(), but the value start te increase and never stop.

Can you please tell me what happen ??

Thanks a lot !!

1st Code :

// Hardware pin definitions

// digital I/O pins

const byte RAIN = 2;

// Constants
const byte  RAIN_PERIOD = 60;
const byte  SWITCH_BOUNCE = 10;
const float RAIN_PER_INT = 0.011;
const int   MSECS_TO_SEC = 1000;
const byte  SECS_TO_MIN = 60;
const byte  MINS_TO_HOUR = 60;
const byte  HOURS_TO_24H = 24;

// Global Variables to keep track of things
// Various timers and indices
long lastSecond; 
byte seconds = 0; 
byte minutes = 0; 
byte hours = 0; 


// volatiles are subject to modification by IRQs
volatile float rainHour[60]; //60 floating numbers to keep track of 60 minutes of rain
volatile unsigned long raintime, rainlast, raininterval;

//Interrupt routines (these are called by the hardware interrupts, not by the main code)

void rainIRQ()
// Count rain gauge bucket tips as they occur
// Activated by the magnet and reed switch in the rain gauge, attached to input D2
{
  raintime = millis(); // grab current time
  raininterval = raintime - rainlast; // calculate interval between this and last event

  if (raininterval > SWITCH_BOUNCE) // ignore switch-bounce glitches less than 10mS after initial edge
  {
    rainHour[minutes] += RAIN_PER_INT; //Increase this minute's amount of rain
    rainlast = raintime; // set up for next event
  }
}


void setup()
{
Serial.begin(9600);



  pinMode(RAIN, INPUT_PULLUP); // input from wind meters rain gauge sensor

  lastSecond = millis();

  // attach external interrupt pins to IRQ functions
  attachInterrupt(0, rainIRQ, FALLING);
  
  // Zero out the arrays
 int i;
  for (i = 0; i < RAIN_PERIOD; i++)
    rainHour[i] = 0;

  // turn on interrupts
  interrupts();
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Ascom command handlers
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void RainRate()
{
  float rainRate;

  for (int i = 0; i < RAIN_PERIOD; i++)
    rainRate += rainHour[i];

  Serial.println(rainRate,5);
}


void loop()
{
  //Keep track of which minute it is
  if(millis() - lastSecond >= MSECS_TO_SEC)
  {
    lastSecond += MSECS_TO_SEC;

    // Calculate all weather readings
    // Calc rain
    calc_rain();

    // Calc Wind
    
  }

  String command = "";
  if (Serial.available() > 0) {
    command = Serial.readStringUntil('\n');
    if (command.equalsIgnoreCase("RR")) {
      // Rain rate (Ascom needs mm/hour)
      // This property can be interpreted as 0.0 = Dry any positive nonzero value = wet.
      //   Rainfall intensity is classified according to the rate of precipitation:
      //   Light rain — when the precipitation rate is < 2.5 mm (0.098 in) per hour
      //   Moderate rain — when the precipitation rate is between 2.5 mm (0.098 in) - 7.6 mm (0.30 in) or 10 mm (0.39 in) per hour
      //   Heavy rain — when the precipitation rate is > 7.6 mm (0.30 in) per hour, or between 10 mm (0.39 in) and 50 mm (2.0 in) per hour
      //   Violent rain — when the precipitation rate is > 50 mm (2.0 in) per hour
      RainRate();
 /*   } else if (command.equalsIgnoreCase("WG")) {
      // Wind gust (Ascom needs m/s) Peak 3 second wind speed over the last 2 minutes
      WindGust();
    } else if (command.equalsIgnoreCase("WS")) {
      // Wind speed (Ascom needs m/s)
      WindSpeed();
    } else if (command.equalsIgnoreCase("PW")) {
      printWeather();*/
    }
  }
}

void calc_rain()
{
  if(++seconds >= SECS_TO_MIN)
  {
    seconds = 0;
    if(++minutes >= MINS_TO_HOUR) minutes = 0;
    rainHour[minutes] = 0; //Zero out this minute's rainfall amount
  }
  if(++minutes >= MINS_TO_HOUR)
  {
    minutes = 0;
    if(++minutes >= HOURS_TO_24H) hours = 0;
    rainHour[hours] = 0; //Zero out this hour's rainfall amount
  } 
}


void printWeather()
{
  Serial.println("*********************");
  
  Serial.print("RR: ");
  RainRate();

  /*Serial.print("WG: ");
  WindGust();

  Serial.print("WS: ");
  WindSpeed();*/

  Serial.println("*********************");
}

2nd code

#define T_rain 500
#define T_wind 2000

// Hardware pin definitions
// digital I/O pins

const byte RAIN = 2;


// Constants
const byte  RAIN_PERIOD = 60;
const byte  SWITCH_BOUNCE = 10;
const float RAIN_PER_INT = 0.011;
const int   MSECS_TO_SEC = 1000;
const byte  SECS_TO_MIN = 60;
const byte  MINS_TO_HOUR = 60;
const byte  HOURS_TO_24H = 24;

// Global Variables to keep track of things
// Various timers and indices
long lastSecond; 
byte seconds = 0; 
byte minutes = 0;
byte hours = 0;

long       LastRainCheck = 0;

// volatiles are subject to modification by IRQs
volatile float rainHour[60]; //60 floating numbers to keep track of 60 minutes of rain
volatile unsigned long raintime, rainlast, raininterval;

//Interrupt routines (these are called by the hardware interrupts, not by the main code)
void rainIRQ()
// Count rain gauge bucket tips as they occur
// Activated by the magnet and reed switch in the rain gauge, attached to input D2
{
  raintime = millis(); // grab current time
  raininterval = raintime - rainlast; // calculate interval between this and last event

  if (raininterval > SWITCH_BOUNCE) // ignore switch-bounce glitches less than 10mS after initial edge
  {
    rainHour[minutes] += RAIN_PER_INT; //Increase this minute's amount of rain
    rainlast = raintime; // set up for next event
  }
}

void setup()
{
Serial.begin(9600);


// WIND SPEED AND RAIN SETUP
  pinMode(RAIN, INPUT_PULLUP); // input from wind meters rain gauge sensor

  lastSecond = millis();

  // attach external interrupt pins to IRQ functions
  attachInterrupt(0, rainIRQ, FALLING);


  // Zero out the arrays
  int i;
  for (i = 0; i < RAIN_PERIOD; i++)
    rainHour[i] = 0;

  // turn on interrupts
  interrupts();

}

void loop() 
{
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// TASK FUNCTIONS
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  //Keep track of which minute it is
  if(millis() - lastSecond >= MSECS_TO_SEC)
  {
  lastSecond += MSECS_TO_SEC;
      // Calculate all weather readings
      // Calc rain
    calc_rain();
 Serial.println("Rain : "),RainRate();
 
  }
}

void calc_rain()
{
  if(++seconds >= SECS_TO_MIN)
  {
    seconds = 0;
    if(++minutes >= MINS_TO_HOUR) minutes = 0;
    rainHour[minutes] = 0; //Zero out this minute's rainfall amount
  }
/*  if(++minutes >= MINS_TO_HOUR)
  {
    minutes = 0;
    if(++minutes >= HOURS_TO_24H) hours = 0;
    rainHour[hours] = 0; //Zero out this hour's rainfall amount
  }/***/ 
}

// FUNCTIONS FOR RAIN AND WIND SPEED

void RainRate()
{
  float rainRate;

  for (int i = 0; i < RAIN_PERIOD; i++)
    rainRate += rainHour[i];

  Serial.println(rainRate,5);
}

In 1st code, shouldn't this:

if(++minutes >= HOURS_TO_24H) hours = 0;

Be:

if(++hours >= HOURS_TO_24H) hours = 0;

?

In the sketch, you declare a variable 'rainRate' inside the function RainRate()

void RainRate()
{
  float rainRate;
  ...

which essentially creates a new variable but doesn't guarantee it starts with the value 0.0. You should assign it

void RainRate()
{
  float rainRate = 0.0;
  ...

Also, you use the variable 'minutes' inside your ISR but do not declare it as 'volatile'

I would also rearrange the order inside setup() to zero out your array before you attach the interrupt since interrupts are running (your call to interrupts() is not necessary since you have not turned them off)

And speaking of turning them off, you should do that while summing the rain amount (and then turn them back on) or your values may change (probably not significantly, but a good habit)

Thanks a lot for all your answers !

It's working perfectly now ! I had to add RainRate = 0.0 !

Thanks agaiin ! :slight_smile: