2023年11月10日 星期五

ESP32 Wifi mesh Control another ESP32 with Relay

Purpose:
利用painlessmesh的WiFi mesh的功能, 在一個mash的網路裡. 由一個ESP32(main Node)搭配Xbox Joystick傳送Json格式的指令, 去控制網絡中另一個Node(ESP32 with RelayBoard)的relay動作.

Using the WiFi mesh function of painlessmesh, in a mash network, an ESP32 (main Node) and Xbox Joystick transmit commands in JSON format to control the relay action of another Node (ESP32 with RelayBoard) in the network.
Architecture:
架構說明:
Xbox左邊搖桿向左切傳輸RELAY4_ON指令, 向下切傳輸RELAY1_ON指令, 向右切傳輸RELAY2_ON指令,  向上切傳輸RELAY3_ON指令, 按下ButtonX傳輸RELAY4_OFF指令, 按下ButtonA傳輸RELAY1_OFF指令, 按下ButtonB傳輸RELAY2_OFF指令, 按下ButtonY傳輸RELAY3_OFF指令.

Move the Xbox left joystick to the left to transmit the RELAY4_ON command, move it downward to transmit the RELAY1_ON command, move it to the right to transmit the RELAY2_ON command, move it upward to transmit the RELAY3_ON command then press ButtonX to transmit the RELAY4_OFF command, press ButtonA to transmit the RELAY1_OFF command, and press ButtonB to transmit the RELAY2_OFF command. , press ButtonY to transmit the RELAY3_OFF command.
Previous article:

Circuit:
圖一: Node10 Circuit

圖二: Node11 circuit

YouTube Demo:

ESP32 Main Node10 Joystick Code:
#include "painlessMesh.h"
//#include <ArduinoJson.h>
#include <Arduino_JSON.h>
#include <ezButton.h>
//-----Global variable---------------------------------------
#define LED_BUILTIN 2
//--------joystick------------------------------------------
#define VRX_PIN_L  33 // ESP32 pin GPIO33 (ADC0)
#define VRY_PIN_L  32 // ESP32 pin GPIO32 (ADC0)
#define VRX_PIN_R  35 // ESP32 pin GPIO33 (ADC0)
#define VRY_PIN_R  34 // ESP32 pin GPIO32 (ADC0)
#define SW_X       18
#define SW_Y       16
#define SW_A       17
#define SW_B       19

#define LEFT_THRESHOLD_L  2200  
#define RIGHT_THRESHOLD_L 900
#define UP_THRESHOLD_L    2200  
#define DOWN_THRESHOLD_L  900  

#define LEFT_THRESHOLD_R  2200  
#define RIGHT_THRESHOLD_R 900
#define UP_THRESHOLD_R    2200  
#define DOWN_THRESHOLD_R  900  

#define COMMAND_NO_L     0x00
#define COMMAND_LEFT_L   0x01
#define COMMAND_RIGHT_L  0x02
#define COMMAND_UP_L     0x04
#define COMMAND_DOWN_L   0x08

#define COMMAND_NO_R     0x00
#define COMMAND_LEFT_R   0x01
#define COMMAND_RIGHT_R  0x02
#define COMMAND_UP_R     0x04
#define COMMAND_DOWN_R   0x08

int valueX_L = 0 ; // to store the X-axis value
int valueY_L = 0 ; // to store the Y-axis value
int command_L = COMMAND_NO_R;
int valueX_R = 0 ; // to store the X-axis value
int valueY_R = 0 ; // to store the Y-axis value
int command_R = COMMAND_NO_R;
//----------------------------------------------

int bValue_A = 0; // To store value of the button
int bValue_B = 0; // To store value of the button
int bValue_X = 0; // To store value of the button
int bValue_Y = 0; // To store value of the button
ezButton buttonA(SW_A);
ezButton buttonB(SW_B);
ezButton buttonX(SW_X);
ezButton buttonY(SW_Y);
//-----------painlessmesh------------------------------------
#define   MESH_PREFIX     "Peter1015"
#define   MESH_PASSWORD   "No18141814"
#define   MESH_PORT       5555
Scheduler userScheduler;  // to control your personal task
painlessMesh  mesh;

