2023年7月29日 星期六

ESP32 communicates with MEGA2560 through uart serial port

Purpose:

Serial data communication is a very popular communication protocol among different data communication. Data communication between ESP32 and Arduino can be done by serial communication. Most microcontrollers can transmit and receive data between them using UART communication.

In this project I have read some data from Arduino Mega TX1 and RX1 from ESP32 pin17 TX2 and pin16 RX2 serially using UART communication protocol.

Fundamental:

Serial communication

Used for communication between the Arduino board and a computer or other devices. All Arduino boards have at least one serial port (also known as a UART or USART), and some have several.

Mega, pins 0 and 1 are used for communication with the computer. Connecting anything to these pins can interfere with that communication, including causing failed uploads to the board.

You can use the Arduino environment’s built-in serial monitor to communicate with an Arduino board. Click the serial monitor button in the toolbar and select the same baud rate used in the call to begin().

In every Arduino board, there is at least one serial pin available. The pins are named TX and RX pins. TX stands for transmitting; RX stands for receive. 

In Arduino Mega, there are additional three serial pins. That means there are four serial communication pins available in Arduino Mega.

ESP32 Serial pins:

ESP32 boards also come with TX and RX pins. Depending on the model, the number of serial pins may vary.

Microcontroller boards like the "Arduino Mega" rely on the ATmega2560 microcontroller. It includes 54 digital input/output pins, of which 16 are analog inputs, 14 are used as PWM outputs, hardware serial port (UART) - 4, crystal oscillator - 16MHz, one ICSP header, one power supply jack, a USB connection, and the RST button. This board basically contains everything needed to support a microcontroller. Therefore, the board can be powered by connecting it to a PC via a USB cable, battery, or AC-DC adapter. By installing a backplane, the board can be protected from accidental discharges.

The SCL and SDA pins of the Mega 2560 R3 board are connected next to the AREF pin. Also, the two newest pins are located near the RST pin. One pin is IOREF, which allows the shield to set the voltage supplied by the Arduino board. The other pin is unassigned and will be reserved for future use. These boards can be used with any existing shield, but can accommodate the latest shields that use these extra pins.

圖一: Mega2560 pin definition
圖二:Mega2560 Specification
圖三: ESP32 功能方塊圖
圖四: ESP32 Pin Definition

Circuit:

圖五: 原理圖

圖六: 線路圖

Code Introduce:

ESP32

//--------- Flag structure --------------------------------------
typedef struct _vFlag
{
  uint8_t BTFlag = 0;
  uint8_t DC_Flag = 0;
  uint8_t CANFlag = 0;
  uint8_t I2C_Flag = 0;
  uint8_t BMP180Flag = 0;
  uint8_t JSONFlag = 0;
  uint8_t Radar_L_Flag = 0;
  uint8_t Radar_R_Flag = 0;
  uint8_t sensor_Flag = 0;
  uint8_t sensor1_Flag = 0;
  uint8_t initial_Flag = 0;
  uint8_t Tone_Flag = -1;
  uint8_t IR_RECV_Flag=0;
  uint8_t IR_SEND_Flag=0;
  uint8_t FunctionFlag = 3;
  uint8_t SendFlag = 0;
  uint8_t BMPCnt = 0;
} vFlag;
vFlag *flag_Ptr;
vFlag flag;
//----------uart--------------
#define RXD2 16
#define TXD2 17

#define LINE_BUFFER_LENGTH 128
//--------- uart structure --------------------------------------
typedef struct _vUart
{
  char c;
  int lineIndex = 0;
  int line1Index = 0;
  int BTlineIndex = 0;
  bool lineIsComment;
  bool lineSemiColon;
  char line[128];
  char line1[128];
  char BTline[20];
  String inputString;
  String BTinputString;
  String S1inputString;
  int V[16];
  char ctemp[30];
  char I2C_Data[80];
  int DC_Spped = 50;
  float Voltage[16];
  int Buffer[128];
  int StartCnt = 0;
  int ReadCnt = 0;
  int sensorValue = 0;
} vUart;
vUart *Uart_Ptr;
vUart Uart;

