顯示具有 arduino模組 標籤的文章。 顯示所有文章
顯示具有 arduino模組 標籤的文章。 顯示所有文章

2023年9月14日 星期四

ECU Simulator CAN Bus Data with ESP32+MCP2515

Purpose:

依據之前的文章 ESP32 + MCP2515 use CanHacker on CAN Bus system和CAN BUS 通訊研究, 重新把ECU simulator跟 ESP32 Canhacker的CAN Bus通訊結果作整理. 

Based on the previous article ESP32 + MCP2515 use CanHacker on CAN Bus system and CAN BUS communication research, the CAN Bus communication results between ECU simulator and ESP32 Canhacker are reorganized.


模擬器提供下列模式:

系統狀態、即時資料:MODE 01
故障診斷:MODE 03,07,0A
故障清除:MODE 04
凍結資料:MODE 02
氧感測器測試:MODE 05
監測結果:MODE 06
車輛資訊:MODE 09 

模擬器提供六組模擬訊號調整旋鈕。由左至右編號為1~6。
預設模擬訊號源為:空氣流量、冷卻液溫度、轉速、車速、進氣溫度、節氣門位置

詢問汽車功能的CAN匯流排節點識別碼0x7DF , 接收汽車OBD資料要將Acceptance
Filter設為0x7E8,都是依據ISO 15765-4文件所定規範。
If ( CANIsTxReady ( ) )
{ TX_Data_Buf2[0] = 0x02 ;
TX_Data_Buf2[1] = 0x01 ;
TX_Data_Buf2[2] = PID_code;
TX_Data_Buf2[3] = 0x00 ;
TX_Data_Buf2[4] = 0x00 ;
TX_Data_Buf2[5] = 0x00 ;
TX_Data_Buf2[6] = 0x00 ;
TX_Data_Buf2[7] = 0x00 ;
CANSendMessage ( 0x7DF , TX_Data_Buf2 ,
8,CAN_TX_PRIORITY_1&
CAN_TX_STD_FRAME&
CAN_TX_NO_RTR_FRAME ) ;
}

if ( CANIsRxReady ( ) )
{
CANReceiveMessage( &RX_ID1 ,
RX_Data_Buf1 , &RX_Data_Len1 ,
&RX1_Message_Flag ) ;
if (RX_ID1==0x7E8)
{ Engine RPM = ((A*256)+B)/4 ; }
}

Reference https://en.wikipedia.org/wiki/OBD-II_PIDs





Circuit:
YouTube Demo:






延伸閱讀

2023年9月10日 星期日

Inductive trash can with ESP32

Purpose:

利用手上ESP32板子為主架構搭配PIR HC-SR505 sensor感應去控制servo motor旋轉角度另添加一塊充電模組可以完成一個充電式感應垃圾桶!!

Using the ESP32 board as the main structure with the PIR HC-SR505 sensor to control the rotation angle of the servo motor, and adding a charging module to complete a rechargeable inductive trash can!!

BOM:

Figure1 PIR HC-SR505

Figure2 充電鋰電池

Figure3 ESP32
                                                                   

