Help multiple timing with millis() - Handling 3 functions run simultaneously

I want to create a simple alert from several sensors, integrated with Telegram and Thingspeak. So, this code is handling 3 functions that run simultaneously, that's why I use millis(). Based on the https://forum.arduino.cc/t/demonstration-code-for-several-things-at-the-same-time/217158/2 I made a simple code to handle timing loops without adding any action but printing on serial monitor and it can work properly. here is the simple code.

The problem is when I add some code to the timing loops to read the sensor, handle telegram messages, and send data to Thingspeak. it has a delay that's not what I intended to do and didn't occur on the sample code above.
here is my code :

const unsigned long interval = 1000;
const unsigned long readinterval = 1000; 
const unsigned long sendinterval = 20000;

unsigned long currentMillis = 0;    
unsigned long SensorReadMillis = 0;   
unsigned long last_call = 0;
unsigned long last_sendmillis = 0;


WiFiSSLClient securedClient;
WiFiClient  client;

UniversalTelegramBot bot(BOT_API_TOKEN, securedClient);


void handleMessages(int num_new_messages) {
  for (int i = 0; i < num_new_messages; i++) {

    message_id = bot.messages[i].message_id;
    chat_id = bot.messages[i].chat_id;
    String text = bot.messages[i].text;
    from_name = bot.messages[i].from_name;


    if (from_name == "") {
      from_name = "Unknown";
    }

    if (text == "/start") {

      bot.sendMessage(chat_id, "Haloo " + (from_name == "Unknown" ? "" : from_name) + ", Welcome", "");


    } else if (text == "/status"){
      togglestatus();
    }


    Serial.println(from_name);
    Serial.println(chat_id);
    Serial.println(text);
  }
}

void setup() {

  Serial.begin(115200);


  pinMode(buzzer, OUTPUT);
  lcd1.init();
  lcd2.init();
  lcd1.backlight();
  lcd2.backlight();
  ThingSpeak.begin(client);
  initflame();
  initdht11();
  initmq2();
  connectToWiFi();

  Serial.print("WiFi connected. IP Address: ");
  Serial.println(WiFi.localIP());

}

void loop() {
  currentMillis = millis();

  readmessage();
  deteksi();
  lcdscreen();
  senddata();

}


void readmessage(){
    if (currentMillis - last_call > interval) {
    int num_new_messages = bot.getUpdates(bot.last_message_received + 1);
    while (num_new_messages) {
      Serial.println("Message received");
      handleMessages(num_new_messages);
      num_new_messages = bot.getUpdates(bot.last_message_received + 1);
    }


    last_call = millis();
  } 
}

void deteksi(){
  flamedetected=readFLAME();
  smokedetected=readSMOKE();
  if (currentMillis - SensorReadMillis >= readinterval) {
    if (flamedetected==LOW){
    bot.sendMessage(chat_id, "Flame detected!!", "");
    Serial.println("flame");
    tone(buzzer, 300, 3000);
  } else if (smokedetected==HIGH){
    bot.sendMessage(chat_id, "Smoke detected!!", "");
    Serial.println("Smoke");
    tone(buzzer, 200, 3000);
  } else if (suhucelsius() > batassuhu){
    bot.sendMessage(chat_id, "Suhu melebihi batas!", "");
  
  }
  else {
    noTone(buzzer);
  }
  SensorReadMillis = millis();
  }

}

void senddata(){
  if (currentMillis - last_sendmillis >= sendinterval){
    ThingSpeak.setField(1, suhucelsius());
  ThingSpeak.setField(2, kelembapan());
  ThingSpeak.setField(3, mq2value());
  ThingSpeak.setField(4, readFLAME());
  
  // write to the ThingSpeak channel
  int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
  Serial.println(x);
  if(x == 200){
    Serial.println("Channel update successful.");
  }
  else{
    Serial.println("Problem updating channel. HTTP error code " + String(x));
  }
  last_sendmillis = millis();

  }
  
}

My expected timing in each function is 1 sec for handling telegram, 1 sec for reading sensor, and 20 sec for sending data to thingspeak. this current code has an unexpected delay around 20 sec for readingsensor. is there any mistake on my code?

thanks in advance for your help.

We have a saying on this forum: The problem is in the part that you are not showing.

Where are the readFLAME(), readSMOKE() and lcdscreen() functions ? We have to see the complete code.

Do you know that you call the readFLAME() and readSMOKE() functions every time the loop() runs ?

