My program seems to work properly with one (or maybe two) temperature probes.
But when I have more (five probes in this case) connected, one function that is called during an alarm event runs too often. Let me explain:
My program should work as follows:
- Every 15 seconds, it queries the five temperature probes, the readings are sent to my local MQTT broker. This section works as it should. (Results display on an Android app)
- Every minute, it queries the five temperature probes, the readings are sent to the ThingSpeak.com MQTT broker. This section also works as it should.
- Every six minutes, it queries the five temperature probes and checks to see if the temperature is too high, too low or within range.
If the temperature is too high or too low, it checks if a "flag" is set, if it is not, it crafts an email (subject and body) with the relevant information, jumps to another function that fires off the email.
When it returns from sending the email, it sets the "flag" that the email has been sent.
The next time it runs, if the "flag" is set, it skips sending a duplicate email.
Once the temperature returns to the "normal" range, it once again crafts an email, jumps to the function to send the email, upon the return, it "unsets" the flag. This also all works as it should.
The problem I am running into is:
if a temperature probe is right on the "balance point" of being "normal" and being too high (or too low), I will get bombarded with emails. Sometimes, three or four (or more) within a minute or two.
In my design, I should ONLY be running the "Check Alarm" function every six minutes.
I understand that I may get multiple emails if multiple probes are too high or too low, this is normal and expected.
But, I may get several emails (for example) with one probe going between 80 (normal) and 81 (too high) several time in a row, until it either gets a bit warmer or cooler so it stop flapping between the set point.
I have written and rewritten this code about four or five different ways with no luck in any of my attempts or ideas on how to correct this issue.
Am I missing something easy here?
Maybe a new set of eyes on the code will see the error in my ways.
NOTE: The code listed below is just a small subset of the bigger program.
What I have below will compile and run, unfortunately, I only have one probe in my test setup and can't get it to fail.
My main circuit is a bit remote and I have to wait basically a full 24 hours to get any good test results.
I'm sure I have left out some details that may be revelant, or if you need further clarification, please don't hesitate to ask and I will try to better explain.
#include <ESP8266WiFi.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP_Mail_Client.h>
const char *wifiSSID = "SSID";
const char *wifiPassword = "Password";
const char *wifiHostName = "TempPublisher-0";
const char *smtpHost = "smtp.gmail.com";
const char *senderEmail = "EMailSenderAddress";
const char *senderPassword = "EMailSenderPassword";
const char *receiverEmail1 = "whoGetsTheEMail";
const int smtpPort = 587;
const int oneWireBuss = 4;
int alarmCheckCounter = 0;
int oneSecond = 1000;
int oneMinute = 60000;
int tempSensorCount = 0;
int temperatureF = 0;
int tempSetPoints = 0;
unsigned long alarmCheckDelay = 0;
WiFiClient wLANClient0;
OneWire oneWire(oneWireBuss);
DallasTemperature sensors(&oneWire);
SMTPSession smtp;
Session_Config config;
SMTP_Message message;
void wifiConnect() {
WiFi.mode(WIFI_STA);
WiFi.hostname(wifiHostName);
WiFi.begin(wifiSSID, wifiPassword);
delay(oneSecond);
Serial.print("\nAttempting connection to WiFi Network... ");
while(WiFi.status() != WL_CONNECTED) {
Serial.print("/");
delay(oneSecond / 8);
Serial.print("\\");
delay(oneSecond / 4);
}
WiFi.setAutoReconnect(true);
WiFi.persistent(true);
Serial.print("\nConnected to WiFi Network: ");
Serial.println(WiFi.SSID());
Serial.print("On IP Address: ");
Serial.println(WiFi.localIP());
Serial.print("With Hostname: ");
Serial.println(WiFi.hostname());
Serial.print("Power Level: ");
Serial.print(WiFi.RSSI());
Serial.println("dB");
}
void eMailConnect() {
MailClient.networkReconnect(true);
smtp.debug(0);
config.server.host_name = smtpHost;
config.server.port = smtpPort;
config.login.email = senderEmail;
config.login.password = senderPassword;
config.login.user_domain = "";
message.sender.name = F("Temp Probes");
message.sender.email = senderEmail;
message.addRecipient(F("SomeBody"), receiverEmail1);
}
void sendEmail() {
smtp.connect(&config);
MailClient.sendMail(&smtp, &message);
Serial.println("Message has been sent!");
}
String tempProbeInfo[6][6] {
{"NotSent", "NotSent", "Probe-1", "80", "65"},
{"NotSent", "NotSent", "Probe-2", "80", "65"},
{"NotSent", "NotSent", "Probe-3", "80", "65"},
{"NotSent", "NotSent", "Probe-4", "80", "65"},
{"NotSent", "NotSent", "Probe-5", "85", "50"},
{"NotSent", "NotSent", "Probe-6", "80", "65"}
};
void alarmCheck() {
sensors.requestTemperatures();
for(alarmCheckCounter = 0; alarmCheckCounter <= tempSensorCount; alarmCheckCounter++) {
temperatureF = roundf(sensors.getTempFByIndex(alarmCheckCounter));
if(temperatureF > (tempSetPoints = tempProbeInfo[alarmCheckCounter][3].toInt())) {
if(tempProbeInfo[alarmCheckCounter][0] == "NotSent") {
String htmlMsg = "<div><h2>" + tempProbeInfo[alarmCheckCounter][2] + "</h2></br><h1><em>The temperature is too high!<em></h1></br><h1>" + temperatureF + "</h1></div>";
message.html.content = htmlMsg.c_str();
message.subject = tempProbeInfo[alarmCheckCounter][2];
sendEmail();
tempProbeInfo[alarmCheckCounter][0] = "Sent";
}
}
else if(temperatureF < (tempSetPoints = tempProbeInfo[alarmCheckCounter][4].toInt())) {
if(tempProbeInfo[alarmCheckCounter][1] == "NotSent") {
String htmlMsg = "<div><h2>" + tempProbeInfo[alarmCheckCounter][2] + "</h2></br><h1><em>The temperature is too low!<em></h1></br><h1>" + temperatureF + "</h1></div>";
message.html.content = htmlMsg.c_str();
message.subject = tempProbeInfo[alarmCheckCounter][2];
sendEmail();
tempProbeInfo[alarmCheckCounter][1] = "Sent";
}
}
else {
if(tempProbeInfo[alarmCheckCounter][0] == "Sent") {
String htmlMsg = "<div><h2>" + tempProbeInfo[alarmCheckCounter][2] + "</h2></br><h1><em>The temperature is normal<em></h1></br><h1>" + temperatureF + "</h1></div>";
message.html.content = htmlMsg.c_str();
message.subject = tempProbeInfo[alarmCheckCounter][2];
sendEmail();
tempProbeInfo[alarmCheckCounter][0] = "NotSent";
}
if(tempProbeInfo[alarmCheckCounter][1] == "Sent") {
String htmlMsg = "<div><h2>" + tempProbeInfo[alarmCheckCounter][2] + "</h2></br><h1><em>The temperature is normal<em></h1></br><h1>" + temperatureF + "</h1></div>";
message.html.content = htmlMsg.c_str();
message.subject = tempProbeInfo[alarmCheckCounter][2];
sendEmail();
tempProbeInfo[alarmCheckCounter][1] = "NotSent";
}
}
}
alarmCheckDelay = millis();
}
void setup() {
Serial.begin(115200);
wifiConnect();
sensors.begin();
tempSensorCount = sensors.getDeviceCount() - 1;
eMailConnect();
}
void loop() {
if(millis() >= (alarmCheckDelay + (oneMinute * 6))) {
alarmCheck();
}
}