How to avoid delay(1) in reading serial data

While using delay(1) in reading serial data from A9G GSM, there is a delay of 6-7 seconds while reading the full HTTP response.
If I completely disable it, then the data is not printing properly and sometimes gives error.
Can someone help on how to avoid this delay(1) and use something else instead of this.
My objective is to read data from GSM module every 1 or 2 second.

Below is the Send Data:

String sendData(String command, const int timeout, boolean debug)
{
  String response = "";
  Serial.print("Command Sent: "); Serial.println(command);
  A9G.println(command);

  while (A9G.available() == 0) {}

  unsigned long time = millis();
  while (millis() - time < timeout)
  {
    delay(100);
    if (A9G.available())
    {
      while (A9G.available())
      {
        char c = A9G.read();
        response += c;
        //    Serial.print(c);
        delay(1);
      }
      break;
    }
  }
if (debug)
{
  Serial.println();
  Serial.print("A9G Response: ");
  Serial.println(response);
}

if (response.indexOf('{') > 0) {
  int l = response.indexOf('{');
  String res = response.substring(l);
  //    Serial.println(res);
  Serial.println("Test");
  response = res;
}
return response;
}

Below is the Serial Monitor Output with Delay(1):

13:26:03.512 -> Command Sent: AT+HTTPGET="http://apk.vehtechs.com/api/imei?imei=123456789456789"
13:26:10.375 ->
13:26:10.375 -> A9G Response:
13:26:10.375 -> OK
13:26:10.375 -> HTTP/1.1 200 OK
13:26:10.375 -> date: Sat, 05 Mar 2022 09:26:03 GMT
13:26:10.375 -> content-type: text/html; charset=UTF-8
13:26:10.375 -> transfer-encoding: chunked
13:26:10.375 -> vary: Accept-Encoding
13:26:10.375 -> server: Apache
13:26:10.375 -> x-powered-by: PHP/7.4.28
13:26:10.375 -> cache-control: no-cache, private
13:26:10.375 -> access-control-allow-origin: *
13:26:10.375 -> access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS
13:26:10.375 -> x-ratelimit-limit: 60
13:26:10.375 -> x-ratelimit-remaining: 59
13:26:10.375 -> x-provided-by: StackCDN
13:26:10.375 -> vary: Accept-Encoding
13:26:10.375 -> x-origin-cache-status: MISS
13:26:10.375 -> x-service-level: standard
13:26:10.375 -> x-backend-server: web6.hosting.stackcp.net
13:26:10.422 -> x-cdn-cache-status: MISS
13:26:10.422 -> x-via: LHR4
13:26:10.422 -> Content-Length: 262
13:26:10.422 ->
13:26:10.422 -> {"isArm":"1","wifi":"0","wifi_password":"","wifi_connssid":"0","wifi_disconnect":0,"wifi_disc_name":"","engine":1,"phoneNumber":"542351685","number1":"","number2":"","number3":"","number4":"","number5":"","gyro":"0","gps":"1","powerSupply":"1","plateNo":"32568"}
13:26:10.422 ->
13:26:10.422 -> Test
13:26:10.422 -> GPRS Data
13:26:10.422 -> isArm= 1
13:26:10.422 -> wifi= 0
13:26:10.422 -> wifi_password=
13:26:10.422 -> wifi_connssid= 0
13:26:10.422 -> wifi_disconnect= 0
13:26:10.422 -> wifi_disc_name=
13:26:10.422 -> engine= 1
13:26:10.422 -> phoneNumber= 542351685
13:26:10.422 -> number1=
13:26:10.422 -> number2=
13:26:10.469 -> number3=
13:26:10.469 -> number4=
13:26:10.469 -> number5=
13:26:10.469 -> gyro= 0
13:26:10.469 -> gps= 1
13:26:10.469 -> powerSupply= 1
13:26:10.469 -> plateNo= 32568

Below is the Serial Monitor Output without Delay(1):

13:12:54.587 -> Command Sent: AT+HTTPGET="http://apk.vehtechs.com/api/imei?imei=123456789456789"
13:12:54.727 ->
13:12:54.727 -> A9G Response: oneNumber":"542351685","number1":"","number2":"","number3":"","number4":"","number5":"","gyro":"0","gps":"1","powerSupply":
13:12:54.727 -> GPRS Data
13:12:54.727 -> deserializeJson() failed: InvalidInput
13:12:54.727 -> Command Sent: AT+HTTPGET="http://apk.vehtechs.com/api/imei?imei=123456789456789"
13:12:54.820 ->
13:12:54.820 -> A9G Response: "1","plateNo":"32568"}
13:12:54.820 -> HTTP/1.1 200 OK
13:12:54.820 -> date: Sat, 05 Mar 2022 09:12:43 GMT
13:12:54.820 -> content-type: text/html; charse
13:12:54.820 -> GPRS Data
13:12:54.820 -> isArm=
13:12:54.820 -> wifi=
13:12:54.820 -> wifi_password=
13:12:54.820 -> wifi_connssid=
13:12:54.820 -> wifi_disconnect= 0
13:12:54.820 -> wifi_disc_name=
13:12:54.820 -> engine= 0
13:12:54.820 -> phoneNumber=
13:12:54.820 -> number1=
13:12:54.820 -> number2=
13:12:54.820 -> number3=
13:12:54.820 -> number4=
13:12:54.820 -> number5=
13:12:54.820 -> gyro=
13:12:54.820 -> gps=
13:12:54.820 -> powerSupply=
13:12:54.820 -> plateNo=