//-------------------------------------------------
void setup()
{
  Uart.inputString.reserve(60);
  Serial.begin(9600);
  Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2);
  Serial.println(F("init"));

}
//-----------------------------------------
void loop()
{
  Serial.print(F("Main at core:"));
  Serial.println(xPortGetCoreID());
  while(1)
  {
    while (Serial.available() > 0)
    {
      Uart.c = Serial.read();

      if ((Uart.c == '\n') || (Uart.c == '\r'))
      { // End of line reached
        if (Uart.lineIndex > 0)
        { // Line is complete. Then execute!
          Uart.line[Uart.lineIndex] = '\0'; // Terminate string
         
          Serial2.write(Uart.line);
          Serial2.write("\r\n");

          processCommand(Uart.line); // do something with the command

          Uart.lineIndex = 0;
          Uart.inputString = "";
        }
        else
        {
          // Empty or comment line. Skip block.
        }
        Uart.lineIsComment = false;
        Uart.lineSemiColon = false;
        Serial.println(F("ok>"));
      }
      else
      {
        //Serial.println( c );
        if ((Uart.lineIsComment) || (Uart.lineSemiColon))
        {
          if (Uart.c == ')')
            Uart.lineIsComment = false; // End of comment. Resume line.
        }
        else
        {
          if (Uart.c == '/')
          { // Block delete not supported. Ignore character.
          }
          else if (Uart.c == '~')
          { // Enable comments flag and ignore all characters until ')' or EOL.
            Uart.lineIsComment = true;
          }
          else if (Uart.c == ';')
          {
            Uart.lineSemiColon = true;
          }
          else if (Uart.lineIndex >= LINE_BUFFER_LENGTH - 1)
          {
            Serial.println("ERROR - lineBuffer overflow");
            Uart.lineIsComment = false;
            Uart.lineSemiColon = false;
          }
          else if (Uart.c >= 'a' && Uart.c <= 'z')
          { // Upcase lowercase
            Uart.line[Uart.lineIndex] = Uart.c - 'a' + 'A';
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += (char)(Uart.c - 'a' + 'A');
          }
          else
          {
            Uart.line[Uart.lineIndex] = Uart.c;
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += Uart.c;
          }
        }
      }
    } //while (Serial.available() > 0)
    while (Serial2.available() > 0)
    {
      Uart.c = Serial2.read();

      if ((Uart.c == '\n') || (Uart.c == '\r'))
      { // End of line reached
        if (Uart.lineIndex > 0)
        { // Line is complete. Then execute!
          Uart.line[Uart.lineIndex] = '\0'; // Terminate string
         
          processCommand(Uart.line); // do something with the command
          Serial.println(Uart.line);
         
          Uart.lineIndex = 0;
          Uart.inputString = "";
        }
        else
        {
          // Empty or comment line. Skip block.
        }
        Uart.lineIsComment = false;
        Uart.lineSemiColon = false;
        Serial.println(F("ok>"));
      }
      else
      {
        //Serial.println( c );
        if ((Uart.lineIsComment) || (Uart.lineSemiColon))
        {
          if (Uart.c == ')')
            Uart.lineIsComment = false; // End of comment. Resume line.
        }
        else
        {
          if (Uart.c == '/')
          { // Block delete not supported. Ignore character.
          }
          else if (Uart.c == '~')
          { // Enable comments flag and ignore all characters until ')' or EOL.
            Uart.lineIsComment = true;
          }
          else if (Uart.c == ';')
          {
            Uart.lineSemiColon = true;
          }
          else if (Uart.lineIndex >= LINE_BUFFER_LENGTH - 1)
          {
            Serial.println("ERROR - lineBuffer overflow");
            Uart.lineIsComment = false;
            Uart.lineSemiColon = false;
          }
          else if (Uart.c >= 'a' && Uart.c <= 'z')
          { // Upcase lowercase
            Uart.line[Uart.lineIndex] = Uart.c - 'a' + 'A';
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += (char)(Uart.c - 'a' + 'A');
          }
          else
          {
            Uart.line[Uart.lineIndex] = Uart.c;
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += Uart.c;
          }
        }
      }
    } //while (Serial2.available() > 0)
   

  }
}
//----------------------------------------
void processCommand(char *data)
{
  int len, xlen, ylen, zlen, alen;
  int tempDIO;
  String stemp;

  len = Uart.inputString.length();
  //---------------------------------------
  if (strstr(data, "VER") != NULL)
  {
    Serial.println(F("ESP32_SEARIAL_20230724"));
  }

}
//-----------------------------------------

