Boa noite,

estou tendo dificuldade em fazer a comparação entre a leitura do texto da serial  e um texto armazenada.

sketch em anexo.

Exibições: 333

Anexos

Responder esta

Respostas a este tópico

olá Guilherme.

      Sempre que vc clica no Botão "enviar" do Terminal do Arduino,  o texto é de fato enviado para o Arduino, e vc recebe este texto via Serial padrão do Arduino.  No entanto, é preciso haver uma forma que permita que vc saiba que uma linha completa foi enviada (independente se a linha é uma frase, se é apenas uma única letra, ou se é uma linha "vazia"). O Terminal do Arduino, permite a vc, quatro opções para indicar que uma linha está completa, e vc pode ver isso na figura a seguir:

(clique na figura para "zoom")

      A primeira opção é "Nenhum final-de-linha".   Nesta opção,  quando vc clicar no Botão "enviar",  o texto será enviado exatamente como vc o digitou, sem acrescentar mais nenhum caracter ao mesmo.  Isto significa que quando este texto for recebido no Arduino, o seu código deverá ter alguma forma de identificar que a linha está completa. Mas veja que isso pode ser um problema, pois vc terá que "sacrificar" algum caracter ou uma palavra para esta finalidade. Vc poderia por exemplo usar o caracter "$" para esta finalidade,  e se digitar  "oi$" no Terminal,  então lá no código do Arduino,  vc deverá considerar que o "$" é o final do texto (ou linha de texto). Obviamente neste exemplo, vc não poderá mais usar o "$" como parte integrante do texto, pois o código sempre irá tratar o mesmo como um fim de texto, e não como parte do texto.   Vc poderia usar também uma palavra como fim do texto, como por exemplo a palavra "FIM", e se digitar "oiFIM" no Terminal,  o código no Arduino terá que identificar "FIM" e assim saber que terminou o texto. E neste caso,  a palavra "FIM" não poderá mais fazer parte do seu texto, já que tem outra finalidade (indicar o fim do texto).  Logo,  esta opção "Nenhum final-de-linha" pode não ser a mais adequada para 99,9% dos casos.

      Para contornar isto, existem as outras três opções:  "Nova-linha",  "Retorno de carro", e "Ambos, NL e CR".  Vamos entender isso.  Ocorre, que existem no código ASCII  padrão,  32 caracteres que são "não-imprimíveis", ou seja, não correspondem a letra ou símbolo no nosso "alfabeto" Ocidental.  E desses 32 caracteres,  dois foram "escolhidos" para serem usados como indicadores do final do texto (ou final da linha de texto) no Terminal do Arduino.  Um destes dois caracteres é o de código 13, que é representado pela sigla "CR" (ou "Carriage Return", também chamado de "ENTER"), que em Hexadecimal é o código 0x0D.  O outro caracter é o de código 10, que é representado pela sigla "LF" (ou "Line Feed", também chamado de "New Line"), que em Hexadecimal é o código 0x0A.

      Assim as outras três opções, combinam estes dois caracteres (ou códigos), de forma a indicar o final do texto (ou linha de texto).  Na segunda opção, "Nova-linha", quando vc clica no Botão "enviar", o caracter do "LF" (código 10 ou 0x0A) é acrescentado ao final do texto para justamente indicar que o texto termina ali.  Na terceira opção, "Retorno de carro", ocorre a mesma coisa, porém o caractere utilizado é o "CR" (código 13 ou 0x0D).  E finalmente na quarta e última opção, os dois caracteres são acrescentados, sendo o "CR" logo após o texto original e seguido pelo caracter "LF" (ou seja, o "LF" é o último caractere enviado).

      Em 99.99% dos casos, usamos justamente a última opção, ou seja o "CR" e "LF" juntos. O motivo disto é histórico, ou seja, está relacionado aos primórdios da Computação/Informática. Mas se tornou praticamente padrão, e por isso também é aconselhável usar este "formato".

      Certamente no seu Terminal do Arduino, está selecionada ou a opção "NL e CR" ou apenas "LF", para a sinalização do final da linha de texto. É possível afirmar isto, pois na imagem que vc postou, sempre há uma linha em branco após vc imprimir no Terminal o texto recebido pelo código no Arduino.  E o "LF" tem esta propriedade:  ele avança uma linha na tela do Terminal. Como vc está usando o "Serial.println",  e este "ln" no final do "print" é justamente para que seja enviado um "LF" ao Terminal, logo após o envio do conteúdo do "print".   E juntando o "LF"  do seu   "Serial.println", com o "LF" que está na própria "msg",  acaba que uma linha a mais é "impressa" no Terminal (neste caso, uma linha "vazia").

      Analisando seu código original, vê-se que não há um tratamento para justamente detectar o final do texto recebido.  E ao que tudo indica,  vc usou um "delay" através do "millis()", justamente para dar tempo para que o texto fosse recebido por completo.  Tudo bem, isto é válido, mas certamente não é a forma mais adequada. E veja que seu "delay" é relativamente curto, de 10 mili-segundos.  Na velocidade de 9600 bps (que vc determinou no "Serial.begin" no "setup"),  cada caractere demora cerca de 1 mili-segundo para ser recebido por completo. Logo,  no período de 10 mili-segundos,  vc receberá no máximo 10 caracteres.  Percebe?   Se seu texto for mais longo que 10 caracteres,  vc "detectará" uma linha menor que a "real", e os demais caracteres serão "detectados" como se estivessem na próxima linha de texto.  Então este é mais um inconveniente.  Claro, vc poderia aumentar o tempo do "delay", mas para quanto?  Não seria melhor não depender desse delay?  A resposta para isso é justamente detectar o final da linha  através  do "CR" ou "LF", e então uma vez feito isso,  vc processa a String  recebida e "montada".  Claro, aí ficará a seu critério manter no texto recebido, os caracteres indicadores do final da linha (seja "LF", seja "CR", sejam ambos).

      Então, "reescrevi" seu código, detectando o final da linha. O código vc pode ver na figura a seguir:

