Go Down

Topic: Comunicação RF-Protocolo (Read 25259 times) previous topic - next topic

vasr

Antes demais obrigado pelas respostas.
Este código continua a dar-me erro:
Code: [Select]
char temp[4];
temp[2] = '\0';

Este é o erro do compilador:error: expected constructor, destructor, or type conversion before '=' token
Relativamente ao que fabiohbm007 referiou e aplicando a meu caso fica:
Com a sequência "1111111"[ENTER]-1111111\r\n.O \r\n fica nas posições a seguir?E como posso limpar o buffer do \n\r?

bubulindo


Antes demais obrigado pelas respostas.
Este código continua a dar-me erro:
Code: [Select]
char temp[4];
temp[2] = '\0';

Este é o erro do compilador:error: expected constructor, destructor, or type conversion before '=' token
Relativamente ao que fabiohbm007 referiou e aplicando a meu caso fica:
Com a sequência "1111111"[ENTER]-1111111\r\n.O \r\n fica nas posições a seguir?E como posso limpar o buffer do \n\r?


Mostra o código todo...

Eu tenho ideia que podes seleccionar se queres caracteres de fim de string na IDE do Arduino... Já viste isso?
This... is a hobby.

vasr

Eu também tenho ideia que é possível faze-lo mas no entento dá-me o erro que referi.
Este é o código que tentei para executar o que referi anteriormente no novo protocolo que implantei;
Code: [Select]
unsigned char buf1[3];
char temp[4];
temp[2]='\0';//aqui dá erro

void setup(){
  Serial.begin(9600);
}

