LOM204A - Criando uma REDE LoRa MESH com Library RADIOHEAD
- Principais Dúvidas
- Tenho 3 módulos para testar LoRa MESH! As principais dúvidas são:
- -E necessário ter uma Bridge?
- -Os outros 2 devem ser nós?
- -Cada nó deve ter o seu ID (0,1,..)?
- -O único que pode transmitir dados deve ser os nós? E todos vão transmitir para o servidor/bridge?
- -Ou a transmissão de dados é bidirecional?
- Respostas
- -Bridges não são obrigatórias, você pode ter quantos nós ou bridges quiser (por exemplo, sua rede pode ser composta de 3 nós)
- -Uma bridge é um nó com recursos adicionais (por exemplo, encaminhando as mensagens recebidas dos nós para um servidor na Internet)
- -Sim, cada nó/bridge tem que ter um ID diferente (0-254)
- -Cada nó pode transmitir para outro nó ou para uma bridge e cada nó ou bridge pode responder ao remetente
- -A comunicação é bidirecional
- É uma biblioteca completa orientada a objetos para enviar e receber pacotes de mensagens por meio de uma variedade de rádios de dados e outros transportes em uma variedade de microprocessadores.DRIVERNeste caso, será utilizado com o SX1276 o driver RH_ABZ da RADIOHEAD, incorporado no LOM204AVejaMANAGERRHDatagram AddressedRHReliableDatagram AddressedRHRouter Multi-hopRHMesh Multi-hop
- Descoberta de rota
Quando um nó de malha RHMesh é inicializado, ele não conhece nenhuma rota para nenhum outro nó (consulte RHRouter para obter detalhes sobre a rota e a tabela de roteamento). Quando você tenta enviar uma mensagem com sendtoWait, primeiro verifica se há uma rota para o nó de destino na tabela de roteamento. Caso contrário, inicializará 'Route Discovery'. Quando um nó precisa descobrir uma rota para outro nó, ele transmite MeshRouteDiscoveryMessage com um tipo de mensagem RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST. Qualquer nodo que receba tal requisição verifica se é uma requisição para uma rota para si mesmo (neste caso ele faz uma resposta unicast para o nodo de origem com uma MeshRouteDiscoveryMessagecom tipo de mensagem RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE) caso contrário retransmite a requisição, após adicionar-se à lista de nodos visitados até então pela requisição.
Se um nodo recebe um RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST que já está listado nos nodos visitados, ele sabe que já viu e retransmitiu esta requisição, portanto a ignora. Isso evita tempestades de transmissão. Quando um nodo recebe um RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST, ele pode usar a lista de nodos já visitados para deduzir rotas de volta ao originador (nodo solicitante). Isso também significa que, quando o nó de destino da solicitação for alcançado, ele (e todos os nós anteriores que a solicitação visitou) terá uma rota de volta ao nó de origem. Isso significa que a resposta unicast RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE será roteada com sucesso de volta ao solicitante da rota original.
O RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE enviado de volta pelo nó de destino contém a lista completa de nós que foram visitados no caminho para o destino. Portanto, nós intermediários que roteiam a resposta de volta para o nó de origem podem usar a lista de nós na resposta para deduzir rotas para todos os nós entre ele e o nó de destino.
Portanto, RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST e RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE juntos garantem que o solicitante original e todos os nós intermediários saibam como rotear para os nós de origem e destino e todos os nós ao longo do caminho.
Observe que há uma condição de corrida aqui que pode afetar o roteamento em rotas multipath. Por exemplo, se a rota para o destino puder percorrer vários caminhos, a última resposta do destino será a usada.
- Falha na rota
O RHRouter (e, portanto, o RHMesh ) usa a entrega confiável de mensagens salto a salto usando confirmações de salto a salto, mas não confirmações de ponta a ponta. Quando sendtoWait() retorna, você sabe que a mensagem foi entregue ao próximo salto, mas não se ela foi (ou mesmo se pode ser) entregue ao nó de destino. Se durante o roteamento hop-to-hop de uma mensagem, um dos nós RHMesh intermediários descobrir que não pode entregar para o próximo salto (por exemplo, devido a uma rota perdida ou nenhum reconhecimento do próximo salto), ele responde ao originador com uma MeshRouteFailureMessage unicastMensagem RH_MESH_MESSAGE_TYPE_ROUTE_FAILURE. Os nós intermediários (no caminho de volta ao originador) e o nó de origem usam esta mensagem para excluir a rota para o nó de destino da mensagem original. Isso significa que se uma rota para um destino se tornar inutilizável (porque um nó intermediário está fora do ar ou saiu do alcance), uma nova rota será estabelecida na próxima vez que uma mensagem for enviada.
- Memória
Os programas RHMesh requerem uma quantidade significativa de SRAM, muitas vezes aproximando-se de 2kbytes, o que está além ou nos limites de alguns Arduinos e outros processadores. Programas com software adicional além dos programas RHMesh básicos podem exigir ainda mais. Se você tiver SRAM insuficiente para o seu programa, isso pode resultar em falha na execução ou travamentos estranhos e outros comportamentos difíceis de rastrear. Neste caso você deve considerar um processador com mais SRAM.
- INSTALE ARDUINO EM SUA MÁQUINA
- INSTALE O PACOTE PARA STM32L0
https://grumpyoldpizza.github.io/ArduinoCore-stm32l0/package_stm32l0_boards_index.json
ARQUIVO-->PREFERENCIAS-->URLS - INSTALE LIBRARY RADIOHEAD
https://github.com/PaulStoffregen/RadioHead
DESCOMPACTE E COPIE PARA USER USUARIO DOCUMENTS ARDUINO LIBRARIES
VÍDEOMONTAGEMSEGUEM EXEMPLOS COM REPLY DA BRIDGENode// node_polite // -*- mode: C++ -*- // Example sketch showing how to create a simple addressed, routed reliable messaging client // with the RHMesh class. // It is designed to work with the other examples abz_mesh_server* // Hint: you can simulate other network topologies by setting the // RH_TEST_NETWORK define in RHRouter.h // Mesh has much greater memory requirements, and you may need to limit the // max message length to prevent wierd crashes #define RH_MESH_MAX_MESSAGE_LEN 50 #include <RHMesh.h> #include <RH_ABZ.h> #include <SPI.h> // In this small artifical network of 4 nodes, #define BRIDGE_ADDRESS 1 // address of the bridge ( we send our data to, hopefully the bridge knows what to do with our data ) #define NODE_ADDRESS 2 // address of this node #define RXTIMEOUT 3000 // it is roughly the delay between successive transmissions // Singleton instance of the radio driver RH_ABZ abz; // Class to manage message delivery and receipt, using the driver declared above RHMesh manager(abz, NODE_ADDRESS); void setup() { //MIGUEL //TCXO - ENABLE pinMode(24, OUTPUT); digitalWrite(24, HIGH); Serial.begin(115200); Serial.print(F("initializing node ")); Serial.print(NODE_ADDRESS); if (!manager.init()) {Serial.println(" init failed");} else {Serial.println(" done");} // Defaults after init are 434.0MHz, 0.05MHz AFC pull-in, modulation FSK_Rb2_4Fd36 abz.setTxPower(10, false); // with false output is on PA_BOOST, power from 2 to 20 dBm, use this setting for high power demos/real usage //abz.setTxPower(1, true); // true output is on RFO, power from 0 to 15 dBm, use this setting for low power demos ( does not work on lilygo lora32 ) abz.setFrequency(868.0); abz.setCADTimeout(500); // long range configuration requires for on-air time boolean longRange = false; if (longRange) { // custom configuration RH_ABZ::ModemConfig modem_config = { 0x78, // Reg 0x1D: BW=125kHz, Coding=4/8, Header=explicit 0xC4, // Reg 0x1E: Spread=4096chips/symbol, CRC=enable 0x08 // Reg 0x26: LowDataRate=On, Agc=Off. 0x0C is LowDataRate=ON, ACG=ON }; abz.setModemRegisters(&modem_config); } else { // Predefined configurations( bandwidth, coding rate, spread factor ): // Bw125Cr45Sf128 Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Default medium range // Bw500Cr45Sf128 Bw = 500 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Fast+short range // Bw31_25Cr48Sf512 Bw = 31.25 kHz, Cr = 4/8, Sf = 512chips/symbol, CRC on. Slow+long range // Bw125Cr48Sf4096 Bw = 125 kHz, Cr = 4/8, Sf = 4096chips/symbol, low data rate, CRC on. Slow+long range // Bw125Cr45Sf2048 Bw = 125 kHz, Cr = 4/5, Sf = 2048chips/symbol, CRC on. Slow+long range if (!abz.setModemConfig(RH_ABZ::Bw125Cr45Sf128)) {Serial.println(F("set config failed"));} } Serial.println("ABZ ready"); } uint8_t data[] = "Hello World!"; // Dont put this on the stack: uint8_t buf[RH_MESH_MAX_MESSAGE_LEN]; uint8_t res; void loop() { Serial.print("Sending to bridge n."); Serial.print(BRIDGE_ADDRESS); Serial.print(" res="); // Send a message to a abz_mesh_server // A route to the destination will be automatically discovered. res = manager.sendtoWait(data, sizeof(data), BRIDGE_ADDRESS); Serial.println(res); if (res == RH_ROUTER_ERROR_NONE) { // Data has been reliably delivered to the next node. // Now we wait for a reply from the destination bridge // This is not automatic, but in this demo, the bridge kindly reply to our initial transmission uint8_t len = sizeof(buf); uint8_t from; if (manager.recvfromAckTimeout(buf, &len, RXTIMEOUT, &from)) { Serial.print("reply from node n."); Serial.print(from); Serial.print(": "); Serial.print((char*)buf); Serial.print(" rssi: "); Serial.println(abz.lastRssi()); delay(RXTIMEOUT); } } else { Serial.println("sendtoWait failed. Are the bridge/intermediate mesh nodes running?"); } }Bridge// bridge_polite // -*- mode: C++ -*- // Example sketch showing how to create a simple addressed, routed reliable messaging client // with the RHMesh class. // It is designed to work with the other examples abz_mesh_server* // Hint: you can simulate other network topologies by setting the // RH_TEST_NETWORK define in RHRouter.h // Mesh has much greater memory requirements, and you may need to limit the // max message length to prevent wierd crashes #define RH_MESH_MAX_MESSAGE_LEN 50 #include <RHMesh.h> #include <RH_ABZ.h> #include <SPI.h> // In this small artifical network of 4 nodes, #define BRIDGE_ADDRESS 1 // address of the bridge ( we send our data to, hopefully the bridge knows what to do with our data ) #define RXTIMEOUT 3000 // it is roughly the delay between successive transmissions // Singleton instance of the radio driver RH_ABZ abz; // Class to manage message delivery and receipt, using the driver declared above RHMesh manager(abz, BRIDGE_ADDRESS); void setup() { //MIGUEL //TCXO - ENABLE pinMode(24, OUTPUT); digitalWrite(24, HIGH); Serial.begin(115200); Serial.print(F("initializing node ")); Serial.print(BRIDGE_ADDRESS); if (!manager.init()) {Serial.println(" init failed");} else {Serial.println(" done");} // Defaults after init are 434.0MHz, 0.05MHz AFC pull-in, modulation FSK_Rb2_4Fd36 abz.setTxPower(2, false); // with false output is on PA_BOOST, power from 2 to 20 dBm, use this setting for high power demos/real usage //abz.setTxPower(1, true); // true output is on RFO, power from 0 to 15 dBm, use this setting for low power demos ( does not work on lilygo lora32 ) abz.setFrequency(868.0); abz.setCADTimeout(500); // long range configuration requires for on-air time boolean longRange = false; if (longRange) { // custom configuration RH_ABZ::ModemConfig modem_config = { 0x78, // Reg 0x1D: BW=125kHz, Coding=4/8, Header=explicit 0xC4, // Reg 0x1E: Spread=4096chips/symbol, CRC=enable 0x08 // Reg 0x26: LowDataRate=On, Agc=Off. 0x0C is LowDataRate=ON, ACG=ON }; abz.setModemRegisters(&modem_config); } else { // Predefined configurations( bandwidth, coding rate, spread factor ): // Bw125Cr45Sf128 Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Default medium range // Bw500Cr45Sf128 Bw = 500 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on. Fast+short range // Bw31_25Cr48Sf512 Bw = 31.25 kHz, Cr = 4/8, Sf = 512chips/symbol, CRC on. Slow+long range // Bw125Cr48Sf4096 Bw = 125 kHz, Cr = 4/8, Sf = 4096chips/symbol, low data rate, CRC on. Slow+long range // Bw125Cr45Sf2048 Bw = 125 kHz, Cr = 4/5, Sf = 2048chips/symbol, CRC on. Slow+long range if (!abz.setModemConfig(RH_ABZ::Bw125Cr45Sf128)) {Serial.println(F("set config failed"));} } Serial.println("ABZ ready"); } uint8_t data[] = "Hello back from bridge"; // Dont put this on the stack: uint8_t buf[RH_MESH_MAX_MESSAGE_LEN]; uint8_t res; void loop() { uint8_t len = sizeof(buf); uint8_t from; if (manager.recvfromAck(buf, &len, &from)) { Serial.print("request from node n."); Serial.print(from); Serial.print(": "); Serial.print((char*)buf); Serial.print(" rssi: "); Serial.println(abz.lastRssi()); // Send a reply back to the originator client res = manager.sendtoWait(data, sizeof(data), from); if ( res != RH_ROUTER_ERROR_NONE) { Serial.print("sendtoWait failed:"); Serial.println(res); } } }Node 2Node 4ALGUNS TESTES EXTRASAgora você sabe que os nós (a alguns centímetros de distância) em sua mesa são capazes de se comunicar.Então, vamos espaçar um nó até que esteja fora do intervalo de malha (até que o log serial do servidor pare de relatar as mensagens do nó) neste ponto, adicione um novo nó 'no meio' (vamos chamá-lo de 'o nó no meio') e depois de um pequeno atraso... o nó original é automaticamente reconectado.Se você achar isso um pouco impraticável (quero dizer, mover os nós a algumas centenas de metros de distância), aqui estão algumas dicas:abaixe a potência dos nós (definindo a potência para 2 dBm, por exemplo) para que algumas paredes dentro de sua casa sejam suficientes (bem... algumas paredes)use a função 'test network' da biblioteca radiohead, no arquivo RHRouter.h perto da linha 33, descomente um dos quatro #defines RH_TEST_NETWORK 1-4, cada um define simula uma rede conforme mostrado na imagem a seguir (na qual alguns nós são mutuamente invisíveis), simples assim... mas lembre-se de comentar a definição quando seus testes terminarem.NOTA Nunca é uma boa ideia manter os nós muito próximos uns dos outros.DICASA biblioteca mesh radiohead não garante a entrega da mensagem ao destino final (o ACK recebido após cada transmissão significa apenas que a mensagem viajou até o primeiro salto). E em muitos casos isso é o suficiente.Se você deseja uma prova de que a mensagem foi entregue, pode adicionar uma resposta no código da bridge (e um recebimento da resposta no código do nó). Você pode encontrar esta pequena adição nos últimos exemplos de código.DÚVIDASFORUMS RADIOHEADREFERÊNCIASSobre a SMARTCOREA SmartCore fornece módulos para comunicação wireless, biometria, conectividade, rastreamento e automação.Nosso portfólio inclui modem 2G/3G/4G/NB-IoT/Cat.M, satelital, módulos WiFi, Bluetooth, GNSS / GPS, Sigfox, LoRa, leitor de cartão, leitor QR code, mecanismo de impressão, mini-board PC, antena, pigtail, LCD, bateria, repetidor GPS e sensores.Mais detalhes em www.smartcore.com.br
Nenhum comentário:
Postar um comentário