Classe RadioMessage

* **Artigo sobre este dispositivo**
* **Wiki SourceForge: RadioMessage**

A classe **RadioMessage** é responsável por controlar a comunicação entre dois (ou mais) arduinos utilizando o módulo de radio frequência **NRF24L01**. Cuida dos detalhes da comunicação facilitando muito o uso do módulo. Além disso implementa um protocolo básico para as mensagens que permite mensagens de tamanho variável.

#### **Canais e Pipes**

O conceito de canal é mais fácil de entender. Este transceiver é capaz de operar em até 125 canais. Cada canal usa uma frequência diferente, portanto, para que dois dispositivos se comuniquem precisam estar operando no mesmo canal.

O pipe (tubo literalmente) é basicamente um endereço para leitura ou escrita. Quando dois dispositivos se comunicam, eles estabelecem pipes (tubos) de comunicação entre eles. O endereço do pipe tem 5 bytes (ou caracteres) sendo que os 4 últimos precisam ser iguais nas duas pontas e o primeiro byte (ou caracter) deve ser diferente. O que é o pipe de leitura para uma ponta deve ser o pipe de escrita na outra e vice versa.

Por exemplo, supondo dois dispositivos A e B, poderíamos declarar os pipes como abaixo:

Para o dispositivo A:

```
const char[7] pipeIn = "1ABCD";
const char[7] pipeOut= "2ABCD";

```

E para o dispositivo B os pipes são invertidos:

```
const char[7] pipeIn = "2ABCD";
const char[7] pipeOut= "1ABCD";

```

Neste exemplo, o dispositivo A lê do pipe "1ABCD" e escreve no pipe "2ABCD". Já o dispositivo B escreve no pipe "1ABCD" e lê do pipe "2ABCD".

A classe **RadioMessage** cuida dos detalhes de leitura e escrita nos pipes, então não é preciso se preocupar com isso para receber ou transmitir mensagens, mas na inicialização (método ***begin()***) é preciso informar os pipes de entrada e saída nas duas pontas.

#### **Inicialização**

Ao criar uma instância da classe é necessário informar os pinos que estão associados aos pinos CE e CS do dispositivo. Os shields que já tem um conector próprio para o NRF24L01 geralmente usam os pinos D9 e D10 do arduino respectivamente, mas se estiver usando um adaptador separado, pode ser usado qualquer outro pino.

Depois é preciso inicializar a instância chamando o método ***begin()***, onde será informado o pipe de entrada, pipe de saída e a taxa de transmissão (datarate). Tenha em mente que a taxa de transmissão precisa ser a mesma nas duas pontas. O NRF24L01 suporta 3 taxas de transmissão: 250 KBPS, 1 MBPS ou 2 MBPS.

**Exemplo de inicialização:**

```
#include <RF24radio.h>

#define CE_PIN    9
#define CS_PIN   10

uint8_t pipeIn [7]= "0Node";
uint8_t pipeOut[7]= "1Node";

RadioMessage rm( CE_PIN, CS_PIN );

void setup()
{
 ...
 rm.begin( pipeIn, pipeOut, RF24_250KBPS );
 ...
}

```

#### **Mensagens**

A classe ***RadioMessage*** define um formato básico para as mensagens (***TRadioMsg***) e um protocolo de comunicação. Uma mensagem é uma estrutura de dados que pode ter de 4 a 32 bytes. É formada por um ***header*** (cabeçalho) e um ***payload*** (carga, dados adicionais). O *header* é obrigatório e ocupa 4 bytes, mas o *payload* é opcional, pode ter de zero a 28 bytes. Abaixo a estrutura do *header*:

```
typedef struct {
   union{
      struct
      {
         byte msgID;
         byte paySize;
         uint serialN;
      };
      long l;
   };
}
THeader;
```

O campo ***msgID*** não é usado pela classe, está disponível para uso da aplicação. O campo ***paySize*** informa o tamanho do *payload* que acompanha a mensagem (de 0 a 28). O campo ***serialN*** é um valor serial que é incrementado sempre que uma mensagem é enviada, bastante útil para *debug* e para saber se alguma mensagem foi perdida.

O *payload* não tem nenhum formato definido, é só um array de bytes. Para o *payload* pode usada qualquer estrutura que tenha até 28 bytes. Abaixo a estrutura completa da mensagem:

```
// Tamanho máximo do payload das mensagens (28 bytes).
//
#define PAYLOAD_MAX_LEN (32-sizeof(THeader))

// Estrutura para envio e recebimento de mensagens.
//
typedef struct
{
   THeader head;
   byte    buff[PAYLOAD_MAX_LEN];
}
TRadioMsg;

```

#### **Envio de mensagens**

TRadioMsg\* makeMessage(TRadioMsg\* msg, byte msgID, byte payloadSize=0, void\* payload=NULL);
int sendMessage( TRadioMsg\* msg );

Para enviar uma mensagem, primeiro monte a estrutura para a mensagem utilizando o método ***makeMessage()***. A seguir envie a mensagem utilizando o método ***sendMessage()***:

**Exemplo, mensagem sem payload:**

```
{
   TRadioMsg msg;
   rm.makeMessage( &msg, 1 );
   rm.sendMessage( &msg );
}

```

Note que como o método ***makeMessage()*** retorna um ponteiro para a estrutura ***TRadioMsg*** enviada no primeiro parâmetro, é possível usar o retorno do método para o envio da mensagem, como exemplificado abaixo:

```
{
   TRadioMsg msg;
   rm.sendMessage( rm.makeMessage( &msg, 1 ) );
}

```

**Mensagem com payload:**

Neste caso, provavelmente existirá uma estrutura que deve ser enviada junto com a mensagem. Apenas como exemplo, o código abaixo declara a estrutura ***TParams*** para servir de *payload* na mensagem:

```
typedef struct
{
   byte  paramB;
   int   paramI;
   float paramF;
}
TParams;

int sendParams( byte msgID, byte parB, int parI, float parF)
{
   TRadioMsg msg;
   TParams par= { parB, parI, parF };
   rm.makeMessage( &msg, msgID, sizeof(TParams), &par );
   return rm.sendMessage( &msg );
}

```

#### **Recebimento de mensagens**

boolean messageWaiting();
int readMessage(TRadioMsg\* msg);

Use o método ***messageWaiting()*** para verificar se há mensagens recebidas. Se houver, use o método ***readMessage()*** para ler a mensagem.