void loop(){
if(Serial.available()>7) {
    memset(buf1, 0, 3);
    unsigned char buf1_ptr = 0;
    for(buf1_ptr=0;buf1_ptr<3;buf1_ptr++) {
      if(buf1_ptr<2){
        for(int i = 0; i<2; i++) {
          temp[i] = Serial.read();
        }
      }else{
          for(int i1 = 0; i1<3; i1++) {
          temp[i1] = Serial.read();
        }
      }
      buf1[buf1_ptr]=atoi(temp);
   }
}

Estou a tentar implementar novo codigo com a informação dada pelo usuário fabiohbm007 mas ainda sem sucesso.

bubulindo

É preciso saber programacão para se fazer algo... colar as coisas com cuspe não resulta.

Code: [Select]
unsigned char buf1[3];
char temp[4];
//temp[2]='\0';//aqui dá erro CLARO QUE DÁ!!!! ISTO POR ACASO É UMA FUNCAO?????

void setup(){
  Serial.begin(9600);
temp[2]='\0'; //E AQUI???? REPARA QUE NÃO dÁ ERRO... QUE ESTRANHO, NÉ??

}

void loop(){
if(Serial.available()>7) {

    memset(buf1, 0, 3);
    unsigned char buf1_ptr = 0;
    for(buf1_ptr=0;buf1_ptr<3;buf1_ptr++) {
      if(buf1_ptr<2){
        for(int i = 0; i<2; i++) {
          temp[i] = Serial.read();
        }
      }else{
          for(int i1 = 0; i1<3; i1++) {
          temp[i1] = Serial.read();
        }
      }
      buf1[buf1_ptr]=atoi(temp);
   }
}
This... is a hobby.

vasr

Eu tinha testado colocar onde o fizeste mas de outra forma, apenas não estava a entender o que pretendias ao colocar o '\0'. Terei mais cuidado em analisar o código, obrigado pela ajuda.

bubulindo

Se eu tiver de escrever um sketch que compila e faz exactamente o que pretendes para demonstrar algo, simplesmente não o farei.
Tem de haver um certo esforco da outra parte em entender as dicas que são dadas... Neste caso, colocaste grande parte do código dentro duma funcão. Porque é que não meteste aquela parte também?
E eu sei porquê. Não sabes o suficiente de programacão em C para perceber que atribuicões de valor tem de ser feitas dentro duma funcão. Isto é relativamente básico... e devias investir um pouco nisto antes de te meteres em coisas mais difíceis.
This... is a hobby.

vasr

#36
Aug 13, 2013, 05:04 am Last Edit: Aug 13, 2013, 05:05 am by vasr Reason: 1
Se ficaste a entender que pretendo que me façam o código, é errado estou aqui para aprender. Apenas não entendi o '\0' e onde o devia por para compilar, meu erro foi não ter perguntado a sua utilidade pois sei programar o básico.
Estou com alguma dificuldade no input da porta série e tento perceber o seu funcionamento com o objetivo de implentar que pretendo.
O problema é o \r\n estar no buffer do arduino?Ou é outro tipo de problema?


fabio_h

dei uma olhada no seu historico, você está quebrando a cabeça com RF desde junho, fez crossposting, e nada?
Não estou te julgando, mas porque não começa a ler blogs por aí e tente entender como funciona o codigo dos outros, eu te postei um código master/slave que faz exatamente isso, fica verificando a serial, trata do \r e assim que vê \n trata os dados e prossegue o programa.
http://forum.arduino.cc/index.php?topic=180671.msg1344485#msg1344485

o setup() que configura o virtualwire eu modifiquei até funcionar corretamente, verifiquei no "saleae"(analizador lógico), te mandei um código 100% correto, você não reaproveitou nada dele? Não usou porque não sabia o que o código fazia. Faça funcionar uma parte por vez, primeiro a parte serial, depois a conversão em partes, depois o RF, e por ultimo junte tudo...

vasr

#38
Aug 14, 2013, 05:21 am Last Edit: Aug 14, 2013, 08:17 am by vasr Reason: 1
Sim já ando com este código a algum tempo, tive de refazer os objetivos. Tenho tentado seguir as sugestões que me são dadas,as que compreendo.
Também já li muita informação acerca mas não a tenho usado da melhor forma por falta de entendemento na sua totalidade.
Acerca do tópico que te referes, desde entao nunca entendi esta parte(extrado do código):
Code: [Select]
if (Serial.available()&&!enviar){
   byte temp=Serial.read();
     if (temp=='\n'){
       buf[i]='\0';
       enviar=1;
     }
   else{
   if((i<80)&&(temp!='\r')){
       buf[i++]=temp;
   }
   }
 }
if (enviar){
 }

}

Nunca encontra o '\n',ou seja enquanto i<80 faz o segundo "if". Quando essa condição não se verificar o programa não faz nada.Estou enganado?

fabio_h


Acho que primeiro deve aprofundar seus conhecimentos, uma coisa importante é  máquina de estados, isso ajuda muito a desmembrar as tarefas do programa, esse código que te passei tem um bugzinho, o tamanho da array errado, mas ão impede que o programa funcione, esse código tem alguns linhas que faz duas verificações/ações, isso ajuda a não torná-lo claro o suficiente.
OK, você não entendeu o funcionamento mas ele funciona sim.
Todo programa é fácil de fazer, basta enumerar as necessidades e limitações, quando diz quero "um programa que transmita comandos da serial por RF", a explicação é simples mas a implementação não.
Vou dar uma clareada no algoritmo:
-inicializa a serial
-zera as variaveis

- se não pode enviar, escuta a serial, se tem dado:
     se o dado for \n chegou o fim da mensagem, marca o fim da mensagem com \0, sinaliza que pode enviar. senão
          se o dado for \r descarta senão
               se o buffer não está cheio salva o dado no buffer

- se pode enviar
    prepara os dados usando o buffer
    envia os dados
    aguarda o envio
    limpa o buffer
    zera as variaveis
    sinaliza que não pode enviar

-outras coisas podem ser colocadas em seguida que ele executará


vasr

Faço um input de "1"[ENTER],fica no buffer de recebimento "1\r\n"
1ª condição if- testa se tem dados e se não esta a enviar, se é verdade coloca o primeiro dado(1 e unico) no buffer de recebimento e coloca-o na variavel temp.
2ª condição if-testa a variavel teste se contém o '\n',se é verdade coloca na respetiva posição do buf '\0'.Variavel enviar=1 e envia.
Senão 3ª condição if-testa se i<80 e se temp nao contem '\r', se é verdade coloca o valor que esta em tem(que é 1) no buffer da respetiva posição dada pela variavel i.
Esta é minha interpretação do programa,o problema que não faz nunca enviar.

vasr

Aguém pode-me dizer se esta é interpretação correta do código anteiormente descrito?Porque não entra na 2ª condição if?Estou a tentar com os códigos fornecidos pelos usuarios resolver o problema mas não consigo colocar em funcionamento codigo que me refiro.
Obrigado pela ajuda anterior.

bubulindo

No último código não colocaste uma condição para limpar a variável enviar.

Vamos por partes... O teu problema é estruturar o código e escrever parte dele. Isso acontece porque:

- não sabes ou tens muita experiência em programação.
- Não tens completamente definido o que pretendes.

A maneira de ultrapassar isto é fazer bocadinho a bocadinho. Em vez de enviares logo imensos dados numa string e teres de fazer parsing da string, é preferível enviar uma string por comando.

Como ficaste confuso com o que é enviado pela IDE do Arduino, vamos esquecer isso por agora.
Então fica já definido que quando fores enviar comandos pela IDE, vais escrever o comando na caixa de texto, no menú pull down na parte de baixo da janela serial vais escolher Não adicionar caracteres de termino ou algo do género para garantir que não baralhas o protocolo e quando quiseres enviar algo carregas no botão enviar e nunca no botão Enter.

Depois diz que variáveis queres enviar. Para um exemplo vamos imaginar que queres enviar três valores que queres que sejam limites para alarmes de Luz, Humidade e Temperatura.

Então o comando que vais enviar vai ter este formato:  XYYYY

X - descrição do valor a mudar (neste caso, T = temperatura, H = humidade e L = luz).
YYYY - valor a enviar em ASCII, como vamos usar este valor para comparar com leituras do AD, tem 4 posições (o AD vai até 1024).

O código mais simples que terias (e tem alguns problemas... mas funcionaria) seria algo como:

Code: [Select]

//colocado fora de funções
char temp[5]; //espaço para receber o valor que queremos.
char tipo = 0;
//variáveis para usares no teu código.
unsigned int lim_temp = 0;
unsigned int lim_hum = 0;
unsigned int lim_luz = 0;
unsigned int lim = 0;

//Dentro da loop()

if(Serial.available() > 5) { //tens de ter 5 caracteres disponíveis para teres um comando completo.
   tipo = Serial.read(); //guarda o tipo.
   for (int i = 0 ; i <4 ; i++) { //vai buscar as 4 variáveis que precisas para o valor.
      temp[i] = Serial.read();
   }
   temp[4] = '\0'; //isto diz ao atoi() onde deve terminar de converter.
   lim_temp = atoi(temp);   
   if (tipo == 'H') lim_hum = lim;
   if (tipo == 'L') lim_luz = lim;
   if (tipo == 'T') lim_temp = lim;
   Serial.print("mudaste a ");
   Serial.print(tipo);
   Serial.print(" para ");
   Serial.println(lim);
} //fim das comunicações.


Estás a ver a mecânica disto?
Agora se enviares
L1024 tornas o limite da luz 1024.

Se enviares H0000, tornas o limite da humidade 0.

Lembra-te que tens sempre de enviar 4 caracteres após o tipo de dado que vais enviar, mesmo que queiras enviar 0.

Experimenta, vê se funciona, vê se serve para o que queres e se não servir, volta cá e explica porquê.

This... is a hobby.

vasr

Antes de mais obrigado pelo teu reply explicativo e atenção dada ao meu tópico.
Tenho que considerar que apesar de saber o que pretendo tenho andado perdido no caminho de como conseguir implentar um código o mais simples e funcional possível e com menor numero de bugs.
Analisei e testei o código me colocaste, esta a funcionar e percebo totalmente.
Fizeste-me pensar numa questão, este código vai ter um programa(ex. em VB) para interagir com este código logo não vai acontecer o ENTER, só apenas o envio. Deste detalhe poderá ser a solução do problema.

Exemplo do protocolo que estou a definir:
temp[0]-número do slave que pretendo comandar (ex.0-99slaves),imput de 2digitos pela serial
temp[1]-tipo de ação (exemplo: se é para desligar,ligar o recolher uma leitura),2digitos ou 1 dependendo das açoes que quero implementar
temp[2]-o pino do arduino que quero fazer a ação anterior,2 digitos
temp[3]-enviar por exemplo um valor de um pwm a atuar(0-255),3 digitos
Sequencia podia ser: "03110200"=Slave 03,ação 1(de por exemplo pwm),pino 10,valor do pwmn=200

Este é o protocolo que tenho defenido.Que acham sobre este protocolo?A implementação será complexa?Pergunto isto pois já fiz varias tentativas até entao mas tenho detetado alguns bugs ou simplemente não esta funcional.








bubulindo

Não me parece que tenhas compreendido o código correctamente...


temp[0]-número do slave que pretendo comandar (ex.0-99slaves),imput de 2digitos pela serial


Num char apenas consegues meter um digito, não dois.

E voltamos ao problema inicial... se o teu Arduino vai comunicar com VB, porque não crias o programa em VB primeiro a enviar os dados em binario (onde um char consegue conter 3 digitos até 255) e depois fazeres o protocolo no Arduino? Isso, se não tiveres os problemas que tens com o Arduino em fazer o código, seria bem mais simples do que o caminho que estás a levar.

Se pretendes mesmo fazer o protocolo que implementaste (com o problema que apontei), não é muito mais difícil. A mecânica está toda lá. Apenas tens de repetir para todos os campos o mesmo processo.

Algo que, se calhar, talvez possa facilitar o processo para ti será fazeres um código estúpido sem usares ciclos e depois optimizares com ciclos. Isto é...

Para o teu exemplo:

Code: [Select]

//2 ID
//2 Accão
//2 pino
//3 valor.

const unsigned char OutHigh = 1;
const unsigned char OutLow = 0;
const unsigned char OutPWM = 3;

char ID[3];
char Accao[3];
char Pino[3]
char Valor[4];

unsigned int num_ID = 0;
unsigned int num_Accao = 0;
unsigned int num_Pino = 0;
unsigned int num_Valor = 0;


if (Serial.available() > 9) {
   ID[2] = '\0';
   Accao[2] = '\0';   
   Pino[2] = '\0';
   Valor[3] = '\0';
   
   //receber os dados para os sítios correctos.
   ID[0] = Serial.read();
   ID[1] = Serial.read();
   Accao[0] = Serial.read();
   Accao[1] = Serial.read();
   Pino[0] = Serial.read();
   Pino[1] = Serial.read();
   Valor[0] = Serial.read();
   Valor[1] = Serial.read();
   Valor[2] = Serial.read();

//convertê-los para um valor usável...
   num_ID = atoi(ID);
   num_Accao = atoi(Accao);
   num_Pino = atoi(Pino)
   num_Valor = atoi(Valor);

//decidir o que fazer...
   if (num_Accao == OutLow) digitalWrite(Pino, LOW);
   if (num_Accao == OutHigh) digitalWrite(Pino, HIGH);
   if (num_Accao == OutPWM) analogWrite(Pino, num_Valor);
}


Isto faz mais ao menos o que pretendes, se tiveres em atencão que tens de enviar uma string completa com 9 caracteres para o comando funcionar. 2 caracteres para ID, 2 para Accao, 2 para Pino e 3 para Valor. Estäs a ver a ideia?

Este protocolo tem problemas... Uma delas é não teres um caracter de início que te permita sincronizar as comunicacões.
A outra é o caracter de final para garantir que o comando está completo.

Finalmente, a implementacão pode ser melhorada, claro... o objectivo é trocares as instrucões que estão repetidas por ciclos de forma a melhorar o desempenho do programa e sistema.

Mas se fosse a ti, olhava ao que disse sobre caracteres de comeco e fim. ;)

This... is a hobby.

Go Up