2025年11月7日 星期五

作業3,4 的ESP32程式

作業3,4 的ESP32程式 


Arduino IDE 安裝建置ESP32開發板

參考 https://shop.mirotek.com.tw/iot/esp32-start-2/   或 

https://randomnerdtutorials.com/installing-the-esp32-board-in-arduino-ide-windows-instructions/

  • 下載Arduino IDE
  • 在 Arduino IDE 設定 ESP32開發板
  • https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  • 安裝 Arduino IDE 程式庫(Library)  

            #include <MFRC522v2.h>
            #include <ArduinoMqttClient.h>


  • 使用範例檔Blink: (組譯 上傳 )



ESP32程式 (作業3/4 相同)

  • WIFI
  • const char* ssid = "alex9ufo";            需修改
  • const char* password = "alex9981"; 需修改

  • MQTT Broker
  • const char* mqttBroker = "broker.mqtt-dashboard.com"; 
  • int mqttPort = 1883;

  • --- MQTT 主題設定 ---

  • const char* topic_UID_publish = "alex9ufo/rfid/UID";

    const char* topic_LED_subscribe = "alex9ufo/rfid/led";       

    const char* topic_LED_status_publish = "alex9ufo/rfid/ledStatus"; 

  •   

  •  

NODE-RED 與 Python TKinter 的 MQTT broker 需配合修改
        
          

          

  
                     



硬體接線

  • Signal         MFRC522     WROOM-32
  • RST/Reset        RST           21
  • SPI SS              SDA           5
  • SPI MOSI        MOSI         23
  • SPI MISO        MISO        19
  • SPI SCK          SCK          18
  •  
  • LED                13   (陰極)   VCC (陽極)   LOW亮   HIGH 滅


      

          

       

       

        

        


      


  



ESP32程式

/***

Signal    MFRC522 WROOM-32

RST/Reset RST     21

SPI SS    SDA     5

SPI MOSI  MOSI    23

SPI MISO  MISO    19

SPI SCK   SCK     18

***/

// 引入 FreeRTOS 函式庫

#include <freertos/FreeRTOS.h>

#include <freertos/task.h>

#include <freertos/semphr.h>

#include <freertos/queue.h>


// Wifi 與 MQttClient 程式庫

#include <ArduinoMqttClient.h>

#include <WiFi.h>


// *** 新增: 解決 'esp_task_wdt_deinit' not declared 的問題 ***

#include "esp_task_wdt.h" 


// --- MFRC522v2 程式庫 ---

#include <MFRC522v2.h>

#include <MFRC522DriverSPI.h>

#include <MFRC522DriverPinSimple.h>

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



// --- Wi-Fi 和 MQTT 設定 ---

const char* ssid = "alex9ufo";

const char* password = "alex9981";

const char* mqttBroker = "broker.mqtt-dashboard.com"; 

int mqttPort = 1883;

WiFiClient wifiClient;

MqttClient mqttClient(wifiClient);



// --- MQTT 主題設定 ---

const char* topic_UID_publish = "alex9ufo/rfid/UID";

const char* topic_LED_subscribe = "alex9ufo/rfid/led";       

const char* topic_LED_status_publish = "alex9ufo/rfid/ledStatus"; 


// --- 硬體腳位設定 ---

#define RST_PIN     21      

#define SS_PIN      5       

#define LED_PIN     13       // 用於 LED 控制的 GPIO 腳位 (假設使用 GPIO 13)


MFRC522DriverPinSimple ss_pin_v2(SS_PIN); 

MFRC522DriverSPI driver{ss_pin_v2};      

MFRC522 mfrc522{driver};                 



// --- 雙核心通訊變數 (使用 FreeRTOS) ---

String new_uid_to_publish = "";

SemaphoreHandle_t xUidMutex; 

QueueHandle_t xLedQueue; 

String current_led_status = "OFF";

SemaphoreHandle_t xStatusMutex;


