Go Down

Topic: Como percorrer dados obtidos da serial? (Read 2598 times) previous topic - next topic

Nov 13, 2012, 06:34 pm Last Edit: Nov 16, 2012, 11:55 am by deckardbot Reason: 1
Olá pessoal, tudo bom?

Preciso ler dados da serial e compara-los com um padrão (protocolo).
Não tenho muita experiência, então não sei se é melhor criar uma string de entrada e depois fazer a comparação ou fazer uma rotina para tratar cada byte recebido sem montar uma string.

Para começar fiz o seguinte código tentando jogar os bytes lidos da serial numa string:
Code: [Select]

const int N = 10;
char inMsg[N];

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

void loop()
{
 if(Serial.available() > 0)
 {
   int i = 0;
   while((Serial.available() > 0) && (i < N))
   {
     inMsg[i] = Serial.read();
     ++i;
   }
   
   // teste: imprime array para verificar o conteudo
   imprimeMsg();
 }
}

void imprimeMsg()
{
 int i = 0;
 //for(i = 0; i < (sizeof(inMsg) / sizeof(char)); i++)
 for(i = 0; i < N; i++)
   {
     Serial.print("inMsg[");
     Serial.print(i);
     Serial.print("] = ");
     Serial.println(inMsg[i]);
   }
}


O problema é que no teste, enviando a string '0123456789', tem ocorrido o seguinte:
Code: [Select]

inMsg[0] = 0
inMsg[1] = \0x00
inMsg[2] = \0x00
inMsg[3] = \0x00
inMsg[4] = \0x00
inMsg[5] = \0x00
inMsg[6] = \0x00
inMsg[7] = \0x00
inMsg[8] = \0x00
inMsg[9] = \0x00
inMsg[0] = 1
inMsg[1] = 2
inMsg[2] = 3
inMsg[3] = 4
inMsg[4] = 5
inMsg[5] = 6
inMsg[6] = 7
inMsg[7] = 8
inMsg[8] = 9
inMsg[9] =

Ou seja, ao invés de montar uma string com todos os bytes está sendo criada uma nova string após o primeiro byte lido da serial.

Obs: ainda falta fazer a rotina do protocolo, mas primeiro preciso garantir que estou obtendo os bytes corretamente.

Alguem tem ideia de como fazer?

Espero que possam ajudar.
Abs.

#1
Nov 13, 2012, 06:52 pm Last Edit: Nov 13, 2012, 07:02 pm by bubulindo Reason: 1
Experimenta isto:

Code: [Select]
const int N = 10;
char inMsg[N+1];

void setup()
{
  Serial.begin(9600);
  inMsg[N] = 0;
}

void loop()
{
  if(Serial.available() >= 10)
  {
    int i = 0;
    while(( i < 10))
    {
      inMsg[i++] = Serial.read();
     
    }
   
    // teste: imprime array para verificar o conteudo
    imprimeMsg();
  }
}

void imprimeMsg(){
    Serial.println(inMsg);
   
}


A tua funcão imprime mensagem está errada... certamente que se correres isto várias vezes vais obter resultados diferentes...

O problema ocorre quando fazes isto:

i < (sizeof(inMsg) / sizeof(char))

sizeof(inMsg) é igual a 10... sizeof(char) é sempre igual a 1...

Quando recebes algo na porta série, o if passa a ser válido... mas se só recebeste um valor, para que vais tentar imprimir os valores todos?



Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

Ola bubulindo,

Obrigado por responder.
Seu código deu certo. Mas a função imprimeMsg() deve percorrer o array de caracteres (string) para verificar se cada índice possui conteúdo válido.
Por exemplo, se eu mandar 123 pela serial, inMsg deve ficar assim:
inMsg[0] = 1
inMsg[1] = 2
inMsg[2] = 3
inMsg[3] =
inMsg[4] =
...

Desta forma eu poderei comparar se corresponde com o protocolo que irei utilizar.

Abs.

Da maneira que está, funciona se mudares a imprimeMsg para o que estava. O que tens de ter em atenção é não imprimires o que ainda não recebeste
Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).


Aproveitando o tópico, gostaria de tirar mais uma duvida:

- Como percorrer um array de caracteres sem saber o seu tamanho?

Tentei desta forma:
Code: [Select]

for(i = 0; i < (sizeof(inMsg) / sizeof(char)); i++)

Porem desta forma não funciona, iterando apenas duas vezes.

Verifiquei que o Arduino trata um 'char array' diferentemente do C.

Em C:
sizeof(char) = 1 byte
char str[10]; sizeof(str) = 10 bytes

Arduino:
sizeof(char) = 1 byte
char str[10]; sizeof(str) = 2 bytes

Como assim?

Experimenta isto


Code: [Select]

char str_1[] = "hello";
char str_2[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
char str_3[10];

void setup() {

char str_1_local[] = "hello";
char str_2_local[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
char str_3_local[10];

Serial.println("These are the external arrays:");
Serial.print("str_1");
Serial.println(sizeof(str_1));
Serial.print("str_2");
Serial.println(sizeof(str_2));
Serial.print("str_3");
Serial.println(sizeof(str_3));

Serial.println("These are the local arrays:");
Serial.print("str_1");
Serial.println(sizeof(str_1_local));
Serial.print("str_2");
Serial.println(sizeof(str_2_local));
Serial.print("str_3");
Serial.println(sizeof(str_3_local));

}

void loop() {}


Eu suspeito que tem a ver com o facto de todo o código do Arduino correr dentro duma funcão (setup ou loop) e não directamente na main. Nada como experimentar esse código em cima e ver as diferencas. Outra coisa que convém teres em atencão tem a ver com o facto que o compilador para AVR pode ou não obedecer às convencões do C para computadores e não sabes exactamente as opcões de optimizacão que activaram no compilador. Tudo isso são possibilidades para explicar isto.

Isto é uma maneira de passar esse problema. Também podes usar um string terminator e percorrer a string até o encontrar. Normalmente usa-se '\0'.

Code: [Select]

#define ARRAY_SIZE   10
char array[ARRAY_SIZE];
unsigned char chars_in_array = 0;


array[chars_in_array++] = Serial.read();


for (i = 0; i< chars_in_array; i++) {
 Serial.println(array[i]);
}


Algo assim...

Edit:

No site tinha isto:

Quote
Note that sizeof returns the total number of bytes. So for larger variable types such as ints, the for loop would look something like this. Note also that a properly formatted string ends with the NULL symbol, which has ASCII value 0.

Logo parece-me que o sizeof vai procurar por um \0 para retornar um valor.
Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

O exemplo que postei... retornou isto:

Quote

These are the external arrays:
str_1 = 6
str_2 = 6
str_3 = 10
These are the local arrays:
str_1 = 6
str_2 = 6
str_3 = 10


Queres meter o código que usaste?
Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

Olá bubulindo,

Testei o seu código e obtive o mesmo resultado. Que está correto.

Só não entendi o porque eu estava obtendo um tamanho errado do array de caracteres.
Mas pelo menos está funcionando ;)

Obrigado pela ajuda!


Provavelmente porque passaste o array para dentro de uma função? Nesse caso, o array é convertido para apontador.

Tens o código completo que usaste para testar? Agora estou curioso.
Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

Go Up