Using SIM800l - reading SMS killing rest of code because of delays

Hello gents,

I am trying to make a project with ARDUINO and SIM800l.

The whole system consist of 4 switches (each switch is responsible for ON/OFF external relay connected to Arduino board).
-When I press switch 1 it should turn relay 1 ON for 6 seconds. Relay should turn OFF after 6 seconds or when I press switch again.
-When I press switch 2 it should turn relay 2 ON for 8 seconds. Relay should turn OFF after 8 seconds or when I press switch again.
-When I press switch 3 it should turn relay 3 ON for 6 seconds. Relay should turn OFF after 6 seconds or when I press switch again.
-When I press switch 4 it should turn relay 4 ON for 7 seconds. Relay should turn OFF after 7 seconds or when I press switch again.

Additionally I have SIM800l, which should turn ON all relays simultaneously. Relay 1 should turn off after 6 seconds, relay 2 after 8 seconds, relay 3 after 6 seconds and relay 4 after 7 seconds.

The problem is my code. I belive delay() is killing it. When I am trying to switch ON relay by switch due to delay between if(mySerial.available()) brackets I am not able to switch it on.

#include <SoftwareSerial.h>
SoftwareSerial mySerial(11,12);  // (Rx,Tx  > Tx,Rx)

char incomingByte; 
String inputString;

const int buttonPinSyrena = 0;
const int buttonPinPompa = 1;
const int buttonPinOswietlenie = 2;
const int buttonPinWyciag = 3;

const int ledPinSyrena =  9;   
const int ledPinPompa =  10; 
const int ledPinOswietlenie =  5; 
const int ledPinWyciag = 6;  

const unsigned long periodSyrena = 6000;
const unsigned long periodPompa = 8000;
const unsigned long periodOswietlenie = 6000; 
const unsigned long periodWyciag = 7000; 

int buttonStateSyrena = 0;
int buttonStatePompa = 0;
int buttonStateOswietlenie = 0;
int buttonStateWyciag = 0;

unsigned long startMillisSyrena;
unsigned long currentMillisSyrena;

unsigned long startMillisPompa;
unsigned long currentMillisPompa;

unsigned long startMillisOswietlenie;
unsigned long currentMillisOswietlenie;

unsigned long startMillisWyciag;
unsigned long currentMillisWyciag;

boolean oldSwitchStateSyrena = LOW;
boolean newSwitchStateSyrena1 = LOW;
boolean newSwitchStateSyrena2 = LOW;
boolean newSwitchStateSyrena3 = LOW;
boolean LEDstatusSyrena = LOW;

boolean oldSwitchStatePompa = LOW;
boolean newSwitchStatePompa1 = LOW;
boolean newSwitchStatePompa2 = LOW;
boolean newSwitchStatePompa3 = LOW;
boolean LEDstatusPompa = LOW;

boolean oldSwitchStateOswietlenie = LOW;
boolean newSwitchStateOswietlenie1 = LOW;
boolean newSwitchStateOswietlenie2 = LOW;
boolean newSwitchStateOswietlenie3 = LOW;
boolean LEDstatusOswietlenie = LOW;

boolean oldSwitchStateWyciag = LOW;
boolean newSwitchStateWyciag1 = LOW;
boolean newSwitchStateWyciag2 = LOW;
boolean newSwitchStateWyciag3 = LOW;
boolean LEDstatusWyciag = LOW;