// --- MFRC522 狀態變數 (Core 1 使用) ---

byte last_UID[10] = {0}; 

byte last_UID_Size = 0;

unsigned long last_publish_time = 0;

const unsigned long REPEAT_DELAY_MS = 5000; 


// --- 函數宣告 ---

void connectWifi();

void connectMqtt();

void onMqttMessage(int messageSize); 

void ledMqttTask(void *pvParameters); 

void rfidLedControlTask(void *pvParameters); 

String uidToHexString(byte *buffer, byte bufferSize);



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

// ------------------------------ CORE 0: MQTT/控制中心任務 -------------------------

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


void onMqttMessage(int messageSize) {

  String topic = mqttClient.messageTopic();

  

  if (topic == topic_LED_subscribe) {

    String command = "";

    while (mqttClient.available()) {

      command += (char)mqttClient.read();

    }

    command.toUpperCase();


    Serial.print("Core 0: Received LED command: ");

    Serial.println(command);


    if (xQueueSend(xLedQueue, &command, (TickType_t)10) != pdPASS) {

        Serial.println("Core 0: Failed to send LED command to Core 1.");

    }

  }

}


void ledMqttTask(void *pvParameters) {

    

    connectWifi();

    vTaskDelay(pdMS_TO_TICKS(1000));

    connectMqtt();

    

    mqttClient.onMessage(onMqttMessage);

    mqttClient.subscribe(topic_LED_subscribe);

    Serial.print("Core 0: Subscribed to ");

    Serial.println(topic_LED_subscribe);


    Serial.println("Core 0: MQTT UID Publish & LED Command Task Running.");


    while (1) {

        

        if (WiFi.status() != WL_CONNECTED) {

            connectWifi();

        }


        if (!mqttClient.connected()) {

            connectMqtt();

            mqttClient.subscribe(topic_LED_subscribe); // 重連後重新訂閱

        }


        mqttClient.poll();

        

        // 1. 處理 MFRC522 UID 發佈 (從 Core 1 接收)

        if (xSemaphoreTake(xUidMutex, (TickType_t)10) == pdTRUE) {

            if (new_uid_to_publish.length() > 0) {

                mqttClient.beginMessage(topic_UID_publish, new_uid_to_publish.length(), false, 1, false);

                mqttClient.print(new_uid_to_publish);

                mqttClient.endMessage(); 

                

                Serial.print("Core 0: Published UID: ");

                Serial.println(new_uid_to_publish);

                

                new_uid_to_publish = "";

            }

            xSemaphoreGive(xUidMutex);

        }


        // 2. 處理 LED 狀態發佈 (從 Core 1 接收並發佈)

        if (xSemaphoreTake(xStatusMutex, (TickType_t)10) == pdTRUE) {

            if (current_led_status != "SENT") {

                mqttClient.beginMessage(topic_LED_status_publish, current_led_status.length(), false, 1, false);

                mqttClient.print(current_led_status);

                mqttClient.endMessage();


                Serial.print("Core 0: Published LED Status: ");

                Serial.println(current_led_status);

                

                current_led_status = "SENT"; 

            }

            xSemaphoreGive(xStatusMutex);

        }

        

        vTaskDelay(pdMS_TO_TICKS(50)); 

    }

}



void connectWifi() {

    Serial.print("Core 0: Connecting to Wi-Fi...");

    WiFi.begin(ssid, password); 

    while (WiFi.status() != WL_CONNECTED) {

        vTaskDelay(pdMS_TO_TICKS(500));

        Serial.print(".");

    }

    Serial.println("\nCore 0: Wi-Fi connected.");

    Serial.print("IP Address: ");

    Serial.println(WiFi.localIP());

}


void connectMqtt() {

    Serial.print("Core 0: Connecting to MQTT Broker: ");

    Serial.println(mqttBroker);

    

    mqttClient.setId("ESP32_MFRC522_LED_Client"); 


    if (!mqttClient.connect(mqttBroker, mqttPort)) {

        Serial.print("Core 0: MQTT connection failed! Error code = ");

        Serial.println(mqttClient.connectError());

        vTaskDelay(pdMS_TO_TICKS(4000));

        return;

    }

    Serial.println("Core 0: MQTT connected.");

}


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

// ------------------------------ CORE 1: RFID/LED 控制任務 -----------------------

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


void rfidLedControlTask(void *pvParameters) {

    pinMode(LED_PIN, OUTPUT);

    digitalWrite(LED_PIN, LOW); 


    vTaskDelay(pdMS_TO_TICKS(500)); 

    mfrc522.PCD_Init();      

    Serial.println("Core 1: RFID/LED Control Task Running.");


    String led_command;

    unsigned long flash_timer = 0;

    bool led_state = false;


    while (1) {

        

        // 1. 處理來自 Core 0 的 LED 命令 (Queue)

        if (xQueueReceive(xLedQueue, &led_command, (TickType_t)0) == pdPASS) {

            

            flash_timer = 0; 


            if (led_command == "ON") {

                digitalWrite(LED_PIN,LOW);

            } else if (led_command == "OFF") {

                digitalWrite(LED_PIN, HIGH);

            } else if (led_command == "FLASH") {

                flash_timer = millis();

            } else if (led_command == "TIMER") {

                flash_timer = millis() + 10000; // 10 秒定時

                digitalWrite(LED_PIN,LOW);

            }

            

            if (xSemaphoreTake(xStatusMutex, (TickType_t)10) == pdTRUE) {

                current_led_status = led_command;

                xSemaphoreGive(xStatusMutex);

            }

        }


        // 2. 處理 LED 邏輯 (閃爍/定時)

        if (flash_timer > 0) {

            if (led_command == "FLASH") {

                if (millis() - flash_timer >= 500) {

                    led_state = !led_state;

                    digitalWrite(LED_PIN, led_state);

                    flash_timer = millis();

                }

            } else if (led_command == "TIMER") {

                if (millis() >= flash_timer) {

                    digitalWrite(LED_PIN, HIGH);

                    flash_timer = 0; 

                    led_command = "OFF";

                    

                    if (xSemaphoreTake(xStatusMutex, (TickType_t)10) == pdTRUE) {

                        current_led_status = "OFF";

                        xSemaphoreGive(xStatusMutex);

                    }

                }

            }

        }

        

        // 3. 處理 RFID 讀取 

        if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {

            

            byte* currentUID = mfrc522.uid.uidByte;

            byte currentUIDSize = mfrc522.uid.size;

            String hexUID = uidToHexString(currentUID, currentUIDSize);

            

            bool is_same_card = true;

            if (currentUIDSize != last_UID_Size) {

                is_same_card = false;

            } else {

                for (int i = 0; i < currentUIDSize; i++) {

                    if (currentUID[i] != last_UID[i]) {

                        is_same_card = false;

                        break;

                    }

                }

            }

            

            bool should_publish = false;

            

            if (!is_same_card) {

                Serial.println("Core 1: New card detected. Publishing immediately.");

                should_publish = true;

            } else if (millis() - last_publish_time >= REPEAT_DELAY_MS) {

                Serial.println("Core 1: Same card detected after 5s. Publishing.");

                should_publish = true;

            }

            

            if (should_publish) {

                if (xSemaphoreTake(xUidMutex, (TickType_t)10) == pdTRUE) {

                    new_uid_to_publish = hexUID; 

                    xSemaphoreGive(xUidMutex);

                }

                

                last_publish_time = millis();

                memcpy(last_UID, currentUID, currentUIDSize); 

                last_UID_Size = currentUIDSize;

            }

            

            mfrc522.PICC_HaltA(); 


        }

        

        vTaskDelay(pdMS_TO_TICKS(10)); 

    }

}


// 將 UID 轉換為十六進位字串 (例如 04C926442A2780)

