Tutorial
A ideia é tentar entender a ferramenta que tenho em mãos para poder dar uma otimizada no funcionamento do meu NEO-M8N para o meu navegador inercial. Eu tenho programado, com parsing de mensagens NMEA, mas pelo que tenho lido, utilizar o protocolo UBX (da própria u-blox) pode me trazer dados de modo mais direto e não mais processados (não que o parsing em si demore, sobretudo no ESP32, mas...).
O documento empregado como referência é o: u-blox 8 / u-blox M8 Receiver description -- Including protocol specification.
No capítulo 8, intitulado Navigation Configuration Settings Description, é comentado sobre configurações específicas (para melhores ajustes da plataforma) para diversos tipos de plataforma (portable, automotivo, no mar, airborne etc.). Essa parte de como configurar é regida pela UBX-CFG-NAV5.
Para sistemas com dinâmicas não muito rápidas (<= 8m/s), é possível ativar um filtro passa baixa para o curso sobre a terra por meio da mensagen UBX-CFG-ODO.
No capítulo 32, intitulado UBX Protocol, traz o que seria o cerne da coisa (o principal). A principal informação é entender como que se dá a criação de uma mensagem típica do protocolo u-box. A figura abaixo mostra um extrato retirado do próprio documento da UBX.
A meta é entender o que vem de cada mensagem, a nível macro, e como utilizar ela de modo pragmático, em código C/C++, no meu navegador inercial. Observe para o checksum abaixo, o que está presente no datasheet e também uma implementação em C/C++ para essa verificação.
A seção 32.3.5 traz o formato dos números (Number Formats). É indicado que todos as mensagens de múltiplos bytes são ordenadas no formato Little Endian. É importante ler essa seção para entender como as mensagens são passadas e seus limites.
A seção 32.4 traz as características de como se falcula o Checksum da mensagem (UBX Checksum). É comentado que segue-se o 8-Bit Fletcher Algorithm (resumidamente detalhado abaixo).
uint8_t UBX_checksum(const uint8_t Class,
const uint8_t ID,
uint16_t Lenght,
const uint8_t *Payload,
uint8_t &checksum_a,
uint8_t &checksum_b) {
// Inicia as variáveis de saída.
checksum_a = 0; checksum_b = 0;
// Class
checksum_a = checksum_a + Class;
checksum_b = checksum_b + checksum_a;
// ID
checksum_a = checksum_a + ID;
checksum_b = checksum_b + checksum_a;
// Lenght -- lembre-se de que é 16 bits.
checksum_a = checksum_a + static_cast<uint8_t>(Length & 0xFF); // LSB
checksum_b = checksum_b + checksum_a;
checksum_a = checksum_a + static_cast<uint8_t>((Length >> 8) & 0xFF); // MSB
checksum_b = checksum_b + checksum_a;
// Realiza as operações conforme datasheet
for (size_t i = 0 ; i < Lenght ; i++) {
checksum_a = checksum_a + Payload[i];
checksum_b = checksum_b + checksum_a;
}
return 0;
}
As seleções para as variáveis serem do tipo uint8_t ou uint16_t vêm das características dos próprios dados passados (veja a primeira figura acima).
A seção 32.5 traz informações a respeito do fluxo de mensagens do protocolo UBX (UBX Message Flow). Ele separa em dois importantes pontos: 1) as mensagens de acknolegdement (confirmação) e de 2) polling (verificação contínua).
No primeiro caso, o datasheet cita o exemplo de quando mensagens da classe CFG são enviadas para o receptor, há o envio pelo receptor de uma mensagem de "confirmação" (UBX-ACK-ACK) ou de "não confirmação" (UBX-ACK-NAK), indicando se a mensagem foi ou não processada internamente. Outros classes de mensagem também fazem uso do mesmo mecanismo.
Para mensagens do tipo polling, o documento indica que mensagems do tipo output ou get/set podem ser consultadas periodicamente (a depender da configuração). Um ponto importante destacado no documento é que se há o interesse em receber determinada mensagem do receptor, pode-se utilizar o envio da mensagem que se deseja receber sem o payload e o receptor retorna a mensagem desejada com o payload completamente recheado.
A seção 32.6 traz as Class ID do prototolo UBX (UBX Class IDs). A figura abaixo traz as mensagens para as class ID do protocolo. Observe que existem os acrônimos utilizados que podem auxiliar no entendimento da mensagem. É muito importante destacar que as diretrizes para a classe CFG é bem extensa e demanda um estudo específico para cada uma delas, assim como para as outras classes. Como eu não estou fazendo um driver, ou seja, algo completo, como se fornecedor eu fosse, eu destinarei foco ao desenvolvimento de ferramenta que eu irei empregar no meu sistema de recepção.
A seção 32.7 traz um overview mensagens possíveis de serem trocadas pelo protocolo UBX (UBX Messages Overview). Importante destacar que as mensagems advindas pelo protocolo UBX a gente consegue fazer, para o NEO-M8N, a coleta de dados brutos (pseudo-range e Doppler) de modo a possibilitar a estrutura fortemente acoplada (tightly coupled) para INS/GNSS. Isso é algo mais para frente ainda, mas é bom ter em mente até onde a gente consegue evoluir no sistema.
Pelo o que eu estou lendo aqui, as informações disponíveis na mensagem UBX-NAV-PVT apresentam as informações que eu julgo necessárias para realizar a integração fracamente acoplada (loosely coupled).
Entendendo ao menos essas informações da estrutura macro do funcionamento do protocolo UBX, a ideia é tentar arquitetar a seguinte sequência de ações:
- Como enviar dados para o receptor, caso ele seja do tipo get/set?
- Caso, a mensagem seja da classe CFG, por exemplo, como receber os dados de UBX-ACK e processá-los para confirmar se deu tudo certo (ACK) ou se deu errado (NAK).
- Como configurar as mensagens que eu desejo receber rotineiramente por polling?
- Como eu faço para ativar e/ou desativar determinadas mensagens para envio pelo receptor? Ou seja, se eu quiser fazer meu receptor enviar apenas mensagens do tipo UBX e não mais do protocolo NMEA (como esse estudo de caso se propõe).
- Como fazer o parsing da mensagens de modo a eu conseguir trabalhar com dados de engenharia.
Eu irei levar essas questões para o próximo post.
Nenhum comentário:
Postar um comentário