Mega2560

#include <Arduino_FreeRTOS.h>
//---------------structure ----------------------------------------
//--------- Flag structure --------------------------------------
typedef struct _vFlag
{
  uint8_t LEDFlag=1;
  uint8_t BTFlag = 0;
  uint8_t ServoFlag = 0;
 
} vFlag;
vFlag *flag_Ptr;
vFlag flag;
//----------uart--------------
#define LINE_BUFFER_LENGTH 64
//--------- uart structure --------------------------------------
typedef struct _vUart
{
  char c;
  int lineIndex = 0;
  int line1Index = 0;
  int BTlineIndex = 0;
  bool lineIsComment;
  bool lineSemiColon;
  char line[128];
  char BTline[20];
  String inputString;
  String BTinputString;
  String S1inputString;
  int V[16];
  char ctemp[30];
  char I2C_Data[80];
  int DC_Spped = 50;
  float Voltage[16];
  int Buffer[128];
  int StartCnt = 0;
  int ReadCnt = 0;
  int sensorValue = 0;
} vUart;
vUart *Uart_Ptr;
vUart Uart;
//------------------------------------------------
const uint8_t LED_PIN = 13;
//----relay--------
uint8_t DIO_1 = 22;
uint8_t DIO_2 = 24;
uint8_t DIO_3 = 26;
uint8_t DIO_4 = 28;
uint8_t DIO_5 = 30;
uint8_t DIO_6 = 32;
uint8_t DIO_7 = 34;
uint8_t DIO_8 = 36;
//-------------------------------------------
char ctemp[20];
//------------------------------
TaskHandle_t hled;
TaskHandle_t huart0;
//------------------------------------------------------------------------------
void initial()
{
  Serial.println(F("Create Task"));
  //----------------------------------------------------------------------
  // create UART task
  xTaskCreate(vUARTTask, "UART Task", configMINIMAL_STACK_SIZE, NULL, 1, &huart0);
  // create blink task
  xTaskCreate(vLEDFlashTask, "LED Task", configMINIMAL_STACK_SIZE, NULL, 2, &hled);
 
  //-------------------------------------------------------------------

}
void setup()
{
  Uart.inputString.reserve(60);
  initial();
  Serial.begin(9600);
  Serial1.begin(115200);
  Serial.setTimeout(2000);
  Serial.println(F("init"));
  //-------------------------------------
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW); // Turn LED off.
  //---------------IO setting-----------------
  pinMode(DIO_1, INPUT);
  pinMode(DIO_2, INPUT);
  pinMode(DIO_3, INPUT);
  pinMode(DIO_4, INPUT);
  pinMode(DIO_5, INPUT);
  pinMode(DIO_6, INPUT);
  pinMode(DIO_7, INPUT);
  pinMode(DIO_8, INPUT);
 // start FreeRTOS
  Serial.println("Systom On!");
  vTaskStartScheduler();
  //if the scheduler start the code don't came here
  Serial.println(F("Die"));
  while (1)
    ;
}
//------------------------------------------------------------------------------
void loop()
{
 
}
//------------------------------------------------------------------------------
// high priority for blinking LED
void vLEDFlashTask(void *pvParameters)
{
  (void)pvParameters;

  pinMode(LED_PIN, OUTPUT);
  for (;;)
  {
    digitalWrite(LED_PIN, HIGH);                    // Turn LED on.
    vTaskDelay((150L * configTICK_RATE_HZ) / 1000L); // Sleep for 50 milliseconds.
    digitalWrite(LED_PIN, LOW);                      // Turn LED off.
    vTaskDelay((150L * configTICK_RATE_HZ) / 1000L); // Sleep for 150 milliseconds.
  }
}
//------------------------------------------------------------------------------
void vUARTTask(void *pvParameters)
{
  Uart.lineIsComment = false;
  Uart.lineSemiColon = false;

  while(1)
  {
    while (Serial.available() > 0)
    {
      Uart.c = Serial.read();

      if ((Uart.c == '\n') || (Uart.c == '\r'))
      { // End of line reached
        if (Uart.lineIndex > 0)
        { // Line is complete. Then execute!
          Uart.line[Uart.lineIndex] = '\0'; // Terminate string
           
          Serial1.write(Uart.line);
          Serial1.write("\r\n");

          processCommand(Uart.line); // do something with the command
                   
          Uart.lineIndex = 0;
          Uart.inputString = "";
        }
        else
        {
          // Empty or comment line. Skip block.
        }
        Uart.lineIsComment = false;
        Uart.lineSemiColon = false;
        Serial.println(F("ok>"));
      }
      else
      {
        //Serial.println( c );
        if ((Uart.lineIsComment) || (Uart.lineSemiColon))
        {
          if (Uart.c == ')')
            Uart.lineIsComment = false; // End of comment. Resume line.
        }
        else
        {
          if (Uart.c == '/')
          { // Block delete not supported. Ignore character.
          }
          else if (Uart.c == '~')
          { // Enable comments flag and ignore all characters until ')' or EOL.
            Uart.lineIsComment = true;
          }
          else if (Uart.c == ';')
          {
            Uart.lineSemiColon = true;
          }
          else if (Uart.lineIndex >= LINE_BUFFER_LENGTH - 1)
          {
            Serial.println("ERROR - lineBuffer overflow");
            Uart.lineIsComment = false;
            Uart.lineSemiColon = false;
          }
          else if (Uart.c >= 'a' && Uart.c <= 'z')
          { // Upcase lowercase
            Uart.line[Uart.lineIndex] = Uart.c - 'a' + 'A';
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += (char)(Uart.c - 'a' + 'A');
          }
          else
          {
            Uart.line[Uart.lineIndex] = Uart.c;
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += Uart.c;
          }
        }
      }
    } //while (Serial.available() > 0)
    while (Serial1.available() > 0)
    {
      Uart.c = Serial1.read();

      if ((Uart.c == '\n') || (Uart.c == '\r'))
      { // End of line reached
        if (Uart.lineIndex > 0)
        { // Line is complete. Then execute!
          Uart.line[Uart.lineIndex] = '\0'; // Terminate string
         
          processCommand(Uart.line); // do something with the command
          Serial.println(Uart.line);
         
          Uart.lineIndex = 0;
          Uart.inputString = "";
        }
        else
        {
          // Empty or comment line. Skip block.
        }
        Uart.lineIsComment = false;
        Uart.lineSemiColon = false;
        Serial.println(F("ok>"));
      }
      else
      {
        //Serial.println( c );
        if ((Uart.lineIsComment) || (Uart.lineSemiColon))
        {
          if (Uart.c == ')')
            Uart.lineIsComment = false; // End of comment. Resume line.
        }
        else
        {
          if (Uart.c == '/')
          { // Block delete not supported. Ignore character.
          }
          else if (Uart.c == '~')
          { // Enable comments flag and ignore all characters until ')' or EOL.
            Uart.lineIsComment = true;
          }
          else if (Uart.c == ';')
          {
            Uart.lineSemiColon = true;
          }
          else if (Uart.lineIndex >= LINE_BUFFER_LENGTH - 1)
          {
            Serial.println("ERROR - lineBuffer overflow");
            Uart.lineIsComment = false;
            Uart.lineSemiColon = false;
          }
          else if (Uart.c >= 'a' && Uart.c <= 'z')
          { // Upcase lowercase
            Uart.line[Uart.lineIndex] = Uart.c - 'a' + 'A';
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += (char)(Uart.c - 'a' + 'A');
          }
          else
          {
            Uart.line[Uart.lineIndex] = Uart.c;
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += Uart.c;
          }
        }
      }
    } //while (Serial1.available() > 0)
  }
}
//------------------------------------------------------------------------------
//----reset-----------
void (*resetFunc)(void) = 0;
//---------------------------------------------------------
void processCommand(char *data)
{

  int len, xlen, ylen, zlen, alen;
  int tempDIO;
  String stemp;
  unsigned int i, j, Comma;

  int val, maxv, minv;
  unsigned long duration;
  float Vpp;

  len = Uart.inputString.length();

  //-------------RESET---------------
  if (strstr(data, "VER") != NULL)
  {
    //Serial.println(F("W_ATE_Board_20201021"));
    Serial.println(F("Mega_SERIAL_20230723"));
  }
  if (strstr(data, "RESET") != NULL)
  {
    Serial.println(F("Reset"));
    resetFunc();
  }
  //===-----------------DIO port 1----------------
  if (strstr(data, "DIO1") != NULL)
  {
    //-DIO11_LOW
    if (data[3] == '1')
    {
      for (int i = 0; i < len; i++)
      {
        if (data[i] == '_')
        {
          //Serial.println("test");
          //Serial.println(i);
          xlen = i;
        }
        //ctemp[i-4]=data[i];
      }
      for (int i = 4; i < xlen; i++)
      {
        ctemp[i - 4] = data[i];
      }
      ctemp[xlen - 4] = '\0';
      tempDIO = atoi(ctemp);
      //Serial.println(tempDIO);
      for (int i = (xlen + 1); i < len; i++)
      {
        ctemp[i - (xlen + 1)] = data[i];
      }
      ctemp[len - (xlen + 1)] = '\0';

      tempDIO = tempDIO * 2 + 20;
      pinMode(tempDIO, OUTPUT);
      //if(strstr(ctemp, "ON") != NULL)
      //if(strcmp(ctemp, "ON")==0)
      //if (strcmp(Uart.ctemp, "LOW") == 0)
      if (strstr(ctemp, "LOW") != NULL)
      {
        digitalWrite(tempDIO, LOW);
      }
      else if (strstr(ctemp, "ON") != NULL)
      {
        digitalWrite(tempDIO, LOW);
      }
      else if (strstr(ctemp, "HIGH") != NULL)
      {
        digitalWrite(tempDIO, HIGH);
      }
      else if (strstr(ctemp, "OFF") != NULL)
      {
        digitalWrite(tempDIO, HIGH);
      }
    }
  }
}

YouTube Demonstration:

ESP32 with HC-SR04 Ultrasonic Sensor

Purpose: 

The ultrasonic sensor uses sonar to determine the distance to an object. the ESP32 and provide several example sketches to determine the distance to an object using the HC-SR04.

Fundamental:

Introducing the HC-SR04 Ultrasonic Sensor(HC-SR04超音波模組)

The HC-SR04 ultrasonic sensor uses sonar to determine the distance to an object. This sensor reads from 2cm to 400cm (0.8inch to 157inch) with an accuracy of 0.3cm (0.1inches), which is good for most hobbyist projects. In addition, this particular module comes with ultrasonic transmitter and receiver modules.

超音波感測器有兩個大大的「眼睛」,很多機器人或小車結構都會利用這個感測器做避障功能,不過其實與其說是眼睛,不如說是「耳朵」,左下角標示的「T」是TX的意思,代表左邊的孔負責傳送(Transport)超音波,而右下角標示「R」是RX代表右側的耳朵負責接收(Receive)超音波回音,也就是左側是嘴巴負責發出聲音,而右側是耳朵負責聽回音,兩者缺一不可。

下方四個腳位則依序為VCC、Trig、Echo、GND,其中Trig代表嘴巴,決定何時發出聲音,Echo則代表耳朵,用來計算聽到回音的時間,再透過公式就可以計算距離了,而VCC與GND則與以往相同,接在5V及GND腳位,這裡說明一下目前超音波有多個版本,有少數版本僅能使用5V,而大多數是5V、3.3V都可用,因此個人建議接在5V的位置。音速 c = 331.5 + 0.607 * t  (其中 t 為攝氏溫度)。 