Figure4 充電板
Circuit:
Figure5 整體架構
YouTube Demo:
演示影片
Code Introduce:
#include <ESP32Servo.h>
#include <BluetoothSerial.h>
//--------- Flag structure --------------------------------------
typedef struct _vFlag
{
  uint8_t LEDFlag=1;
  uint8_t BTFlag = 0;
  uint8_t ServoFlag = 0;
  uint8_t PIR_Flag = 1;
  uint8_t PIR_status = 0;
} vFlag;
vFlag *flag_Ptr;
vFlag flag;
//----------uart--------------
#define LINE_BUFFER_LENGTH 64
//--------- uart structure --------------------------------------
typedef struct _vUart
{
  char c;
  int lineIndex = 0;
  int line1Index = 0;
  int BTlineIndex = 0;
  bool lineIsComment;
  bool lineSemiColon;
  char line[128];
  char BTline[20];
  String inputString;
  String BTinputString;
  String S1inputString;
  int V[16];
  char ctemp[30];
  char I2C_Data[80];
  int DC_Spped = 50;
  float Voltage[16];
  int Buffer[128];
  int StartCnt = 0;
  int ReadCnt = 0;
  int sensorValue = 0;
} vUart;
vUart *Uart_Ptr;
vUart Uart;
//------------------------------------------------
#define LED_BUILTIN 2
BluetoothSerial SerialBT;
//------------------------------------------------
Servo myservo;  // create servo object to control a servo
// Recommended PWM GPIO pins on the ESP32 include 2,4,12-19,21-23,25-27,32-33
int servoPin = 13;
//-----------------------
int inPin = 22;  //PIR pin
//-------------------------------------------------
void setup()
{
  Serial.begin(9600);
  Serial.println(F("init"));
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(inPin, INPUT);
  SerialBT.begin("BT_Servo");    // BTName
  myservo.setPeriodHertz(50);    // standard 50 hz servo
  myservo.attach(servoPin, 500, 2400); // attaches the servo on pin 13 to the servo object
  myservo.write(0);
}
//-----------------------------------------
void loop()
{
  Serial.print(F("Main at core:"));
  Serial.println(xPortGetCoreID());
  while(1)
  {
    if(flag.LEDFlag == 1)  //flash LED
    {
      digitalWrite(LED_BUILTIN, HIGH);
      vTaskDelay(300);
      digitalWrite(LED_BUILTIN, LOW);
      vTaskDelay(300);
    }
    if (flag.PIR_Flag == 1)  //start PIR detect
    {
      Serial.println(flag.PIR_status);
      if(digitalRead(inPin) == HIGH)
      {  
        if(flag.PIR_status==0)
        {
          Serial.println("Presence detected");
          myservo.write(100);
          flag.PIR_status=1;
          vTaskDelay(20);    
        }
      }
      else
      {
        if(flag.PIR_status==1)
        {
          Serial.println("No detected");
          myservo.write(0);
          flag.PIR_status=0;  
        }
      }
    }
    while (Serial.available() > 0)
    {
      Uart.c = Serial.read();

      if ((Uart.c == '\n') || (Uart.c == '\r'))
      { // End of line reached
        if (Uart.lineIndex > 0)
        { // Line is complete. Then execute!
          Uart.line[Uart.lineIndex] = '\0'; // Terminate string
          //Serial.println( F("Debug") );
          //Serial.println( Uart.inputString );
          processCommand(Uart.line); // do something with the command
          //傳輸給藍芽
          SerialBT.println(Uart.line);
         
          Uart.lineIndex = 0;
          Uart.inputString = "";
        }
        else
        {
          // Empty or comment line. Skip block.
        }
        Uart.lineIsComment = false;
        Uart.lineSemiColon = false;
        Serial.println(F("ok>"));
      }
      else
      {
        //Serial.println( c );
        if ((Uart.lineIsComment) || (Uart.lineSemiColon))
        {
          if (Uart.c == ')')
            Uart.lineIsComment = false; // End of comment. Resume line.
        }
        else
        {
          if (Uart.c == '/')
          { // Block delete not supported. Ignore character.
          }
          else if (Uart.c == '~')
          { // Enable comments flag and ignore all characters until ')' or EOL.
            Uart.lineIsComment = true;
          }
          else if (Uart.c == ';')
          {
            Uart.lineSemiColon = true;
          }
          else if (Uart.lineIndex >= LINE_BUFFER_LENGTH - 1)
          {
            Serial.println("ERROR - lineBuffer overflow");
            Uart.lineIsComment = false;
            Uart.lineSemiColon = false;
          }
          else if (Uart.c >= 'a' && Uart.c <= 'z')
          { // Upcase lowercase
            Uart.line[Uart.lineIndex] = Uart.c - 'a' + 'A';
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += (char)(Uart.c - 'a' + 'A');
          }
          else
          {
            Uart.line[Uart.lineIndex] = Uart.c;
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += Uart.c;
          }
        }
      }
    } //while (Serial.available() > 0)
    while (SerialBT.available())
    {
      //讀取藍芽資料
      String BTdata = SerialBT.readString();
      //顯示在序列視窗
      Serial.println(BTdata);
      //char charBuf[BTdata.length() + 1];
      //BTdata.toCharArray(charBuf, BTdata.length());
      BTprocessCommand(BTdata); // do something with the command
      //processCommand(charBuf); // do something with the command
    }//while (BT.available())

  }
}
void BTprocessCommand(String data)
{
  if (data == "100")
  {
    Serial.println(F("SERVO_100"));
    myservo.write(100);
  }
  if (data == "10")
  {
    Serial.println(F("SERVO_10"));
    myservo.write(10);
    //myservo.detach();
  }
  if (data == "180")
  {
    Serial.println(F("SERVO_180"));
    myservo.write(180);
  }
  if (data == "50")
  {
    Serial.println(F("SERVO_50"));
    myservo.write(50);
    //myservo.detach();
  }
}
//----------------------------------------
void processCommand(char *data)
{
  int len, xlen, ylen, zlen, alen;
  int tempDIO;
  String stemp;

  len = Uart.inputString.length();
  //---------------------------------------
  if (strstr(data, "VER") != NULL)
  {
    Serial.println(F("ESP32_20230710"));
  }
  //-------------- Servo --------------------
  if (strstr(data, "SERVO_5")!= NULL)
  {
    Serial.println(F("SERVO_5"));
    myservo.write(5);
    //myservo.detach();
  }
  if (strstr(data, "SERVO_10")!= NULL)
  {
    Serial.println(F("SERVO_10"));
    myservo.write(10);
  }
  if (strstr(data, "SERVO_50")!= NULL)
  {
    Serial.println(F("SERVO_50"));
    myservo.write(50);
  }
  if (strstr(data, "SERVO_100")!= NULL)
  {

    Serial.println(F("SERVO_100"));
    myservo.write(100);
  }
  if (strstr(data, "SERVO_180")!= NULL)
  {
    Serial.println(F("SERVO_180"));
    myservo.write(180);
  }
  if (strstr(data, "SERVO_270")!= NULL)
  {
    Serial.println(F("SERVO_270"));
    myservo.write(270);
  }
}
//------------------------------------------




延伸閱讀

2023年8月15日 星期二

ESP32 Temperature and Humidity I2C LCD Display

Purpose:

This Project 利用NTP pool.ntp.org server來抓取現在時間, 並利用DHT22溫溼度感應器, 將現在的時間和溫度, 濕度顯示在 I2C介面的LCD面板上.

This project use the NTP (Network Time Protocol) to capture the current time, and use the DHT22 temperature and humidity sensor to display the current time, temperature, and humidity on the LCD panel of the I2C interface.

Fundamental:

NTP

The Network Time Protocol (NTP) is a networking protocol for clock synchronization between computer systems over packet-switched, variable-latency data networks. 

NTP is a protocol designed to synchronize the clocks of computers over a network to a common timebase (usually UTC).

Coordinated Universal Time (UTC)

NTP意圖將所有參與電腦的協調世界時(UTC)時間同步到幾毫秒的誤差內。

pool.ntp.org來取得時間即可

網路時間協定(英語:Network Time Protocol,縮寫:NTP)

LCD

The LCD1602 comes in 2 possible configurations: I2C configuration and standard configuration. The I2C configuration is usually simpler to use. The default I2C address of the LCD1602 module is 0x27.

DHT22

Digital-output relative humidity & temperature sensor/module

DHT22 output calibrated digital signal. It utilizes exclusive digital-signal-collecting-technique and humidity

sensing technology, assuring its reliability and stability.Its sensing elements is connected with 8-bit single-chip computer.

Every sensor of this model is temperature compensated and calibrated in accurate calibration chamber and the calibration-coefficient is saved in type of programme in OTP memory, when the sensor is detecting, it will cite coefficient from memory.

Circuit:


YouTubeDemo:



Code Introduce:

#include <WiFi.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "DHT.h"
//----------------------------------------------------------------------
LiquidCrystal_I2C LCD = LiquidCrystal_I2C(0x27, 16, 2);

#define NTP_SERVER     "pool.ntp.org"
#define UTC_OFFSET     0
#define UTC_OFFSET_DST 0
//---------------DHT22--------------------
#define DHTPIN 14
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
DHT dht(DHTPIN, DHTTYPE);
float Humidity;
float Temperature;
//--------- Flag structure --------------------------------------
typedef struct _vFlag
{
  uint8_t BTFlag = 0;
  uint8_t DC_Flag = 0;
  uint8_t CANFlag = 0;
  uint8_t I2C_Flag = 0;
  uint8_t RFIDWrite = 0;
  uint8_t RFIDRead = 0;
  uint8_t dht22 = 0;
  uint8_t sensor1_Flag = 0;
  uint8_t initial_Flag = 0;
  uint8_t FunctionFlag = 0;
} vFlag;
vFlag *flag_Ptr;
vFlag flag;
//--------- uart structure --------------------------------------
//----------uart--------------
#define LINE_BUFFER_LENGTH 64
typedef struct _vUart
{
  char c;
  int lineIndex = 0;
  int line1Index = 0;
  int BTlineIndex = 0;
  bool lineIsComment;
  bool lineSemiColon;
  char line[128];
  char BTline[20];
  String inputString;
  String BTinputString;
  String S1inputString;
  int V[16];
  char ctemp[30];
  char I2C_Data[80];
  int DC_Spped = 50;
  float Voltage[16];
  int Buffer[128];
  int StartCnt = 0;
  int ReadCnt = 0;
  int sensorValue = 0;
} vUart;
vUart *Uart_Ptr;
vUart Uart;