//Number for this node
int nodeNumber = 10;
void sendMessage() ;
String readings;
String getReadings();
Task taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &sendMessage );
//--------------------Json data ------------------------------
StaticJsonDocument<200> json_doc;
char json_output[100];
DeserializationError json_error;
const char* payload_node;
const char* payload_function;
const char* payload_data;
//------------------------------------------------------------
//char line[16];
//--------- Flag structure --------------------------------------

#define LINE_BUFFER_LENGTH 1024
typedef struct _vFlag
{
  uint8_t LEDFlag=0;
  uint8_t BTFlag=0;
  uint8_t FunctionFlag=1;
  uint8_t SendFlag=0;
}vFlag;
vFlag *flag_Ptr;
vFlag flag;
//--------- uart structure --------------------------------------
//----------uart--------------
#define LINE_BUFFER_LENGTH 64
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;
} vUart;
vUart *Uart_Ptr;
vUart Uart;
//-------------------------------------
TaskHandle_t hled;
TaskHandle_t huart;

void vLEDFlashTask(void *pvParameters);
void vUARTTask(void *pvParameters);

void initial()
{
  Serial.println(F("Create Task"));
  //----------------------------------------------------------------------
  // Now set up two tasks to run independently.
  xTaskCreatePinnedToCore(
    vLEDFlashTask, "LEDTask" // A name just for humans
    ,
    1024 // This stack size can be checked & adjusted by reading the Stack Highwater
    ,
    NULL, 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,
    &hled //handle
    ,
    0);

  xTaskCreatePinnedToCore(
    vUARTTask, "UARTTask" // A name just for humans
    ,
    1024 // This stack size can be checked & adjusted by reading the Stack Highwater
    ,
    NULL, 3 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,
    &huart //handle
    ,
    0);

  //----------------------------------------------------------------------
}
String getReadings()
{
  JSONVar jsonReadings;
 
  //Serial.print(F("meshTask at core:"));
  //Serial.println(xPortGetCoreID());
  jsonReadings["node"] = nodeNumber;
  //jsonReadings["node"] = String(normAccel.XAxis);
  //jsonReadings["node ID"] = String(mesh.getNodeId());
  if(flag.FunctionFlag==1)
  {
    jsonReadings["function"] = "Joystick";
  }
 
  readings = JSON.stringify(jsonReadings);
  return readings;
}
void sendMessage()
{
  //String msg = "Hello from node 1 ";
  String msg = getReadings();
  //msg += mesh.getNodeId();

  if(flag.SendFlag ==1)
  {
    msg=Uart.BTinputString;
    Uart.BTinputString="";
    flag.SendFlag=0;
  }
  mesh.sendBroadcast( msg );
  taskSendMessage.setInterval( random( TASK_SECOND * 1, TASK_SECOND * 2 ));
}

void receivedCallback( uint32_t from, String &msg ) {
  Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
  flag.LEDFlag=1;
}

void newConnectionCallback(uint32_t nodeId) {
    Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);  
}

void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
  flag.LEDFlag=0;
}

void nodeTimeAdjustedCallback(int32_t offset) {
    Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

void setup() {
  Serial.begin(9600);
  /**240(default 240 160 80 40 20 and 10Mhz)***/
  setCpuFrequencyMhz(160);
  initial();
  //-----------------------------------------------------------------
  buttonA.setDebounceTime(50); // set debounce time to 50 milliseconds
  buttonB.setDebounceTime(50); // set debounce time to 50 milliseconds
  buttonX.setDebounceTime(50); // set debounce time to 50 milliseconds
  buttonY.setDebounceTime(50); // set debounce time to 50 milliseconds
  //------------------------------------------------
  //-------------------------------------------------------------------
  //mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
  mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages
  mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT );
  mesh.onReceive(&receivedCallback);
  mesh.onNewConnection(&newConnectionCallback);
  mesh.onChangedConnections(&changedConnectionCallback);
  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
  userScheduler.addTask( taskSendMessage );
  taskSendMessage.enable();
  //-------------------------------------------
  Serial.println(F("System On!"));
  //-------------------------------------------
}