例: 攝氏20度時的音速約為: 331.5 +    0.607*20 = 343.64 公尺/秒

音速公尺/秒 換算成 公分/微秒:343.64 * 100 / 1000000 = 0.034364 公分/微秒,亦即

音速每公分需要29.1 微秒:  1 / 0.034364 = 29.1 微秒/公分

超音波發射的距離為來回,因此單程距離 = 時間差 / 2  再除以  29.1 微秒 / 公分,同樣的如果      要換算成英吋,只要將 29.1 再乘以 2.54 即可, 使用pulseIn()讀取脈衝訊號,並計算

Circuit:

要換算成英吋,只要將 29.1 再乘以 2.54 即可, 使用pulseIn()讀取脈衝訊號,並計算

YouTube Demonstration:



Code Introduce:

//--------- Flag structure --------------------------------------
typedef struct _vFlag
{
  uint8_t BTFlag = 0;
  uint8_t DC_Flag = 0;
  uint8_t CANFlag = 0;
  uint8_t I2C_Flag = 0;
  uint8_t BMP180Flag = 0;
  uint8_t HCSR04Flag = 0;
  uint8_t LEDFlag = 1;
  uint8_t initial_Flag = 0;
  uint8_t FunctionFlag = 3;
  uint8_t SendFlag = 0;
  uint8_t BMPCnt = 0;
} vFlag;
vFlag *flag_Ptr;
vFlag flag;
//------LED------------------
#define LED_BUILTIN 2
//-----hcsr04 sensor------------------
#define TRIGPIN_PIN  12//發出聲波腳位(ESP32 GPIO12)
#define ECHO_PIN    14//接收聲波腳位(ESP32 GPIO14)
//int TRIGPIN_PIN17=17;
//int ECHO_PIN16=16;
long duration;
int distance;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
int interval = 1000;
//----------uart--------------
#define LINE_BUFFER_LENGTH 64
//--------- uart structure --------------------------------------
typedef struct _vUart
{
  char c;
  int lineIndex = 0;
  int line1Index = 0;
  int BTlineIndex = 0;
  bool lineIsComment;
  bool lineSemiColon;
  char line[128];
  char BTline[20];
  String inputString;
  String BTinputString;
  String S1inputString;
  int V[16];
  char ctemp[30];
  char I2C_Data[80];
  int DC_Spped = 50;
  float Voltage[16];
  int Buffer[128];
  int StartCnt = 0;
  int ReadCnt = 0;
  int sensorValue = 0;
} vUart;
vUart *Uart_Ptr;
vUart Uart;