//---------------------------------------------------------------------------------
#ifndef LED_BUILTIN
#define LED_BUILTIN 2
#endif
//----------------------------------------------------------------
TaskHandle_t hled;
TaskHandle_t huart;
//------------------------------------------------------------------------------
void initial()
{
  Serial.println(F("Create Task"));
  //----------------------------------------------------------------------
  xTaskCreatePinnedToCore(
    vUARTTask, "UARTTask" // A name just for humans
    ,
    1024 // This stack size can be checked & adjusted by reading the Stack Highwater
    ,
    NULL, 3 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,
    &huart //handle
    ,
    0);

  //--------------- create task----------------------------------
  xTaskCreatePinnedToCore(
    vLEDTask, "LEDTask" // A name just for humans
    ,
    1024 // This stack size can be checked & adjusted by reading the Stack Highwater
    ,
    NULL, 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,
    &hled //handle
    ,
    0);
  //----------------------------------------------------------------------
}

void setup()
{
  Serial.begin(9600);
  Serial.println(F("init"));
  initial();
  pinMode(LED_BUILTIN, OUTPUT);
  LCD.init();
  LCD.backlight();
  LCD.setCursor(0, 0);
  LCD.print("Connecting to ");
  LCD.setCursor(0, 1);
  LCD.print("WiFi ");

  WiFi.begin("Wokwi-GUEST", "", 6);
  while (WiFi.status() != WL_CONNECTED) {
    delay(250);
    spinner();
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  LCD.clear();
  LCD.setCursor(0, 0);
  LCD.println("Online");
  LCD.setCursor(0, 1);
  LCD.println("Updating time...");
  configTime(8*3600, 0, "pool.ntp.org","time.nist.gov"); // enable NTP for Taipei time
  //configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);

  dht.begin();
}

void loop()
{
  //

  Serial.print(F("Main at core:"));
  Serial.println(xPortGetCoreID());
  while(1)
  {
    if(flag.dht22==0)
    {
      for(int i=0;i<40;i++)
      {
        printLocalTime();
        delay(200);
      }
      LCD.clear();
      flag.dht22=1;
    }
   
   
    if(flag.dht22==1)
    {
      float h = dht.readHumidity();

      float t = dht.readTemperature();

      float f = dht.readTemperature(true);
     
      if (isnan(h) || isnan(t) || isnan(f))
      {
        Serial.println("Failed to read from DHT sensor!");
        return;
      }

      float hif = dht.computeHeatIndex(f, h);

      float hic = dht.computeHeatIndex(t, h, false);

      Serial.print("Humidity: ");
      Serial.print(h);
      Serial.print(" % ");
      Serial.print("Temperature: ");
      Serial.print(t);
      Serial.print(" *C ");
      Serial.print(f);
      Serial.print(" *F ");
      Serial.print("Heat index: ");
      Serial.print(hic);
      Serial.print(" *C ");
      Serial.print(hif);
      Serial.println(" *F");

      String Line="Temp: "+String(t);
      String Line1="Humi: "+String(h);
      for(int i=16;i>=0;i--)
      {
        LCD.setCursor(i,0);
        LCD.print(Line);
        LCD.print(" ");
        LCD.setCursor(i,1);
        LCD.print(Line1);
        LCD.print(" ");
        delay(200);
      }
      delay(200);
      LCD.clear();
      flag.dht22=0;
    }
    vTaskDelay(5);
  }
}
//-------------------------------------------
void vUARTTask(void *pvParameters)
{
  (void)pvParameters;

  Serial.print(F("UARTTask at core:"));
  Serial.println(xPortGetCoreID());
  vTaskDelay(100);
  for (;;)
  {
    while (Serial.available() > 0)
    {
      Uart.c = Serial.read();
 
      if ((Uart.c == '\n') || (Uart.c == '\r'))
      { // End of line reached
        if (Uart.lineIndex > 0)
        { // Line is complete. Then execute!
          Uart.line[Uart.lineIndex] = '\0'; // Terminate string
          //Serial.println( F("Debug") );
          //Serial.println( Uart.inputString );
          processCommand(Uart.line); // do something with the command
          Uart.lineIndex = 0;
          Uart.inputString = "";
        }
        else
        {
          // Empty or comment line. Skip block.
        }
        Uart.lineIsComment = false;
        Uart.lineSemiColon = false;
        Serial.println(F("ok>"));
      }
      else
      {
        //Serial.println( c );
        if ((Uart.lineIsComment) || (Uart.lineSemiColon))
        {
          if (Uart.c == ')')
            Uart.lineIsComment = false; // End of comment. Resume line.
        }
        else
        {
          if (Uart.c == '/')
          { // Block delete not supported. Ignore character.
          }
          else if (Uart.c == '~')
          { // Enable comments flag and ignore all characters until ')' or EOL.
            Uart.lineIsComment = true;
          }
          else if (Uart.c == ';')
          {
            Uart.lineSemiColon = true;
          }
          else if (Uart.lineIndex >= LINE_BUFFER_LENGTH - 1)
          {
            Serial.println("ERROR - lineBuffer overflow");
            Uart.lineIsComment = false;
            Uart.lineSemiColon = false;
          }
          else if (Uart.c >= 'a' && Uart.c <= 'z')
          { // Upcase lowercase
            Uart.line[Uart.lineIndex] = Uart.c - 'a' + 'A';
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += (char)(Uart.c - 'a' + 'A');
          }
          else
          {
            Uart.line[Uart.lineIndex] = Uart.c;
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += Uart.c;
          }
        }
      }
    } //while (Serial.available() > 0)
    vTaskDelay(5);
  }
}
//-------------------------------------------------------------------------
static void vLEDTask(void *pvParameters)
{
  (void)pvParameters;

  Serial.println(F("LEDTask at core:"));
  Serial.println(xPortGetCoreID());
  pinMode(LED_BUILTIN, OUTPUT);
  for (;;) // A Task shall never return or exit.
  {
    digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
    vTaskDelay(200);
    digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
    vTaskDelay(200);
  }
}
//----------------------------------------
void processCommand(char *data)
{
  int len, xlen, ylen, zlen, alen;
  int tempDIO;
  String stemp;

  len = Uart.inputString.length();
  //---------------------------------------
  if (strstr(data, "VER") != NULL)
  {
    Serial.println(F("ESP32_20230811"));
  }
  //-------------- RFID --------------------
  if (strstr(data, "DHT22_ON") != NULL)
  {
    flag.dht22 = 1;
    Serial.println(F("DHT22_ON"));
  }
  if (strstr(data, "DHT22_OFF") != NULL)
  {
    flag.dht22 = 0;
    Serial.println(F("DHT22_OFF"));
  }
 
}
//-----------------------------------------
void printLocalTime()
{
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    LCD.setCursor(0, 1);
    LCD.println("Connection Err");
    return;
  }
  //LCD.clear();
  LCD.setCursor(0, 0);
  LCD.println("Online");

  LCD.setCursor(8, 0);
  LCD.println(&timeinfo, "%H:%M:%S");

  LCD.setCursor(0, 1);
  LCD.println(&timeinfo, "%d/%m/%Y   %Z");
}

