Comunicação RF-Protocolo

Boa noite,

Tenho dois arduinos, um é o master e o outro é o slave (na prática serão varios slaves) e ambos têm um recetor e transmissor de 434Mhz.Pretendo criar uma trama(ou protocolo) para controlar através do master os slaves.A trama será introduzida pela porta série(uma ação para o slave fazer),como por exemplo acender um simples led.Essa trama terá que ser carregada para um char array(exemplo buf[10]) pois estou a utilizar a virtualwire.h para fazer a comunicação.
Um exemplo de trama/protocolo que tentei executar foi este:
_ _ _ _ _ _ _ _ fim(p8)
Numero de inicio da trama(posição0) ID do slave pretendido(posição1e2 que dá até99) Ação a executa(posição3) Pino(posição 4) Para leitura de retorno(5,6,7)
Em que cada "
" corresponde a uma posição no array.
Cada posição do array dá para colocar 8bits,ou seja de 0-255.Porque utilizar duas posições para colocar 99 se numa dá 256?(é o que perguntam)
Eu na porta série tenho que colocar uma sequencia para ser carregada no array e enviada.Assim seria mais facil pois seria só carregar a sequencia inteira no buffer atrasvés de um ciclo for.Alguma sugestão de reduzir a trama e de facil introdução pela porta série?

Desde já obrigado pela ajuda.

No meu blog http://microsrus.blogspot.com tenho alguns posts com indicacões sobre como fazer um protocolo e reduzi-lo ao máximo.

Por exemplo, quando dizes:

(posição0) ID do slave pretendido(posição1e2 que dá até99)

Estás a pensar em ASCII e isso vai trazer-te trabalho que nunca mais acaba. Para comecar, o numero vai ser uma string e como tal tens de comparar strings e não variáveis. Isso adiciona complexidade à programacão e probabilidade de erros.

Se enviares em formato binário, um byte dá-te a possibilidade de enderecares 255 nós. Em vez dos 9 que tu julgas ser possível em ASCII. Nota que ASCII também tem letras, logo podes usar códigos de letras para enderecar nós. Ficando assim com um numero maior por byte. Se olhares aqui asciitable.com vês que tens 10 carateres com numeros e 50 com letras. Dando-te a possibilidade de enderecares 60 num formato que o utilizador compreende de forma mais simples. Mas como a comunicacõa é feita entre microcontroladores, enviar em binário é a forma mais rápida de o fazer. Quer em termos de processamento, quer em termos de tamanho de trama.

Depois o teu protocolo não tem um caracter de inicio... assim nunca sabes quando comeca uma mensagem ou acaba. Isso também é má prática.

Não percebo a tua questão final. Importas-te de explicar de novo?

bubulindo:Eu tenho que enviar a trama/protocolo pela porta serie como uma sequência.Exemplo "12221"(exemplo de sequencia),em que coloca cada numero numa posição do array e envia.
Este é um extrado do código que coloca a sequencia no buffer de envio:

char buf1[11];
while (Serial.available()>0) {
    serialNUM = Serial.read();
    //Serial.print("aqui");  //gets one byte from serial buffer
    buf1[i]=(serialNUM-48);
    i++;
    flag=1;
    delay(2);  // allow buffer to fill with next character
    }
    if (flag==1) {
    i=2;  //so you can see the captured string 
    flag=0;
    buf1[0]=1;
    buf1[1]=checksumENVIA();
    buf1[10]=1;
    vw_send((uint8_t *)buf1,11);
    vw_wait_tx();
   
  }
}

Neste caso estou a trabalhar com carateres,ou seja até nove.Estou tentar agora utilizar por bytes mas não sei como depois colocar no buffer.Tenho de dar "ordens" aos slaves por uma sequencia colocada na porta serie ou algo identico.
Dá-me um exemplo do que sugeres para entender melhor.
Obrigado pela ajuda!

Então tens o teu PC ligado a um Arduino com o módulo RF e do outro lado tens outro arduino com outro módulo RF e queres que este arduino execute os comandos que pretendes, correcto?

Podes criar dois protocolos... um em ASCII que é enviado pela porta série para tu perceberes melhor e depois outro para comunicacão entre os dois módulos que já pode ir em binário.

Outra seria criares um software no teu PC para falar em binário com o primeiro arduino e então não tinhas de te chatear.

Sim bubulindo é esse sistema.
Eu terei que criar um software tal como estas a sugerir.Mas mesmo como sofware,como faço em binário?Tenho que utilizar na mesma a introdução de uma sequência via porta serie.Meu problema é que em binário fica dificil colocar a sequencia no buffer de envio.

faz o arduino aceitar pela serial o modo ascii em converter em binario, pode fazer assim:
você digita:
[zona/device/acao] ---> [001/001/001] que o arduino transforma em três bytes,

e para aumentar a segurança pode usar na transmissão implementada pelo arduino:
CRC - para validar os dados,
numero sequencial ou um time stamp - para tornar o pacote valido apenas uma vez,
HASH - para impedir que alguem comande sua rede com packet replay, nos controles com rolling code mais recentes, usa-se um hash de 256 bits ou mais, acho muita coisa, creio que uma encriptação XOR sane este problema.

