Updating Screen while another function runs

Hello,

Posted several times on other topics. Managed to get it fixed couple of times here and have done more improvements to my own project.

However, I have realised that my screen would not be updating for 20seconds due to it entering the function. Currently, I cant seem to think of an idea that will allow the screen to actively refresh as the function is running.

The code is below :

#include <M5Stack.h>
#include <M5LoRa.h>
#include "ThingSpeak.h"
#include "secrets.h"
#include <WiFi.h>

char ssid[] = SECRET_SSID;   // your network SSID (name) 
char pass[] = SECRET_PASS;   // your network password
int keyIndex = 0;            // your network key Index number (needed only for WEP)
WiFiClient  client;

unsigned long myChannelNumber = SECRET_CH_ID;
const char * myWriteAPIKey = SECRET_WRITE_APIKEY;

int number1 = 0;
int number2 = 0;
int number3 = 0;
int number4 = 0;

String outgoing;              // outgoing message

byte msgCount = 0;            // count of outgoing messages
byte localAddress = 0xFF;     // address of this device
byte destination = 0xBB;      // destination to send to

long lastSendTime = 0;        // last send time
int interval = 1000;          // interval between sends

float humidflt;
//float tempfltupl;
float pressureflt;
float tempflt;

/*const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];

char messageFromPC[numChars] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;*/

String incoming;

void setup() {

  Serial.begin(115200);  //Initialize serial

  WiFi.mode(WIFI_STA);   
  ThingSpeak.begin(client);  // Initialize ThingSpeak
  
  M5.begin();
  while (!Serial);

  Serial.println("LoRa Duplex B");

      // Connect or reconnect to WiFi
  if(WiFi.status() != WL_CONNECTED){
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(SECRET_SSID);
    while(WiFi.status() != WL_CONNECTED){
      WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network. Change this line if using open or WEP network
      Serial.print(".");
      delay(5000);     
    } 
    Serial.println("\nConnected.");
    M5.Lcd.print("Connected");
    M5.Lcd.clear(BLACK);
  }

  // override the default CS, reset, and IRQ pins (optional)
  LoRa.setPins();// set CS, reset, IRQ pin

  if (!LoRa.begin(433E6)) {             // initialize ratio at 915 MHz
    Serial.println("LoRa init failed. Check your connections.");
    while (true);                       // if failed, do nothing
  }

  Serial.println("LoRa init succeeded.");
}

void loop() {
  
  if (millis() - lastSendTime > interval) {
    String message = "Data Received";   // send a message
    sendMessage(message);
    //Serial.println("Sending " + message);
    //M5.Lcd.setTextColor(BLUE);
    //M5.Lcd.println("Sending \r" + message);
    lastSendTime = millis();            // timestamp the message
    interval = random(1000) + 500;    // 2-3 seconds
  }

  // parse for a packet, and call onReceive with the result:
  onReceive(LoRa.parsePacket());

  if(M5.BtnA.wasPressed()){
    M5.Lcd.setCursor(0, 0);
    M5.Lcd.clear(BLACK);
  }

  if(M5.BtnB.wasPressed()){
    reinit();
  }

  M5.update();
}

void reinit(){
  Serial.println("LoRa Duplex Reinitialization");

  // override the default CS, reset, and IRQ pins (optional)
  LoRa.setPins();// set CS, reset, IRQ pin

  if (!LoRa.begin(433E6)) {             // initialize ratio at 915 MHz
    Serial.println("LoRa init failed. Check your connections.");
    M5.Lcd.setCursor(0, 0);
    M5.Lcd.setTextColor(RED);
    M5.Lcd.println("Init failed!!!");
    while (true);                       // if failed, do nothing
  }

  Serial.println("LoRa init succeeded.");
}

void sendMessage(String outgoing) {
  LoRa.beginPacket();                   // start packet
  LoRa.write(destination);              // add destination address
  LoRa.write(localAddress);             // add sender address
  LoRa.write(msgCount);                 // add message ID
  LoRa.write(outgoing.length());        // add payload length
  LoRa.print(outgoing);                 // add payload
  LoRa.endPacket();                     // finish packet and send it
  msgCount++;                           // increment message ID
}

