Start alarm message of tone if event flag for period of time

Hello Everybody, and Happy New Year to all.

Would you please help me with my small project? I have a DS18b20 temperature sensor to monitor the temperature of the boiler cylinder. The boiler shall stop heating the water at 60 C, so when it is 60 C, the main switch will automatically turn off. However, the water's temperature will keep rising between 63-65 C for a few minutes because the elements are still hot. Sometimes the main switch fails to stop and the water keeps heating up. Would you please help me develop the sketch to start the buzzer alarm only if the sensor temperature is above 60 C for more than 15 min? Thank you

// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 4  on the Arduino
#define ONE_WIRE_BUS 4

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// arrays to hold device address
DeviceAddress insideThermometer;

void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");

  // locate devices on the bus
  Serial.print("Locating devices...");
  sensors.begin();
  Serial.print("Found ");
  Serial.print(sensors.getDeviceCount(), DEC);
  Serial.println(" devices.");

  // report parasite power requirements
  Serial.print("Parasite power is: "); 
  if (sensors.isParasitePowerMode()) Serial.println("ON");
  else Serial.println("OFF");
  if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0"); 
  
  Serial.print("Device 0 Address: ");
  printAddress(insideThermometer);
  Serial.println();

  sensors.setResolution(insideThermometer, 9);
 
  Serial.print("Device 0 Resolution: ");
  Serial.print(sensors.getResolution(insideThermometer), DEC); 
  Serial.println();
}

// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{

  float tempC = sensors.getTempC(deviceAddress);
  if(tempC == DEVICE_DISCONNECTED_C) 
  {
    Serial.println("Error: Could not read temperature data");
    return;
  }
  Serial.print("Temp C: ");
  Serial.print(tempC);
  Serial.print(" Temp F: ");
  Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
}
/*
 * Main function. It will request the tempC from the sensors and display on Serial.
 */
void loop(void)
{ 
  // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");
  
  // It responds almost immediately. Let's print out the data
  printTemperature(insideThermometer); // Use a simple function to print out the data
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}

Welcome to the forum

When the temperature becomes greater than 60 degrees (NOTE - not when it is greater than 60 degrees. See the StateChangeDetection example in the IDE), save the value of millis() as the start time

Each time through loop(), if the temperature is still greater than 60 degrees subtract the start time from the current value of millis(). If 15 minutes has passed then sound the buzzer

Hello

Here comes a pseudo code to be implemented:

if (temp>AlarmTemp and TimerIsNotStarted)  startTimer() 
if (temp<AlarmTemp) haltTimer(), haltBuzzer()
if (Timerexpired) startBuzzer()

Design a timer based on the BLINKWITHOUTDELAY example of the IDE. This example is the mother of all timers used inside the Arduino biotop.

Have a nice day and enjoy coding in C++.

1 Like

Hi @haypackup

welcome to the arduino-forum.

Well done posting code as a code-section in your very first posting.

This code seems to be an example-code taken from somewhere.
If you would have wrote this code yourself you would not ask such basic questions.
It is completely OK to be a beginner. Everybody here was a beginner in the past.

So I want to ask a few questions:

do you know what a variable in programming is?
do you know what an if-condition in programming is?

This is important information to adapt the answers to your knowledge-level.

I guess a high spohisticated answer like

"store actual value in a variable, compare this value with a limit-value
if above limit start a non-blocking timer
if temperature goes below limit stop timer
check if timer has more than 15 minutes if yes start beeping"

Is a bit too high for you.

Anyway: additionally to your microcontroller temperature alarm there should be a device that can shutoff the heating in a very direct way if temperature goes too high.
An emergency shutoff

Very direct way means:
There should be a thermo-switch that has solid mechanical contact to the boiler for high reliable temperature"-feeling"

The contact of this thermo-switch shall be normally closed if temperature is below limit and be in series with the temperature-regulator switch.

Be in series with the temperature-regulator is very important as the whole thing is switched off as soon as a wire is broken or for any reason there is no contact.

This will force the owner to repair it.

If you use a switch normally opened that should close in case of too high temperature this
way would not work with a broken wire.

It is the same with a microcontroller:
if measuring temperature must go through a microcontroller and the microcontroller is the one who switches off there are much more points where this system could fail compared to a direct thermo-switch.

