這篇文章來源于DevicePlus.com英語網(wǎng)站的翻譯稿。
點擊這里閱讀 LoRaLib 開發(fā)板 >
為了控制 Arduino長距離通信教程–LoRenz 開發(fā)板中構建的LoRenz開發(fā)板,我開發(fā)了LoRaLib——用于SX1278芯片的開源Arduino庫。這個庫從零開始設計,目的只有一個:制作易于使用的API,即使是初學者也可以實現(xiàn)LoRa通信。該庫的目標是使遠程通信與串行通信一樣簡單。
軟件
Arduino IDE
LoRaLib Arduino 庫 (可在 GitHub 上獲得)
LoRaLib 庫
SX1278有多種不同設置,允許用戶完全自定義范圍、數(shù)據(jù)速率和功耗,但是最重要的三個設置如下所示:
帶寬 SX1278允許的帶寬設置為7.8 kHz至500 kHz。帶寬值越高,數(shù)據(jù)傳輸越快。然而,這是以降低總靈敏度為代價的,因此降低了最大范圍。
擴頻因子 在LoRa調制中,每個信息位由多個啁啾表示。擴頻因子是指每位數(shù)據(jù)有多少啁啾。SX1278支持7種不同的設置,擴頻因子越高,數(shù)據(jù)傳輸越慢,范圍越大。
編碼速率 為了提高傳輸?shù)姆€(wěn)定性,SX1278可以執(zhí)行錯誤檢查功能。此錯誤檢查的度量稱為編碼速率,可以設定四個值。編碼速率設為最低的4/5時,傳輸不太穩(wěn)定,速度稍快。編碼速率設為最高的4/8時,鏈路更可靠,但代價是數(shù)據(jù)傳輸速率較慢。
庫的默認設置為:帶寬為500 kHz、編碼速率為4/5和擴頻因子為12。這些設置是范圍、穩(wěn)定性和數(shù)據(jù)速率之間的合理平衡。當然,這些設置可以通過函數(shù)隨時更改。
該庫內置數(shù)據(jù)包類和尋址系統(tǒng)。地址長度為8字節(jié),那么最大的尋址數(shù)量就是1.8千億億(1.8 × 10^19)。這個數(shù)值大的離譜。相比之下,NASA估計我們銀河系中的恒星數(shù)量僅為“4億”(4×10^11)。每個數(shù)據(jù)包由源地址、目標地址和最多240字節(jié)的有效負載組成。當然,該庫還提供了幾種讀取和寫入分組數(shù)據(jù)的方法。
讓我們來看一下使用這個庫是多么容易。假設我們有兩個帶有SX1278模塊的LoRenz開發(fā)板。它們相距幾百米,所以我們可以使用默認設置。首先,我們必須包含庫頭文件。然后,我們用默認設置創(chuàng)建 LoRa 類的一個實例,用目標地址和消息創(chuàng)建 packet 類的一個實例。源地址由庫自動生成并寫入Arduino EEPROM。要檢查所有內容是否已正確保存,我們會讀取數(shù)據(jù)包信息并將其打印到串行端口。接下來,我們只需調用 tx() 函數(shù)即可。一會兒之后……完成!只需一個命令,我們的數(shù)據(jù)包就傳送成功了!
// include the library #include // create instance of LoRa class with default settings LoRa lora; // create instance of packet class // destination: "20:05:55:FE:E1:92:8B:95" // data: "Hello World !" packet pack("20:05:55:FE:E1:92:8B:95", "Hello World!"); void setup() { Serial.begin(9600); // initialize the LoRa module with default settings lora.init(); // create a string to store the packet information char str[24]; // print the source of the packet pack.getSourceStr(str); Serial.println(str); // print the destination of the packet pack.getDestinationStr(str); Serial.println(str); // print the length of the packet Serial.println(pack.length); // print the data of the packet Serial.println(pack.data); } void loop() { Serial.print("Sending packet "); // start transmitting the packet uint8_t state = lora.tx(pack); if(state == 0) { // if the function returned 0, a packet was successfully transmitted Serial.println(" success!"); } else if(state == 1) { // if the function returned 1, the packet was longer than 256 bytes Serial.println(" too long!"); } // wait a second before transmitting again delay(1000); }
當然,我們需要第二套配有LoRenz 開發(fā)板的Arduino來接收該數(shù)據(jù)包。 系統(tǒng)設置不變,只是這次我們調用 rx() 函數(shù),然后打印接收到的數(shù)據(jù)包。此函數(shù)將等待數(shù)據(jù)包,如果數(shù)據(jù)沒有在某個時間內到達,該函數(shù)將超時,以便您的代碼不會完全掛起。該庫甚至還會檢查傳輸?shù)臄?shù)據(jù)包是否已損壞,如果是,則將其丟棄。
// include the library #include // create instances of LoRa and packet classes with default settings LoRa lora; packet pack; void setup() { Serial.begin(9600); // initialize the LoRa module with default settings lora.init(); } void loop() { Serial.print("Waiting for incoming transmission ... "); // start receiving single packet uint8_t state = lora.rx(pack); if(state == 0) { // if the function returned 0, a packet was successfully received Serial.println("success!"); // create a string to store the packet information char str[24]; // print the source of the packet pack.getSourceStr(str); Serial.println(str); // print the destination of the packet pack.getDestinationStr(str); Serial.println(str); // print the length of the packet Serial.println(pack.length); // print the data of the packet Serial.println(pack.data); } else if(state == 1) { // if the function returned 1, no packet was received before timeout Serial.println("timeout!"); } else if(state == 2) { // if the function returned 2, a packet was received, but is malformed Serial.println("CRC error!"); } }
當然,這只是最基本的例子。庫本身可以做更多事情,而且我還在繼續(xù)開發(fā)更多的功能。有關該庫和所有其他功能的更深入信息,請參閱我的 GitHub 以及那里托管的文檔。
Arduino 加密
本文結束之前,我還想討論一下Arduino的加密。我在上一篇文章中提到了這個問題?,F(xiàn)在,我們發(fā)送的所有數(shù)據(jù)都是未加密的。這意味著擁有相同配置、使用相同模塊和相同設置的任何人都能攔截和閱讀我們的消息。攻擊者甚至可以發(fā)送自己的消息,而我們卻無法分辨。顯然,這并不安全。
最簡單的解決方案就是使用某種加密。具體地,我決定使用 Rijndael 密碼。沒聽說過吧?這是因為這個名字是荷蘭語,因此不好記憶和發(fā)音。密碼本身實際上非常普遍,但名稱更加引人注目:AES。它是一種對稱密碼,可在加密速度和安全性之間提供出色的平衡。此外,Arduino還提供了幾個AES庫!本項目使用的庫是Davy Landman開發(fā)的AESLib(可從 GitHub 上獲得)。
如上所述,AES是一種對稱密碼 – 這意味著它使用相同的密鑰來加密和解密消息?,F(xiàn)在,我們只有兩個設備,因此將密鑰硬編碼到Arduino中非常容易。當然,如果我們想要動態(tài)添加更多設備并創(chuàng)建某種無線網(wǎng)絡,我們必須以某種方式實現(xiàn)安全密鑰交換,例如使用Diffie-Hellman交換。但是我們現(xiàn)在不會深入這個領域,我們只需將密鑰硬編碼到我們的Arduino程序中即可。
那么我們應該如何修改上一章的代碼呢?修改并不多,說實話,我們只需添加密鑰以及一個加密或解密數(shù)據(jù)包中的數(shù)據(jù)。這是發(fā)射機部分,加密通過 aes128_enc_single() 函數(shù)完成。
// include the libraries #include #include // create instance of LoRa class with default settings LoRa lora; // create instance of packet class // destination: "20:05:55:FE:E1:92:8B:95" // data: "Hello World !" packet pack("20:05:55:FE:E1:92:8B:95", "Hello World! "); // our secret 16-byte long key uint8_t key[] = {0x2C, 0x66, 0x54, 0x94, 0xE3, 0xAE, 0xC7, 0x32, 0xC4, 0x66, 0xC8, 0xBE, 0xF3, 0x71, 0x22, 0x36}; void setup() { Serial.begin(9600); // initialize the LoRa module with default settings lora.init(); // create strings to store the packet information char src[24]; char dest[24]; // print the source of the packet pack.getSourceStr(src); Serial.print("Source:ttt"); Serial.println(src); // print the destination of the packet pack.getDestinationStr(dest); Serial.print("Destination:tt"); Serial.println(dest); // print the length of the packet Serial.print("Total # of bytes:t"); Serial.println(pack.length); // print the contents of unencrypted packet Serial.println("-------- Plain text ---------"); Serial.println(pack.data); // encrypt the data aes128_enc_single(key, pack.data); // print the contents of encrypted packet Serial.println("--- Encrypted with AES128 ---"); Serial.println(pack.data); } void loop() { Serial.print("Sending packet "); // start transmitting the packet uint8_t state = lora.tx(pack); if(state == 0) { // if the function returned 0, a packet was successfully transmitted Serial.println(" success!"); } else if(state == 1) { // if the function returned 1, the packet was longer than 256 bytes Serial.println(" too long!"); } // wait a second before transmitting again delay(1000); }
接收機部分如下所示,解密通過相同密鑰和函數(shù) aes128_dec_single() 完成。
// include the libraries #include #include // create instances of LoRa and packet classes with default settings LoRa lora; packet pack; // our secret 16-byte long key uint8_t key[] = {0x2C, 0x66, 0x54, 0x94, 0xE3, 0xAE, 0xC7, 0x32, 0xC4, 0x66, 0xC8, 0xBE, 0xF3, 0x71, 0x22, 0x36}; void setup() { Serial.begin(9600); // initialize the LoRa module with default settings lora.init(); } void loop() { Serial.print("Waiting for incoming transmission ... "); // start receiving single packet uint8_t state = lora.rx(pack); if(state == 0) { // if the function returned 0, a packet was successfully received Serial.println("success!"); // create strings to store the packet information char src[24]; char dest[24]; // print the source of the packet pack.getSourceStr(src); Serial.print("Source:ttt"); Serial.println(src); // print the destination of the packet pack.getDestinationStr(dest); Serial.print("Destination:tt"); Serial.println(dest); // print the length of the packet Serial.print("Total # of bytes:t"); Serial.println(pack.length); // print the contents of encrypted packet Serial.print("Encrypted (AES128):t"); Serial.println(pack.data); // decrypt the data aes128_dec_single(key, pack.data); // print the contents of unencrypted packet Serial.print("Plain text:tt"); Serial.println(pack.data); } else if(state == 1) { // if the function returned 1, no packet was received before timeout Serial.println("timeout!"); } else if(state == 2) { // if the function returned 2, a packet was received, but is malformed Serial.println("CRC error!"); } }
使用了密鑰之后,我們的消息現(xiàn)在是安全的。如果有人偷聽我們的談話,他無法看到除地址之外的任何內容,每個數(shù)據(jù)包中都是240字節(jié)的亂碼。同樣,如果攻擊者試圖傳輸他自己的消息,我們會立即知道,因為他傳輸?shù)南⒉粫用堋?/p>
在Arduino上用AES加密非常簡單,所以我推薦使用該加密方法。這不僅僅是一個很好的編程實踐。您永遠不知道誰以及為什么可能會偷聽您看似無辜的對話。
結論
現(xiàn)在,Arduino遠程無線通信的短暫旅途就要結束了。如果您開發(fā)自己的LoRenz開發(fā)板并將其應用于一些很酷的Arduino項目,請告訴我!如果您有改進LoRenz開發(fā)板和LoRaLib庫的想法,請在GitHub上與我分享。
我對開發(fā)板進行了測試,當帶寬為500kHz、擴展因子為12、編碼率為4/8時,在無障礙環(huán)境中我能夠實現(xiàn)超過500米的可靠傳輸;在茂密的森林中傳輸距離則超過200米。所有這一切都只是通過一根10cm天線實現(xiàn)的,而且發(fā)射器電源也只是廉價的9V電池而已(接收器從USB端口接電,最終通過Arduino板載穩(wěn)壓器供電)。這個距離還可以更長(通過降低帶寬),但是這會導致傳輸速度顯著降低,在上述設置不變的情況下傳輸速度大約為1 kbps。
然而,對于我將來的項目,這些距離綽綽有余。請在社交媒體上關注DevicePlus,這樣您就不會錯過任何有趣的內容!
審核編輯:湯梓紅
-
通信
+關注
關注
18文章
6036瀏覽量
136083 -
開發(fā)板
+關注
關注
25文章
5067瀏覽量
97613 -
Arduino
+關注
關注
188文章
6471瀏覽量
187233
發(fā)布評論請先 登錄
相關推薦
評論