Projeto

Geral

Perfil

Comunicação » Histórico » Versão 4

Onias Castelo Branco, 21/03/2017 21:07 h

1 1 Renan Pícoli
h1. Comunicação
2
3 4 Onias Castelo Branco
[[Instalações dos drivers]]
4
5 2 Renan Pícoli
h2. 1. FIRMWARE
6
7 1 Renan Pícoli
Em main.cpp há três objetos maiores (mais complexos): um da classe Robo, um da classe USB_STM32 (usb) e outro da classe NRF24L01P (declarados em radio/bsp.h e instanciados em src/bsp.cpp)
8
Além do objeto auxiliar _usbserialbuffer, um buffer circular de uint8_t
9
OBS: quando a classe Robo é instanciada em bsp.cpp, pode-se escolher um modo de teste, no qual apenas a serial (e a linha de comando acessada pelo Tera Term) é usada.
10 2 Renan Pícoli
11
h3. 1.1 CLASSE NR24L01P
12
13 1 Renan Pícoli
NR24L01P está declarada em /inc/hal/nrf24l01p.h e herda publicamente da classe de abstrata MODEM (declarada em /inc/hal/modem.h
14
Seu contrutor recebe como parâmetro um objeto da classe abstrata SPI (declarada em /inc/hal/spi.h com métodos para escrita e início/término de comunicação) e objetos da classe abstrata IO_Pin (declarada em /inc/hal/io_pin.h, com métodos para leitura, escrita e configuração de pinos).
15
Possui um buffer circular para dados transmitidos (_txbuffer) e outro para dados recebidos (_rxbuffer).
16
Esta classe conta com métodos para:
17
sinalizar que o transmissor está disponível para receber uma payload (TxReady());
18
configurar o transmissor e mandar uma payload para a fila de transmissão (TxPackage() e TxPackage_ESB());
19
sinalizar que o receptor  tem uma ou mais payloads disponíveis para leitura (RxSize());
20
ler uma payload para um buffer (RxData(...));
21
função para configurar como receptor e iniciar o monitoramento de pacotes (StartRX() e StartRX_ESB());
22
funções de configuração (SetRXFrequency() e Config()) e inicialização (Init());
23
Uma função de “manutenção” InterruptCallback(), que é chamada de tempos em tempos e quando o pino de IRQ do nRF24 for a nível baixo. Essa função faz uma verificação de alguns registradores, para lidar com os casos de máximo número de retransmissões, chegada de pacote válido, pacote transmitido com “sucesso” (critérios diferentes se o ACK estiver ou não habilitado) ou fila de transmissão cheia, além de fazer a temporização dos leds.Por exemplo, se um pacote de tamanho válido foi recebido, a payload é lida e colocada no _rxbuffer da classe (outras classes ou interrupções não devem acessar o hardware do nRF24, apenas acessam os buffers circulares). Se um pacote foi transmitido, o pino CE é resetado, pacotes na fila de recepção são ignorados.
24
25
OBS: em caso de sucesso, o led verde da Transmissora e o led azul da receptora acendem. Caso, o receptor não receba, nenhum led acende.
26
27 2 Renan Pícoli
h3. 1.2 CLASSE USB_STM32
28
29
Classe declarada em /inc/hal_stm32/usb_stm32.h e herda publicamente da classe USB (declarada em /inc/hal_stm32/usb.h. Esta classe é amiga da classe 
30
USB_DEVICE_CLASS, o que lhe permite acessar métodos privados ou protegidos de USB_DEVICE_CLASS.
31 1 Renan Pícoli
O microcontrolador possui um controlador OTG_FS e um OTG_HS, totalmente conforme à especificação USB 2.0 . Usamos o OTG_FS.
32
Nota: USB On-The-Go, abreviada USB OTG, o dispositivo pode atuar tanto como mestre quanto como escravo.
33
É uma Virtual COM Port, emula uma porta serial (porta COM).
34
O dispositivo USB emula uma virtual COM port.
35
CDC (communication devices class)
36
A função OTG_FS_IRQHandler() implementada em /src/bsp.cpp é chamada quando o periférico OTG_FS da Discovery dispara uma interrupção para indicar que dados foram recebidos, por exemplo.
37
38 2 Renan Pícoli
h3. 1.3 CLASSE USB_DEVICE_CLASS_CDC_VCP
39
40 1 Renan Pícoli
Declarada em /inc/usb/usb_device_class_cdc_vcp.h, herda publicamente de USB_DEVICE_CLASS. Como alguns métodos de USB_DEVICE_CLASS_CDC_VCP sobrecarregam métodos de USB_DEVICE_CLASS, da qual USB_STM32 é amiga, USB_STM32 pode acessar estes métodos. 
41
USB_DEVICE_CLASS_CDC_VCP implementa uma virtual COM port (vcp), possui um buffer circular de envio (_datainbuffer) e um de recepção (_dataoutbuffer). Para enviar dados, usa-se um dos métodos USB_DEVICE_CLASS_CDC_VCP.SendData(). Para receber, usa-se um dos métodos USB_DEVICE_CLASS_CDC_VCP.GetData().
42
43 2 Renan Pícoli
h3. 1.4 PROTOBUF
44 1 Renan Pícoli
45
Utiliza-se a biblioteca nanopb (https://github.com/nanopb/nanopb), uma implementação em ANSI C do protobuf, protocolo de serialização desenvolvido pela Google (veja https://developers.google.com/protocol-buffers/).
46
Nanopb is an ANSI-C library for encoding and decoding messages in Google's Protocol Buffers format with minimal requirements for RAM and code space. It is primarily suitable for 32-bit microcontrollers. https://jpa.kapsi.fi/nanopb/docs/index.html
47
Nanopb é uma biblioteca em ANSI-C para codificação e decodificação de mensagens no formato Protocol Buffers da Google com requisitos mínimos de RAM e tamanho de código. É adequado principalmente para uso em microcontroladores de 32 bits.
48
49
To begin with, you must provide a .proto file describing your messsage’s format:
50
For starters, consider this simple message:
51
message Example {
52
   required int32 value = 1;
53
}
54
Save this in message.proto and compile it using  protoc:
55
user@host:~$ protoc -omessage.pb message.proto
56
user@host:~$ python nanopb/generator/nanopb_generator.py message.pb
57
You should now have in message.pb.h:
58
typedef struct {
59
   int32_t value;
60
} Example;
61
62
extern const pb_field_t Example_fields[2];
63
This was how you would generate the files message.pb.c (contains initializers for const arrays) and message.pb.h (contains type declarations). Once you have finished this step, you will need only encode and decode messages.
64
 Now in your main program do this to encode a message:
65
Example mymessage = {42}; //initialize your structure
66 3 Renan Pícoli
uint8_t buffer [10];	//declares a buffer for the encoded message
67 1 Renan Pícoli
68
// generates a auxiliary object
69
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
70
71
// encodes the message. Example_fields teaches the format
72
pb_encode(&stream, Example_fields, &mymessage);
73
After that, buffer will contain the encoded message. The number of bytes in the message is stored in stream.bytes_written.
74
Example mymessage; //declares your structure
75 3 Renan Pícoli
uint8_t buffer [10] =...;// buffer filled with the encoded message
76 1 Renan Pícoli
77
// generates a auxiliary object
78
pb_istream_t stream = pb_istream_from_buffer(buffer, sizeof(buffer));
79
80
// decodes the message. Example_fields teaches the format
81
pb_decode(&stream, Example_fields, &mymessage);
82
Using Protocol Buffers is a way of serializing structured data (e.g. the object representing our robot) for communications with ease, efficiency and maintaining compatibility with older versions.
83 2 Renan Pícoli
84
h2. 2. LABVIEW
85
86
O arquivo principal do projeto é SSL Vision Log Player.vi, que possui um loop while de rótulo “Communication”, no qual clusters(análogos a structs de C) são continuamente lidos de uma “Lossy stream”, os quais representam nosso time, o  time adversário, as posições onde a bola foi detectada, a geometria do campo, informações do juiz e a Time Stamp recebida. A Time Stamp recebida menos a Time Stamp medida no momento da execução é armazenada em Total Delay. our_robots (um vetor de Robot) é convertido para grSim Robot Commando e é mandado para transmissão, a qual pode ser via UDP (UDP TX, grSim Packet Command UDP Test.vi transmite para o grSim) ou via serial (SERIAL TX, Serial Transmitter.vi, que codifica usando protobuf e escreve na porta COM implementada na Discovery dedicada a transmitir para os robôs).
87
88
h3. 2.1 SERIAL TX (Serial Transmitter.vi)
89
90
Um dos controles (Porta:) permite selecionar a porta que será usada, por exemplo, uma porta COM, um feedback node armazena o valor anterior de Porta: e se eles diferirem (ou não havia porta selecionada antes) ou se houve um erro na escrita anterior, Visa Close fecha a porta anteriormente aberta, faz-se error_out.status=FALSE para limpar qq erro e a vi Visa Configure Serial Port abre e configura a porta serial. Por outro lado, se a porta não mudou e não houve erro, apenas passa-se a porta anterior (via feedback node) para a função VISA Write, que escreve na serial uma string gerada a partir da saída da vi grSim Robot Command, que recebe um grSim Robot Command, o codifica usando protobuf e o transforma em um array de bytes. Antes de passar o cluster para a serialização, um ajuste é feito: os campos velnormal e veltangent são trocados e a veltangent final tem seu sinal invertido, para corrigir uma confusão quanto à definição dessas velocidades.