Function is triggering more that once and I don't know why.

Hi,

I am fairly new to Arduino and I am making a sensor for my holding tank at a house I own. It is suppose to sense when an alarm gores off that is currently hooked up to the holding tank. I have that woking but when It goes off it is suppose to send an email or text to me so I can call and have it pumped. The problem is when the alarm goes off the program ends up sending an email 6 times. Currently I have not gotten to the actual email code but have put serial.println to indicate that the function has triggered. I have included a screen shot of the serial monitor and the code I am using. Any help will be most welcome.

/*
  Holding Tank Alarm v0.01
 
 Reads an analog input on pin 0, converts it to voltage. If voltage is above 0 volts it sends a text that the 
 tank needs to be pumped. Connects wirelessly to WiFi in the house. If connection is lost program will continue
 try to reconnect to WiFi and sends a text that it has reestablished connection. Program checks RTC on startup
 and once a month afterwards to set the time.
 
 */

// add libraries
#include <Time.h>
#include <TimeAlarms.h>


// the setup routine runs once when you press reset:
void setup() {

  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  setTime(22,00,0,1,30,15); 
  void SendEmai();
  SendEmail();
}

// the loop routine runs over and over again forever:
void loop() {

  int NextMessageTime = 0;
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0); 
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float voltage = sensorValue * (5.0 / 1023.0);
  // print out the value you read:
  Serial.println(voltage);
  if (voltage>0 && NextMessageTime == 0) {
    //display time
    digitalClockDisplay();
    // wait one second between clock display
    Alarm.delay(1000); 

    //send email here
    if (voltage > 0 && NextMessageTime > 0) {
      Serial.println("Send email here");
      Serial.println(NextMessageTime);

      NextMessageTime=0;
    }
    if (Alarm.timerRepeat(60, Repeats)){
      NextMessageTime=1;
    }
  }
}

void digitalClockDisplay()
{
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(); 
}

void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void Repeats(){
  Serial.println("60 second timer");  
  SendEmail();  
}

void SendEmail()
{
  Serial.println("Email sent"); 
 // NextMessageTime=1;
}

You are sending the e-mail based on the alarm BEING active, rather than based on the level BECOMING active. Once the alarm is active, it will continue to send messages until the alarm is no longer active. You need to remember that you've already sent the alarm, and NOT send it again until the alarm has turned off, and then back on again.

Regards,
Ray L.

Thanks Ray,

What I was trying to do was once the voltage was detected was to send an email once and then after a period of time send another email. And after the emails stop I would know that the tank has been pumped. So I would need to know both when it first becomes active and that it is still active so I can monitor if the tank has been pumped. I will be having renters in this house on a weekly basis and I would prefer that they don't have to deal with the current alarm and lots of people do not how to deal with the alarm. I hope that a makes sense. I am not sure if I have the logic correct in the sketch. Thanks.

d

Well, your first problem then is that you re=send the message based on NextMessageTime being ==0. But NextMessageTime is a local variable in loop() which you initialize to 0. So, it is ALWAYS 0 when you do:

if (voltage>0 && NextMessageTime == 0)

You need to either make it global (move it outside loop()), or declare it as static, and initialize it in setup(), not in loop().

Regards,
Ray L.

Thanks for the help Ray,

I have simplified the code so there are no conditional statements and I am still having the problem. I am using the time and timealarms libraries found here TimeAlarms Library, Run Functions At Specific Times and in particular Alarm.timerRepeat(60, SendEmail); which should trigger every 60 seconds but it will trigger four to five times in a row and then trigger again in 60 seconds again 4-5 times. Below is the sketch that I am using. The sketch is not fully done but I was testing the library with short time intervals to see if it would suit my needs.

Thanks again.

d

/*
Holding Tank Alarm v0.01

Reads an analog input on pin 0, converts it to voltage. If voltage is above 0 volts it sends a text that the 
tank needs to be pumped. Connects wirelessly to WiFi in the house. If connection is lost program will continue to try to reconnect to WiFi and sends a text that it has reestablished connection. Program checks RTC on startup and once a month afterwards to set the time.
*/

// add libraries
#include <Time.h>
#include <TimeAlarms.h>

void setup() 
{
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
setTime(22,00,0,1,30,15); 
SendEmail();

}

void loop() {

// read the input on analog pin 0:
int sensorValue = analogRead(A0);

// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (5.0 / 1023.0);

// print out the value you read:
Serial.println(voltage);

//display time
digitalClockDisplay();
// wait one second between clock display
Alarm.delay(1000);

// timer for every 60 seconds

Alarm.timerRepeat(60, SendEmail);
}

void digitalClockDisplay()
{
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.println(); 
}

void printDigits(int digits)
{
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}

void SendEmail()
{

Serial.println("Email sent");

}

Not surprising it's misbehaving. The first time loop() is called, you call:

Alarm.timerRepeat(60, SendEmail);

This creates a timer that will call SendE-mail every 60 seconds.

Next time loop() is called (about 100 uSec later), you again, call:

Alarm.timerRepeat(60, SendEmail);

Now you have TWO timers calling SendEmail every 60 seconds.

and so on, and so on. In under a second, you've got thousands of timers all trying to call SendEmail every 60 seconds, until eventually you'll run out of memory, and the program crashes.

Call timerOnce() ONCE when the event happens that you want to send an e-mail. When SendEmail is called, increment a counter to track how many times you've sent the e-mail. If you haven't hit the limit, call timerOnce again, to trigger the next e-mail. Otherwise, just return, and no more e-mails will go out until the next event that warrants it.

Regards,
Ray L.

You've included what is apparently a function prototype or forward declaration of your SendEmail() function in the setup() function.

This function prototype or forward declaration should probably appear in your code near the top, outside of any function.

Declaring it inside the setup( ) function, as you have done, would appear to limit it's scope to that function, if you intended to call it from loop( ), then it would not work.

michinyon:
You’ve included what is apparently a function prototype or forward declaration of your SendEmail() function in the setup() function.

This function prototype or forward declaration should probably appear in your code near the top, outside of any function.

Declaring it inside the setup( ) function, as you have done, would appear to limit it’s scope to that function, if you intended to call it from loop( ), then it would not work.

True its not needed, however the IDE will still generate one globally. And in this case the names are different:
void SendEmai();
SendEmail();