Coding4Fun - WiFi Arduino + ASP.NET Core 家用打卡鐘
2 |
前陣子入手 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 接腳 |
---|---|
RST | D1 (GPIO5) |
NSS | D2 (GPIO4) |
MOSI | D7 (GPIO13/HMISO) |
MISO | D6 (GPIO12/HMOSI) |
SCK | D5 (GPIO14/HSCLK) |
GND | G |
VCC(3.3V) | 3V |
IRQ | 未用 |
另外,我接了一個小蜂鳴器,負極接地,正極接 D8 控制輸出 3V 或 0V 控制產生長短嗶聲,提供刷卡結果的聲音回饋。組裝完成,找了個名片盒下方鑽孔透出 USB 插口當成簡易外殼,趕著 12 月起新制上路,專案要上線,就先不想什麼 3D 列印了。
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, 感謝指正。