void onReceive(int packetSize) {
  int counter = 0;
  if (packetSize == 0) return;          // if there's no packet, return

  // read packet header bytes:
  int recipient = LoRa.read();          // recipient address
  byte sender = LoRa.read();            // sender address
  byte incomingMsgId = LoRa.read();     // incoming msg ID
  byte incomingLength = LoRa.read();    // incoming msg length

  incoming = "";

  while (LoRa.available()) {
    incoming += (char)LoRa.read();
    counter++;
    M5.Lcd.setCursor(0,0);
    M5.Lcd.setTextColor(YELLOW, BLACK);
    M5.Lcd.setTextSize(2.5);
    

    if (counter == incomingLength)
    {
      //tempflt = incoming.toFloat();
      //Serial.println(incoming);
      int commaIndex = incoming.indexOf(',');
      int secondCommaIndex = incoming.indexOf(',', commaIndex + 1);
      //int finalIndex = incoming.IndexOf('\n', secondCommaIndex + 1);

      String temp = incoming.substring(0, commaIndex);
      String hum = incoming.substring(commaIndex + 1, secondCommaIndex);
      String pres = incoming.substring(secondCommaIndex + 1);

      float temperature = temp.toFloat();
      float humidity = hum.toFloat();
      float pressure = pres.toFloat();

      Serial.print("Temperature : ");
      Serial.println(temperature);
      Serial.print("Humidity : ");
      Serial.println(humidity);
      Serial.print("Pressure : ");
      Serial.println(pressure);

      M5.Lcd.printf("Temp: %2.1f \r\nHumi: %2.1f%%  \r\nPressure:%2.2fPa\r\n", temperature, humidity, pressure);

      ThingSpeak.setField(1, temperature);
      ThingSpeak.setField(2, humidity);
      ThingSpeak.setField(3, pressure);
      
      int x = ThingSpeak.writeFields(myChannelNumber,myWriteAPIKey);
      if(x == 200){
        Serial.println("Channel update successful.");
        //M5.Lcd.setCursor(0,50);
        //M5.Lcd.setTextSize(2.0);
        //M5.Lcd.printf("TMP Rcv2: %f \r", tempflt);
      }
      else{
        Serial.println("Problem updating channel. HTTP error code " + String(x));
      }
      delay(20000);
      
    }

  }
  
    
      // Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different
  // pieces of information in a channel.  Here, we write to field 1.
  

  if (incomingLength != incoming.length()) {   // check length for error
    Serial.println("error: message length does not match length");
    return;                             // skip rest of function
  }

  // if the recipient isn't this device or broadcast,
  if (recipient != localAddress && recipient != 0xFF) {
    Serial.println("This message is not for me.");
    return;                             // skip rest of function
  }

  // if message is for this device, or broadcast, print details:
  //Serial.println("Received from: 0x" + String(sender, HEX));
  //Serial.println("Sent to: 0x" + String(recipient, HEX));
  //Serial.println("Message ID: " + String(incomingMsgId));
  //Serial.println("Message length: " + String(incomingLength));
  //Serial.println("Message: " + incoming);
  Serial.println("RSSI: " + String(LoRa.packetRssi()));
  M5.Lcd.println("RSSI: " + String(LoRa.packetRssi()));
  //Serial.println("Snr: " + String(LoRa.packetSnr()));
  //Serial.println();

  /*M5.Lcd.setTextColor(YELLOW);
  M5.Lcd.println("Message: " + incoming);*/
}

Any help/ideas would be greatly appreciated! Thank you!

If you really need the 20 seconds wait in the middle of "the function" you're going to have to rewrite it to use millis() for the timing instead of delay().

There are lots of tutorials/examples of using millis(). Start with the BlinkWithoutDelay IDE example which might be enough for your particular case.

Steve

why do you have a 20 sec delay in onReceive()? don't you always want to process any received messages?

slipstick:
If you really need the 20 seconds wait in the middle of "the function" you're going to have to rewrite it to use millis() for the timing instead of delay().

There are lots of tutorials/examples of using millis(). Start with the BlinkWithoutDelay IDE example which might be enough for your particular case.

Will take a look in that. Thanks!

gcjr:
why do you have a 20 sec delay in onReceive()? don't you always want to process any received messages?

Yes. I do want to process any received messages at all times. However, I also need to upload data onto ThingSpeak, and that 20seconds is necessary for the upload to be successful.

Also have a look at:
Demonstration for several things at the same time

You should not be in one function for more than a fraction of a millisecond. Loop() should be going round thousands of times per second.