Этот репозиторий - место, в котором я включаю все проекты для разработки Lora Rhmesh для моей диссертации. Я предоставляю все проекты в папке
projects. Вся разработка, собранная из многих различных проектов, разбросанных по всему Интернету, но я стараюсь упростить и подготовить их к работающему и понятному проекту.Я разрабатываю в основном на плате ESP32, связанной с чипом Lora RFM95. Он передает на 915 МГц. Я разрабатываю 2 среды, Arduino IDE, платформу IO Vscode.
Не стесняйтесь использовать их и свяжитесь со мной, если хотите!
Этот пример наброска показывает, как создать простой адресуемой, маршрутизированный надежный клиент обмена сообщениями с классом Rhmesh. Он предназначен для работы с другими примерами RF95_MESH_SERVER
#define SELF_ADDRESS NODE3_ADDRESS
#define TARGET_ADDRESS FINAL_ADDRESS
RH_TEST_NETWORK определить вашу топологию в rhrouter.cpp. Узнайте больше в разделе «Принудительная топология» [RFM95] ------------- [ESP32]
RESET -------------- GPIO14
NSS/CS -------------- GPIO5
SCK -------------- GPIO18
MOSI -------------- GPIO23
MISO -------------- GPIO19
DIO0 -------------- GPIO2
3.3V -------------- 3.3V
GND -------------- GND


Если у вас есть другая схема проводки, не забудьте изменить эти строки в main.cpp
#define RFM95_CS 5
#define RFM95_RST 14
#define RFM95_INT 2

Этот пример топологии 4 узла, в которой ожидается, что узел FINAL_ADDRESS будет последним узлом в сети, моделируя общую топологию, в которой этот последний узел будет действовать как пограничный узел, подключенный к Интернету, собирая сообщения с других узлов в течение всего времени жизни, а затем отправлять их в облако. Узел 1-3 собирает данные датчика, а затем отправляется в конечный узел, а в узле процесса 1-3 может быть посредник для друг друга. Не стесняйтесь делать совершенно другую схему адресации.
#define NODE1_ADDRESS 1
#define NODE2_ADDRESS 2
#define NODE3_ADDRESS 3
#define FINAL_ADDRESS 255 // purposefully using the last namber
Вы можете активно изменить поведение текущих узлов, изменив эту линию. Убедитесь, что вы изменили его для каждого другого узла!
const uint8_t selfAddress_ = NODE3_ADDRESS;
const uint8_t targetAddress_ = FINAL_ADDRESS;

После того, как маршрут будет обнаружен для целевого узла, он будет сохранен в качестве въезда в таблицу маршрутизации в этом отдельном узле. Сохраняя следующий прямой узел, который, как ожидается, сможет подключить его с целевым узлом, даже в качестве посредника. Таким образом, в этом примере node 2 сохраняет только node 1 в его входе в свой маршрут, чтобы подключиться к node final , не зная, является ли node 1 единственным промежуточным узлом, или может быть больше. Следовательно, ожидается, что node 1 будет иметь маршрут для подключения к node final , в этом примере это будет прямое соединение. node 2 не имеет прямого пути к node final , но он имеет прямое соединение с node 3
Изменить на 915.0, 434,0 или другая частота, должна соответствовать LORA Chip/RX FREQ!
#define RF95_FREQ 915.0
Используя сетку, он имеет гораздо большие требования к памяти, чем просто RH или RHROUTER, и вам может потребоваться ограничить максимальную длину сообщения (символы), чтобы предотвратить ужасные сбои. Хотя вы можете изменить и экспериментировать с длиной сообщений, изменив это
#define RH_MESH_MAX_MESSAGE_LEN 50
Вы можете добавить конкретные режимы LORA для модуля RFM95, редактируя rhSetup() . По умолчанию после init (без какого-либо явного .set ) составляют 434,0 МГц, 0,05 МГц AFC, модуляция FSK_RB2_4FD36.
RHDriver.setTxPower(23, false);
RHDriver.setFrequency(RF95_FREQ);
RHDriver.setCADTimeout(500);
Несмотря на то, что этот проект работает на RHMESH, который ожидал бы, что у пользователя будет полностью динамическая и жидкая топология, вы можете вызвать маршруты/топологию. Это требует немного жесткого кодирования, вы можете осмотреть код в rhrouter.cpp (строка 223-263). У него уже есть некоторые предварительные примеры топологии, которые заставляют маршрутизацию определенным образом (он делает это путем отбрасывания/не обработки сообщений, которые не соответствуют пути), и макрос RH_TEST_NETWORK необходимо определить (прежде чем вызовать #include "rhmesh.h") для активации этой вынужденной топологии. Вы можете добавить свой собственный код, который напоминает вашу желаемую топологию.
...
#ifdef RH_TEST_NETWORK
if (
#if RH_TEST_NETWORK==1
// This network looks like 1-2-3-4
(_thisAddress == 1 && _from == 2)
|| (_thisAddress == 2 && (_from == 1 || _from == 3))
|| (_thisAddress == 3 && (_from == 2 || _from == 4))
|| (_thisAddress == 4 && _from == 3)
#elif RH_TEST_NETWORK==2
// This network looks like 1-2-4
// | | |
// --3--
(_thisAddress == 1 && (_from == 2 || _from == 3))
|| _thisAddress == 2
|| _thisAddress == 3
|| (_thisAddress == 4 && (_from == 2 || _from == 3))
...
Мы отправим сообщение в другой узел Rhmesh, используя этот код, маршрут к месту назначения будет обнаружен автоматически. Эта функция обнаружения является основной точкой использования RHMESH, она автоматически генерирует таблицу маршрутизации для этого узла (для дальнейшего изучения, ознакомьтесь с функцией bool doArp(uint8_t address); в RHMesh.h ).
if (RHMeshManager.sendtoWait(reinterpret_cast<uint8_t *>(&msgSend[0]), msgSend.size(), targetAddress_) == RH_ROUTER_ERROR_NONE) {
После этой строки возврат true означает, что мы были надежно доставили сообщение в следующий узел, и следующий узел прислал нам «ACK». Если через определенное время нет ACK, SendTowait вернет false . Важным примечанием является то, что ACK не из целевого узла, а любой, который успешно получил сообщение (кроме целевого узла, является промежуточным узлом). В настоящее время RHMESH не говорит, было ли успешно получено сообщение в «окончательный» целевой узел. Способ обойти это «просто», добавляя логику высокого уровня/приложения к «окончательному» целевому узлу, отправив несколько REPLY_TYPE на «начальный» узел отправителя после того, как он получил сообщение, как искусственный ACK (такая функция в настоящее время не реализована в этом репо).
После успешной отправки сообщения мы превращаемся в RECEIVING_MODE и ждем сообщения, поступающего из другого узла. В то время как recvfromAckTimeout активен, он будет проводить действия до тех пор, пока не появится сообщение или не достигнут тайм -аут.
if (RHMeshManager.recvfromAckTimeout(_msgRcvBuf, (uint8_t *) sizeof(_msgRcvBuf), 3000, &_msgFrom)) {
localVariable_
_tempVariable
globalVariable