String uidToHexString(byte *buffer, byte bufferSize) {

    String output = "";

    for (byte i = 0; i < bufferSize; i++) {

        if (buffer[i] < 0x10) {

            output += "0";

        }

        output += String(buffer[i], HEX);

    }

    output.toUpperCase();

    return output;

}


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

// ------------------------------------ SETUP & LOOP -------------------------------

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


void setup() {

    Serial.begin(115200);

    

    // *** 最終解決方案: 引入 esp_task_wdt.h 並呼叫 esp_task_wdt_deinit() ***

    // 這將完全禁用 Task WDT,解決不斷出現的 'task not found' 錯誤。

    esp_task_wdt_deinit();

    

    Serial.println("Task Watchdog Timer (TWDT) completely disabled.");


    SPI.begin();

    

    // 初始化 Mutex 和 Queue

    xUidMutex = xSemaphoreCreateMutex(); 

    xStatusMutex = xSemaphoreCreateMutex();

    xLedQueue = xQueueCreate(5, sizeof(String)); 

    

    if (xUidMutex == NULL || xStatusMutex == NULL || xLedQueue == NULL) {

        Serial.println("FreeRTOS resource creation failed!");

        while (1);

    }

    

    // 啟動 Core 0 上的 MQTT 任務

    xTaskCreatePinnedToCore(

        ledMqttTask,      

        "MQTT_PUB_Task",  

        10000,            

        NULL,             

        1,                

        NULL,             

        0                 // 核心 ID (Core 0)

    );


    // 啟動 Core 1 上的 RFID/LED 控制任務

    xTaskCreatePinnedToCore(

        rfidLedControlTask,         

        "RFID_LED_Task",      

        12288,             

        NULL,             

        1,                

        NULL,             

        1                 // 核心 ID (Core 1)

    );

}


void loop() {

    vTaskDelay(1); 

}




//=======================================================

程式碼是一個使用 ESP32 雙核心 (Dual-Core) 架構的專案,結合了 MFRC522 RFID 讀卡器MQTT 網路通訊以及 LED 控制。它專門為了解決多工處理時可能發生的看門狗計時器 (WDT) 錯誤,並將網路和硬體任務分派到不同的核心上運行。

以下是程式碼的逐行說明:


I. 標頭檔引入 (Includes)

程式碼說明
#include <freertos/...>引入 FreeRTOS 函式庫,用於支援 ESP32 的雙核心操作、任務創建、互斥鎖 (Mutex) 和佇列 (Queue) 等。
#include <ArduinoMqttClient.h>引入 MQTT 客戶端函式庫,用於連接 MQTT Broker。
#include <WiFi.h>引入 ESP32 的 Wi-Fi 函式庫。
#include "esp_task_wdt.h"【關鍵修正】 引入 ESP32 Task Watchdog Timer 相關定義。這是解決您序列埠中 task not found 錯誤的關鍵,允許我們在 setup() 中完全禁用它。
#include <MFRC522v2.h>引入 MFRC522 RFID 讀卡器函式庫及相關驅動程式。

這個程式碼是一個使用 ESP32 雙核心 (Dual-Core) 架構的專案,結合了 MFRC522 RFID 讀卡器MQTT 網路通訊以及 LED 控制。它專門為了解決多工處理時可能發生的看門狗計時器 (WDT) 錯誤,並將網路和硬體任務分派到不同的核心上運行。

以下是程式碼的逐行說明:


I. 標頭檔引入 (Includes)

程式碼說明
#include <freertos/...>引入 FreeRTOS 函式庫,用於支援 ESP32 的雙核心操作、任務創建、互斥鎖 (Mutex) 和佇列 (Queue) 等。
#include <ArduinoMqttClient.h>引入 MQTT 客戶端函式庫,用於連接 MQTT Broker。
#include <WiFi.h>引入 ESP32 的 Wi-Fi 函式庫。
#include "esp_task_wdt.h"【關鍵修正】 引入 ESP32 Task Watchdog Timer 相關定義。這是解決您序列埠中 task not found 錯誤的關鍵,允許我們在 setup() 中完全禁用它。
#include <MFRC522v2.h>引入 MFRC522 RFID 讀卡器函式庫及相關驅動程式。

II. 設定與硬體初始化

程式碼說明
const char* ssid = "alex9ufo";Wi-Fi 網路名稱。
const char* mqttBroker = ...MQTT Broker (代理人) 的網址 (例如 broker.mqtt-dashboard.com)。
MqttClient mqttClient(wifiClient);建立 MQTT 客戶端物件,使用 WiFi 連線。
const char* topic_UID_publish = ...

發布 (Publish) RFID UID 的主題 (alex9ufo/rfid/UID) 11

const char* topic_LED_subscribe = ...

訂閱 (Subscribe) LED 控制命令的主題 (alex9ufo/rfid/led) 2222

const char* topic_LED_status_publish = ...

發布 (Publish) LED 當前狀態的主題 (alex9ufo/rfid/ledStatus) 3333

#define RST_PIN 27 / #define SS_PIN 5定義 MFRC522 讀卡器的 RST (重設) 和 SS (片選) 腳位。
#define LED_PIN 2定義 LED 腳位 (GPIO 2)。
MFRC522 mfrc522{driver};建立 MFRC522 讀卡器物件。

這個程式碼是一個使用 ESP32 雙核心 (Dual-Core) 架構的專案,結合了 MFRC522 RFID 讀卡器MQTT 網路通訊以及 LED 控制。它專門為了解決多工處理時可能發生的看門狗計時器 (WDT) 錯誤,並將網路和硬體任務分派到不同的核心上運行。

以下是程式碼的逐行說明:


I. 標頭檔引入 (Includes)

程式碼說明
#include <freertos/...>引入 FreeRTOS 函式庫,用於支援 ESP32 的雙核心操作、任務創建、互斥鎖 (Mutex) 和佇列 (Queue) 等。
#include <ArduinoMqttClient.h>引入 MQTT 客戶端函式庫,用於連接 MQTT Broker。
#include <WiFi.h>引入 ESP32 的 Wi-Fi 函式庫。
#include "esp_task_wdt.h"【關鍵修正】 引入 ESP32 Task Watchdog Timer 相關定義。這是解決您序列埠中 task not found 錯誤的關鍵,允許我們在 setup() 中完全禁用它。
#include <MFRC522v2.h>引入 MFRC522 RFID 讀卡器函式庫及相關驅動程式。

II. 設定與硬體初始化

程式碼說明
const char* ssid = "alex9ufo";Wi-Fi 網路名稱。
const char* mqttBroker = ...MQTT Broker (代理人) 的網址 (例如 broker.mqtt-dashboard.com)。
MqttClient mqttClient(wifiClient);建立 MQTT 客戶端物件,使用 WiFi 連線。
const char* topic_UID_publish = ...

發布 (Publish) RFID UID 的主題 (alex9ufo/rfid/UID) 11

const char* topic_LED_subscribe = ...

訂閱 (Subscribe) LED 控制命令的主題 (alex9ufo/rfid/led) 2222

const char* topic_LED_status_publish = ...

發布 (Publish) LED 當前狀態的主題 (alex9ufo/rfid/ledStatus) 3333

#define RST_PIN 27 / #define SS_PIN 5定義 MFRC522 讀卡器的 RST (重設) 和 SS (片選) 腳位。
#define LED_PIN 2定義 LED 腳位 (GPIO 2)。
MFRC522 mfrc522{driver};建立 MFRC522 讀卡器物件。

III. FreeRTOS 任務間通訊變數 (IPC)

