2014年10月26日 星期日

{ HZ1050 @ Raspberry Pi @ UART 模式 } 125KHz RFID 讀卡器使用說明

HZ-1050 125KHz RFID 讀卡器模組學習套件可至露天賣場訂購:
詳細的介紹,請上露天賣場。


HZ-1050, 125KHz RFID 讀卡器 @ UART - 樹莓派範例實際接線

上篇講到使用 Arduino UART 的方式讀取 HZ-1050 125KHz RFID 讀卡器 ( 文中簡稱 HZ1050 ) 回傳 RFID 卡號 ( 因為 HZ1050 主要是針對 EM4100 以及 EM4001 RFID 卡,因此以下在文中簡稱 EM 卡 )。

本篇是 Raspbeey Pi ( 本文稱為樹莓派 ) 控制 HZ1050 系列的第一篇,這三篇依其接收方式不同有:
  1. UART
  2. Wiegand 26 / 34
  3. UART + Wiegand 26 / 34
這三篇的程式碼,會將輸出結果都會轉向到 { 3V3 } 整合型 LCD 上;但是可以經由自行修改將結果輸出到命令列視窗下,而且程式也預留比對成功或是失敗的程式碼區塊讓使用者可以自行加入處理的程式碼。

HZ1050, UART, Raspberry Pi 測試電路圖說明:

HZ1050, UART 模式下, Raspberry Pi 測試電路圖

樹莓派與 HZ1050 UART 的電路圖如上所示,由於兩者電壓準位不同,因此 HZ1050 的 TXD 接腳,必須使用套件中的電壓準位模組將電壓準位轉換為樹莓派的電壓準位 3V3,避免搞掉了樹莓派 !!!

Note: 套件中的電壓準位轉換模組,可以在 3V3 與 5V0 電壓準位之間雙向轉換 ( A 端接 5V0 裝置,B 端接 3V3 裝置 ),因此也適用在 I2C 的雙線雙線通訊電壓準位轉換上。

實際的接線如下圖:
HZ-1050, 125KHz RFID 讀卡器 @ UART - 樹莓派範例實際接線

接線圖中使用的 { 3V3 } 整合型 LCD 可至露天賣場選購。


樹莓派的設定:

要在樹莓派中使用 UART 的功能,首先必須將其開啟,然後再安裝 wiringPi 函式庫 ( 不曉得的話,可以到賣場這篇網頁裡 "Ctrl + F" 找 UART,照著它下面的步驟安裝 wiringPi 函示庫與開啟樹莓派的 UART 功能 ),

最後到賣場所提提供的商品雲端硬碟中下載原始碼 ( 沒有連結就自己 Keyin ) 到樹莓派系統中


Note:網頁最下方提供三個樹莓派編輯環境設置的部落格網頁連結,可幫助使用者在樹莓派中撰寫程式以及遠端操作 !


樹莓派 UART 程式碼說明:

下面使用的程式碼是 {HZ1050}/codes/Raspberry_Pi/RASPI_UART/HZ1050_UARTDemo.c,編譯時請使用下面的指令:

sudo gcc HZ1050_UARTDemo.c -lwiringPi -o hz1050_uartdemo

下面列出的程式碼,未包括整合型 LCD 使用 I2C 通訊的控制程式碼,請至下一篇說明WIEGAND 模式的網頁中看。
HZ1050_UART_Demo.c, line 21 - 28
 21 #include <stdio.h>
 22 #include <stdlib.h>         // exit
 23 #include <unistd.h>         // usleep
 24 #include <errno.h>
 25 #include <string.h>         // strcnimp
 26 #include <wiringPi.h>
 27 #include <wiringSerial.h>
 28 

line 21 - 27:程式中所需要的標頭檔宣告
line 29 - 69:整合型 LCD 使用 I2C 通訊的控制程式碼 ( 這裡未列出,請直接參考原始碼 ! 若無特別需要,這些程式碼不需要再做修改,直接參考 main() 函式裡的使用方式即可 )。

HZ1050_UART_Demo.c, line 70 - 87
 70 //******************************************************************************
 71 // UART
 72 //******************************************************************************
 73 
 74 // 要比對的 RFID Tag ID;可以更改為
 75 char hexTagID[11] = "0x002285EA";  // 一定要 8 個 16 進位,不足的前方補 0
 76 long decTagID     = 2262506;            // 2262506 = 0x2285EA
 77 
 78 int pUART;
 79 unsigned char udata[4];
 80 char data[8];
 81 int dataIdx;
 82 
 83 long tagID;
 84 
 85 //******************************************************************************
 86 //******************************************************************************
 87 //#define DEBUG       // if DEBUG 

line 75 - 76:程式中要比對的 EM 卡號。line 75 是轉換為 16 進位轉換為字元表示;line 76 直接就是 EM 卡上的號碼。
line 78 - 83:程式中用到的變數。

HZ1050_UART_Demo.c, line 88 - 189
 88 
 89 int main()
 90 {
 91     int i;
 92 
 93     // 初始化 wiringPi,並使用 BCM_GPIO 的接腳號碼
 94     if (wiringPiSetupGpio() == -1)
 95     {
 96         fprintf (stderr, "Unable to setup wiringPi GPIO, errno: %s\n", strerror (errno)) ;
 97         exit(1);
 98     }
 99     
100     // 取得存取 LCD IIC 的 FD
101     if((pIIC_LCD = wiringPiI2CSetup(LCD_I2C_ADDR)) == -1)
102     {
103         fprintf (stderr, "Unable to get file handle of IIC (LCD), errno: %s\n", strerror (errno)) ;
104         exit(1) ;
105     }
106     
107     // 開啟串列埠
108     // 速度只能設定為 9600 或是 19200 bps,並在板子上使用跳線帽先做設定    
109     if ((pUART = serialOpen ("/dev/ttyAMA0", 9600)) < 0)
110     {
111         fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
112         return 1 ;
113     }
114     dataIdx = 0;
115     tagID = 0;
116     //--*
117         
118     lcd_init();
119     delay(100);
120     lcd_Clear();
121     delay(100);
122     
123     for(;;)
124     {
             << 省略line 125 - 186 >>
187     }
188     return 0;
189 }

