这个存储库是我为论文开发的所有项目的所有项目。我提供
projects文件夹中的所有项目。从互联网上散布的许多不同项目中收集的所有开发项目,但我试图简化并将其修饰为一个工作和可理解的项目。我主要在ESP32板上开发,该板与RFM95 Lora芯片相连。它在915 MHz上传输。我在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节点有望成为网络中的最后一个节点,模拟了一个通用拓扑,其中最后一个节点将充当连接到Internet的边界节点,在其一生中收集来自其他节点的消息,然后将它们发送到云。节点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芯片/RX的Freq!
#define RF95_FREQ 915.0
通过使用网格,它的内存需求不仅仅是RH或RHROUTER,您可能需要限制最大消息长度(字符)以防止Wierd崩溃。尽管您可以通过更改消息长度进行更改和实验
#define RH_MESH_MAX_MESSAGE_LEN 50
您可以通过编辑rhSetup()来为RFM95模块添加特定的LORA模式。初始化后(没有任何显式.set )后的默认值为434.0MHz,0.05MHz 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); in 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