//----------------------------------------------
void spinner()
{
  static int8_t counter = 0;
  const char* glyphs = "\xa1\xa5\xdb";
  LCD.setCursor(15, 1);
  LCD.print(glyphs[counter++]);
  if (counter == strlen(glyphs)) {
    counter = 0;
  }
}
//-----------------------------------------




延伸閱讀

2023年8月14日 星期一

RFID-RC522 module with ESP32 using Arduino IDE2

Purpose:

想利用ESP32+RFID-RC522來學習做一套門禁系統, 當感應到認可的卡片時, 可開門允許通過, 否則則警示非法卡片.

I want to use ESP32+RFID-RC522 to learn to make an access control system. When an approved card is sensed, the door can be opened to allow passage, otherwise it will warn of illegal cards.

Fundamental:

RFID 是一種無線通訊技術,以無線電波傳遞訊息,只要在電波範圍內,即可傳送訊號,不會傳輸屏障之問題。這種設備的運作為一個讀卡設備會發出一個電磁場,而感應卡內部有線圈,當線圈靠近磁場時,會產生感應電流,就可以做為電力傳輸資訊。另外,感應卡平常沒有靠近場時,內部晶片根本沒有電力可以工作,不用擔心卡片放在一起資料不見。
RFID設備所使用的頻段分為低頻(LF,125KHz)、高頻(HF,13.56MHz)、 超高頻(UHF,868~915MHz)、微波(Microwave,2.45 & 5.814GHz),各個頻 段的設備有不同的物理特性,如讀取的距離與讀取的速度,因此在不同應用情境中會採用不同頻段的設備。

RFID is a wireless communication technology that uses radio waves to transmit information. 
As long as it is within the range of the radio waves, the signal can be transmitted without the problem of transmission barriers. 
The operation of this kind of equipment is that a card reading device will emit an electromagnetic field, and there is a coil inside the proximity card. 
When the coil is close to the magnetic field, an induced current will be generated, which can be used as power to transmit information. 
In addition, when the proximity card is not close to the field, the internal chip has no power to work at all, so there is no need to worry about the data missing when the cards are put together.
The frequency bands used by RFID equipment are divided into low frequency (LF, 125KHz), high frequency (HF, 13.56MHz), ultra high frequency (UHF, 868~915MHz), microwave (Microwave, 2.45 & 5.814GHz), the equipment of each frequency band is Different physical characteristics, such as reading distance and reading speed, so devices with different frequency bands will be used in different application scenarios.

圖一: RFID-RC522感應器13.56MHz
圖二: 感應卡MIFARE卡