void loop()
{
  Serial.print(F("Main at core:"));
  Serial.println(xPortGetCoreID());
  while (1)
  {
    buttonA.loop(); // MUST call the loop() function first
    buttonB.loop(); // MUST call the loop() function first
    buttonX.loop(); // MUST call the loop() function first
    buttonY.loop(); // MUST call the loop() function first
    // Read the button value
    bValue_A = buttonA.getState();
    bValue_B = buttonB.getState();
    bValue_X = buttonX.getState();
    bValue_Y = buttonY.getState();

    if (buttonA.isPressed()) {
      Serial.println("The buttonA is pressed");
      Uart.BTinputString="{\"node\":10,\"ButtonA\":\"OFF\"}";
      flag.SendFlag=1;
    }
    if (buttonA.isReleased()) {
      Serial.println("The buttonA is released");
     
    }
    if (buttonB.isPressed()) {
      Serial.println("The buttonB is pressed");
      Uart.BTinputString="{\"node\":10,\"ButtonB\":\"OFF\"}";
      flag.SendFlag=1;
    }
    if (buttonB.isReleased()) {
      Serial.println("The buttonB is released");
      // TODO do something here
    }
    if (buttonX.isPressed()) {
      Serial.println("The buttonX is pressed");
      Uart.BTinputString="{\"node\":10,\"ButtonX\":\"OFF\"}";
      flag.SendFlag=1;
    }
    if (buttonX.isReleased()) {
      Serial.println("The buttonX is released");
      // TODO do something here
    }
    if (buttonY.isPressed()) {
      Serial.println("The buttonY is pressed");
      Uart.BTinputString="{\"node\":10,\"ButtonY\":\"OFF\"}";
      flag.SendFlag=1;
    }
    if (buttonY.isReleased()) {
      Serial.println("The buttonY is released");
      // TODO do something here
    }
    //--------------------------------------------------------
    valueX_L = analogRead(VRX_PIN_L);
    valueY_L = analogRead(VRY_PIN_L);
    valueX_R = analogRead(VRX_PIN_R);
    valueY_R = analogRead(VRY_PIN_R);
    // converts the analog value to commands
    // reset commands
    command_L = COMMAND_NO_L;
    command_R = COMMAND_NO_R;
    // check left/right commands
   
    if (valueX_L > LEFT_THRESHOLD_L)
      command_L = command_L | COMMAND_LEFT_L;
    else if (valueX_L < RIGHT_THRESHOLD_L)
      command_L = command_L | COMMAND_RIGHT_L;
   
    // check up/down commands
    if (valueY_L > UP_THRESHOLD_L)
      command_L = command_L | COMMAND_UP_L;
    else if (valueY_L < DOWN_THRESHOLD_L)
      command_L = command_L | COMMAND_DOWN_L;


    // print command to serial and process command
   
    if (command_L & COMMAND_LEFT_L) {
      Serial.println("COMMAND LEFT_L");
      Uart.BTinputString="{\"node\":10,\"ButtonX\":\"ON\"}";
      flag.SendFlag=1;
    }

    if (command_L & COMMAND_RIGHT_L) {
      Serial.println("COMMAND RIGHT_L");
      Uart.BTinputString="{\"node\":10,\"ButtonB\":\"ON\"}";
      flag.SendFlag=1;
    }

    if (command_L & COMMAND_UP_L) {
      Serial.println("COMMAND UP_L");
      Uart.BTinputString="{\"node\":10,\"ButtonY\":\"ON\"}";
      flag.SendFlag=1;
    }

    if (command_L & COMMAND_DOWN_L) {
      Serial.println("COMMAND DOWN_L");
      Uart.BTinputString="{\"node\":10,\"ButtonA\":\"ON\"}";
      flag.SendFlag=1;
    }
   
    //-----------------------------------------------------
    if (valueX_R > LEFT_THRESHOLD_R)
      command_R = command_R | COMMAND_LEFT_R;
    else if (valueX_R < RIGHT_THRESHOLD_R)
      command_R = command_R | COMMAND_RIGHT_R;
   
    // check up/down commands
    if (valueY_R > UP_THRESHOLD_R)
      command_R = command_R | COMMAND_UP_R;
    else if (valueY_R < DOWN_THRESHOLD_R)
      command_R = command_R | COMMAND_DOWN_R;
   
    if (command_R & COMMAND_LEFT_R) {
      Serial.println("COMMAND LEFT_R");
      // TODO: add your task here
    }

    if (command_R & COMMAND_RIGHT_R) {
      Serial.println("COMMAND RIGHT_R");
      // TODO: add your task here
    }

    if (command_R & COMMAND_UP_R) {
      Serial.println("COMMAND UP_R");
      // TODO: add your task here
    }

    if (command_R & COMMAND_DOWN_R) {
      Serial.println("COMMAND DOWN_R");
      // TODO: add your task here
    }
    //-----------------------------------------------------
    //-----------painlessmesh------------------------------
    mesh.update();
  }//----while(1)-------------------------------------------

}
//--------------------------------------------------------
/*--------------------------------------------------*/
void vLEDFlashTask(void *pvParameters) // This is a task.
{
  (void)pvParameters;
 
  Serial.print(F("LEDTask at core:"));
  Serial.println(xPortGetCoreID());
  pinMode(LED_BUILTIN, OUTPUT);
  //oldMillis = millis();
  for (;;) // A Task shall never return or exit.
  {
    if(flag.LEDFlag==1)
    {
      digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
      vTaskDelay(200);
      digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
      vTaskDelay(200);
    }
    else{
      vTaskDelay(10);
    }
  }
}