The tone() function can be used with and without the parameter 'duration'. You use a duration of 3 seconds. That means that the code has a delay of 3 seconds.

Perhaps a online server slows it down, because you call it too often.

here is the full code :

#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"
#include <WiFiS3.h>
#include <WiFiSSLClient.h>
#include <UniversalTelegramBot.h>
#include "dht11ta.h"
#include "flameta.h"
#include "mq2ta.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ThingSpeak.h>

#define buzzer 4
#define MAX_Y 8
#define MAX_X 12
bool flamedetected = false;
bool smokedetected = false;
ArduinoLEDMatrix matrix;
LiquidCrystal_I2C lcd1(0x26 , 16, 2);
LiquidCrystal_I2C lcd2(0x27 , 16, 2);
uint8_t grid[MAX_Y][MAX_X] = {
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
};

unsigned long myChannelNumber = 123456;
const char * myWriteAPIKey = "XXXXXXXXXXXX";

#define WIFI_SSID "wifi"
#define WIFI_PASSWORD "11111111"

#define BOT_API_TOKEN "12345:XXXXXXXXXXXXXX"

float batassuhu = 30.00;
String chat_id = "";
int message_id = -1;
String from_name = "Unknown";

const unsigned long interval = 1000;
const unsigned long readinterval = 1000; 
const unsigned long sendinterval = 20000;

unsigned long currentMillis = 0;   
unsigned long SensorReadMillis = 0;   
unsigned long last_call = 0;
unsigned long last_sendmillis = 0;


WiFiSSLClient securedClient;
WiFiClient  client;

UniversalTelegramBot bot(BOT_API_TOKEN, securedClient);

String inlineKeyboardJson = "";

void handleMessages(int num_new_messages) {
  for (int i = 0; i < num_new_messages; i++) {

    message_id = bot.messages[i].message_id;
    chat_id = bot.messages[i].chat_id;
    String text = bot.messages[i].text;
    from_name = bot.messages[i].from_name;


    if (from_name == "") {
      from_name = "Unknown";
    }

    if (text == "/start") {
      bot.sendMessage(chat_id, "Haloo " + (from_name == "Unknown" ? "" : from_name) + ", Welcome", "");


    } else if (text == "/status"){
      togglestatus();
    }


    Serial.println(from_name);
    Serial.println(chat_id);
    Serial.println(text);
  }
}

void setup() {

  Serial.begin(115200);


  pinMode(buzzer, OUTPUT);
  lcd1.init();
  lcd2.init();
  lcd1.backlight();
  lcd2.backlight();
  ThingSpeak.begin(client);


  matrix.begin();


  initflame();
  initdht11();
  initmq2();


  connectToWiFi();

  Serial.print("WiFi connected. IP Address: ");
  Serial.println(WiFi.localIP());


  matrix.beginDraw();
  matrix.stroke(0xFFFFFFFF);
  const char text[] = "ON";
  matrix.textFont(Font_4x6);
  matrix.beginText(0, 1, 0xFFFFFF);
  matrix.println(text);
  matrix.endText();
  matrix.endDraw();
}

void loop() {
  currentMillis = millis();

  readmessage();
  deteksi();
  lcdscreen();
  senddata();

  



}

void connectToWiFi() {
  Serial.println();
  Serial.print("Connecting to WiFi network ");
  Serial.println(WIFI_SSID);

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  securedClient.setCACert(TELEGRAM_CERTIFICATE_ROOT);

  byte i = 0, j = 0, dir = 1;

  while (WiFi.status() != WL_CONNECTED) {
    grid[i][j] = !grid[i][j];
    j += dir;
    if (j > 11 || j < 0) {
      dir *= -1;
      j += dir;
      i++;
    }
    if (i > 7) {
      i = 0;
      if (dir == 1) {
        dir = -1;
        j = 11;
      } else {
        dir = 1;
        j = 0;
      }
    }
    matrix.renderBitmap(grid, 8, 12);
    delay(100);
  }
}


void togglestatus(){
  bot.sendMessage(chat_id, "Suhu : " + String(suhucelsius()) + "°C\ Kelembaban : " + String(kelembapan()) + "%", "");
  bot.sendMessage(chat_id, "Api : " + String(readFLAME() ? "tidak terdeteksi api" : "terdeteksi panas api!!") , "");
  bot.sendMessage(chat_id, "Asap : " + String(readSMOKE() ? "terdeteksi ada asap!!" : "tidak ada asap") , "");
}
void readmessage(){
    if (currentMillis - last_call > interval) {

    int num_new_messages = bot.getUpdates(bot.last_message_received + 1);
    while (num_new_messages) {
      Serial.println("Message received");
      handleMessages(num_new_messages);
      num_new_messages = bot.getUpdates(bot.last_message_received + 1);
    }


    last_call = millis();
  } 
}
void lcdscreen(){
  lcd1.setCursor(0, 0);
  lcd1.print("Suhu :");
  lcd1.setCursor(9, 0);
  lcd1.print(String(suhucelsius()) + " C");
  lcd1.setCursor(0, 1);
  lcd1.print("Klmbpn :");
  lcd1.setCursor(9, 1);
  lcd1.print(String(kelembapan()) + " %");
  lcd2.setCursor(0, 0);
  lcd2.print("Api :");
  lcd2.setCursor(7, 0);
  lcd2.print(String(readFLAME() ? "tidak ada" : "ada api!!"));
  lcd2.setCursor(0, 1);
  lcd2.print("Asap :");
  lcd2.setCursor(7, 1);
  lcd2.print(String(readSMOKE() ? "ada asap!!" : "tidak ada"));
}
void deteksi(){
  flamedetected=readFLAME();
  smokedetected=readSMOKE();
  Serial.println(mq2value());
  if (currentMillis - SensorReadMillis >= readinterval) {
    if (flamedetected==LOW){
    bot.sendMessage(chat_id, "Flame detected!!", "");
    Serial.println("flame");
    tone(buzzer, 300, 3000);
  } else if (smokedetected==HIGH){
    bot.sendMessage(chat_id, "Smoke detected!!", "");
    Serial.println("Smoke");
    tone(buzzer, 200, 3000);
  } else if (suhucelsius() > batassuhu){
    bot.sendMessage(chat_id, "Suhu melebihi batas!", "");
  
  }
  else {
    noTone(buzzer);
  }
  SensorReadMillis = millis();
  }

}

void senddata(){
  if (currentMillis - last_sendmillis >= sendinterval){
    ThingSpeak.setField(1, suhucelsius());
  ThingSpeak.setField(2, kelembapan());
  ThingSpeak.setField(3, mq2value());
  ThingSpeak.setField(4, readFLAME());
  Serial.println(suhucelsius());
  
  // write to the ThingSpeak channel
  int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
  Serial.println(x);
  if(x == 200){
    Serial.println("Channel update successful.");
  }
  else{
    Serial.println("Problem updating channel. HTTP error code " + String(x));
  }
  last_sendmillis = millis();

  }
  
}

mq2ta.h

2024-03-13 16_03_06-Window
flameta.h
2024-03-13 16_03_18-Window
dht11ta.h
2024-03-13 16_03_39-Window

readFLAME() and readSMOKE() is a function to read data from the sensor, yes I call it on every time the loops run because the project needs to detect if there is a smoke or a fire near the sensor.

at first, I didn't add the tone duration, but if that was so, the buzzer kept beeping and did not stop until the sensor changed its value.

this is my full code if you need to review it:
full code
thanks in advance

If you give a tone() without duration, then you have to call noTone() to stop it. You can use a millis-timer for that.
Have you told which Arduino board you use ?
I can not compile your code or run it in a simulator to find out how long everything takes.
Can you add timing measurements ?

For example:

Serial.print("bot.SendMessage takes ");
unsigned long t1 = millis();

bot.sendMessage(...           // the code to be measured

unsigned long t2 = millis();
unsigned long elapsedMillis = t2 - t1;
Serial.print(elapsedMillis);
Serial.println(" ms");

If you use a ESP32, then it might be possible to simulate your project in the Wokwi simulator.

I am using Arduino Uno R4 Wifi, I have tried to cut the buzzer duration for only 1000ms and still have the same issue, the readsensor still has a delay around 20 seconds, maybe the issue is not on this section of the code. What I'm expected from the code is the buzzer beep everytime the sensor has "true" value and it will stop after "false" but it still need 20 sec to update the current value of the sensor. the interval is similar with my millis() for thingspeak send data, is there any relation about this issue?

I changed the thingspeak send data interval to 40 sec, but the deteksi() still has 20 sec delay, It has nothing to do with thingspeak

Please don't post screenshots of code; you can add files as separate code blocks in one post.

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