程式碼說明
String new_uid_to_publish = "";Core 1 讀取到新卡時,將 UID 暫存於此,供 Core 0 發布。
SemaphoreHandle_t xUidMutex;互斥鎖 (Mutex):保護 new_uid_to_publish,確保 Core 0 和 Core 1 同時存取時不會發生資料衝突。
QueueHandle_t xLedQueue;佇列 (Queue):Core 0 接收到 MQTT LED 命令後,將命令字串放入佇列,供 Core 1 讀取和執行。
String current_led_status = "OFF";紀錄 LED 當前狀態,用於 Core 0 發布狀態確認。
SemaphoreHandle_t xStatusMutex;互斥鎖:保護 current_led_status 變數。
byte last_UID[10] = {0};儲存上次讀取的卡片 UID,用於防止重複發布,並實現 5 秒重複延遲邏輯。

這個程式碼是一個使用 ESP32 雙核心 (Dual-Core) 架構的專案,結合了 MFRC522 RFID 讀卡器MQTT 網路通訊以及 LED 控制。它專門為了解決多工處理時可能發生的看門狗計時器 (WDT) 錯誤,並將網路和硬體任務分派到不同的核心上運行。

以下是程式碼的逐行說明:


I. 標頭檔引入 (Includes)

程式碼說明
#include <freertos/...>引入 FreeRTOS 函式庫,用於支援 ESP32 的雙核心操作、任務創建、互斥鎖 (Mutex) 和佇列 (Queue) 等。
#include <ArduinoMqttClient.h>引入 MQTT 客戶端函式庫,用於連接 MQTT Broker。
#include <WiFi.h>引入 ESP32 的 Wi-Fi 函式庫。
#include "esp_task_wdt.h"【關鍵修正】 引入 ESP32 Task Watchdog Timer 相關定義。這是解決您序列埠中 task not found 錯誤的關鍵,允許我們在 setup() 中完全禁用它。
#include <MFRC522v2.h>引入 MFRC522 RFID 讀卡器函式庫及相關驅動程式。

II. 設定與硬體初始化

程式碼說明
const char* ssid = "alex9ufo";Wi-Fi 網路名稱。
const char* mqttBroker = ...MQTT Broker (代理人) 的網址 (例如 broker.mqtt-dashboard.com)。
MqttClient mqttClient(wifiClient);建立 MQTT 客戶端物件,使用 WiFi 連線。
const char* topic_UID_publish = ...

發布 (Publish) RFID UID 的主題 (alex9ufo/rfid/UID) 11

const char* topic_LED_subscribe = ...

訂閱 (Subscribe) LED 控制命令的主題 (alex9ufo/rfid/led) 2222

const char* topic_LED_status_publish = ...

發布 (Publish) LED 當前狀態的主題 (alex9ufo/rfid/ledStatus) 3333

#define RST_PIN 27 / #define SS_PIN 5定義 MFRC522 讀卡器的 RST (重設) 和 SS (片選) 腳位。
#define LED_PIN 2定義 LED 腳位 (GPIO 2)。
MFRC522 mfrc522{driver};建立 MFRC522 讀卡器物件。

III. FreeRTOS 任務間通訊變數 (IPC)

程式碼說明
String new_uid_to_publish = "";Core 1 讀取到新卡時,將 UID 暫存於此,供 Core 0 發布。
SemaphoreHandle_t xUidMutex;互斥鎖 (Mutex):保護 new_uid_to_publish,確保 Core 0 和 Core 1 同時存取時不會發生資料衝突。
QueueHandle_t xLedQueue;佇列 (Queue):Core 0 接收到 MQTT LED 命令後,將命令字串放入佇列,供 Core 1 讀取和執行。
String current_led_status = "OFF";紀錄 LED 當前狀態,用於 Core 0 發布狀態確認。
SemaphoreHandle_t xStatusMutex;互斥鎖:保護 current_led_status 變數。
byte last_UID[10] = {0};儲存上次讀取的卡片 UID,用於防止重複發布,並實現 5 秒重複延遲邏輯。

IV. Core 0 網路任務 (MQTT/控制中心) 函式