//-------------------------------------------
void vUARTTask(void *pvParameters)
{
  (void)pvParameters;

  Serial.print(F("UARTTask at core:"));
  Serial.println(xPortGetCoreID());
  for (;;)
  {
    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)
    vTaskDelay(10);
  }
}
//------------------------------------------------------------
void processCommand(char *data)
{
  int len, xlen, ylen, zlen, alen;
  char ctemp[20];

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

}



ESP32 Node11 Relay Code:
#include "painlessMesh.h"
#include <Arduino_JSON.h>
//-------------------------------------------------------------
#define   MESH_PREFIX     "Peter1015"
#define   MESH_PASSWORD   "No18141814"
#define   MESH_PORT       5555
//-----Global variable---------------------------------------
#define LED_BUILTIN 2
//-----Relay------------------
#define RELAY1       15
#define RELAY2       13
#define RELAY3       32
#define RELAY4       33
//--------- Flag structure --------------------------------------
typedef struct _vFlag
{
  uint8_t LEDFlag=0;
  uint8_t NodeFlag=0;
  uint8_t FunctionFlag=1;
  uint8_t SendFlag=0;
}vFlag;
vFlag *flag_Ptr;
vFlag flag;
typedef struct _vUart
{
  String inputString;
  String BTinputString;
} vUart;
vUart *Uart_Ptr;
vUart Uart;
//---------------------------------------------------
Scheduler userScheduler; // to control your personal task
painlessMesh  mesh;

//Number for this node
int nodeNumber = 11;
// User stub
void sendMessage() ; // Prototype so PlatformIO doesn't complain
String readings;
String getReadings();
Task taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &sendMessage );

TaskHandle_t hled;

void vLEDFlashTask(void *pvParameters);

void initial()
{
  Serial.println(F("Create Task"));
  //----------------------------------------------------------------------
  // Now set up two tasks to run independently.
  xTaskCreatePinnedToCore(
    vLEDFlashTask, "LEDTask" // A name just for humans
    ,
    1024 // This stack size can be checked & adjusted by reading the Stack Highwater
    ,
    NULL, 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,
    &hled //handle
    ,
    0);
  //----------------------------------------------------------------------
}
String getReadings()
{
  JSONVar jsonReadings;
 
  //Serial.print(F("meshTask at core:"));
  //Serial.println(xPortGetCoreID());
  jsonReadings["node"] = nodeNumber;
  //jsonReadings["node"] = String(normAccel.XAxis);
  //jsonReadings["node ID"] = String(mesh.getNodeId());
  if(flag.FunctionFlag==1)
  {
    jsonReadings["function"] = "RelayBoard";
  }
 
  readings = JSON.stringify(jsonReadings);
  return readings;
}
void sendMessage() {
  String msg = getReadings();
  //msg += mesh.getNodeId();

  if(flag.SendFlag ==1)
  {
    msg=Uart.BTinputString;
    Uart.BTinputString="";
    flag.SendFlag=0;
  }
  mesh.sendBroadcast( msg );
  taskSendMessage.setInterval( random( TASK_SECOND * 1, TASK_SECOND * 2 ));
}