Eu utilzo este protocolo:
carater inicio+soma+informação+carater fim
informação=ID slave+ação+pino que faz ação

Apenas faço o input da informação pela porta serie.
Exemplo de sequencia ASCII informção :
03+1+01=sequencia introduzida "03101"=5bytes
Mas assim só tenho 0-9 enquanto em binario teria 0-255 ou seja, 0-255IDS+0-255açoes+0-255pinos=3bytes e o protocolo teria menos posições no buffer de envio(virtualwire.h).
fabiohbm007: [001/001/001]=sequencia"001001001"?
Que acham coloco por 5bytes(por ASCII) ou binario(3bytes)?

Obrigado pela ajuda.

eu utilizaria apenas o caracter de inicio, o fim poderia ser o \n que toda vez que da enter o windows/linux acrescenta na string da serial
se você usar ascii como entrada na serial tem que colocar um separador para o arduino saber quando começa um campo e termina outro
03101 poderia ser 03 10 1 ou 03 1 01.
fazendo i03/1/01 o arduino sabe onde começa e termina cada campo.

no meu exemplo mando [001/001/001], treze bytes pela serial e o arduino codifica em binario: [ox01] [0x01] [0x01], três bytes...

coloque a soma ou CRC sempre na ultima posição do pacote, assim fica facil usar o for e já compara ao ultimo.

Se usar pilhas, separe um bit para sinalizar bateria fraca.
usaria a seguinte estrutura em bytes ou bits:

[master/slave] [bateria] [nome] | [tamanho mensagem] | [mensagem] | [timestamp] | [hash]|  [crc]
 1bit        1bit       6bits    |                       |             |                  |              |     
               1 byte             |        1 byte        |   1 a n bytes |  4 bytes   |  8 bytes  |  1 byte

o hash é anexado pelo master mas o slave pode optar em nao refazer a verificação do hash, apenas qaundo for questao de seguranca, portao, alarme, etc

Entao vou enviar a sequencia 001001001?Depois coloco buf[0]=001,buf[1]=001 e buf[2]=001?

sim pode ser, lembrando que vai até 255 byte

Ou tens outra ideia?Qual a melhor forma,a que tinha anterior ou 0-255?

vasr:
Entao vou enviar a sequencia 001001001?Depois coloco buf[0]=001,buf[1]=001 e buf[2]=001?

Isso. Era aqui que me referia, que o valor só vai até 255 em decimal (1 byte).

Como se faz nestes casos,usa-se código ASCII 0-9 ou 1byte(0-255)?

Como coloco a sequência na respetiva posição do array?
Por exemplo:
Sequência:"001002003"colocada por porta serie.E terei que colocar no buf[0]=001,buf[1]=002 e buf[3]=003.
Alguma ajuda?

unsigned int buf[3];

char temp[4];

temp[3] = '\0';


if (Serial.available>8) { //9 caracteres...
unsigned char buf_ptr = 0; 

   for (buf_ptr = 0; buf_ptr <3; buf_ptr++) { corre todos os elementos de buf.
      for(int i = 0; i<3; i++) { //lê para temporário... 
         temp[i] = Serial.read();
      }
   buf[buf_ptr] = atoi(temp);
   }

}
//verifica recepcão. 
for (int j = 0; j<3; j++ {
   Serial.print("buf[");
   Serial.print(j);
   Serial.print("] = ");
   Serial.println(buf[j]);
}

Obrigado pela ajuda, já esta funcional.

Esta a fazer o carregamento do buffer do lado do Master correto mas no Slave recebe outro tipo de informação.
Codigo do slave(estou só a imprimir o que recebe):

void loop(){
  if(vw_get_message(buf, &buflen)) 
  {
   for (int j = 0; j<7; j++) {
   Serial.print("buf[");
   Serial.print(j);
   Serial.print("] = ");
   Serial.println(buf[j]);
   }
  }
}

No master coloco:
buf1[0]=1;
buf1[1]=6;
buf1[2]=1;
buf1[3]=2;
buf1[4]=3;
buf1[5]=0;
buf1[6]=1;
E no slave recebo:
buf[0] = 1;
buf[1] = 0;
buf[2] = 6;
buf[3] = 0;
buf[4] = 1;
buf[5] = 0;
buf[6] = 2;

Mostra aqui o setup do receptor e transmissor e também o código do transmissor.

Ela está a intercalar zeros na mensagem... isso é estranho, mas como estas funcões são mais ou menos standard, creio que o problema estará fora da funcão. Então podes ser tu a intercalar os zeros sem querer, ou podem as configuracões não bater certo com os dois dispositivos.

Alterei no código que implementaste

unsigned int buf[3];

para:

unsigned char buf[3];

Já funciona desta forma.Obrigado pela ajuda!

Eu duvido muito que funcione...

Repara...

unsigned char buf[3];

E nisto...

void loop(){
if(vw_get_message(buf, &buflen))
{
for (int j = 0; j<7; j++) {
Serial.print("buf[");
Serial.print(j);
Serial.print("] = ");
Serial.println(buf[j]);
}
}
}

Estás literalmente a escrever e a ler algo que não tem lugar definido. Ou aumentaste o buf para 7?