2025年12月31日 星期三

使用telegram 控制wokwi LED + 模擬 RFID (UID共10個)

使用telegram 控制wokwi LED + 模擬 RFID (UID共10個) 




需修改 Token 與 Chat ID

#define BOTtoken "80221700986:AAGyemymK9_d1HcTrGJWl3mtqHmilxB64_5Zw"
#define CHAT_ID  "729635218469"

步驟一:建立 Bot 並取得 Token
  1. 開啟 Telegram,搜尋並打開官方的 @BotFather
  2. 發送指令 /newbot,依照指示設定 Bot 的名稱和 username。Bot username:必須是唯一的,且以「bot」結尾,不能與其他 Bot 或用戶重複。
  3. 建立成功後,BotFather 會提供一串 API Token,請妥善保存,這串 Token 就像是 Bot 的密碼。 
步驟二:與 Bot 互動以生成更新
  1. 在 Telegram 搜尋你的 Bot,打開聊天室並點擊 Start 或隨意發送一則訊息 (例如 "Hi")。
  2. 如果是群組/頻道:將 Bot 加入群組或頻道,並確保 Bot 具備接收訊息的權限,然後在群組/頻道中發送訊息。 
步驟三:透過 API 查詢 Chat ID
  1. 打開瀏覽器,輸入以下網址,將 <token> 替換成你從 BotFather 取得的 API Token:
    https://api.telegram.org/bot<token>/getUpdates
  2. 查看頁面中的 JSON 內容,尋找 result 陣列中的 message 物件,chat 物件裡就有 id 欄位,這個數字就是你的 Chat ID。
    • 個人聊天 ID 格式:純數字 (e.g., 123456789)。
    • 群組/頻道 ID 格式:需加上 -100 前綴 (e.g., -100123456789)。 








WOKWI程式

#include <SPI.h>
#include <MFRC522.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// --- 硬體腳位 ---
#define SS_PIN    5
#define RST_PIN   22
#define LED_PIN   2
#define I2C_SDA   17
#define I2C_SCL   16

// --- 設定區 ---
const char* ssid = "Wokwi-GUEST";
const char* password = "";
#define BOTtoken "80221700986:AAGyemymK9_d1HcTrGJWl3mtqHmilxB64_5Zw"
#define CHAT_ID  "729635218469"

LiquidCrystal_I2C lcd(0x27, 16, 2);
MFRC522 mfrc522(SS_PIN, RST_PIN);
WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

// --- 全域變數與隊列 ---
QueueHandle_t rfidQueue;
struct RfidMsg { char uid[20]; };

String lastRfidUid = "尚未感應";
bool ledStatus = false;
bool isFlashing = false;
unsigned long lastTimeBotRan;
const unsigned long botRequestDelay = 1000;
String keyboardJson = "[[\"/on\", \"/off\"], [\"/flash\", \"/timer\"], [\"/rfidUid\", \"/status\"]]";

// --- Telegram 指令處理 ---
void handleNewMessages(int numNewMessages) {
  for (int i = 0; i < numNewMessages; i++) {
    String chat_id = String(bot.messages[i].chat_id);
    String text = bot.messages[i].text;
   
    Serial.printf("\n[Telegram] CMD: %s\n", text.c_str());
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("CMD: " + text);

    isFlashing = false;
    if (text == "/on") {
      digitalWrite(LED_PIN, HIGH); ledStatus = true;
      lcd.setCursor(0, 1); lcd.print("LED: ON");
      bot.sendMessage(chat_id, "💡 LED 已開啟", "");
    }
    else if (text == "/off") {
      digitalWrite(LED_PIN, LOW); ledStatus = false;
      lcd.setCursor(0, 1); lcd.print("LED: OFF");
      bot.sendMessage(chat_id, "🌑 LED 已關閉", "");
    }
    else if (text == "/flash") {
      isFlashing = true;
      lcd.setCursor(0, 1); lcd.print("Mode: Flash");
      bot.sendMessage(chat_id, "✨ LED 閃爍中", "");
    }
    else if (text == "/timer") {
      digitalWrite(LED_PIN, HIGH); ledStatus = true;
      bot.sendMessage(chat_id, "⏳ 5秒計時...", "");
      vTaskDelay(5000 / portTICK_PERIOD_MS);
      digitalWrite(LED_PIN, LOW); ledStatus = false;
      bot.sendMessage(chat_id, "✅ 時間到", "");
    }
    else if (text == "/rfidUid") {
      bot.sendMessage(chat_id, "🆔 UID: " + lastRfidUid, "");
    }
    else if (text == "/status") {
      bot.sendMessage(chat_id, "📊 LED: " + String(ledStatus ? "ON" : "OFF") + "\nUID: " + lastRfidUid, "");
    }
    else {
      bot.sendMessageWithReplyKeyboard(chat_id, "請選擇指令:", "", keyboardJson, true);
    }
  }
}

// --- Core 0: 處理所有通訊與邏輯 ---
void telegramTask(void *pvParameters) {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) { vTaskDelay(500 / portTICK_PERIOD_MS); }
 
  configTime(0, 0, "pool.ntp.org");
  client.setInsecure();
  bot.sendMessageWithReplyKeyboard(CHAT_ID, "🚀 系統啟動成功!", "Markdown", keyboardJson, true);

  RfidMsg rMsg;
  while (true) {
    // 檢查是否有新指令
    if (millis() > lastTimeBotRan + botRequestDelay) {
      int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
      while (numNewMessages) {
        handleNewMessages(numNewMessages);
        numNewMessages = bot.getUpdates(bot.last_message_received + 1);
      }
      lastTimeBotRan = millis();
    }

    // 從 Queue 接收來自 Core 1 的 RFID 卡號並發送 Telegram (解決衝突關鍵)
    if (xQueueReceive(rfidQueue, &rMsg, 0) == pdPASS) {
      lastRfidUid = String(rMsg.uid);
      bot.sendMessage(CHAT_ID, "🔔 偵測到卡片!\nUID: " + lastRfidUid, "");
      Serial.println("Telegram 已同步推播卡號");
    }

    if (isFlashing) {
      digitalWrite(LED_PIN, !digitalRead(LED_PIN));
      vTaskDelay(300 / portTICK_PERIOD_MS);
    }
    vTaskDelay(10 / portTICK_PERIOD_MS);
  }
}

// --- Core 1: 僅負責 RFID 掃描 (不進行網路操作) ---
void rfidTask(void *pvParameters) {
  SPI.begin();
  mfrc522.PCD_Init();
  RfidMsg rMsg;
  while (true) {
    if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
      String uidStr = "";
      for (byte i = 0; i < mfrc522.uid.size; i++) {
        uidStr += (mfrc522.uid.uidByte[i] < 0x10 ? "0" : "");
        uidStr += String(mfrc522.uid.uidByte[i], HEX);
      }
      uidStr.toUpperCase();
     
      // 更新 LCD
      lcd.clear();
      lcd.setCursor(0, 0); lcd.print("RFID Read!");
      lcd.setCursor(0, 1); lcd.print("ID: " + uidStr);
     
      // 將資料傳入 Queue,交給 Core 0 處理網路發送
      uidStr.toCharArray(rMsg.uid, 20);
      xQueueSend(rfidQueue, &rMsg, portMAX_DELAY);

      mfrc522.PICC_HaltA();
      mfrc522.PCD_StopCrypto1();
    }
    vTaskDelay(200 / portTICK_PERIOD_MS);
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  Wire.begin(I2C_SDA, I2C_SCL);
  lcd.init(); lcd.backlight();
  lcd.print("Init Queue...");

  // 建立隊列:長度 10,每個元素大小為 RfidMsg
  rfidQueue = xQueueCreate(10, sizeof(RfidMsg));

  if (rfidQueue != NULL) {
    xTaskCreatePinnedToCore(telegramTask, "Telegram_Task", 10240, NULL, 1, NULL, 0);
    xTaskCreatePinnedToCore(rfidTask, "RFID_Task", 4096, NULL, 1, NULL, 1);
  }
}

void loop() { vTaskDelay(portMAX_DELAY); }




這份程式碼是一個基於 ESP32 雙核心架構 的物聯網應用,結合了 Telegram 機器人 遠端控制、RFID 刷卡識別 以及 I2C LCD 實時顯示

其核心設計目標是「穩定性」,透過 FreeRTOS Queue (隊列) 機制解決了 WiFi 連網與硬體掃描之間的資源衝突。


核心功能說明

1. 遠端指令控制 (Telegram Bot)

使用者可以透過 Telegram 手機 App 向機器人發送以下指令,ESP32 會即時做出反應:

  • /on / /off:直接開啟或關閉 ESP32 上的 LED 燈。

  • /flash:使 LED 進入持續閃爍模式。

  • /timer:開啟 LED 並在 5 秒後自動熄滅(非阻塞式計時)。

  • /rfidUid:查詢系統最後一次讀取到的 RFID 卡片編號。

  • /status:回報目前 LED 狀態(亮/滅)與最後的卡片 UID。

  • 自定義按鈕選單:系統啟動時會自動彈出按鈕選單,使用者不需手動打字,點擊螢幕即可控制。

2. RFID 刷卡識別與主動推播

  • 當 RFID 模組偵測到卡片感應時,ESP32 會讀取卡片的唯一識別碼 (UID)。

  • 自動通知:讀取成功後,ESP32 會主動傳送 Telegram 訊息給使用者(例如:「🔔 偵測到卡片!UID: 9FD6B1BD」)。

