Skip to content

LabirasIFPI/ROS2_LR

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 

Repository files navigation

ROS2_LR_Protocol Framework

O ROS2_LR_Protocol é um framework leve e robusto criado para facilitar a comunicação via rádio LoRa entre nós (como um gateway e robôs) no contexto de sistemas embarcados (frequentemente ESP32 com FreeRTOS).

O framework simplifica o gerenciamento do módulo LoRa ao encapsular a biblioteca padrão, gerir a comunicação assíncrona por meio de Tasks em background no FreeRTOS e garantir a integridade dos dados usando um protocolo unificado de tamanho fixo.


📦 Estrutura de Pacotes (PacketDef.h)

O protocolo define uma estrutura estrita em formato de bloco de dados compacto de 21 bytes, otimizado para evitar preenchimento de memória (padding) com __attribute__((packed)).

Tipos de Mensagem (MsgType)

Para classificar o tráfego, utiliza-se a enumeração MsgType. Você pode estendê-la como necessário. Alguns exemplos integrados incluem:

  • Comandos (Gateway -> Robô): MSG_CMD_VEL, MSG_LED_COR
  • Respostas (Robô -> Gateway): MSG_TELEMETRY
  • Genéricas/Customizadas: MSG_USER_CUSTOM_1

Carga Útil (Payload Data)

O conteúdo das mensagens vai nos 16 bytes centrais (packet.data). Graças à diretiva union, a mesma região de memória trafega structs exclusivas sem desperdício e de forma tipada, facilitando a vida do desenvolvedor.

  • PayloadCmdVel: Transporta pares de valores flutuantes (float linear_x, float angular_z).
  • PayloadLed: Transporta propriedades (color_code, blink_rate).
  • PayloadTelemetry: Transporta telemetria de sensores (accel_x, accel_y, estado).
  • raw_data[16]: Um coringa que o permite acoplar dados puros ou tratar a carga manualmente byte a byte.

📚 Catálogo de Funções (Quick Reference)

Abaixo encontra-se a tabela de consulta rápida das principais funções oferecidas pelo LoRaHandler.

Função / Método Parâmetros Retorno Descrição Quando Utilizar
LoRaHandler(...) int ss: Pino CS
int rst: Pino Reset
int dio0: Pino de Interrupção
uint8_t myId: ID na rede
N/A (Construtor) Constrói o objeto vinculando as portas de hardware e cria a trava (Mutex) do barramento SPI. Na declaração global do firmware, preparando o objeto para inicialização.
begin() long frequency: Frequência de operação do LoRa em Hz (ex: 915E6) bool: true se sucesso, false se rádio ausente Comunica-se via SPI com o módulo rádio para inicialização e ativa a Task paralela do FreeRTOS para ouvir a rede. Dentro do setup() para ligar efetivamente o hardware.
setCallback() PacketCallback callback: O ponteiro da sua função de processamento void Associa a sua rotina de código ao motor de recepção. A função será chamada quando um pacote passar pelo CRC. No setup(), logo após o rádio estar operante.
sendPacket() uint8_t targetId: ID Destino
uint8_t type: O ID do MsgType
void* payloadData: A sua struct
size_t payloadSize: Tamanho da struct
void Limpa a payload, formata a mensagem, calcula o checksum CRC-16 e escreve de modo seguro (bloqueando o Mutex) no barramento do rádio. Em qualquer rotina que necessite exportar comandos ou dados de sensores para outros nós.
calculateCRC16() const uint8_t *data: Buffer
size_t length: Tamanho
uint16_t: Hash validado Privado. Roda o polinómio CCITT-FALSE (0x1021) pelos bytes em memória. Uso interno automático. Invocada na entrada e saída de rádio.

🚀 Como Utilizar o LoRaHandler

A classe LoRaHandler (LoRaHandler.cpp / .h) encapsula a inicialização, envio, recebimento assíncrono e segurança do barramento SPI.

1. Inicialização

No seu firmware, você inicializa a comunicação instanciando a classe e fornecendo os pinos do SPI e o "ID" daquele nó.

#include "LoRaHandler.h"

// Definindo os pinos do barramento SPI
#define SS_PIN 5
#define RST_PIN 14
#define DIO0_PIN 2

