Smart Home Automation Forum
[arduino code examples for A32 Pro]-07 Communication between ESP32-S3 and Tuya module - Printable Version

+- Smart Home Automation Forum (https://www.kincony.com/forum)
+-- Forum: Technical Support (https://www.kincony.com/forum/forumdisplay.php?fid=20)
+--- Forum: KC868-A32/A32 Pro (https://www.kincony.com/forum/forumdisplay.php?fid=27)
+--- Thread: [arduino code examples for A32 Pro]-07 Communication between ESP32-S3 and Tuya module (/showthread.php?tid=6686)



[arduino code examples for A32 Pro]-07 Communication between ESP32-S3 and Tuya module - admin - 09-14-2024

Code:
/*
* Copyright (c) 2024 KinCony IoT (https://www.kincony.com)
*
* This Arduino program implements communication between ESP32-S3 and the Tuya module
* via UART (serial communication). It listens for specific packets from the Tuya module
* and responds according to predefined commands. Additionally, it uses an LED connected
* to GPIO45 to indicate the network status based on the Tuya module's response, and a button
* on GPIO21 to initiate a manual quick configuration (EZ mode).
*
* Functionality:
* 1. The ESP32-S3 communicates with the Tuya module via serial (UART).
* 2. The program listens for specific commands from the Tuya module, such as heartbeat, product info requests, work mode requests, and network status.
* 3. When the ESP32-S3 receives a heartbeat packet (0x55 0xAA 00 00 00 00 0xFF), it responds with a heartbeat response (0x55 0xAA 03 00 00 01 00 03).
* 4. When the ESP32-S3 receives a network status update, it controls an LED connected to GPIO45 to indicate the current state:
*    - Fast blink (every 250ms) indicates the device is in quick configuration mode (EZ mode).
*    - Slow blink (every 1500ms) indicates the device is in hotspot configuration mode (AP mode).
*    - Solid ON indicates the device is successfully connected to the cloud.
* 5. A button connected to GPIO21 is used to send a command to the Tuya module to start the quick configuration mode.
*
* Pin definitions:
* - TXD (ESP32 to Tuya module): GPIO15
* - RXD (Tuya module to ESP32): GPIO16
* - LED for network status indication: GPIO45
* - Button for starting quick configuration: GPIO21
*/

#include <HardwareSerial.h>

// Create a HardwareSerial object for UART communication on ESP32
HardwareSerial tuyaSerial(1);

// Define the GPIO pins for TXD and RXD used for serial communication with the Tuya module
#define TXD_PIN 15
#define RXD_PIN 16

// Set the baud rate for Tuya module communication to 9600
#define BAUD_RATE 9600

// Define the GPIO for LED and Button
#define LED_PIN 45
#define BUTTON_PIN 21

// Define LED flash intervals (in milliseconds) for different states
#define FAST_FLASH_INTERVAL 250      // Fast blink for EZ mode
#define SLOW_FLASH_INTERVAL 1500     // Slow blink for AP mode
#define LONG_LIGHT_INTERVAL 10000    // Long light for cloud connection (simulating always ON)

// Variables to control LED state
bool ledState = LOW;                 // Tracks the current state of the LED
unsigned long previousMillis = 0;    // Used to track time for blinking the LED
unsigned long flashInterval = LONG_LIGHT_INTERVAL;  // Default interval (long ON)

// Define the response packets for different commands from the Tuya module

// Heartbeat response: Tuya expects this response after sending a heartbeat
uint8_t heartBeatResponse[] = {0x55, 0xAA, 0x03, 0x00, 0x00, 0x01, 0x00, 0x03};

// Product info response with details (e.g., product ID, firmware version, etc.)
uint8_t productInfoResponse[] = {
  0x55, 0xAA, 0x03, 0x01, 0x00, 0x2A, 0x7B, 0x22, 0x70, 0x22, 0x3A, 0x22,
  0x63, 0x68, 0x6D, 0x7A, 0x6C, 0x67, 0x6A, 0x70, 0x61, 0x64, 0x70, 0x71,
  0x78, 0x64, 0x6B, 0x6F, 0x22, 0x2C, 0x22, 0x76, 0x22, 0x3A, 0x22, 0x31,
  0x2E, 0x30, 0x2E, 0x30, 0x22, 0x2C, 0x22, 0x6D, 0x22, 0x3A, 0x30, 0x7D, 0xAA
};

// Work mode response: Sent when the Tuya module asks for the current work mode
uint8_t workModeResponse[] = {0x55, 0xAA, 0x03, 0x02, 0x00, 0x00, 0x04};

// Network status response: Sent when the Tuya module asks for the network status
uint8_t netStatusResponse[] = {0x55, 0xAA, 0x03, 0x03, 0x00, 0x00, 0x05};

// Subsequent heartbeat response: Sent after the first heartbeat response
uint8_t secondHeartBeatResponse[] = {0x55, 0xAA, 0x03, 0x00, 0x00, 0x01, 0x01, 0x04};

// Command to start quick configuration (EZ mode) when the button is pressed
uint8_t quickConfigCommand[] = {0x55, 0xAA, 0x03, 0x05, 0x00, 0x01, 0x00, 0x08};

void setup() {
  // Initialize the serial communication for debugging at 115200 baud rate
  Serial.begin(115200);

  // Initialize the serial communication with Tuya module at 9600 baud rate
  tuyaSerial.begin(BAUD_RATE, SERIAL_8N1, RXD_PIN, TXD_PIN);

  // Initialize the GPIO for LED and button
  pinMode(LED_PIN, OUTPUT);       // Set the LED pin as output
  pinMode(BUTTON_PIN, INPUT_PULLUP); // Use internal pull-up resistor for the button

  // Debug message to indicate that the serial communication has been initialized
  Serial.println("ESP32-Tuya serial communication initialized.");
}

void loop() {
  // Handle LED blinking based on the current flash interval
  unsigned long currentMillis = millis();  // Get the current time
  if (currentMillis - previousMillis >= flashInterval) {
    previousMillis = currentMillis;        // Update the time tracker
    ledState = !ledState;                  // Toggle the LED state
    digitalWrite(LED_PIN, ledState);       // Update the LED state
  }

  // Check if the button is pressed (active low)
  if (digitalRead(BUTTON_PIN) == LOW) {
    Serial.println("Button pressed, sending quick config command...");
    sendPacket(quickConfigCommand, sizeof(quickConfigCommand));  // Send quick config command
    delay(500);  // Debounce delay to avoid multiple triggers
  }

  // Check if there is any data available from the Tuya module
  if (tuyaSerial.available()) {
    uint8_t incomingPacket[7];  // Array to store the received packet
    size_t bytesRead = tuyaSerial.readBytes(incomingPacket, 7); // Read 7 bytes from Tuya module

    // Check if the packet has a valid header (0x55, 0xAA)
    if (bytesRead >= 2 && incomingPacket[0] == 0x55 && incomingPacket[1] == 0xAA) {
      // If less than 7 bytes were received, wait for more data
      if (bytesRead < 7) {
        delay(50); // Wait briefly to receive the remaining bytes
        while (tuyaSerial.available()) {
          incomingPacket[bytesRead++] = tuyaSerial.read(); // Continue reading remaining bytes
          if (bytesRead >= 7) break;
        }
      }

      // If the packet is still incomplete, discard it
      if (bytesRead < 7) return;

      // Process the received packet
      processTuyaPacket(incomingPacket, 7);
    } else {
      // If the header is invalid, discard the packet
      tuyaSerial.flush(); // Clear the serial buffer
    }
  }

  // Small delay to prevent CPU overload
  delay(100);
}

// Function to process the received packet from Tuya module and send appropriate responses
void processTuyaPacket(uint8_t* packet, size_t size) {
  // Ensure the packet size is correct and the header is valid
  if (size == 7 && packet[0] == 0x55 && packet[1] == 0xAA) {
    // Check the command byte (packet[2]) to determine the type of request
    switch (packet[2]) {
      case 0x00:
        // Heartbeat request
        if (packet[3] == 0x00 && packet[4] == 0x00 && packet[5] == 0x00 && packet[6] == 0xFF) {
          Serial.println("Heartbeat received.");
          sendPacket(heartBeatResponse, sizeof(heartBeatResponse));  // Send heartbeat response
        }
        break;
      case 0x01:
        // Product info request
        Serial.println("Product info request received.");
        sendPacket(productInfoResponse, sizeof(productInfoResponse));  // Send product info response
        break;
      case 0x02:
        // Work mode request
        Serial.println("Work mode request received.");
        sendPacket(workModeResponse, sizeof(workModeResponse));  // Send work mode response
        break;
      case 0x03:
        // Network status request
        Serial.println("Network status request received.");
        sendPacket(netStatusResponse, sizeof(netStatusResponse));  // Send network status response

        // Change LED flash pattern based on network status (packet[6])
        if (packet[6] == 0x00) {
          flashInterval = FAST_FLASH_INTERVAL;  // Set LED to fast blink for EZ mode
        } else if (packet[6] == 0x01) {
          flashInterval = SLOW_FLASH_INTERVAL;  // Set LED to slow blink for AP mode
        } else if (packet[6] == 0x04) {
          flashInterval = LONG_LIGHT_INTERVAL;  // Set LED to long ON for cloud connection
          digitalWrite(LED_PIN, HIGH);          // Ensure LED is ON
        }
        break;
      default:
        Serial.println("Error: Unhandled command received.");
        break;
    }
  }
}

// Function to send a response packet to the Tuya module
void sendPacket(uint8_t* packet, size_t size) {
  // Send the packet via UART to the Tuya module
  tuyaSerial.write(packet, size);

  // Debug: Print the sent packet for logging purposes
  Serial.print("Sent packet: ");
  for (size_t i = 0; i < size; i++) {
    Serial.print(packet[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}
arduino ino file download: 
.zip   7-tuya-wifi-config.zip (Size: 2.89 KB / Downloads: 43)
BIN file (you can use esp32 download tool download to ESP32-S3 with address 0x0 then directly to use) download: 
.zip   7-tuya-wifi-config.ino.merged.zip (Size: 182.85 KB / Downloads: 43)