2026 作業3 RFID+ Telegram 練習
(Wokwi 與 Telegram 二者溝通訊息反映比較慢)
歡迎 Alex 使用 RFID 控制系統
/on : 開啟 LED
/off : 關閉 LED
/flash : 閃爍模式
/timer : 開啟 5 秒
rfid-rc522.chip.c 與 rfid-rc522.chip.json 還是需要沿用作業2
如何下載及安裝 telegram(電報) app 、如何中文化它的操作介面
https://alex9ufoexploer.blogspot.com/2025/04/telegram-app.html
Telegram 安裝快速簡便:手機用戶至 App Store 或 Google Play 搜尋「Telegram」下載;電腦用戶可從 官方網站 或 Microsoft Store 下載 Desktop 版本。安裝後輸入手機號碼並填寫驗證碼即可註冊使用。
以下是 Telegram 安裝與設定的詳細步驟:
1. 手機版安裝 (Android/iOS)
- 下載: Android 開啟 Google Play,iOS 開啟 App Store,搜尋 "Telegram" 並安裝。
- 註冊: 開啟 APP,點擊 "Start Messaging",輸入手機號碼。
- 驗證: 輸入收到的簡訊驗證碼 (SMS) 完成登入。
2. 電腦版安裝 (Windows/Mac/Linux)
- 下載: 前往 Telegram 官網 或 Microsoft Store 下載 Telegram Desktop。
- 安裝:執行下載的安裝檔,按指示完成安裝。
- 登入: 開啟程式,使用手機版 Telegram 掃描 QR Code 或輸入手機號碼驗證登入。
3. 設定繁體中文界面
若需要中文介面,可以在安裝登入後點擊以下連結進行切換:
- 繁體中文(台灣)語言包: 點擊此連結切換。
- 切換方法: 點擊連結後,在彈出視窗點選 "Change" 或 "Apply Language"。
4. 常見問題
- 驗證碼: 若收不到簡訊,請檢查手機號碼是否正確,或嘗試使用語音驗證。
- 同步: 只要使用相同手機號碼,手機和電腦的對話紀錄會自動同步。
#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 = "";
// Telegram 設定 修改成自己的 BOTtoken CHAT_ID
#define BOTtoken "80212700986:AbAGymymK9_d1HcTGJWl3mtqHmilxB64_5Zw"
#define CHAT_ID "79654218469"
// 物件初始化
WiFiClientSecure secured_client;
UniversalTelegramBot bot(BOTtoken, secured_client);
LiquidCrystal_I2C lcd(0x27, 16, 2);
MFRC522 mfrc522(SS_PIN, RST_PIN);
// --- 全域變數與 FreeRTOS 隊列 ---
QueueHandle_t rfidQueue;
struct RfidMsg { char uid[20]; };
enum LedMode { LED_OFF, LED_ON, LED_FLASH, LED_TIMER };
LedMode currentMode = LED_OFF;
unsigned long timerStartTime = 0;
bool statusNeedsUpdate = false;
// --- 輔助函式:顯示訊息到 Serial 與 LCD ---
void displayLog(String line1, String line2) {
Serial.println(">>> " + line1 + " | " + line2);
lcd.clear();
lcd.setCursor(0, 0); lcd.print(line1.substring(0, 16));
lcd.setCursor(0, 1); lcd.print(line2.substring(0, 16));
}
// --- 狀態回傳函式 ---
void broadcastStatus(String state, String source) {
bot.sendMessage(CHAT_ID, "📢 LED Status: " + state + " (via " + source + ")", "");
displayLog("Cmd: " + state, "From: " + source);
}
// --- 接收指令解析 ---
void executeCommand(String cmd, String source) {
cmd.toLowerCase();
cmd.trim();
if (cmd.length() == 0) return;
Serial.printf("[Command] From: %s, Text: %s\n", source.c_str(), cmd.c_str());
if (cmd == "on" || cmd == "/on") {
currentMode = LED_ON;
broadcastStatus("ON", source);
}
else if (cmd == "off" || cmd == "/off") {
currentMode = LED_OFF;
broadcastStatus("OFF", source);
}
else if (cmd == "flash" || cmd == "/flash") {
currentMode = LED_FLASH;
broadcastStatus("FLASHING", source);
}
else if (cmd == "timer" || cmd == "/timer") {
currentMode = LED_TIMER;
timerStartTime = millis();
broadcastStatus("TIMER_START", source);
}
}
// --- 任務 1: LED 硬體動作 ---
void ledTask(void *pvParameters) {
pinMode(LED_PIN, OUTPUT);
while (true) {
switch (currentMode) {
case LED_ON: digitalWrite(LED_PIN, HIGH); break;
case LED_OFF: digitalWrite(LED_PIN, LOW); break;
case LED_FLASH:
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
vTaskDelay(300 / portTICK_PERIOD_MS);
continue;
case LED_TIMER:
digitalWrite(LED_PIN, HIGH);
if (millis() - timerStartTime > 5000) {
currentMode = LED_OFF;
statusNeedsUpdate = true;
}
break;
}
vTaskDelay(50 / portTICK_PERIOD_MS);
}
}
// --- 任務 2: 通訊處理 ---
void commTask(void *pvParameters) {
WiFi.begin(ssid, password);
displayLog("WiFi Connecting", ssid);
while (WiFi.status() != WL_CONNECTED) {
vTaskDelay(500 / portTICK_PERIOD_MS);
Serial.print(".");
}
Serial.println("\nWiFi Connected!");
displayLog("WiFi Online", WiFi.localIP().toString());
secured_client.setInsecure();
// --- Reset 後發送歡迎訊息與指令清單 ---
String welcome = "歡迎 Alex 使用 RFID 控制系統\n";
welcome += "/on : 開啟 LED\n";
welcome += "/off : 關閉 LED\n";
welcome += "/flash : 閃爍模式\n";
welcome += "/timer : 開啟 5 秒";
bot.sendMessage(CHAT_ID, welcome, "");
Serial.println("歡迎訊息已發送到 Telegram");
RfidMsg rMsg;
unsigned long lastBotRun = 0;
while (true) {
if (millis() - lastBotRun > 1000) {
int num = bot.getUpdates(bot.last_message_received + 1);
for (int i = 0; i < num; i++) {
executeCommand(bot.messages[i].text, "Telegram");
}
lastBotRun = millis();
}
if (statusNeedsUpdate) {
broadcastStatus("OFF (Timer end)", "SYSTEM");
statusNeedsUpdate = false;
}
if (xQueueReceive(rfidQueue, &rMsg, 0) == pdPASS) {
bot.sendMessage(CHAT_ID, "🔔 RFID Detect: " + String(rMsg.uid), "");
displayLog("RFID Scanned", String(rMsg.uid));
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
// --- 任務 3: RFID 掃描 ---
void rfidTask(void *pvParameters) {
SPI.begin();
mfrc522.PCD_Init();
RfidMsg rMsg;
while (true) {
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
String uid = "";
for (byte i = 0; i < mfrc522.uid.size; i++) {
uid += (mfrc522.uid.uidByte[i] < 0x10 ? "0" : "");
uid += String(mfrc522.uid.uidByte[i], HEX);
}
uid.toUpperCase();
memset(rMsg.uid, 0, sizeof(rMsg.uid));
uid.substring(0, 19).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);
Wire.begin(I2C_SDA, I2C_SCL);
lcd.init(); lcd.backlight();
displayLog("System Loading", "Initializing...");
rfidQueue = xQueueCreate(10, sizeof(RfidMsg));
xTaskCreatePinnedToCore(commTask, "Comm", 10240, NULL, 1, NULL, 0);
xTaskCreatePinnedToCore(ledTask, "LED", 2048, NULL, 2, NULL, 1);
xTaskCreatePinnedToCore(rfidTask, "RFID", 4096, NULL, 1, NULL, 1);
}
void loop() {}



沒有留言:
張貼留言