line 93 - 98:wiringPi 的初始化,並使用 BCM GPIO 的號碼。
line 101 - 105:開啟 I2C 與 LCD 的通訊。
line 109 - 113:開啟 UART,並設定傳輸速度為 9600 bps。
line 118 - 121:LCD 的初始化和清除螢幕。

HZ1050_UART_Demo.c, line 122 - 187
122     
123     for(;;)
124     {
125         if (serialDataAvail (pUART))
126         {
127             udata[dataIdx++] = serialGetchar(pUART);            
128         }
129         
130         if(dataIdx == 4) 
131         {
132             // unsigned char to char
133             for( i = 0; i < 8; i += 2 )
134             {
135               data[i] = 0x30 + udata[i/2] / 16;
136               if( data[i] > 0x39 ) data[i] += 7;  // 大於 ASCII '9' 就要變成英文 A(0x41)...      
137               data[i+1] = 0x30 + udata[i/2] % 16;
138               if( data[i+1] > 0x39 ) data[i+1] += 7;
139               #ifdef DEBUG
140                 printf("0x%2X, 0x%2x", data[i], data[i+1] );
141               #endif
142             }
143             #ifdef DEBUG
144               printf("\n");
145             #endif
146 
147             // 轉成 16 進位資料並比對
148             char strHexCode[11];
149             sprintf( strHexCode, "0x%s", data );
150             // 顯示 16 進位資料在 LCD 上
151       lcd_DisplayCharAt( 1, 1, "HEX:", 4 );
152       lcd_DisplayCharAt( 1, 5, strHexCode, 10 );
153             // 16 進位比對,注意是字串比對
154             if( ( strncmp(strHexCode, hexTagID, 10 ) ) == 0 )
155             {
156                  printf("HEX compare ok.\n");
157                  /*
158                   增加比對成功的處理碼在這邊
159                   ...      
160                  */
161             }
162             else
163             {
164                 printf("HEX compare failed.\n");
165             }
166             
167             // 轉換為 10 進位資料並比對            
168             tagID = strtol( strHexCode,  NULL, 0 );
169             // 顯示 10 進位在 LCD 上
170             char strdecbuf[17];
171             sprintf( strdecbuf, "DEC:%10lu", tagID );
172             lcd_DisplayCharAt( 2, 1, strdecbuf, 14 );
173             if( tagID == decTagID )
174             {
175                  printf("DEC compare ok.\n");
176                  /*
177                   增加比對成功的處理碼在這邊
178                   ...
179                  */
180             }
181             else
182             {
183                 printf("DEC compare failed.\n");
184             }
185             dataIdx = 0;
186         }
187     }

for 迴圈 ( line 123 - 187 ) 裡面的程式碼會一直重複執行。當 UART 接收到資料後,會先將資料放到 udata 陣列中,一但陣列數目已經到達 4 個,就會進入 line 130 - 186if 判斷式中開始處理。

line 133 - 145:將 udata 陣列中 4 個的 16 進位資料,轉換成 10 進位字元資料。如下解釋:

假設 EM 鑰匙卡號為 0002262506,轉換為 16 進位為 0x002285EA,放入到陣列中就是

udata[] = { 0x00, 0x22, 0x85, 0xEA};

轉換為 10 進位的字元就是

data[] = { '0', '0', '2', '2', '8', '5', 'E', 'A' };

若不是很了解的話,將 line 87 前方的雙斜線移除掉重新編譯再執行,就可以看到計算的結果。
line 147 - 152:將 data 字元陣列處理一下,變成以 0x 開頭的字串,用來輸出顯示在整合型 LCD 上。
line 153 - 165:EM 卡號 ( strHexCode ) 與 line 75 的字串比對一下。成功,就輸出 16 進位字串比對成功的字串 ( line 153 - 159 );失敗,就輸入 16 進位字串比對失敗的字串 ( line 162 - 164 )。

line 167 - 172:將 strHexCode 字串轉換成 long 整數型態 ( line 167 ),組合成合適的字串 ( line 170 ) 用以在 LCD 上顯示 ( line 171 )。
line 173 - 184:EM 卡號 ( tagID ) 與 line 76 的 long 整數做比對。成功,就輸出 10 進位數比對成功的字串;失敗,就輸出 10 進位比對失敗的字串。


測試結果:

進入到檔案所在的位置,完成編譯之後在命令列中輸入

sudo ./hz1050_uartdemo

然後拿出套件中的鑰匙卡在 HZ1050 的線圈上方停留一下,就會看到 ( 如下圖所示 ) 鑰匙卡的號碼出現在整合型 LCD 上,第一行是以 16 進位表示,第二行是以 10 進位表示。
HZ1050. UART 模式下,使用樹莓派測試的結果


結論:

與 Arduino UART 的程式比較一下,兩個程式碼非常接近,而且動作幾乎相同,使用者應該很容易了解 !!!

UART 接收 HZ1050 資料的方法都說完了 ! 那麼就讓我們進入到處理接收 Wiegand Code ( 韋根碼 ) 的處理方式吧 !!!!



<< 部落格 HZ-1050,125KHz RFID 讀卡器模組相關網頁連結 >>


<<樹莓派編輯環境設置系列文章>>

沒有留言:

張貼留言