RFID感應器是頻率為13.56MHz的 RFID-RC522,而他的感應卡為MIFARE卡,MIFARE卡又有分不同儲存容量的卡。MIFARE S50 內部儲存容量1Kbyte,MIFARE S70 內部儲存容量 4Kbytes,各劃分為 16 區與 64 區,每區都有獨立的 A / B 兩層存取控制密碼,每區有4個BLOCK,每個BLOCK有16個字節。
The RFID sensor is an RFID-RC522 with a frequency of 13.56MHz, and its proximity card is a MIFARE card, and the MIFARE card has different storage capacities. 
The internal storage capacity of MIFARE S50 is 1Kbyte, and the internal storage capacity of MIFARE S70 is 4Kbytes. 
Each area is divided into 16 areas and 64 areas. Each area has an independent A / B two-layer access control password. Each area has 4 BLOCKs. 16 bytes.
圖: Read Data


Bill of Material :
圖: RFID-RC522感應器13.56MHz
圖: 感應卡MIFARE卡
圖:ESP32
Circuit:

YouTube Demo:


Code Introduce:

#include <SPI.h>
#include <MFRC522.h>
//----------------------------------------------------------------------
//--------- Flag structure --------------------------------------
typedef struct _vFlag
{
  uint8_t BTFlag = 0;
  uint8_t DC_Flag = 0;
  uint8_t CANFlag = 0;
  uint8_t I2C_Flag = 0;
  uint8_t RFIDWrite = 0;
  uint8_t RFIDRead = 0;
  uint8_t sensor_Flag = 0;
  uint8_t sensor1_Flag = 0;
  uint8_t initial_Flag = 0;
  uint8_t FunctionFlag = 0;
} vFlag;
vFlag *flag_Ptr;
vFlag flag;
//--------- uart structure --------------------------------------
//----------uart--------------
#define LINE_BUFFER_LENGTH 64
typedef struct _vUart
{
  char c;
  int lineIndex = 0;
  int line1Index = 0;
  int BTlineIndex = 0;
  bool lineIsComment;
  bool lineSemiColon;
  //char *line;
  char line[128];
  //char line1[128];
  char BTline[20];
  //char R_line[20];
  //char L_line[20];
  String inputString;
  String BTinputString;
  String S1inputString;
  int V[16];
  char ctemp[30];
  char I2C_Data[80];
  int DC_Spped = 50;
  float Voltage[16];
  int Buffer[128];
  int StartCnt = 0;
  int ReadCnt = 0;
  int sensorValue = 0;
} vUart;
vUart *Uart_Ptr;
vUart Uart;
//-------------------------------------
//Typical pin layout used:
//* -----------------------------------------------------------------------------------------
// *             MFRC522                    
// *             Reader/PCD   ESP32          
// * Signal      Pin          Pin          
// * --------------------------------------
// * RST/Reset   RST          21            
// * SPI SS      SDA(SS)      5            
// * SPI MOSI    MOSI         23
// * SPI MISO    MISO         19
// * SPI SCK     SCK          18
//------ESP32 RFID setting ----------------
const int SPI_CS_PIN = 5;
const int INT_PIN = 21;

MFRC522 mfrc522;
MFRC522::MIFARE_Key key;
//16(sector),4(block)
byte sector = 15;  
byte block = 0;    

byte blockData[]    = {
        0x01, 0x02, 0x03, 0x04, //  1,  2,   3,  4,
        0x05, 0x06, 0x07, 0x08, //  5,  6,   7,  8,
        0x09, 0x0a, 0xff, 0x0b, //  9, 10, 255, 11,
        0x0c, 0x0d, 0x0e, 0x0f  // 12, 13, 14, 15
    };

byte buffer[18];

MFRC522::StatusCode status;

struct RFIDTag {    
   byte uid[4];
   char *name;
};

struct RFIDTag tags[] = {  
   {{60,209,110,133}, "employee1"},
   {{0xD4,0xD3,0xC0,0x61}, "employee2"},
   {{0xDC,0x14,0xD3,0x38}, "ESP32"}
};

byte totalTags = sizeof(tags) / sizeof(RFIDTag);

char *reference;

//---------------------------------------------------------------------------------
#ifndef LED_BUILTIN
#define LED_BUILTIN 2
#endif
//----------------------------------------------------------------
TaskHandle_t hled;
TaskHandle_t huart;
//------------------------------------------------------------------------------
void initial()
{
  Serial.println(F("Create Task"));
  //----------------------------------------------------------------------
  xTaskCreatePinnedToCore(
    vUARTTask, "UARTTask" // A name just for humans
    ,
    1024 // This stack size can be checked & adjusted by reading the Stack Highwater
    ,
    NULL, 3 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,
    &huart //handle
    ,
    0);

  //--------------- create task----------------------------------
  xTaskCreatePinnedToCore(
    vLEDTask, "LEDTask" // A name just for humans
    ,
    1024 // This stack size can be checked & adjusted by reading the Stack Highwater
    ,
    NULL, 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,
    &hled //handle
    ,
    0);
  //----------------------------------------
  //----------------------------------------------------------------------
  //vTaskSuspend(hfunction); //暫停TASK運行
  //----------------------------------------------------------------------
}