程式碼說明
void connectWifi()連接到設定好的 Wi-Fi 網路,直到連線成功為止。
void connectMqtt()連接到 MQTT Broker,如果連線失敗則印出錯誤代碼並等待。
void onMqttMessage(int messageSize)MQTT 訂閱回調函式:當收到訂閱主題 (alex9ufo/rfid/led) 的訊息時被觸發。它將收到的命令 (例如 "ON", "FLASH") 轉換為大寫,並透過 xQueueSend 傳送到 Core 1 處理。
void ledMqttTask(void *pvParameters)Core 0 主任務:負責所有網路通訊。
1. 確保 Wi-Fi 和 MQTT 連線正常。
2. 呼叫 mqttClient.poll() 處理連線和接收訊息。

3. 發布 UID: 檢查 new_uid_to_publish 是否有新資料(使用 xUidMutex 保護),如果有則發布到 alex9ufo/rfid/UID 主題 4

4. 發布狀態: 檢查 current_led_status 是否有更新(使用 xStatusMutex 保護),如果有則發布到 alex9ufo/rfid/ledStatus 主題 5555

5. vTaskDelay(pdMS_TO_TICKS(50)):釋放 CPU 給其他任務,保持 Core 0 的系統穩定。

V. Core 1 硬體控制任務 (RFID/LED) 函式

程式碼說明
void rfidLedControlTask(void *pvParameters)Core 1 主任務:負責所有硬體操作和邏輯控制。
1. 初始化 LED 腳位和 MFRC522 讀卡器 (mfrc522.PCD_Init())。
2. 處理 LED 命令: 透過 xQueueReceive 從 Core 0 接收 LED 命令。根據命令執行 ON/OFF/FLASH/TIMER 邏輯。
3. 處理 LED 邏輯: 根據接收到的命令,使用 flash_timer 變數實現 LED 閃爍 (FLASH) 或定時關閉 (TIMER) 的邏輯。
4. 處理 RFID 讀取: 檢查是否有新卡 (PICC_IsNewCardPresent) 並讀取序列號 (PICC_ReadCardSerial)。
5. 卡片去重與計時: 判斷是新卡還是上次讀取的舊卡。新卡立即發布;舊卡則必須等待 REPEAT_DELAY_MS (5000ms) 後才允許再次發布,避免重複洗板。
6. 傳送 UID: 如果滿足發布條件,將 UID 轉為字串並存入 new_uid_to_publish (使用 xUidMutex 保護),等待 Core 0 發布。
String uidToHexString(...)輔助函式:將 RFID 讀取的 Byte 陣列 (UID) 轉換為十六進位字串,方便 MQTT 傳輸和資料庫儲存。

VI. 主程式設定區塊 (setup()loop())

程式碼說明
void setup()程式開始時只執行一次。
Serial.begin(115200);設定序列埠輸出速率。
esp_task_wdt_deinit();【最終修正的核心】 這是徹底解決 Task Watchdog Timer 錯誤的指令。它會完全禁用 ESP32 系統內部的任務看門狗,避免網路或 FreeRTOS 任務繁忙時出現錯誤重啟或序列埠報錯。
SPI.begin();初始化 SPI 介面,供 MFRC522 使用。
xUidMutex = xSemaphoreCreateMutex();初始化 FreeRTOS 資源 (互斥鎖和佇列)。
xTaskCreatePinnedToCore(...)創建並啟動任務:
- ledMqttTask 綁定到 Core 0:處理較慢的網路 I/O 操作。
- rfidLedControlTask 綁定到 Core 1:處理即時的硬體 I/O (RFID/LED) 和控制邏輯。
void loop()在 FreeRTOS 架構下,loop() 函式通常閒置或只包含極小的延遲。
vTaskDelay(1);loop 函式維持運作並釋放給系統底層任務 (Idle Task)。


沒有留言:

張貼留言

ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite

 ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite  ESP32 VS Code 程式 ; PlatformIO Project Configuration File ; ;   Build op...