Never wait.
The other option is to use a multitasking system. For example the ESP32 and the Raspberry Pi Pico already have a multitasking system running. For the Arduino MKR Zero (and similar boards) there is a Arduino Schedular that switches a task during a delay.

If you have a basic Arduino board, then never wait. Do not wait in a while-statement for something. Read serial data as soon as it arrives. Put it in a buffer. Process the data when a complete command is received.

void loop()
{
  if( A9G.available() > 0)
  {
    byte data = (byte) A9G.read();
    buffer[index] = data;
    index++;

    if a complete command is received, then
      process_the_command();
  }
}
1 Like

Hi, thanks. I m using ESP32.
Can you provide a complete example of this task how to do it.

Thank you

The serial input basics tutorial may be of interest.

Here is how I receive serial on a ESP32. No delay(1) needed.

void fReceiveSerial_LIDAR( void * parameters  )
{
  bool BeginSentence = false;
  sSerial.reserve ( StringBufferSize300 );
  char OneChar;
  for ( ;; )
  {
    EventBits_t xbit = xEventGroupWaitBits (eg, evtReceiveSerial_LIDAR, pdTRUE, pdTRUE, portMAX_DELAY);
    if ( LIDARSerial.available() >= 1 )
    {
      while ( LIDARSerial.available() )
      {
        OneChar = LIDARSerial.read();
        if ( BeginSentence )
        {
          if ( OneChar == ‘>’)
          {
            if ( xSemaphoreTake( sema_ParseLIDAR_ReceivedSerial, xSemaphoreTicksToWait10 ) == pdTRUE )
            {
              xQueueOverwrite( xQ_LIDAR_Display_INFO, ( void * ) &sSerial );
              xEventGroupSetBits( eg, evtParseLIDAR_ReceivedSerial );
              //
            }
            BeginSentence = false;
            break;
          }
          sSerial.concat ( OneChar );
        }
        else
        {
          if ( OneChar == ‘<’ )
          {
            sSerial = “”; // clear string buffer
            BeginSentence = true; // found begining of sentence
          }
        }
      } //  while ( LIDARSerial.available() )
    } //if ( LIDARSerial.available() >= 1 )
    xSemaphoreGive( sema_ReceiveSerial_LIDAR );
  }
  vTaskDelete( NULL );
} //void fReceiveSerial_LIDAR( void * parameters  )

Here is how I send serial with an ESP32.

void fSendSerialToBrain( void *pvParameters )
{
  struct stu_LIDAR_INFO pxLIDAR_INFO;
  xSemaphoreGive ( sema_SendSerialToBrain );
  String sSerial;
  sSerial.reserve ( 300 );
  for (;;)
  {
    xEventGroupWaitBits (eg, evtSendSerialToBrain, pdTRUE, pdTRUE, portMAX_DELAY);
    // Serial.println ( " fSendSerialToBrain " );
    if ( xSemaphoreTake( sema_SendSerialToBrain, xZeroTicksToWait ) == pdTRUE ) // grab semaphore, no wait
    {
      int CellCount = 1;
      xSemaphoreTake( sema_LIDAR_INFO, xSemaphoreTicksToWait );
      xQueueReceive ( xQ_LIDAR_INFO, &pxLIDAR_INFO, QueueReceiveDelayTime );
      xSemaphoreGive( sema_LIDAR_INFO );
      sSerial.concat( "<!," ); //sentence begin
      sSerial.concat( String(ScanPoints) + "," );
      for ( CellCount; CellCount <= ScanPoints; CellCount++ )
      {
        sSerial.concat( String(pxLIDAR_INFO.Range[CellCount]) + "," );
      }
      sSerial.concat( ">" ); //sentence end
      // Serial.println ( sSerial );
      SerialBrain.println ( sSerial );
      //      ////
      //      xEventGroupSetBits( eg, evtSendLIDAR_Info_For_ALARM );
      //      xSemaphoreGive ( sema_SendSerialToBrain );
      sSerial = "";
    }
  }
  vTaskDelete( NULL );
} // void fSendSerialToBrain( void *pvParameters )

no delay needed

Actually A9G intenally print the 1st character of response after 6 seconds when the HTTPGET command is sent to A9G. Any solution about that?

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