//-------------------------------------------------
void setup()
{
  Serial.begin(9600);
  Serial.println(F("init"));
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(TRIGPIN_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
}
//-----------------------------------------
void loop()
{
  Serial.print(F("Main at core:"));
  Serial.println(xPortGetCoreID());
  while(1)
  {
    if(flag.LEDFlag == 1)
    {
      digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
      vTaskDelay(300);
      digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
      vTaskDelay(300);
    }
    while (Serial.available() > 0)
    {
      Uart.c = Serial.read();

      if ((Uart.c == '\n') || (Uart.c == '\r'))
      { // End of line reached
        if (Uart.lineIndex > 0)
        { // Line is complete. Then execute!
          Uart.line[Uart.lineIndex] = '\0'; // Terminate string
          //Serial.println( F("Debug") );
          //Serial.println( Uart.inputString );
          processCommand(Uart.line); // do something with the command
         
          Uart.lineIndex = 0;
          Uart.inputString = "";
        }
        else
        {
          // Empty or comment line. Skip block.
        }
        Uart.lineIsComment = false;
        Uart.lineSemiColon = false;
        Serial.println(F("ok>"));
      }
      else
      {
        //Serial.println( c );
        if ((Uart.lineIsComment) || (Uart.lineSemiColon))
        {
          if (Uart.c == ')')
            Uart.lineIsComment = false; // End of comment. Resume line.
        }
        else
        {
          if (Uart.c == '/')
          { // Block delete not supported. Ignore character.
          }
          else if (Uart.c == '~')
          { // Enable comments flag and ignore all characters until ')' or EOL.
            Uart.lineIsComment = true;
          }
          else if (Uart.c == ';')
          {
            Uart.lineSemiColon = true;
          }
          else if (Uart.lineIndex >= LINE_BUFFER_LENGTH - 1)
          {
            Serial.println("ERROR - lineBuffer overflow");
            Uart.lineIsComment = false;
            Uart.lineSemiColon = false;
          }
          else if (Uart.c >= 'a' && Uart.c <= 'z')
          { // Upcase lowercase
            Uart.line[Uart.lineIndex] = Uart.c - 'a' + 'A';
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += (char)(Uart.c - 'a' + 'A');
          }
          else
          {
            Uart.line[Uart.lineIndex] = Uart.c;
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += Uart.c;
          }
        }
      }
    } //while (Serial.available() > 0)
    if(flag.HCSR04Flag==1)
    {
      currentMillis = millis();
     
      pinMode(TRIGPIN_PIN, OUTPUT);
      digitalWrite(TRIGPIN_PIN, LOW);  //關閉超音波
      delayMicroseconds(2);  //sustain at least 10us HIGH pulse
      digitalWrite(TRIGPIN_PIN, HIGH); //啟動超音波
      delayMicroseconds(10);  //sustain at least 10us HIGH pulse
      digitalWrite(TRIGPIN_PIN, LOW);  //關閉超音波
      pinMode(ECHO_PIN, INPUT);
      duration= pulseIn(ECHO_PIN, HIGH);
      distance= duration/29/2;
      if (duration==0)
      {
        Serial.println("No pulse is from sensor");
      }
      else {
        Serial.print("Ultrasonic sensor is shown distance:");
        Serial.print(distance);
        Serial.println("cm");
      }
    }
  }
}
//----------------------------------------
void processCommand(char *data)
{
  int len, xlen, ylen, zlen, alen;
  int tempDIO;
  String stemp;

  len = Uart.inputString.length();
  //---------------------------------------
  if (strstr(data, "VER") != NULL)
  {
    Serial.println(F("ESP32_20230710"));
  }
   if (strstr(data, "HCSR04_ON") != NULL)
  {
    flag.HCSR04Flag = 1;
    flag.LEDFlag = 0;
    Serial.println(F("HCSR04_ON"));
  }
  if (strstr(data, "HCSR04_OFF") != NULL)
  {
    flag.HCSR04Flag = 0;
    flag.LEDFlag = 1;
    Serial.println(F("HCSR04_OFF"));
  }  
}
//-----------------------------------------