0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Arduino長距離通信教程–LoRaLib庫

劉丹 ? 來源:huzp_bbs ? 作者:huzp_bbs ? 2023-02-24 09:51 ? 次閱讀

這篇文章來源于DevicePlus.com英語網(wǎng)站的翻譯稿。

點擊這里閱讀 LoRaLib 開發(fā)板 >

poYBAGPzFjKAQuZcAACINIX9R_c055.jpg

為了控制 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,這樣您就不會錯過任何有趣的內容!

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 通信
    +關注

    關注

    18

    文章

    6036

    瀏覽量

    136083
  • 開發(fā)板
    +關注

    關注

    25

    文章

    5067

    瀏覽量

    97613
  • Arduino
    +關注

    關注

    188

    文章

    6471

    瀏覽量

    187233
收藏 人收藏

    評論

    相關推薦

    請問USB模擬串口如何實現(xiàn)長距離通信

    本帖最后由 一只耳朵怪 于 2018-6-19 11:12 編輯 honeywell 1900系列的掃描槍支持USB數(shù)據(jù)線的串口通信方式,但是USB傳輸距離有限,目標距離約為100米,有什么好的方法嗎?能否使用USB轉RJ
    發(fā)表于 06-14 14:32

    長距離光模塊大全

    `  光模塊作為最常見的光電轉換器件,在光通信網(wǎng)絡中,傳輸容量最受人們關注,也是最為核心的一大參數(shù)。其中,光模塊的傳輸距離就各不相同。在光通信網(wǎng)絡傳輸?shù)牟煌I域、環(huán)節(jié)中,對光模塊的特性要求也各不相同
    發(fā)表于 10-18 15:25

    RS485為什么在長距離通信時要加一個終端電阻呢?

    RS485為什么在長距離通信時要加一個終端電阻呢?
    發(fā)表于 04-27 17:38

    長距離通信器S1503 的應用編程原理

    S1503 是瑞典TagMaster AB公司生產(chǎn)的長距離通信器,在自動識別系統(tǒng)中有廣泛的應用。本文重點介紹S1503 系統(tǒng)結構和應用編程原理, 并說明其特點和應用前景。
    發(fā)表于 05-14 16:31 ?10次下載

    長距離光纖通信系統(tǒng)中的新型技術

    給出了超長距離高速光纖通信系統(tǒng)的定義;介紹了高速超長距離光纖通信系統(tǒng)的特征;綜述了高速光纖通信系統(tǒng)在光放大器、色散補償、前向糾錯等方面的最新
    發(fā)表于 12-17 15:56 ?24次下載

    長距離EPON的設計研究方案

    長距離EPON的設計研究方案 目前在電力、煤炭、鐵路、部隊等專網(wǎng)通信領域,開始越來越多的用到EPON技術,然而在這些應用領域經(jīng)常會遇到傳輸距離
    發(fā)表于 03-16 14:55 ?777次閱讀
    <b class='flag-5'>長距離</b>EPON的設計研究方案

    長距離EPON的研究分析

    長距離EPON的研究分析 摘要:目前的EPON協(xié)議規(guī)定了EPON最長傳輸距離與差分距離均不得超過20km,本文探討了長距離EPON的實現(xiàn)方法。通過對EPON物
    發(fā)表于 03-16 16:11 ?866次閱讀

    基于Semtech的LoRa擴頻通信技術實現(xiàn)的超長距離低功耗物聯(lián)網(wǎng)解決方案

    致力于亞太地區(qū)市場的領先半導體元器件分銷商大聯(lián)大控股宣布,其旗下友尚推出基于Semtech的LoRa擴頻通信技術實現(xiàn)的超長距離低功耗物聯(lián)網(wǎng)解決方案,該方案以Semtech 的SX1276和ST
    發(fā)表于 02-12 12:17 ?1119次閱讀
    基于Semtech的LoRa擴頻<b class='flag-5'>通信</b>技術實現(xiàn)的超<b class='flag-5'>長距離</b>低功耗物聯(lián)網(wǎng)解決方案

    CAN轉光纖設備長距離穩(wěn)定傳輸數(shù)據(jù)

    使用光纖傳輸數(shù)據(jù)的方式大家應該都不陌生,光纖可以有效的消除長距離通信干擾。
    的頭像 發(fā)表于 10-17 15:38 ?5093次閱讀

    通信教程的04_SPI接口說明及原理

    通信教程04_SPI接口說明及原理
    的頭像 發(fā)表于 02-05 12:29 ?3966次閱讀

    通信教程03_I2C簡史 基礎原理及協(xié)議

    通信教程03_I2C簡史,基礎原理及協(xié)議
    的頭像 發(fā)表于 02-05 13:14 ?3006次閱讀

    通信教程02 幾種常見串行通信及基礎原理

    通信教程02_幾種常見串行通信及基礎原理
    的頭像 發(fā)表于 02-26 16:12 ?9887次閱讀

    通信教程01 什么是并行通信?什么是串行通信?

    通信教程01_什么是并行通信?什么是串行通信?
    的頭像 發(fā)表于 02-26 16:27 ?1.2w次閱讀

    物聯(lián)網(wǎng)通信網(wǎng)絡層中短距離無線通信網(wǎng)與長距離無線通信網(wǎng)的區(qū)別

    互聯(lián)網(wǎng)以TCP/IP有線網(wǎng)絡為主要數(shù)據(jù)傳輸載體。而物聯(lián)網(wǎng)的信息傳輸則更多依賴于無線傳輸網(wǎng)絡技術,包括短距離無線通信(RFID和Mesh)、長距離無線通信(GSM和各種CDMA
    的頭像 發(fā)表于 09-23 11:12 ?8660次閱讀

    Arduino長距離通信教程–LoRenz開發(fā)板

    在本文中,我將向您介紹“LoRenz-Arduino開發(fā)板”,不僅能完成所有這些任務,而且還能給您帶來更多功能。此外,更重要的是,LoRenz軟件和硬件都是完全開源的!
    的頭像 發(fā)表于 02-24 09:51 ?1151次閱讀
    <b class='flag-5'>Arduino</b><b class='flag-5'>長距離</b><b class='flag-5'>通信教</b>程–LoRenz開發(fā)板