實習 2-1 , 2-2 ,2-3
Arduino 程式說明2
//wifi & MQTT
#include <WiFi.h> //定義Wifi 程式庫
#include <PubSubClient.h> //定義MQTT Pub發行 Sub 訂閱 程式庫
//RC522 SPI Mode
#include <SPI.h> //定義MFRC522 RFID read 與 ESP32 介面
#include <MFRC522.h> //定義MFRC522 RFID read程式庫
//GPIO 2 D1 Build in LED
#define LED 2 //定義LED接腳
//定義MFRC522 RFID read 與
ESP32 介面 接腳連接Pin assign
/* Wiring RFID RC522 module
=============================================================================
GND = GND 3.3V =
3.3V
The following table shows the typical pin layout
used:
*
MFRC522 ESP32 Arduino
Arduino Arduino Arduino
Arduino
*
Reader/PCD Uno/101
Mega Nano v3 Leonardo/Micro Pro
Micro
* Signal Pin
Pin Pin
Pin Pin Pin
Pin
*
-----------------------------------------------------------------------------------------
* RST/Reset RST
GPIO27 9 5
D9 RESET/ICSP-5
RST
* SPI SS SDA(SS)
GPIO5 10 53
D10 10
10
* SPI MOSI MOSI
GPIO23 11 / ICSP-4 51
D11 ICSP-4
16
* SPI MISO MISO
GPIO19 12 / ICSP-1 50
D12 ICSP-1
14
* SPI SCK SCK
GPIO18 13 / ICSP-3 52
D13 ICSP-3
15
*
[1] (1, 2) Configurable, typically defined as
RST_PIN in sketch/program.
[2] (1, 2) Configurable, typically defined as SS_PIN
in sketch/program.
[3] The SDA pin might be labeled SS on some/older
MFRC522 boards
=============================================================================
*/
#define SS_PIN 5 // ESP32 pin GIOP5 //MFRC522 SS接腳 與 ESP32 的連接Pin
#define RST_PIN 27 // ESP32 pin GIOP27 //MFRC522 RST接腳 與 ESP32 的連接Pin
// WiFi SSID password , SSID 和密碼進行Wi-Fi 設定
const char *ssid = "alex9ufo"; // Enter
your Wi-Fi name
const char *password = "alex9981";
// Enter Wi-Fi password
// MQTT Broker伺服器名稱 使用者名稱 密碼 發行主題
訂閱主題的定義
const char *mqtt_broker =
"broker.mqtt-dashboard.com";
const char *topic1 = "alex9ufo/esp32/led";
const char *topic2 =
"alex9ufo/esp32/RFID";
const char *topic =
"alex9ufo/esp32/Starting";
const char *topic3 =
"alex9ufo/esp32/led_status";
const char *mqtt_username = "alex9ufo";
const char *mqtt_password = "public";
const int mqtt_port = 1883;
//布林代數 LED狀態 是否連上網路ESP32 ready ?
bool ledState = false;
bool atwork = false;
//定義WiFiClient 別名
//PubSubClient 物件名稱(網路用戶端物件)
//初始化MFRC522卡
WiFiClient espClient;
PubSubClient client(espClient);
MFRC522 rfid(SS_PIN, RST_PIN); // Create MFRC522
instance
//定義long 變數
long lastMsg = 0;
long lastMsg1= 0;
//定義 MQTT 發行及訂閱需要的變數
char msg[50];
String json = "";
bool Flash = false; //true
bool Timer = false; //true
bool Send = false; //true
int Count= 0;
//定義 MQTT 發行及訂閱需要的變數
char jsonChar1[50];
//client.publish("alex9ufo/Esp32/RFID"
//宣告任務Task1
TaskHandle_t Task1;
// Wifi reconnect 重新連線需要的變數
unsigned long previousMillis = 0;
unsigned long interval = 30000;
//===========================================================
//任務1副程式Task1_senddata
//由於ESP32有著240/160MHz的雙核心CPU
//一般我們的程式都僅在ESP32的核心1執行(核心編號1),
//所以根本沒用到第二個核心(核心編號0)
void Task1_senddata(void * pvParameters ) {
//無窮迴圈
for (;;) {
//偵測上傳旗標是否為true
Serial.println("Reading RFID
tag");
if (rfid.PICC_IsNewCardPresent()) { // new tag is available
if (rfid.PICC_ReadCardSerial())
{ // NUID has been readed
MFRC522::PICC_Type
piccType = rfid.PICC_GetType(rfid.uid.sak);
Serial.print("RFID/NFC
Tag Type: ");
Serial.println(rfid.PICC_GetTypeName(piccType));
String
rfidno="";
// print UID
in Serial Monitor in the hex format
Serial.print("UID:");
for (int i = 0; i <
rfid.uid.size; i++) {
Serial.print(rfid.uid.uidByte[i] < 0x10 ? " 0" : " ");
Serial.print(rfid.uid.uidByte[i], HEX);
}
Serial.println();
String json =
printHex(rfid.uid.uidByte, rfid.uid.size);
json.trim();
json.toUpperCase();
//
Convert JSON string to character array
json.toCharArray(jsonChar1, json.length()+1);
if
(client.connected()) {
Serial.print("Publish message: ");
Serial.println(json);
// Publish JSON character array to MQTT topic
client.publish(topic2,jsonChar1);
rfid.PICC_HaltA(); // halt PICC
rfid.PCD_StopCrypto1(); // stop encryption on PCD
}
else
{
Serial.print("MQTT
not connected ");
}
}
}
else
{
//
PN532 probably timed out waiting for a card
Serial.println("Timed out
waiting for a card");
}
//Task1休息,delay(X)不可省略
delay(1000);
}
}
//===========================================================
//副程式 UID No. in the hex
format
//===========================================================
String printHex(byte *buffer, byte bufferSize) {
String id = "";
for (byte i = 0; i < bufferSize;
i++) {
id += buffer[i] <
0x10 ? "0" : "";
id += String(buffer[i],
HEX);
id +=" ";
}
return id;
}
//===========================================================
//副程式 setup wifi
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid); //print ssid
WiFi.begin(ssid, password); //初始化WiFi
函式庫並回傳目前的網路狀態
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
} //假設 wifi 未連接 show
………
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
//===========================================================
// 接收MQTT主題後呼叫運行程式
//===========================================================
void callback(char *topic, byte *payload, unsigned
int length) {
Serial.print("Message arrived in
topic: ");
Serial.println(topic);
Serial.print("Message: ");
String message;
//將接收資料轉成字串以利後續判斷
for (int i = 0; i < length; i++) {
message += (char)
payload[i]; // Convert *byte to string
}
Serial.print(message);
//判斷是否為 on , off , toggle , flash , timer
if (message == "on" && !ledState) {
digitalWrite(LED, HIGH);
// Turn on the LED
ledState = true;
//ledState = ture HIGH
//設定 各個 旗號
Flash = false;
Timer = false;
json ="ON";
Send = true ;
}
if (message == "off" && ledState) {
digitalWrite(LED, LOW);
// Turn off the LED
ledState = false;
//ledState = false LOW
Flash = false;
Timer = false;
json ="OFF";
Send = true ;
}
if (message == "flash" ) {
digitalWrite(LED, LOW);
// Turn off the LED
Flash = true;
Timer = false;
json ="FLASH";
Send = true ;
}
if (message == "timer" ) {
digitalWrite(LED, LOW);
// Turn off the LED
Flash = false;
Timer = true;
json ="TIMER";
Send = true ;
Count= 11;
}
if (message == "toggle" ) {
digitalWrite(LED,
!digitalRead(LED)); // Turn the LED toggle
if (digitalRead(LED))
ledState =
true;
else
ledState =
false;
Flash = false;
Timer = false;
json
="TOGGLE";
Send = true ;
}
Serial.println();
Serial.println("-----------------------");
}
//===========================================================
// 若目前沒有和伺服器相連,則反覆執行直到連結成功
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT
connection...");
// Attempt to connect
if
(client.connect("esp32-client-")) {
Serial.println("connected");
// Subscribe
client.subscribe("alex9ufo/esp32/led");
client.subscribe("alex9ufo/esp32/RFID");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again
in 5 seconds");
// Wait
5 seconds before retrying
delay(5000);
if (WiFi.status() !=
WL_CONNECTED) {
Serial.println("Reconnecting to WiFi...");
WiFi.disconnect();
WiFi.reconnect();
}
}
}
}
//===========================================================
//判斷 旗號Flash , Timer 是否為真
void LED_Message() {
if (Flash){
digitalWrite(LED,
!digitalRead(LED));
delay(500);
if (digitalRead(LED))
ledState =
true;
else
ledState =
false;
} //(Flash)
if (Timer) {
digitalWrite(LED, HIGH);
delay(500);
if (digitalRead(LED))
ledState =
true;
else
ledState =
false;
Count=Count-1;
if (Count == 0 ){
Timer=false;
digitalWrite(LED, LOW);
ledState =
false;
}
} //(Timer)
////判斷 旗號 Send 是否為真 回傳MQTT訊息到MQTT Broker
if (client.connected()) {
if (Send) {
// Convert JSON
string to character array
json.toCharArray(jsonChar1, json.length()+1);
Serial.print("Publish message: ");
Serial.println(json);
// Publish JSON
character array to MQTT topic
client.publish(topic3,jsonChar1);
}
Send = false;
//處理過後 旗號 Send為假
}
else
{
if (WiFi.status() !=
WL_CONNECTED) {
Serial.println("Reconnecting to WiFi...");
WiFi.disconnect();
WiFi.reconnect();
}
}
}
//===========================================================
//setup()這個函式只會執行大括號裡面的程式一遍, 主要就是在Arduino一開機後,//將所有初始該設置的東西先設置好
void setup() {
// Set software serial baud to 115200;
Serial.begin(115200);
delay(1000); // Delay for stability
//======================================================
// Connecting to a WiFi network
setup_wifi();
// Setting LED pin as output
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW); // Turn off the LED initially
//======================================================
SPI.begin();
// Init SPI bus
rfid.PCD_Init(); // Init MFRC522
Serial.println(F("Ready!"));
Serial.println(F("==================================================="));
Serial.println("Tap an RFID/NFC
tag on the RFID-RC522 reader");
// Connecting to an MQTT broker
client.setServer(mqtt_broker,
mqtt_port);
client.setCallback(callback);
while (!client.connected()) {
String client_id =
"esp32-client-";
client_id +=
String(WiFi.macAddress());
Serial.printf("The
client %s connects to the public MQTT broker\n", client_id.c_str());
if
(client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
Serial.println("Public HiveMQ MQTT broker (broker.mqtt-dashboard.com)
connected");
} else {
Serial.print("Failed with state ");
Serial.print(client.state());
delay(2000);
}
}
// MQTT Publish and subscribe
client.subscribe(topic1);
client.publish(topic,"ESP32 at
work");
//在核心0啟動任務1
xTaskCreatePinnedToCore(
Task1_senddata, /*任務實際對應的Function*/
"Task1",
/*任務名稱*/
10000,
/*堆疊空間*/
NULL,
/*無輸入值*/
0,
/*優先序0*/
&Task1,
/*對應的任務變數位址*/
0);
/*指定在核心0執行 */
}
//===========================================================
//重複循環執行你所寫入loop()內的程式碼
void loop()
{
if (!client.connected()) { //假設未連接的處理程序
reconnect();
Serial.print(" client not
connected reconnect ");
delay(200);
}
client.loop();
// Process LED
message
LED_Message();
unsigned long currentMillis = millis();
// if WiFi is down,
try reconnecting
if ((WiFi.status() != WL_CONNECTED)
&& (currentMillis - previousMillis >=interval)) {
Serial.print(millis());
Serial.println("Reconnecting to
WiFi...");
WiFi.disconnect();
WiFi.reconnect();
previousMillis = currentMillis;
client.setCallback(callback);
}
}
//===========================================================
沒有留言:
張貼留言