void setup() {

  // initialize the LED pin as an output:
  pinMode(ledPinSyrena, OUTPUT);
  pinMode(ledPinPompa, OUTPUT);
  pinMode(ledPinOswietlenie, OUTPUT);
  pinMode(ledPinWyciag, OUTPUT);

  pinMode(buttonPinSyrena, INPUT_PULLUP);
  pinMode(buttonPinPompa, INPUT_PULLUP);
  pinMode(buttonPinOswietlenie, INPUT_PULLUP);
  pinMode(buttonPinWyciag, INPUT_PULLUP); 

  digitalWrite(9, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(6, HIGH);
  
  Serial.begin(9600);
  mySerial.begin(9600);

  mySerial.println("AT+CMGF=1");
  delay(700);  
  mySerial.println("AT+CNMI=1,2,0,0,0");

}

void loop() {

  buttonStateSyrena = digitalRead(buttonPinSyrena);
  buttonStatePompa = digitalRead(buttonPinPompa);
  buttonStateOswietlenie = digitalRead(buttonPinOswietlenie);
  buttonStateWyciag = digitalRead(buttonPinWyciag);
  
    // SYRENA
    newSwitchStateSyrena1 = buttonStateSyrena;
    delay(1);
    newSwitchStateSyrena2 = buttonStateSyrena;
    delay(1);
    newSwitchStateSyrena3 = buttonStateSyrena;

    if (  (newSwitchStateSyrena1==newSwitchStateSyrena2) && (newSwitchStateSyrena1==newSwitchStateSyrena3) )
    {
        if ( newSwitchStateSyrena1 != oldSwitchStateSyrena ) 
        {
 
           // has the button switch been closed?
           if ( newSwitchStateSyrena1 == HIGH )
           {
               if ( LEDstatusSyrena == LOW ) { digitalWrite(9, HIGH);  LEDstatusSyrena = HIGH; } //zamiast 13 wpisac 9 po testach
               else                    { digitalWrite(9, LOW);   LEDstatusSyrena = LOW; startMillisSyrena = millis(); } //zamiast 13 wpisac 9 po testach
           }
           oldSwitchStateSyrena = newSwitchStateSyrena1;
        }  
    }
    if(LEDstatusSyrena == LOW)
    {
      currentMillisSyrena = millis();
      if(currentMillisSyrena - startMillisSyrena >= periodSyrena)
      {
        oldSwitchStateSyrena = LOW;
      }
    }  

    // POMPA
    newSwitchStatePompa1 = buttonStatePompa;
    delay(1);
    newSwitchStatePompa2 = buttonStatePompa;
    delay(1);
    newSwitchStatePompa3 = buttonStatePompa;

    if (  (newSwitchStatePompa1==newSwitchStatePompa2) && (newSwitchStatePompa1==newSwitchStatePompa3) )
    {
 
        if ( newSwitchStatePompa1 != oldSwitchStatePompa ) 
        {
 
           // has the button switch been closed?
           if ( newSwitchStatePompa1 == HIGH )
           {
               if ( LEDstatusPompa == LOW ) { digitalWrite(10, HIGH);  LEDstatusPompa = HIGH; } //zamiast 13 wpisac 10 po testach
               else                    { digitalWrite(10, LOW);   LEDstatusPompa = LOW; startMillisPompa = millis(); } //zamiast 13 wpisac 10 po testach
           }
           oldSwitchStatePompa = newSwitchStatePompa1;
        }  
    }
    if(LEDstatusPompa == LOW)
    {
      currentMillisPompa = millis();
      if(currentMillisPompa - startMillisPompa >= periodPompa)
      {
        oldSwitchStatePompa = LOW;
      }
    }    

    // OSWIETLENIE
    newSwitchStateOswietlenie1 = buttonStateOswietlenie;
    delay(1);
    newSwitchStateOswietlenie2 = buttonStateOswietlenie;
    delay(1);
    newSwitchStateOswietlenie3 = buttonStateOswietlenie;

    if (  (newSwitchStateOswietlenie1==newSwitchStateOswietlenie2) && (newSwitchStateOswietlenie1==newSwitchStateOswietlenie3) )
    {
 
        if ( newSwitchStateOswietlenie1 != oldSwitchStateOswietlenie ) 
        {
 
           // has the button switch been closed?
           if ( newSwitchStateOswietlenie1 == HIGH )
           {
               if ( LEDstatusOswietlenie == LOW ) { digitalWrite(5, HIGH);  LEDstatusOswietlenie = HIGH; }
               else                    { digitalWrite(5, LOW);   LEDstatusOswietlenie = LOW; startMillisOswietlenie = millis(); }
           }
           oldSwitchStateOswietlenie = newSwitchStateOswietlenie1;
        }  
    }
    if(LEDstatusOswietlenie == LOW)
    {
      currentMillisOswietlenie = millis();
      if(currentMillisOswietlenie - startMillisOswietlenie >= periodOswietlenie)
      {
        oldSwitchStateOswietlenie = LOW;
      }
    }  

    // WCYIAG
    newSwitchStateWyciag1 = buttonStateWyciag;
    delay(1);
    newSwitchStateWyciag2 = buttonStateWyciag;
    delay(1);
    newSwitchStateWyciag3 = buttonStateWyciag;

    // if all 3 values are the same we can continue
    if (  (newSwitchStateWyciag1==newSwitchStateWyciag2) && (newSwitchStateWyciag1==newSwitchStateWyciag3) )
    {
 
        if ( newSwitchStateWyciag1 != oldSwitchStateWyciag ) 
        {
 
           if ( newSwitchStateWyciag1 == HIGH )
           {
               if ( LEDstatusWyciag == LOW ) { digitalWrite(6, HIGH);  LEDstatusWyciag = HIGH; }
               else                    { digitalWrite(6, LOW);   LEDstatusWyciag = LOW; startMillisWyciag = millis(); }
           }
           oldSwitchStateWyciag = newSwitchStateWyciag1;
        }  
    }

    if(LEDstatusWyciag == LOW)
    {
      currentMillisWyciag = millis();
      if(currentMillisWyciag - startMillisWyciag >= periodWyciag)
      {
        oldSwitchStateWyciag = LOW;
      }
    }  

if(mySerial.available()){

        startDelay1 = millis();

  delay(30);
  
        while(mySerial.available()){
        incomingByte = mySerial.read();
        inputString += incomingByte; 
        }
  
  delay(30);      

        Serial.println(inputString);
        inputString.toUpperCase(); 

        if (inputString.indexOf("ON") > -1){
          if(LEDstatusSyrena == HIGH){oldSwitchStateSyrena = LOW;}
          if(LEDstatusPompa == HIGH){oldSwitchStatePompa = LOW;}
          if(LEDstatusOswietlenie == HIGH){oldSwitchStateOswietlenie = LOW;}
          if(LEDstatusWyciag == HIGH){oldSwitchStateWyciag = LOW;}
        }

  delay(20);
  
        if (inputString.indexOf("OK") == -1){
        mySerial.println("AT+CMGDA=\"DEL ALL\"");

        delay(1000);
        }

        inputString = "";
}



}

read the tutorials about millis()

I am using millis() in my code. It works good. But I have to deal with the communication between ARDUINO and SIM800l.

if(mySerial.available()){

        startDelay1 = millis();

  delay(30);
 
        while(mySerial.available()){
        incomingByte = mySerial.read();
        inputString += incomingByte;
        }
 
  delay(30);     

        Serial.println(inputString);
        inputString.toUpperCase();

        if (inputString.indexOf("ON") > -1){
          if(LEDstatusSyrena == HIGH){oldSwitchStateSyrena = LOW;}
          if(LEDstatusPompa == HIGH){oldSwitchStatePompa = LOW;}
          if(LEDstatusOswietlenie == HIGH){oldSwitchStateOswietlenie = LOW;}
          if(LEDstatusWyciag == HIGH){oldSwitchStateWyciag = LOW;}
        }

  delay(20);
 
        if (inputString.indexOf("OK") == -1){
        mySerial.println("AT+CMGDA=\"DEL ALL\"");

        delay(1000);
        }

        inputString = "";
}



}