3. 實時狀態顯示 (LCD 1602)

  • 指令顯示:LCD 會顯示目前收到的 Telegram 指令內容。

  • 狀態顯示:同步顯示 LED 目前是 ON 還是 OFF

  • 卡片顯示:刷卡時,LCD 第二行會立刻顯示該卡片的 UID。


程式設計特點:

A. 雙核心任務分配 (Dual Core)

ESP32 有兩個處理核心,程式將工作分開處理以確保流暢度:

  • Core 0 (TelegramTask):負責處理最耗資源的 WiFi 連線、HTTPS 加密通訊

  • Core 1 (RFIDTask):負責高頻率的 RFID 掃描,確保刷卡時反應靈敏,不會因為網路延遲而漏讀卡片。

B. Queue (隊列) 通訊機制

這是解決你之前 Reset 崩潰問題的關鍵。

  • 運作邏輯:當 Core 1 讀到卡片時,它不直接傳送 Telegram 訊息(因為網路硬體被 Core 0 佔用),而是將資料放進一個名為 rfidQueue 的「信箱」。Core 0 會定期檢查信箱,領取資料後再統一由 Core 0 發送。

  • 優點:有效防止兩個核心同時搶奪 WiFi/SPI 硬體資源,提升系統長時間運行的穩定性。

C. 安全連線 (HTTPS)

  • 程式碼包含 configTimeclient.setInsecure()。這是因為 Telegram API 強制要求 SSL 加密,程式會先進行網路校時,確保加密連線握手成功。


硬體清單與連接參考

  • 控制器:ESP32

  • 顯示器:LCD 1602 (需帶 I2C 轉接板,接 GPIO 16/17)

  • 讀卡器:RC522 RFID 模組 (SPI 介面,接 GPIO 5, 18, 19, 23)

  • 執行器:LED 燈 (接 GPIO 2)


iOS下載網址:https://reurl.cc/VaKlNQ
Android下載網址:https://reurl.cc/alQALY
PC/Mac/Linux下載網址:https://reurl.cc/lL8Ag6
macOS下載網址:https://reurl.cc/EKkeeK
網頁版連結:https://reurl.cc/mdaAAM


安裝 Telegram 很簡單,無論是手機還是電腦,都可以透過官方網站或應用商店下載,下載後用手機號碼註冊登入即可使用,手機版可到 App Store/Google Play 搜尋下載,電腦版則到 telegram.org 官網選擇對應系統(Windows, macOS, Linux)安裝。 
手機版安裝 (iOS & Android)
  1. iOS (iPhone/iPad):打開 App Store,搜尋 "Telegram" 即可下載安裝。
  2. Android (安卓):打開 Google Play 商店,搜尋 "Telegram" 即可下載安裝。
  3. 開啟與註冊:安裝後打開 App,點選「Start Messaging」,輸入手機號碼並完成驗證碼即可註冊登入。 
電腦版安裝 (Windows/macOS/Linux)
  1. 前往官網:用瀏覽器訪問 Telegram 官方網站 telegram.org。
  2. 選擇下載:在下載頁面選擇您電腦系統(Windows, macOS, Linux)的版本,並下載安裝包。
  3. 安裝程式:執行下載的檔案,按照安裝向導的指示完成安裝。
  4. 登入:啟動程式,用手機號碼登入即可使用。 
中文化設定 (手機/電腦)

  • 方法:在 Telegram 中點選語言包連結 (例如:繁體中文(台灣)連結),會自動開啟 App 並提示你切換語言,點「Change」或「Apply」即可。 
由於 Telegram 預設是英文介面,且在軟體內的 Settings 中,也找不到中文語言的選項,因為官方並未提供中文化的版本,不過,使用者還是可以透過加入「Telegram中文」群組,如行動裝置能搜尋帳號「Tele_zh_TW」、電腦版與網頁版則透過「 https:// Telegram .me/Tele_zh_TW」連結進入,並安裝由網友自發維護,對應的中文語系檔案後,即能毫無障礙且無縫享用 Telegram 的所有功能。


如果已經下載完成,但還不是中文頁面,可掃描以上QRcode,或點此連結直接幫你們翻譯成中文:👉https://t.me/setlanguage/taiwan‬

沒有留言:

張貼留言

使用telegram 控制wokwi LED + 模擬 RFID (UID共10個)

使用telegram 控制wokwi LED + 模擬 RFID (UID共10個)  需修改  Token 與  Chat ID #define BOTtoken "80221700986:AAGyemymK9_d1HcTrGJWl3mtqHmilxB64_5Zw...