An additional alarm is not a problem as a not given alarm combined with direct off-switching by thermo-switch still would work.

best regards Stefan

I do not understand why this long reply with much criticism and hardware recommendations. My code is quite long, with too many functions to control relays and take readings from different parts of the system. I made my inquiry very simple, with an example from the DS18b20 library, to seek help for only one part of the project.
The code connected with Blynk IoT to fire a notification when that event happens and it works very well, including some automation controls. I just need to fire that alarm after x minutes, not immediately.
Therefore, to avoid confusing others by posting about 500 lines of code, I deliberately ease it.
If the temperature has been above 60 C for more than x minutes,
do something. That's all.

Hi,
Why does your boiler heater main switch only work correctly sometimes?
I fail to why you need to modify your code, instead of fixing the main switch?
Apologies if I have missed the point of your question. It has been known.
Good luck..........

Thank you for your reply. As I explained earlier, that was as example. it is more complicated issue and the system has been upgraded to me under an automation system. During this upgrading progressing time, i need to build a very simple control to give me a notification if the event( tempC > 60 for x minute) that to make me investigate the problem of why the main switch is fail to cut off the power.

Have you tried adding some thinking to the pseudcode in @paulpaulson's #3 above?

I'll reiterate and expand on it since I have no life, and thought that the chatGPT AI might take a crack at figuring out his thinking. This is kinda straightforward once you get the hang of it. Perhaps you never had occasion to time anything.

@paulpaulson writes

if (temp>AlarmTemp and TimerIsNotStarted)  startTimer() 

if (temp<AlarmTemp) haltTimer(), haltBuzzer()

if (Timerexpired) startBuzzer()

And I used chatGPT to elaborate in English:

From a quiet pre-alarm state, where timeRunning is initially false…

  • If the temperature goes above 60 and the timer is not running, note the time. Set timerRunning true.

  • If the temperature goes below 60, reset the system. So stop the buzzer if it is buzzing, and set timerRunning false again.

  • If the timer has been active for the desired period (too long, danger Will Robinson!) turn on the buzzer. It's OK to keep turning on the buzzer, on is on it can't get any more on than that, so.

I added the thing about Will Robinson, ignore that if you are younger than, well, too young to remember him.

That's three if statements, and the implicit requirement is that those three statements be execute every time you loop the loop().

You can use millis() for timing. To start a "timer", save the value of millis(). To see how long such a timer has been running, get the current value of millis() and subtract the value it was when the timer started.

See "blink without delay" example in the IDE for one such use of millis() so you can see how to save and compare times procured by millis(), the number of milliseconds since the program started.

Since you did not provide your full code, we have to assume that you have a free running loop() function that achieves a reasonable fast repetition of those three statements over and over and over… your loop( ) is freely running, right? Without long blockages that woukd frustrate the logic?

HTH and enjoy converting @paulpaulson's ideas into C++. Let us know how it is going.

a7

OK, psych! I was kidding about chatGPT...

But I had some more time and energy. I am not a fan of writing code for people, so I helped chatGPT whip something up, for reals:

#include <stdio.h>
#include <time.h>

void check_alarm_condition(int alarm_condition) {
    static clock_t start_time;
    clock_t current_time;

    if (alarm_condition) {
        if (start_time == 0) {
            start_time = millis();  // Initialize start_time if it has not been set yet
        }

        current_time = millis();
        if ((current_time - start_time) > 60000) {  // 60000 milliseconds is equal to 10 minutes
            printf("Alarm condition has been true for 10 minutes\n");
            turnOnBuzzer();  // Turn on the buzzer
        }
    } else {
        start_time = 0;  // Reset start_time if the alarm condition is no longer true
        turnOffBuzzer();  // Turn off the buzzer
    }
}

chatGPT suggested calling this function from main

while (1) {
    check_alarm_condition(alarm_condition);
}

HTH and enjoy the future, where programming will be getting an AI to know WTF you mean. I started with

Please [sic] a function I can call frequently to check to see if an alarm condition has been true for a certain length of time. For knowing what time has elapsed, please use the function millis(), which is the number of milliseconds the program that will call this function has been running. Raise an alarm after 10 minutes.

a7

1 Like

I spotted something I didn't like, so I asked chatGPT for a tweak, viz:

One tiny more problem. Does it print, and turn on the buzzer repeatedly? I would like to turn the buzzer on just once and print the notification just once, when appropriate

and here's the revised code

#include <stdio.h>
#include <time.h>

void check_alarm_condition(int alarm_condition) {
    static clock_t start_time;
    static int alarm_raised;
    clock_t current_time;

    if (alarm_condition) {
        if (start_time == 0) {
            start_time = millis();  // Initialize start_time if it has not been set yet
        }

        current_time = millis();
        if ((current_time - start_time) > 60000 && !alarm_raised) {  // 60000 milliseconds is equal to 10 minutes
            printf("Alarm condition has been true for 10 minutes\n");
            turnOnBuzzer();  // Turn on the buzzer
            alarm_raised = 1;  // Set the flag to indicate that the alarm has been raised
        }
    } else {
        start_time = 0;  // Reset start_time if the alarm condition is no longer true
        alarm_raised = 0;  // Reset the flag if the alarm condition is no longer true
        turnOffBuzzer();  // Turn off the buzzer
    }
}

a7

1 Like

That sounds interesting.

Try this without using any additional libraries.

#include <OneWire.h>
#include <DallasTemperature.h>

unsigned long highTempTime;
unsigned long lastReadTime;  // Timestamp of the last time the analog input was read
unsigned long startMsgTime;
unsigned long lastMsgTime;
OneWire oneWire(2);
DallasTemperature sensors(&oneWire);
void setup() {
  Serial.begin(115200);
  sensors.begin();
}

void loop() {

  //sensors.requestTemperatures();  // request the temperature from the sensor
  float temperature = sensors.getTempCByIndex(0);  // get the temperature in Celsius
  Serial.println("Temperature= " + String(temperature));
  // Check if the temperature value is above the threshold
  if (temperature > 60.00) {
    highTempTime += millis() - lastReadTime;  // Increment by the time elapsed since the last reading
    lastReadTime = millis();                  // Update the last read time
                                              // Check if the counter variable has reached 15minutes (900,000 milliseconds)
    if (highTempTime >= 900000) {
      // Write your logic, for example print a message to the serial monitor
      Serial.println("High Temp");
    }
  } else {
    // Reset the counter variable if the  value falls below the threshold
    highTempTime = 0;
    lastReadTime = millis();  // Update the last read time

    // Write your logic, for example print a message to the serial monitor
    Serial.println("Normal state");
  }
}

It is also possible to avoid repeating sending an alarm or notification every cycle when your temperature becomes higher than the threshold by only sending it in a specific period, for example; if the temperature is above 60 for more than 15 min, print message every 5 min

#include <OneWire.h>
#include <DallasTemperature.h>
unsigned long highTempTime;
unsigned long lastReadTime;  // Timestamp of the last time the analog input was read
unsigned long startMsgTime;
unsigned long lastMsgTime;
OneWire oneWire(2);
DallasTemperature sensors(&oneWire);
void setup() {
  Serial.begin(115200);
    sensors.begin();

}

void loop() {
 sensors.requestTemperatures();  // request the temperature from the sensor
  float temperature = sensors.getTempCByIndex(0);  // get the temperature in Celsius
 Serial.println("Temperature= " + String(temperature));
  // Check if the analog value is above the threshold
  if (temperature > 60) {
    // Increment a counter variable
    Serial.println("Condition is True");
    highTempTime += millis() - lastReadTime;  // Increment by the time elapsed since the last reading
    lastReadTime = millis();  // Update the last read time

    // Check if the counter variable has reached 15 minutes (900,000 milliseconds)
    if (highTempTime >= 900000) {
      // Print a message to the serial monitor
     //startMsgTime = millis();

      if (millis() - lastMsgTime > 300000) {
      Serial.println("High Temperature= "+String(temperature));
      lastMsgTime = millis();

      }
      // Wait for 5 minutes before printing the message again
      //highCurrentTime += 5000;  // Increment the counter by 5 minutes
    }
  } else {
    // Reset the counter variable if the analog value falls below the threshold
    highTempTime = 0;
    lastReadTime = millis();  // Update the last read time

    // Print a message to the serial monitor
    Serial.println("Normal state, Temp= " + String(temperature));
  }
}

I tried the second sketch and it works.

1 Like

Thank you so much @HayderIsmael . That Sketch solved the whole problem even better than I expected.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.