void setup()
{
  Serial.begin(9600);
  Serial.println(F("init"));
  initial();
  SPI.begin();
  pinMode(INT_PIN, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
pinMode(16, OUTPUT);  //PASS
  pinMode(17, OUTPUT);
  mfrc522.PCD_Init(SPI_CS_PIN, INT_PIN);
  Serial.print(F("Reader "));
  Serial.print(F(": "));
  mfrc522.PCD_DumpVersionToSerial();
  Serial.println();
 
  for (byte i = 0; i < 6; i++)
  {
    key.keyByte[i] = 0xFF;
  }

}

void loop()
{
  Serial.print(F("Main at core:"));
  Serial.println(xPortGetCoreID());
  while(1)
  {
    if(flag.RFIDWrite==1)
    {
      if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial())
      {
       
        Serial.print(F("Card UID:"));
        dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
        Serial.println();
        Serial.print(F("PICC type: "));
        MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
        Serial.println(mfrc522.PICC_GetTypeName(piccType));
       
        writeBlock(sector, block, blockData);  
       
        mfrc522.PICC_HaltA();
        mfrc522.PCD_StopCrypto1();
      }
    }
   
    if(flag.RFIDRead==1)
    {
      if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial())
      {
        byte *id = mfrc522.uid.uidByte;
        byte idSize = mfrc522.uid.size;

        Serial.print(F("Card UID:"));
        dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
       
        Serial.println();
        Serial.print(F("PICC type: "));
        MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
        Serial.println(mfrc522.PICC_GetTypeName(piccType));  

        bool they_match = false;
        for (byte i=0; i<totalTags; i++)
        {
          if (memcmp(tags[i].uid, id, idSize) == 0)
          {
            Serial.println(tags[i].name);  
            they_match = true;
            break;
          }
        }


        if(they_match)
        {
          Serial.print(F("Access Granted!"));
digitalWrite(16, HIGH);
        }else
        {
          Serial.print(F("Access Denied!"));
digitalWrite(17, HIGH);
        }
 
        mfrc522.PICC_HaltA();  
vTaskDelay(1000);
        digitalWrite(16, LOW);
        digitalWrite(17, LOW);
      }
    }//---1
    if(flag.RFIDRead==2)
    {
      if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial())
      {
        // Dump debug info about the card; PICC_HaltA() is automatically called
        mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
       
      }
    }
    if(flag.RFIDRead==3)
    {
      if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial())
      {
       
        Serial.print(F("Card UID:"));
        dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
        Serial.println();
        Serial.print(F("PICC type: "));
        MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
        Serial.println(mfrc522.PICC_GetTypeName(piccType));
       
        readBlock(sector, block, buffer);      

        mfrc522.PICC_HaltA();
        mfrc522.PCD_StopCrypto1();
      }
    }
    vTaskDelay(5);
  }
}
//-------------------------------------------
void vUARTTask(void *pvParameters)
{
  (void)pvParameters;

  Serial.print(F("UARTTask at core:"));
  Serial.println(xPortGetCoreID());
  vTaskDelay(100);
  for (;;)
  {
    while (Serial.available() > 0)
    {
      Uart.c = Serial.read();
 
      if ((Uart.c == '\n') || (Uart.c == '\r'))
      { // End of line reached
        if (Uart.lineIndex > 0)
        { // Line is complete. Then execute!
          Uart.line[Uart.lineIndex] = '\0'; // Terminate string
          //Serial.println( F("Debug") );
          //Serial.println( Uart.inputString );
          processCommand(Uart.line); // do something with the command
          Uart.lineIndex = 0;
          Uart.inputString = "";
        }
        else
        {
          // Empty or comment line. Skip block.
        }
        Uart.lineIsComment = false;
        Uart.lineSemiColon = false;
        Serial.println(F("ok>"));
      }
      else
      {
        //Serial.println( c );
        if ((Uart.lineIsComment) || (Uart.lineSemiColon))
        {
          if (Uart.c == ')')
            Uart.lineIsComment = false; // End of comment. Resume line.
        }
        else
        {
          if (Uart.c == '/')
          { // Block delete not supported. Ignore character.
          }
          else if (Uart.c == '~')
          { // Enable comments flag and ignore all characters until ')' or EOL.
            Uart.lineIsComment = true;
          }
          else if (Uart.c == ';')
          {
            Uart.lineSemiColon = true;
          }
          else if (Uart.lineIndex >= LINE_BUFFER_LENGTH - 1)
          {
            Serial.println("ERROR - lineBuffer overflow");
            Uart.lineIsComment = false;
            Uart.lineSemiColon = false;
          }
          else if (Uart.c >= 'a' && Uart.c <= 'z')
          { // Upcase lowercase
            Uart.line[Uart.lineIndex] = Uart.c - 'a' + 'A';
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += (char)(Uart.c - 'a' + 'A');
          }
          else
          {
            Uart.line[Uart.lineIndex] = Uart.c;
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += Uart.c;
          }
        }
      }
    } //while (Serial.available() > 0)
    vTaskDelay(5);
  }
}
//-------------------------------------------------------------------------
static void vLEDTask(void *pvParameters)
{
  (void)pvParameters;

  Serial.println(F("LEDTask at core:"));
  Serial.println(xPortGetCoreID());
  pinMode(LED_BUILTIN, OUTPUT);
  for (;;)
  {
    digitalWrite(LED_BUILTIN, HIGH);
    vTaskDelay(200);
    digitalWrite(LED_BUILTIN, LOW);
    vTaskDelay(200);
  }
}
//----------------------------------------
void processCommand(char *data)
{
  int len, xlen, ylen, zlen, alen;
  int tempDIO;
  String stemp;

  len = Uart.inputString.length();
  //---------------------------------------
  if (strstr(data, "VER") != NULL)
  {
    Serial.println(F("ESP32_20230811"));
  }
  //-------------- RFID --------------------
  if (strstr(data, "RFID_WRITE_ON") != NULL)
  {
    flag.RFIDWrite = 1;
    flag.RFIDRead = 0;
    Serial.println(F("RFID_WRITE_ON"));
  }
  if (strstr(data, "RFID_WRITE_OFF") != NULL)
  {
    flag.RFIDWrite = 0;
    flag.RFIDRead = 0;
    Serial.println(F("RFID_WRITE_OFF"));
  }
  if (strstr(data, "RFID_READ_1") != NULL)
  {
    flag.RFIDRead = 1;
    flag.RFIDWrite = 0;
    Serial.println(F("RFID_READ_1"));
  }
  if (strstr(data, "RFID_READ_2") != NULL)
  {
    flag.RFIDRead =2;
    flag.RFIDWrite = 0;
    Serial.println(F("RFID_READ_2"));
  }
  if (strstr(data, "RFID_READ_3") != NULL)
  {
    flag.RFIDRead =3;
    flag.RFIDWrite = 0;
    Serial.println(F("RFID_READ_3"));
  }
  if (strstr(data, "RFID_READ_OFF") != NULL)
  {
    flag.RFIDRead = 0;
    flag.RFIDWrite = 0;
    Serial.println(F("RFID_READ_OFF"));
  }
}
//-----------------------------------------