(clique na figura para "zoom")

      Veja que detecto o "CR".  Dessa forma,  funciona para qualquer das opções que tenham o "CR".  E funcionará mesmo que vc use a opção do "CR" e "LF" juntos,  porque se o "LF" for recebido,  ele é descartado (já que é menor que 0x20, o "32"). Isto ocorre porque o código em execução descarta qualquer dos 32 caracteres ASCII "não-imprimíveis", ou seja não os acrescenta ao texto final (o primeiro caracter imprimível, é o 0x20, que é o caracter "espaço").

      O resultado da execução deste código, para as mesmas "entradas" de texto que vc utilizou como exemplo, pode ser visto na figura a seguir:

(clique na figura para "zoom")

      E porque seu código original não funcionou?  Agora fica claro:  quando vc recebeu o texto, vc recebeu também o "CR" e "LF" junto ao final do texto. E quando vc compara com a String constante "teste", esta String não tem o "CR" e o "LF", e portanto não será igual ao texto recebido via Serial. Claro, isto poderia ser facilmente resolvido acrescentando o "CR" e o "LF" ao final da String constante "teste". Mas isto é menos versátil, e por isso preferi usar a técnica que apresentei no código reescrito (além de que se seu Sistema tiver temporizações mais complexas, o método que usei não irá falhar, enquanto o outro...).

      Este exemplo é bastante didático,  e ajuda muito a dismistificar a coisa. Então o achei muito apropriado para isso.

      Mas fique atento:  evite  usar coisas como "Serial.readString", pois esta função tende a ser do tipo "bloqueante", e o mesmo vale para "Serial.readStringUntil" embora neste caso a possibilidade de "bloqueio" seja menor. Digo isto, porque muitos podem considerar usar estas funções por acharem que elas são "uma mão na roda", mas elas podem ser um grande problema em Sistemas mais "realísticos". Então se possível, não  as use.

      O código "reescrito", é este aqui:   "comparar_strings_01.zip"

      Um documento que escrevi,  ajuda expandir as coisas:  "config_IDE_Arduino_00.pdf"

      Espero ter ajudado.

      Abrçs,

      Elcids

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço