تقوم مكتبة Loramesher بتنفيذ بروتوكول توجيه في المجال للمسافة لتوصيل الرسائل بين عقد Lora. للتفاعل مع رقاقة راديو Lora ، نستفيد من Radiolib ، وهي مكتبة اتصال متعددة الاستخدامات تدعم وحدات سلسلة Lora المختلفة.
في هذه اللحظة ، تم اختبار Loramesher ضمن الوحدات التالية:
يمكنك طلب إضافة وحدة أخرى إلى المكتبة عن طريق فتح مشكلة.
يمكنك التحقق من library.json لمزيد من التفاصيل. في الأساس ، نستخدم radiolib الذي ينفذ الاتصال المنخفض المستوى إلى وحدات Lora المختلفة و Freertos لجدولة مهام الصيانة.
هناك ، في الملفات المصدر لهذا التنفيذ الأول ، مثالًا لاختبار الوظائف الجديدة. هذا المثال هو تنفيذ عداد ، وإرسال رسالة بث كل 10 ثوان. لتسهيل الفهم ، سنقوم بإزالة وظائف إضافية غير ضرورية لجعل متحكم يعمل مع مكتبة Loramesher.
كدليل على المفهوم ، سنرسل عدادًا رقميًا على لورا. سيتم زيادة قيمتها كل 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); }
};
وظائف لاستخدامها بعد الحصول على الحزمة باستخدام 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->payload .packet->getPayloadLength() . سيخبرنا هذا حجم الحمولة الكبيرة ، في أنواع DataPackets ، لحزمة معينة. في حالتنا ، نرسل دائمًا dataPacket واحد فقط.printPacket(dPacket[i]) ، والتي ستطبع العداد المستلم. يرجى الاطلاع على ورقة الوصول المفتوحة "تنفيذ مكتبة Lora Mesh" للحصول على وصف مفصل. إذا كنت تستخدم مكتبة 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}}