void dump_byte_array(byte *buffer, byte bufferSize)
{
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}

void writeBlock(byte _sector, byte _block, byte _blockData[])
{
  if (_sector < 0 || _sector > 15 || _block < 0 || _block > 3) {
   
    Serial.println(F("Wrong sector or block number."));
    return;
  }

  if (_sector == 0 && _block == 0) {
    Serial.println(F("First block is read-only."));
    return;
  }

  byte blockNum = _sector * 4 + _block;
  byte trailerBlock = _sector * 4 + 3;  


  Serial.println(F("Authenticating using key A..."));
  status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
      Serial.print(F("PCD_Authenticate() failed: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
      return;
  }

  Serial.print(F("Writing data into block ")); Serial.print(blockNum);
  Serial.println(F(" ..."));
  dump_byte_array(_blockData, 16); Serial.println();

  status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockNum, _blockData, 16);

  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Write() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  Serial.println(F("Data was written."));
}
//----------------------------------------------
void readBlock(byte _sector, byte _block, byte _blockData[])
{
  if (_sector < 0 || _sector > 15 || _block < 0 || _block > 3)
{
    Serial.println(F("Wrong sector or block number."));
    return;
  }

  byte blockNum = _sector * 4 + _block;  
  byte trailerBlock = _sector * 4 + 3;  

  // Authenticate using key A
  Serial.println(F("Authenticating using key A..."));
  status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
      Serial.print(F("PCD_Authenticate() failed: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
      return;
  }

  byte buffersize = 18;
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockNum, _blockData, &buffersize);

  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_read() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  Serial.print(F("Data in block ")); Serial.print(blockNum); Serial.println(F(":"));
  dump_byte_array(_blockData, 16); Serial.println();
  Serial.println();

  Serial.println(F("Data was read."));
}
//-----------------------------------------






延伸閱讀