// Needed for painless library
void receivedCallback( uint32_t from, String &msg )
{
  JSONVar myObject = JSON.parse(msg.c_str());
  if (myObject.hasOwnProperty("node")) {
    //Serial.print("myObject[\"node\"] = ");
    //Serial.println((int) myObject["node"]);
    if((int) myObject["node"]==10)
    {
      flag.NodeFlag=1;
    }
  }
  if (myObject.hasOwnProperty("function")) {
    //Serial.print("myObject[\"function\"] = ");
    //Serial.println((const char*) myObject["function"]);
  }
  if (myObject.hasOwnProperty("ButtonA")) {
   
    if(flag.NodeFlag==1)
    {
      //Serial.print("myObject[\"ButtonA\"] = ");
      //Serial.println((const char*) myObject["ButtonA"]);
      String str=(const char*)myObject["ButtonA"];
      if(str=="ON")
      {
        digitalWrite(RELAY1, LOW);
      }
      if(str=="OFF")
      {
        digitalWrite(RELAY1, HIGH);
      }
    }
  }
  if (myObject.hasOwnProperty("ButtonB")) {
   
    if(flag.NodeFlag==1)
    {
      String str=(const char*)myObject["ButtonB"];
      if(str=="ON")
      {
        digitalWrite(RELAY2, LOW);
      }
      if(str=="OFF")
      {
        digitalWrite(RELAY2, HIGH);
      }
    }
  }
  if (myObject.hasOwnProperty("ButtonY")) {
   
    if(flag.NodeFlag==1)
    {
      String str=(const char*)myObject["ButtonY"];
      if(str=="ON")
      {
        digitalWrite(RELAY3, LOW);
      }
      if(str=="OFF")
      {
        digitalWrite(RELAY3, HIGH);
      }
    }
  }
  if (myObject.hasOwnProperty("ButtonX")) {
   
    if(flag.NodeFlag==1)
    {
      String str=(const char*)myObject["ButtonX"];
      if(str=="ON")
      {
        digitalWrite(RELAY4, LOW);
      }
      if(str=="OFF")
      {
        digitalWrite(RELAY4, HIGH);
      }
    }
  }

  Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
  flag.LEDFlag=1;
}

void newConnectionCallback(uint32_t nodeId) {
    Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
   
}

void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
  flag.LEDFlag=0;
}

void nodeTimeAdjustedCallback(int32_t offset) {
    Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

void setup() {
  Serial.begin(9600);
  setCpuFrequencyMhz(160);
  initial();
  //---------------------------------------------------
  pinMode(RELAY1, OUTPUT);
  digitalWrite(RELAY1, HIGH);
  pinMode(RELAY2, OUTPUT);
  digitalWrite(RELAY2, HIGH);
  pinMode(RELAY3, OUTPUT);
  digitalWrite(RELAY3, HIGH);
  pinMode(RELAY4, OUTPUT);
  digitalWrite(RELAY4, HIGH);
  //---------------------------------------------------
  //mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
  mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages
  mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT );
  mesh.onReceive(&receivedCallback);
  mesh.onNewConnection(&newConnectionCallback);
  mesh.onChangedConnections(&changedConnectionCallback);
  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
  userScheduler.addTask( taskSendMessage );
  taskSendMessage.enable();
}

void loop()
{
  Serial.print(F("Main at core:"));
  Serial.println(xPortGetCoreID());
  while (1)
  {
    mesh.update();
  }

}

/*--------------------------------------------------*/
void vLEDFlashTask(void *pvParameters) // This is a task.
{
  (void)pvParameters;
 
  Serial.print(F("LEDTask at core:"));
  Serial.println(xPortGetCoreID());
  pinMode(LED_BUILTIN, OUTPUT);
  //oldMillis = millis();
  for (;;) // A Task shall never return or exit.
  {
    if(flag.LEDFlag==1)
    {
      digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
      vTaskDelay(200);
      digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
      vTaskDelay(200);
    }
    else{
      vTaskDelay(10);
    }
  }
}

//-------------------------------------------




沒有留言:

張貼留言