前陣子入手 Mini PC,主要目的是跑 CentOS 當家用伺服器。利用週末 Coding For Fun,完成我的第一項應用,結合 WiFi Aruduino (ESP2688) + MFRC522 RFID 卡片應感模組,我寫了一個家用打卡鐘,「協助」小閃光與小木頭改掉賴床的壞習慣。(怎麼協助?簡單,科技執法外加罰則就可以囉)

在 FB 貼完影片引來不少迴響。Arduino 實體接線取自網路教學、程式來自現成範例小幅修改,接收打卡訊息的 ASP.NET Core 網站原理也很單純沒啥學問,原本沒打算獻醜,但陸續接到網友詢問製作細節,想想還是分享經驗,給有興趣的同學加減參考。

首先,我的 Arduino 主板用的是 ESP8266 NodeMcu,有整合 USB 介面並焊好接腳,內建 WiFi 功能可直接插 USB 上傳程式(有些版本需外接模組才能接電腦),支援 Arduino IDE,有現成程式庫及範例,寫起來跟標準 Arduino 沒什麼兩樣,重點台灣網拍就買得到,兩百塊有找就可以玩玩無線網路回報數據或遠端遙控等有趣應用~~,真便宜耶,效果太高了~~。沒接觸過的同學,我推薦 YouTuber 「佑來了」老師這篇給初學者的ESP8266 入門介紹與冤枉路分享 ,很值得一看。

MFRC 522 RFID 感應模組可讀取日常生活常見的感應卡片,如悠遊卡、iCash、信用卡及各式門禁卡,一樣能在網拍找到,價格一百出頭。

使用 ESP8266 的一項好處是它在創客界應用甚廣,可參考教學資源眾多。MRFC522 讀卡實做我主要參考這篇:WiFi RFID Reader 包含接線說明、照片、程式範例。文章裡用的 ESP8266 接腳代碼是 GPIOn,但電路板標示則是 D1/D2/D3...,需自行依所用主板規格對照 PIN 腳。我用的板子是 LoLin V3,規格如,故訊息接腳分別對映到 D1、D2、D5、D6、D7。

MFRC 522 接腳ESP8266 NodeMCU v3 接腳
RSTD1 (GPIO5)
NSSD2 (GPIO4)
MOSID7 (GPIO13/HMISO)
MISOD6 (GPIO12/HMOSI)
SCKD5 (GPIO14/HSCLK)
GNDG
VCC(3.3V)3V
IRQ未用

另外,我接了一個小蜂鳴器,負極接地,正極接 D8 控制輸出 3V 或 0V 控制產生長短嗶聲,提供刷卡結果的聲音回饋。組裝完成,找了個名片盒下方鑽孔透出 USB 插口當成簡易外殼,趕著 12 月起新制上路,專案要上線,就先不想什麼 3D 列印了。

thumbnail

MFRC 522 程式庫取自 Miguel Balboa 的開源專案,將 Github src 目錄 的 .h, .cpp 檔複製到 .ino (Arduino 程式檔)所在目錄,透過 include "MFRC522.h" 載入程式庫,參考網路範例完成 RFID 識別碼讀取部分。至於將內容上傳到 ASP.NET Core ,則是參考 ESP8266 程式庫內附範例及另一篇文章。總之,我不會 C 語言只能東抄西抄拼裝合成獸,測試成功的一刻我都想歡呼了。(很難想像,光是怎麼將 byte[] 轉成十六進字串就耗了我起過一個小時,有種老拳師被人挑斷手腳筋的悲涼感... Orz)

程式範例如下,自己都覺得醜,但身為 C 語言麻瓜我無力優化,很怕改一改不知為什麼就壞了(重溫程式菜鳥「搞出來就偷笑,每一步都如履薄冰」的滋味),但程式至少能動,大家加減參考。

#include <stdio.h>
#include <stdlib.h>
#include <Arduino.h>
#include "ESP8266WiFi.h"
#include <SPI.h>
#include "MFRC522.h"
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
ESP8266WiFiMulti WiFiMulti;

#define RST_PIN  5 // RST-PIN for RC522 - GPIO5 
#define SS_PIN  4 // SDA-PIN for RC522 - GPIO4 
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance

const char* ssid = "無線AP名稱";
const char* password = "無線AP密碼";

void setup() {
  Serial.begin(115200);
  // Set WiFi to station mode and disconnect from an AP if it was previously connected
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP(ssid, password);

  while (WiFiMulti.run() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP=");
  Serial.println(WiFi.localIP());
  
  SPI.begin();           // Init SPI bus
  mfrc522.PCD_Init();    // Init MFRC522
  
  Serial.println("RFID ready");
  //Set  D8 output mode to control buzzer
  pinMode(D8, OUTPUT);
}

void loop() {
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    delay(50);
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    delay(50);
    return;
  }
  // Show some details of the PICC (that is: the tag/card)
  Serial.print(F("Card UID:"));
  // Convert card uid to hex string
  to_hex(mfrc522.uid.uidByte, mfrc522.uid.size);
  // Send card uid to ASP.NET Core MVC action
  send_data();
  Serial.println();
}

void beep(int len) {
  digitalWrite(D8, HIGH);
  delay(len);
  digitalWrite(D8, LOW);
}

char hexStr[32];
void to_hex(byte *buffer, byte buffSize) {
  char* s = &hexStr[0];
  for (byte i = 0; i < buffSize; i++) {
    snprintf(s, 3, "%02x", buffer[i]);
    s += 2;
  }   
  hexStr[buffSize * 2] = 0;
  Serial.print(hexStr);
}

void send_data() {
    HTTPClient http;
    http.begin("http://192.168.1.123:5000/home/punchin"); 
    http.addHeader("Content-Type", "text/plain");
    int httpCode = http.POST(hexStr);
    if(httpCode > 0) {
        if(httpCode == HTTP_CODE_OK) {
            String payload = http.getString();
            Serial.println(payload);
            if (strcmp(payload.c_str(), "OK") == 0) {
              beep(100); delay(50); beep(100);
            }
            else if (strcmp(payload.c_str(), "DP") == 0) { //Duplicated
              beep(80);delay(40);beep(80);delay(40);beep(80);delay(40);beep(80);
            }
            else if (strcmp(payload.c_str(), "NT") == 0) { //Invalid 
              beep(200);
            }
            else { //Other Response
              beep(500);
            }
        }
        else { //HTTP Status<>200
          beep(500);
        }
    } else {
        Serial.printf("HTT Error: %s\n", http.errorToString(httpCode).c_str());
        beep(500);
    }
    http.end();
}

ESP8266 + MFRC522 + ASP.NET Core Web Punch Clock


Comments

# by Ronald

謝謝分享,想玩,另外 耗了我起過一個小時,錯別字 超

# by Jeffrey

to Ronald, 感謝指正。

Post a comment