When my program going through code shown above it is normal that not reacting for rest of code due to delay(). Is it possible to use interrupt ? I mean, when I receive a message then I jump to the code shown above, execute and jump out again and execute rest of code ?

with this code

 while(mySerial.available()){
        incomingByte = mySerial.read();
        inputString += incomingByte;
        }

you are not guaranteed to have read everything. Emptying the incoming buffer is a fast operation that goes faster that the pace at which new bytes arrive

adding delay(30); before starting reading helps a bit ensuring you have received some of the data but is not fool proof. (using String is not great either)

I would suggest to study Serial Input Basics to handle this in the right way

Thanks a lot.

Is it a chance that this will work ?

if(mySerial.available()){

    static byte ndx = 0;
    char endMarker = '\n';
    char rc;
   
    while (mySerial.available() > 0 && newData == false) {
        rc = mySerial.read();

        if (rc != endMarker) {
            receivedChars[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
            receivedChars[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }      

    if (newData == true) {
        mySerial.print("This just in ... ");
        mySerial.println(receivedChars);
        if (receivedChars == 'ON'){
          if(LEDstatusSyrena == HIGH){oldSwitchStateSyrena = LOW;}
          if(LEDstatusPompa == HIGH){oldSwitchStatePompa = LOW;}
          if(LEDstatusOswietlenie == HIGH){oldSwitchStateOswietlenie = LOW;}
          if(LEDstatusWyciag == HIGH){oldSwitchStateWyciag = LOW;}
        }        
        newData = false;
        mySerial.println("AT+CMGDA=\"DEL ALL\"");
    }

}

that's better because you'll wait to get everything but you end up being stuck in the while loop until you've received the end marker. Usually you put this code without the while in a function which you call from the loop and let the loop perform the 'while' for you. Once newData is true, then you know there is something to deal with.

Also you do this

   while (mySerial.available() > 0 && newData == false) {... }
if (newData == true) {...}

There is no need for testing if newData is true after the while since it's a mandatory condition to exit the while. if you get to that point, newData is definitely true.

Thanks. Something like this ?

if(mySerial.available()){

    static byte ndx = 0;
    char endMarker = '\n';
    char rc;
   
    if (mySerial.available() > 0 && newData == false) {

        mySerial.print("This just in ... ");
        mySerial.println(receivedChars);
        if (receivedChars == 'ON'){
          if(LEDstatusSyrena == HIGH){oldSwitchStateSyrena = LOW;}
          if(LEDstatusPompa == HIGH){oldSwitchStatePompa = LOW;}
          if(LEDstatusOswietlenie == HIGH){oldSwitchStateOswietlenie = LOW;}
          if(LEDstatusWyciag == HIGH){oldSwitchStateWyciag = LOW;}
              
        newData = false;
        mySerial.println("AT+CMGDA=\"DEL ALL\"");

        rc = mySerial.read();

        if (rc != endMarker) {
            receivedChars[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
            receivedChars[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }    

}

no :slight_smile:

not sure where that fits either. The tutorial shows you how to organize the code correctly with a function you call from the loop