這篇文章來源于DevicePlus.com英語網(wǎng)站的翻譯稿。點擊此處閱讀本文第一部分 >
在上一篇文章自制 Arduino RFID門鎖中,我們制作了Arduino RFID門鎖,并且能夠使用RFID標簽或鍵盤來解鎖。那么,如果您想要進一步簡化流程該怎么辦呢?在第二部分中,我們將添加一個附加功能:使用智能手機來解鎖。這是一種更簡單的控制門的辦法,尤其是當所有人都希望能夠通過一個設(shè)備就能控制所有物品的時候。那么我們該怎么做呢?我們將會把藍牙模塊連接到先前的設(shè)置中,并連接電子門。
HC-05 藍牙模塊
ABK-704L 電氣設(shè)備
Arduino Nano
RFID RC522
壓電蜂鳴器
2x 330 電阻
4×4 鍵盤
LCD適配器I2C
LCD16X2BL
DC-DC 降壓模塊 MP1584EN
軟件
MIT App Inventor 2
Arduino IDE
Github
步驟1:連接藍牙
在這一步中,我們將深入研究HC-05藍牙模塊。
Arduino-info Wiki
有以下兩種操作模式:
指令模式 – 將AT指令發(fā)送到藍牙模塊;
數(shù)據(jù)模式 – 從另一個藍牙模塊接收和傳輸數(shù)據(jù)。默認的模式是數(shù)據(jù)模式,默認設(shè)置如下:
波特率:9600 bps,數(shù)據(jù):8位,停止位:1位,奇偶校驗:無
密碼:1234
設(shè)備名稱:HC-05
針對我們的應(yīng)用程序,我們將使用數(shù)據(jù)模式,因為我們僅需要使用串行通信來從手機接收信息。
有關(guān)串行通信的更多信息,請參考Arduino串行通信教程。
圖1:藍牙模塊引腳
在此應(yīng)用程序中,我們需要使用以下引腳—Arduino-info Wiki:
VCC: +5 電源
GND: 系統(tǒng) / Arduino接地
TX: 將串行數(shù)據(jù)從HC-05傳輸?shù)?Arduino 串行接收端口
RX: 接收來自Arduino 串行發(fā)送端口的串行數(shù)據(jù)
圖2:HC-05 和Arduino Nano的接線圖
圖3:藍牙和Arduino之間的連接
代碼
藍牙使用串行通信;“Serial.write(Serial.read());”連接了RX和TX引腳后,該指令將會正常運行。如果這對藍牙模塊不適用,則下面的代碼返回的內(nèi)容與您在Arduino IDE中編寫的文本相同。
void setup(){ Serial.begin(9600); Serial.println("What did you say?:"); } void loop(){ if (Serial.available()) Serial.write(Serial.read()); }
您需要在設(shè)備管理器中找到Arduino的編程端口;連接藍牙后,將出現(xiàn)“藍牙鏈接上的標準串行”,您必須選擇“USB-SERIAL”才能對Arduino進行編程。您需要使用串行電纜上傳程序,不能使用無線藍牙將程序上傳到開發(fā)板。
連接RX和TX后,您將收到許多錯誤信息,如下所示:
為了避免這些錯誤,您需要在藍牙的TX引腳沒有連接到Arduino開發(fā)板的情況下上傳程序。藍牙的TX引腳具有低阻抗,而Arduino的RX輸入具有高阻抗。最終的阻抗將為較低的一個,而RX輸入將會被繞過(從USB端口產(chǎn)生的電流直接通過藍牙輸出,而不是Arduino開發(fā)板)。這就是數(shù)據(jù)無法傳輸?shù)狡谕恢命c的原因。另外,電流直接流入設(shè)備的輸出端將會在模塊之間產(chǎn)生錯誤的連接,會導(dǎo)致電氣故障。我們想要做的是對Arduino進行編程,而不是將數(shù)據(jù)發(fā)送到藍牙模塊。
斷開藍牙的TX引腳后,一切都會正常工作,您就可以上傳代碼了。
圖4:連接藍牙TX引腳而導(dǎo)致的電氣故障
圖5: HC-05 和Arduino Nano的接線圖,顯示了上傳代碼之前的正確連接
上傳代碼后,下一步是連接到電腦上的藍牙。您需要重新連接藍牙的TX引腳,因為現(xiàn)在我們將使用無線通信,串行電纜只用于供電。
請按照以下步驟將藍牙連接到PC(在Windows 10系統(tǒng)上):
打開設(shè)置(Settings)
點擊設(shè)備(Devices)
選擇藍牙(Bluetooth)
點擊開啟(ON)
找到“HC-05”并點擊“PAIR”
輸入密碼“1234”
圖6:在Windows 10系統(tǒng)上連接藍牙模塊
如果您已經(jīng)按照上述步驟進行了操作,那么您的藍牙連接應(yīng)該就成功了,您可以對模塊進行測試。有一種簡單的檢查連接是否成功建立的方法:在Arduino IDE中鍵入一個單詞,然后查看是否返回相同的單詞,如果是的話,就說明一切正常,您可以繼續(xù)往下進行了!如果不是,請返回之前的步驟并再次對藍牙配對。
因為我們不再使用通過電纜的串行通信,所以需要找到藍牙的COM。我們需要回到端口(PORTS)部分的設(shè)備管理器(Device Manager),并搜索藍牙設(shè)備。在我的應(yīng)用中是PORT 17:
在設(shè)備管理器中找到COM后,您需要在Arduino IDE中執(zhí)行相同的操作(即將COM端口設(shè)置為COM 17)。您需要點擊TOOLS → PORT → COM 17。
圖7:在Arduino IDE中設(shè)置COM
選擇正確的COM后,您可以對模塊進行測試,查看是否工作正常。
請確保您在串行監(jiān)視器中選擇了以下兩個選項:
NL & CR
9600 波特
在我們的演示中,我們將輸入信息“Hello!”
輸出內(nèi)容應(yīng)與輸入內(nèi)容相同:
步驟2:設(shè)備
讓我們參考一下上一篇文章自制Arduino RFID門鎖!我們將使用與之前相同的組件,然后增加一個藍牙模塊(HC-05)。為了將數(shù)據(jù)從智能手機傳輸?shù)紸rduino,我們需要藍牙模塊。
斷開藍牙的TX引腳很重要,否則我們將會遇到跟步驟1中相同的錯誤。
有三種方式可以打開門鎖:
從鍵盤輸入密碼
將標簽放在RFID附近
從智能手機輸入密碼
圖8:所有組件的接線圖
該鎖具有很高的電流量(800mA)。我們添加一個綠色LED燈來查看代碼是否運行正常。鍵入“*123456#” 代碼且系統(tǒng)解鎖后,LED指示燈將為高電平。
圖9:組件之間的連接
在下一步中,我們將添加電池和繼電器。我們使用兩節(jié)9V電池給門鎖供電。如果您打算將設(shè)備電壓設(shè)置為固定值,則需要購買一種可以從開關(guān)電源的220V電壓中獲得5V電壓的設(shè)備。
因為鎖的電流消耗很高,所以電池并聯(lián)連接。在這種情況下,Arduino由電池供電。我們需要使用將9V轉(zhuǎn)換為5V的DC-DC降壓模塊。輸入電壓由Arduino開發(fā)板的Vin引腳進入。我們將不再使用計算機USB的供電。
降壓模塊的輸出電壓要固定在5V。您需要使用萬用表進行校準;輸入電壓為9V,我們將旋扭電位器,直到輸出電壓為5V。
圖10:DC-DC降壓模塊(MP1584EN)
圖11:測量電池電壓
圖12:最終設(shè)置的接線圖
圖13:最終設(shè)置
完整代碼
#include #include #include #include #include #include int state_bt=1; int relPin; int stare=0; byte COD[10]; byte AUX[10]; int k=0; String codacces="*123456#"; String ; //nfc #define RST_PIN 9 // Configurable, see typical pin layout above #define SS_PIN 10 // Configurable, see typical pin layout above MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance #define NEW_UID {0xDE, 0xAD, 0xBE, 0xEF} MFRC522::MIFARE_Key key; //lcd LiquidCrystal_I2C lcd(0x27,16,2); //TASTATURA const byte numRows= 4; //number of rows on the keypad const byte numCols= 4; //number of columns on the keypad //keymap defines the key pressed according to the row and columns just as appears on the keypad char keymap[numRows][numCols]= { {'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', 'C'}, {'*', '0', '#', 'D'} }; //Code that shows the the keypad connections to the arduino terminals byte rowPins[numRows] = {2,3,4,5}; //Rows 0 to 3 byte colPins[numCols]= {A0,7,8,9}; //Columns 0 to 3 //initializes an instance of the Keypad class Keypad myKeypad= Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols); void setup() { pinMode(A0,OUTPUT); digitalWrite(A0,HIGH); pinMode(A3,OUTPUT); digitalWrite(A3,HIGH); pinMode(A1,OUTPUT); digitalWrite(A1,HIGH); pinMode(A2,OUTPUT); digitalWrite(A2,LOW); pinMode(6,OUTPUT); digitalWrite(6,HIGH); //nfc Serial.begin(9600); // Initialize serial communications with the PC Serial.println("What did you say?:"); while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4) SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522 card for (byte i = 0; i < 6; i++) { key.keyByte[i] = 0xFF; } lcd.init(); lcd.backlight(); lcd.setCursor(0,0); lcd.clear(); lcd.print("BLOCKED"); } void citireNFC(){ for (byte i =0; i<(mfrc522.uid.size); i++) { COD[i]=mfrc522.uid.uidByte[i]; } Serial.print("COD"); Serial.print(COD[0]); Serial.print(COD[1]); Serial.print(COD[2]); Serial.print(COD[3]); } void pairNFC(){ Serial.println("COD in pair"); Serial.print(COD[0]); Serial.print(COD[1]); Serial.print(COD[2]); Serial.print(COD[3]); long r=0; int c=0; for(int i=1;i<=EEPROM.read(0);i++){ switch(i%4){ case 1 :{AUX[0]=EEPROM.read(i); break;} case 2 :{AUX[1]=EEPROM.read(i); break;} case 3 :{AUX[2]=EEPROM.read(i); break;} case 0 :{AUX[3]=EEPROM.read(i); break;} } if((i)%4==0) {Serial.println(r); if( AUX[0]==COD[0] && AUX[1]==COD[1] && AUX[2]==COD[2] && AUX[3]==COD[3] ){ lcd.clear(); lcd.setCursor(0,0); lcd.print("CODE ALREADY IN"); lcd.setCursor(0,1); lcd.print("SYSTEM"); delay(2000); c=1; break;} } } if(c==0){int ttt=EEPROM.read(0); Serial.println("CODE PAIRED"); Serial.print(COD[0]); Serial.print(COD[1]); Serial.print(COD[2]); Serial.print(COD[3]); EEPROM.write(ttt+1,COD[0]); EEPROM.write(ttt+2,COD[1]); EEPROM.write(ttt+3,COD[2]); EEPROM.write(ttt+4,COD[3]); ttt=ttt+4; Serial.println("ttt"); Serial.println(ttt); EEPROM.write(0,0); EEPROM.write(0,ttt); lcd.clear(); lcd.setCursor(0,0); lcd.print("CODE PAIRED"); delay(2000);} } boolean validareNFC(){ boolean c=false; for(int i=1;i<=EEPROM.read(0);i++){ switch(i%4){ case 1 :{AUX[0]=EEPROM.read(i); break;} case 2 :{AUX[1]=EEPROM.read(i); break;} case 3 :{AUX[2]=EEPROM.read(i); break;} case 0 :{AUX[3]=EEPROM.read(i); break;} } if((i)%4==0) { if( AUX[0]==COD[0] && AUX[1]==COD[1] && AUX[2]==COD[2] && AUX[3]==COD[3]) c=true; }} return c; } int comparareCOD(String a) { if(a.equals(codacces)) return 1; else if(a.equals(codpairing)) return 2; else return 0; } String iaCOD(char x) { char vec[10]; vec[0]=x; lcd.setCursor(0,0); lcd.clear(); lcd.print('X'); for(int i=1;i<8;i++) {vec[i]=myKeypad.waitForKey(); lcd.print('X');} vec[8]=NULL; String str(vec); return str; } void loop() { //Start BT autentification if(Serial.available()) { char c=Serial.read(); switch (state_bt) { case 1: if(c=='*') state_bt=2; else state_bt=1; break; case 2: if(c=='1') state_bt=3; else state_bt=1; break; case 3: if(c=='2') state_bt=4; else state_bt=1; break; case 4: if(c=='3') state_bt=5; else state_bt=1; break; case 5: if(c=='4') state_bt=6; else state_bt=1; break; case 6: if(c=='5') state_bt=7; else state_bt=1; break; case 7: if(c=='6') state_bt=8; else state_bt=1; break; case 8: if(c=='#') state_bt=9; else state_bt=1; break; case 9: lcd.init(); lcd.backlight(); lcd.print("OPEN"); digitalWrite(6,LOW); delay(5000); digitalWrite(6,HIGH); lcd.init(); lcd.backlight(); lcd.print("BLOCKED"); state_bt=1; break; default: break; } } switch(stare){ case 0: { mfrc522.PCD_Init(); if ( mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial() ){ citireNFC(); if(validareNFC()) {stare=1; lcd.clear(); lcd.setCursor(0,0); lcd.print("VALID NFC CODE"); delay(1000); return; } else{ lcd.clear(); lcd.setCursor(0,0); lcd.print("INVALID NFC CODE"); delay(1000); lcd.setCursor(0,0); lcd.clear(); lcd.print("BLOCKED"); return; } } char c=myKeypad.getKey(); if(c != NO_KEY){ String codcurent=iaCOD(c); int A=comparareCOD(codcurent); if(A==0) {lcd.clear(); lcd.print("INVALID CODE"); delay(2000); lcd.setCursor(0,0); lcd.clear(); lcd.print("BLOCKED"); return;} if(A==1) {lcd.setCursor(0,0); lcd.clear(); lcd.print("VALID CODE"); delay(2000); stare = 1; return;} if(A==2); {stare=2; lcd.clear(); lcd.setCursor(0,0); lcd.print("Pairing..."); delay(2000); return;} } break; } case 1:{ lcd.clear(); lcd.setCursor(0,0); lcd.print("UNLOCKED"); digitalWrite(A3,LOW); digitalWrite(A1,LOW); digitalWrite(A2,HIGH); //tone(6,3000,5010); digitalWrite(6,LOW); delay(5000); digitalWrite(6,HIGH); digitalWrite(A3,HIGH); digitalWrite(A1,HIGH); digitalWrite(A2,LOW); stare=0; lcd.setCursor(0,0); lcd.clear(); lcd.print("BLOCKED"); return; } case 2:{ mfrc522.PCD_Init(); if ( mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial() ){ citireNFC(); pairNFC(); stare=0; delay(2000); lcd.clear(); lcd.setCursor(0,0); lcd.print("BLOCKED"); } break; } } }
步驟3:應(yīng)用程序
在此步驟中,我們將為系統(tǒng)創(chuàng)建應(yīng)用程序。我使用的是MIT App Inventor 2程序。這個程序很簡單,不需要很高的編程技能,可以在此處下載:MIT AppInventor。為了打開該應(yīng)用程序,您需要:
下載應(yīng)用程序
用您的Google賬號進行登錄
開始一個新的項目
在安裝了程序之后,您會找到如下的一個圖形界面:
圖 14 : MIT AppInventor
為了對您的程序進行測試,您需要在手機上從Google Play下載“MIT AI2”應(yīng)用程序。這是一個免費的應(yīng)用程序,專門用于將網(wǎng)絡(luò)應(yīng)用程序同步到智能手機上。
圖15:Google Play上的MIT AppInventor
如果您想要在手機上查看應(yīng)用程序的屏幕,需要點擊Connect → AI Companion。
圖16:連接應(yīng)用程序
點擊之后,該應(yīng)用程序?qū)槟峁﹥煞N操作方式:
您可以掃描條形碼(在您的設(shè)備上啟動MIT AI2 Companion,然后掃描條形碼或鍵入用于連接的代碼,以對您的應(yīng)用程序進行實時測試)
在您的應(yīng)用程序中輸入6個字母的代碼
我將使用第二種方法,將電腦產(chǎn)生的6個字母的代碼輸入到手機應(yīng)用程序中。
圖17:網(wǎng)絡(luò)與手機同步
我選擇這個應(yīng)用程序是因為它易于使用;您無需具備編程技能即可實現(xiàn)如上所述的簡單代碼。您只需要構(gòu)思一下應(yīng)用程序的外觀,在該應(yīng)用程序中進行外觀設(shè)置也非常簡單。
我們先從用戶界面開始:
圖18:用戶界面
圖19:我的用于無線打開門鎖的應(yīng)用程序
您可以在屏幕上添加應(yīng)用程序的任何元素(按鈕,圖像,文本框,標簽)。在右側(cè)菜單中,您可以選擇想要從屏幕上獲取的特征(水平對齊,應(yīng)用名稱,標題)。如果您想要背景圖像,可以從背景圖像(Background Image)菜單中進行選擇。在該應(yīng)用程序中,我選擇在藍牙和手機之間的連接打開時顯示綠色背景,在連接關(guān)閉時顯示紅色背景。
該應(yīng)用程序中屏幕上的三個要素:
圖20:不可見的組件
傳感器組件 & 用戶界面組件 – MIT App Inventor
1.Bluetooth Client1 – 檢測藍牙設(shè)備的組件。該系統(tǒng)中返回以下內(nèi)容的函數(shù):
配對的藍牙設(shè)備的地址和名稱 – AddressesAndNames
設(shè)備上的藍牙是否可用 – 可用(Available)
是否啟用藍牙 – 是(Enabled)
2.Clock1 – 不可見的組件,通過手機上的內(nèi)置時鐘提供即時時間。它可以按照設(shè)置的時間間隔定期地觸發(fā)計時器,并執(zhí)行時間的計算、操作和轉(zhuǎn)換。
3.Notifier1 – 通知器組件顯示警報對話框、消息和臨時警報,并通過以下方式創(chuàng)建Android日志條目:
ShowMessageDialog: 顯示一條用戶必須通過按下按鈕才能關(guān)閉的消息。
LogError: 將錯誤消息記錄到Android日志中。
LogInfo: 將信息消息記錄到Android日志中。
圖21:屏幕模塊
如果未連接藍牙,您會收到一個錯誤信息,該錯誤信息會顯示在連接狀態(tài)(Link Status)部分中。我在沒有連接設(shè)備的情況下輸入了打開門的密碼,應(yīng)用程序提醒我設(shè)備沒有打開。這是一個很好的通知器,因為您有可能會忘記進行設(shè)備的配對,這樣就無法把門打開。
圖22:通知器顯示錯誤信息
該應(yīng)用程序有三個按鈕:
1. 連接:該按鈕被啟動時,將會顯示一個文本列表供用戶選擇。此按鈕相當于藍牙查找器。如果您使用該應(yīng)用時附近開啟的藍牙設(shè)備多余一個,則這些藍牙將會顯示在搜索框中。我的附近只有一個打開的藍牙,即HC-05模塊。
圖23:搜索藍牙設(shè)備
圖24:listpicker模塊
2. 斷開連接:此按鈕將會把應(yīng)用程序與手機之間的連接斷開。點擊按鈕后,背景色變?yōu)榧t色。
圖25:斷開連接模塊
3. 發(fā)送文本:僅在建立連接時有效。程序通過藍牙的“SendText”函數(shù)發(fā)送文本數(shù)據(jù)。在狀態(tài)部分將顯示消息“消息已發(fā)送”(Message Sent)。
圖26:發(fā)送文本模塊
應(yīng)用程序是如何工作的 – Pevest App Inventor 2: 學習編碼
“當輸入Clock1.Timer指令時,該應(yīng)用程序會檢查藍牙是否打開。變量 ByteAvailable 和 CommandByte將被初始化設(shè)置為0,以用于傳輸。如果獲取到了有關(guān)數(shù)據(jù),則使用ReceiveSigned1ByteNumber讀取傳入數(shù)據(jù)的第一個字節(jié)。這是指令字節(jié)。根據(jù)指令的值,將采用合適的藍牙模塊中的方法(method)來讀取下一個字節(jié)?!?/p>
圖 27: 傳輸模塊/ ? Pevest App Inventor 2
結(jié)論
該項目由于需要使用大量的外圍設(shè)備之間的通信而具有一定的挑戰(zhàn)性,因此我花了一些時間來尋找連接所有組件的理想方式。它幫助我了解了制造復(fù)雜設(shè)備的過程中可能發(fā)生的一些錯誤,以及避免這些錯誤的方法。
Tiberia Todeila
Tiberia目前在Politehnica大學進行最后一年的學習,專業(yè)方向為電氣工程。她非常熱衷于設(shè)計和開發(fā)那些讓我們的日常生活變得更加輕松的智能家居設(shè)備。
審核編輯黃宇
-
智能手機
+關(guān)注
關(guān)注
66文章
18419瀏覽量
179733 -
RFID
+關(guān)注
關(guān)注
387文章
6092瀏覽量
237244 -
Arduino
+關(guān)注
關(guān)注
187文章
6461瀏覽量
186525
發(fā)布評論請先 登錄
相關(guān)推薦
評論