ไลบรารี Loramesher ใช้โปรโตคอลการกำหนดเส้นทางระยะทางสำหรับการสื่อสารข้อความระหว่างโหนด Lora สำหรับการโต้ตอบกับชิปวิทยุ LORA เราใช้ประโยชน์จาก Radiolib ซึ่งเป็นห้องสมุดการสื่อสารอเนกประสงค์ซึ่งรองรับโมดูล LORA Series ที่แตกต่างกัน
ในขณะนี้ Loramesher ได้รับการทดสอบภายในโมดูลต่อไปนี้:
คุณสามารถขอเพิ่มโมดูลอื่นในห้องสมุดโดยเปิดปัญหา
คุณสามารถตรวจสอบ library.json สำหรับรายละเอียดเพิ่มเติม โดยพื้นฐานแล้วเราใช้ radiolib ที่ใช้การสื่อสารระดับต่ำไปยังโมดูล LORA ที่แตกต่างกันและ Freertos สำหรับการจัดตารางเวลาการบำรุงรักษา
ในไฟล์ต้นฉบับของการใช้งานครั้งแรกนี้เป็นตัวอย่างในการทดสอบฟังก์ชันใหม่ ตัวอย่างนี้คือการใช้งานตัวนับส่งข้อความออกอากาศทุก ๆ 10 วินาที เพื่อให้เข้าใจได้ง่ายขึ้นเราจะลบฟังก์ชั่นเพิ่มเติมที่ไม่จำเป็นเพื่อให้ไมโครคอนโทรลเลอร์ทำงานกับไลบรารี Loramesher
เพื่อเป็นข้อพิสูจน์แนวคิดเราจะส่งเคาน์เตอร์ตัวเลขผ่าน Lora ค่าของมันจะเพิ่มขึ้นทุก ๆ 10 วินาทีจากนั้นแพ็คเก็ต TE จะถูกส่ง ในการเริ่มต้นเราจำเป็นต้องใช้ประเภทของข้อมูลที่เราจะใช้
ในกรณีนี้เราจะส่ง uint32_t เท่านั้นซึ่งเป็นตัวนับเอง
uint32_t dataCounter = 0;
struct dataPacket {
uint32_t counter = 0;
};
dataPacket* helloPacket = new dataPacket;
ในการเริ่มต้นการใช้งานใหม่คุณสามารถกำหนดค่าพารามิเตอร์ LORA ที่ไลบรารีจะใช้ หากโหนดของคุณต้องการรับข้อความไปยังแอปพลิเคชันให้ดูที่ส่วนฟังก์ชั่นแพ็คเก็ตที่ได้รับ
คุณสามารถกำหนดค่าพารามิเตอร์ที่แตกต่างกันสำหรับการกำหนดค่า LORA การใช้ LoRaMesherConfig คุณสามารถกำหนดค่าพารามิเตอร์ต่อไปนี้ (บังคับ*):
นี่คือตัวอย่างเกี่ยวกับวิธีการกำหนดค่า Loramesher โดยใช้การกำหนดค่านี้:
//Get the LoraMesher instance
LoraMesher& radio = LoraMesher::getInstance();
//Get the default configuration
LoraMesher::LoraMesherConfig config = LoraMesher::LoraMesherConfig();
//Change some parameters to the configuration
//(TTGO T-Beam v1.1 pins)
config.loraCS = 18
config.loraRst = 23
config.loraIrq = 26
config.loraIo1 = 33
config.module = LoraMesher::LoraModules::SX1276_MOD;
//Initialize the LoraMesher. You can specify the LoRa parameters here or later with their respective functions
radio.begin(config);
//After initializing you need to start the radio with
radio.start();
//You can pause and resume at any moment with
radio.standby();
//And then
radio.start();
ระวังกฎหมายท้องถิ่นที่ใช้กับความถี่วิทยุ
หากโหนดของคุณต้องการรับแพ็กเก็ตจากโหนดอื่น ๆ คุณควรทำตามขั้นตอนถัดไป:
ฟังก์ชั่นที่ได้รับการแจ้งเตือนทุกครั้งที่ไลบรารีได้รับแพ็คเก็ตสำหรับแอปดูเหมือนว่า:
/**
* @brief Function that process the received packets
*
*/
void processReceivedPackets(void*) {
for (;;) {
/* Wait for the notification of processReceivedPackets and enter blocking */
ulTaskNotifyTake(pdPASS, portMAX_DELAY);
//Iterate through all the packets inside the Received User Packets FiFo
while (radio.getReceivedQueueSize() > 0) {
Serial.println("ReceivedUserData_TaskHandle notify received");
Serial.printf("Queue receiveUserData size: %dn", radio.getReceivedQueueSize());
//Get the first element inside the Received User Packets FiFo
AppPacket<dataPacket>* packet = radio.getNextAppPacket<dataPacket>();
//Print the data packet
printDataPacket(packet);
//Delete the packet when used. It is very important to call this function to release the memory of the packet.
radio.deletePacket(packet);
}
}
}
มีบางสิ่งสำคัญที่เราต้องระวัง:
void* ในพารามิเตอร์ulTaskNotifyTake(pdPASS,portMAX_DELAY) หรือเทียบเท่า ฟังก์ชั่นนี้ช่วยให้ไลบรารีสามารถแจ้งฟังก์ชั่นเพื่อประมวลผลแพ็กเก็ตที่รอดำเนินการradio.getReceivedQueueSize()radio.getNextAppPacket<T>() โดยที่ t คือประเภทของข้อมูลของคุณradio.deletePacket(packet) มันจะปลดปล่อยหน่วยความจำที่ได้รับการจัดสรรสำหรับแพ็คเก็ต หากไม่ได้ดำเนินการอาจทำให้เกิดการรั่วไหลของหน่วยความจำและจากข้อผิดพลาดของหน่วยความจำ TaskHandle_t receiveLoRaMessage_Handle = NULL;
/**
* @brief Create a Receive Messages Task and add it to the LoRaMesher
*
*/
void createReceiveMessages() {
int res = xTaskCreate(
processReceivedPackets,
"Receive App Task",
4096,
(void*) 1,
2,
&receiveLoRaMessage_Handle);
if (res != pdPASS) {
Serial.printf("Error: Receive App Task creation gave error: %dn", res);
}
}
radio.setReceiveAppDataTaskHandle(receiveLoRaMessage_Handle);
ในส่วนนี้เราจะแสดงให้คุณเห็นว่ามีอะไรอยู่ใน AppPacket
class AppPacket {
uint16_t dst; //Destination address, normally it will be local address or BROADCAST_ADDR
uint16_t src; //Source address
uint32_t payloadSize = 0; //Payload size in bytes
T payload[]; //Payload
size_t getPayloadLength() { return this->payloadSize / sizeof(T); }
};
functionalities ที่จะใช้หลังจากได้รับแพ็คเก็ตด้วย AppPacket<T>* packet = radio.getNextAppPacket<T>() :
packet->getPayloadLength() มันจะทำให้คุณมีขนาดน้ำหนักบรรทุกในจำนวน Tradio.deletePacket(packet) มันจะปล่อยหน่วยความจำที่จัดสรรสำหรับแพ็คเก็ตนี้ ในส่วนนี้เราจะนำเสนอวิธีการสร้างและส่งแพ็กเก็ต ในตัวอย่างนี้เราจะใช้โครงสร้างข้อมูล AppPacket
void loop() {
helloPacket->counter = dataCounter++;
//Create packet and send it.
radio.createPacketAndSend(BROADCAST_ADDR, helloPacket, 1);
//Or if you want to send large and reliable payloads you can call this function too.
radio.sendReliable(dstAddr, helloPacket, 1);
//Wait 10 seconds to send the next packet
vTaskDelay(10000 / portTICK_PERIOD_MS);
}
ในรูปก่อนหน้านี้เราจะเห็นว่าเรากำลังใช้ HelloPacket เราเพิ่มตัวนับภายในและเราสร้างและส่งแพ็คเก็ตโดยใช้ Loramesher
ส่วนที่สำคัญที่สุดของรหัสชิ้นนี้คือฟังก์ชั่นที่เราเรียกใน radio.createPacketAndSend() :
เมื่อได้รับแพ็คเก็ตเราต้องเข้าใจว่าคิวจะส่งคืนเราอย่างไร ด้วยเหตุผลนี้ในส่วนย่อยถัดไปเราจะอธิบายวิธีการใช้การประมวลผลแพ็คเก็ตอย่างง่าย
/**
* @brief Print the counter of the packet
*
* @param data
*/
void printPacket(dataPacket data) {
Serial.printf("Hello Counter received n %dn", data.counter);
}
/**
* @brief Iterate through the payload of the packet and print the counter of the packet
*
* @param packet
*/
void printDataPacket(AppPacket<dataPacket>* packet) {
//Get the payload to iterate through it
dataPacket* dPacket = packet->payload;
size_t payloadLength = packet->getPayloadLength();
for (size_t i = 0; i < payloadLength; i++) {
//Print the packet
printPacket(dPacket[i]);
}
}
processReceivedPackets() เราเรียกฟังก์ชัน printDataPacket()packet->payloadpacket->getPayloadLength() สิ่งนี้จะแจ้งให้เราทราบว่าน้ำหนักบรรทุกมีขนาดใหญ่แค่ไหนในประเภทข้อมูลสำหรับแพ็คเก็ตที่กำหนด ในกรณีของเราเราจะส่งฐานข้อมูลเพียงครั้งเดียวเสมอprintPacket(dPacket[i]) ที่จะพิมพ์ตัวนับที่ได้รับ โปรดดู "การใช้งาน Open Access ของเรา" การใช้งาน Lora Mesh Library "สำหรับคำอธิบายโดยละเอียด หากคุณใช้ห้องสมุด Loramesher ในงานวิชาการโปรดอ้างอิงสิ่งต่อไปนี้:
@ARTICLE{9930341,
author={Solé, Joan Miquel and Centelles, Roger Pueyo and Freitag, Felix and Meseguer, Roc},
journal={IEEE Access},
title={Implementation of a LoRa Mesh Library},
year={2022},
volume={10},
number={},
pages={113158-113171},
doi={10.1109/ACCESS.2022.3217215}}