// ID deste nó na rede (ex: 10)
#define MY_NODE_ID 10

// Cria o handler de forma global
LoRaHandler lora(SS_PIN, RST_PIN, DIO0_PIN, MY_NODE_ID);

void setup() {
    Serial.begin(115200);
    
    // Inicializa o LoRa na frequência escolhida (ex: 915 MHz)
    // O método 'begin' automaticamente cria uma Task background (no Core 0) para ouvir a rede.
    if (!lora.begin(915E6)) {
        Serial.println("Erro: LoRa falhou ao iniciar!");
        while (1);
    }
}

2. Recepção Orientada a Eventos (Callbacks)

A forma correta de receber mensagens é usar callbacks. Quando a task de monitoramento (taskLoop) deteta um pacote lícito, livre de ruído, endereçado a você (target_id == MY_NODE_ID) ou endereçado via broadcast (target_id == 255), o framework notifica a sua função de serviço.

void aoReceberPacote(LoRaPacket& pacote) {
    Serial.printf("Mensagem de %d recebida!\n", pacote.sender_id);
    
    // Roteamento baseado no Tipo de Mensagem
    switch (pacote.msg_type) {
        case MSG_CMD_VEL:
            Serial.printf("Comando de Velocidade: Linear=%.2f Angular=%.2f\n", 
                           pacote.data.cmd.linear_x, 
                           pacote.data.cmd.angular_z);
            break;
            
        case MSG_TELEMETRY:
            Serial.printf("Telemetria: Acelerômetro X: %.2f\n", pacote.data.telemetry.accel_x);
            break;
    }
}

void setup() {
    // ... lora.begin(915E6) ...
    
    // Injeta a sua função no motor do LoRa
    lora.setCallback(aoReceberPacote);
}

3. Envio de Mensagens

Em qualquer parte do seu programa principal, você pode usar sendPacket sem se preocupar em corromper o receptor que está rodando noutro Core do ESP32.

void enviarLeituraSD() {
    PayloadTelemetry dadosSensor;
    dadosSensor.accel_x = 1.05;
    dadosSensor.accel_y = 0.98;
    dadosSensor.bumper_state = 1;
    
    uint8_t destinoId = 1; // ID do Gateway receptor
    
    // Parâmetros: ID Destino, Tipo da Mensagem, Ponteiro para os Dados, Tamanho dos Dados
    lora.sendPacket(destinoId, MSG_TELEMETRY, &dadosSensor, sizeof(dadosSensor));
}

🛡️ Segurança e Confiabilidade (Under the Hood)

1. Integridade de Dados por CRC-16 (CCITT-FALSE)

Redes RF estão altamente expostas a "flip de bits" e corrupção devido a ruído ambiental. O pacote reserva seus últimos 2 bytes para um algoritmo matemático CRC-16.

  • Transmissão: Ao invocar sendPacket, a RAM do payload é formatada/zerada e é extraída uma assinatura polinomial sobre todos os bytes válidos (19 bytes iniciais). O checksum viaja no final do pacote.
  • Recepção: Apenas mensagens que fechem a re-validação matemática (calculatedCRC == pacote.checksum) são repassadas à Callback do usuário. Se falhar por conta de lixo aéreo, interrupções ou colisões de canal, a mensagem é silenciosamente descartada.

2. Proteção de Concorrência SPI (Mutex)

O envio na função principal e a escuta por pacotes no background disputam os mesmos fios elétricos do rádio SPI. No FreeRTOS, a sobreposição é fatal. A classe LoRaHandler encapsula um Mutex de Semáforo (_spiMutex). Tanto sendPacket() (Main) quanto taskLoop() (Task LoRa) obrigatoriamente retêm autorização atômica antes de falar com o rádio (xSemaphoreTake). Caso uma transação esteja no meio, a outra thread aguarda alguns décimos de segundo até que termine, prevenindo crashes no ESP32 ou estado inconsistente.

About

A lightweight LoRa communication bridge designed to seamlessly integrate embedded systems (ESP32/FreeRTOS) with ROS 2. It enables long-distance, wireless transmission of standard robotics data, such as cmd_vel and telemetry, featuring asynchronous processing and CRC-16 validation.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors