Go Down

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

deckardbot

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.

bubulindo

#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?



This... is a hobby.

deckardbot

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.

bubulindo

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
This... is a hobby.

deckardbot


deckardbot

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?

bubulindo

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.
This... is a hobby.

bubulindo

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?
This... is a hobby.

deckardbot

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!


bubulindo

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.
This... is a hobby.

Go Up