Limpe a matriz existente ao obter um novo comando serial

Estou começando a construir meu primeiro projeto Arduino, mas estou tendo alguns problemas com a comunicação serial.

Eu obtenho dados seriais do console e os armazeno em uma matriz de char chamada “dados”.

Então, quando eu enviar uma nova mensagem de console para o Arduino, quero limpar o array “data” existente e armazena apenas os novos dados nesse array.

Não entendo exatamente o que há de errado com meu código: acredito que as instruções aninhadas Serial.available () não funcionam mas não tenho ideias sobre como consertar o código.

Os dados são armazenados corretamente pelo Arduino, mas ele concatena a string mais recente com a antiga.

int count = 0; char data[30]; boolean dataComplete = false; void setup() { Serial.begin(9600); } void loop() { if (Serial.available() > 0){ if (dataComplete == true){ Serial.println("There is data already, clearing..."); char data[30]; dataComplete = false; } if (dataComplete == false){ Serial.println("New command, collecting..."); while (Serial.available()>0){ char character = Serial.read(); data[count] = character; count++; } dataComplete = true; } } Serial.print("Command received: "); Serial.println(data); delay(1000); } 

Agradecemos antecipadamente!

Resposta

Para limpar uma matriz, você faria:

for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0; 

ou

memset(data, 0, sizeof(data)); 

, que faz a mesma coisa usando uma função de biblioteca.

No entanto, porque strings de caracteres (não se referindo a objetos “String” aqui) são encerrados por um byte zero, apenas o primeiro byte precisa ser zerado:

data[0] = (char)0; 

fará isso .

Resposta

Em primeiro lugar, este é um excelente exemplo de por que o espaço em branco é importante. Seu código é realmente difícil de ler do jeito que está, visto que o examinando rapidamente, parece que a segunda instrução if está fora da primeira.

Código corrigido:

int count = 0; char data[30]; boolean dataComplete = false; void setup() { Serial.begin(9600); } void loop() { if (Serial.available() > 0){ if (dataComplete == true){ Serial.println("There is data already, clearing..."); char data[30]; dataComplete = false; } if (dataComplete == false){ Serial.println("New command, collecting..."); while (Serial.available()>0){ char character = Serial.read(); data[count] = character; count++; } dataComplete = true; } } Serial.print("Command received: "); Serial.println(data); delay(1000); } 

Além disso, parece que imprime” Comando recebido: “a cada iteração, independentemente de haver novos dados ou não (embora este possa ser o recurso pretendido).

Como mencionado, você não limpa a variável, apenas cria uma nova. Você precisará limpar e redefinir count para corrigir esse problema. No entanto, apenas redefinir a contagem não funcionará se o segundo comando for mais curto que o antes.

Além disso, por que você complica o código com a variável dataComplete? Simplifiquei o código abaixo:

int count = 0; char data[30]; boolean dataComplete = false; void setup() { Serial.begin(9600); } void loop() { if (Serial.available()){ Serial.println("New command, collecting..."); count = 0; data[] = ""; while (Serial.available()){ char character = Serial.read(); data[count] = character; count++; } } Serial.print("Command received: "); Serial.println(data); delay(1000); } 

Resposta

Isso provavelmente não faça o que pretende fazer:

Serial.println("There is data already, clearing..."); char data[30]; 

Sua saída diz que você está limpando a matriz data, mas você “não está fazendo tal coisa. Na verdade, você está declarando uma nova variável local chamada data, que é independente do data global que você já declarou no topo do seu programa. Variáveis locais existem apenas dentro do escopo em que são declaradas (dentro de seu invólucro mais próximo { }).

Em vez disso, sua count variável mantém registro de quantos dados você recebeu. Então, talvez faça o seguinte:

Serial.println("There is data already, clearing..."); count = 0; 

Isso não é a única coisa que pode fazer com que seu programa opere inesperadamente, mas deve pelo menos corrigir o problema declarado em sua pergunta.

Comentários

  • Também é necessário um terminador nulo para os dados: Adicione data[count]='\0'; depois de dataComplete = true;
  • Sim, isso ‘ é verdade, mas o maior problema é que não há como o remetente indicar o fim de uma transmissão de dados diferente de uma pausa. E já que isso é serial, haverá uma pausa longa o suficiente entre cada caractere transmitido.
  • Obrigado a vocês dois. Meu código estava errado e alterá-lo para ” count = 0 ” funcionou. Eu também adicionei um delimitador para indicar o fim de um comando de entrada e ele funciona como pretendido agora. No entanto, a única maneira que funcionou para esvaziar a matriz ” data ” foi usando um loop for conforme indicado por @JRobert: desta forma mais recente os comandos funcionam mesmo se forem mais curtos do que os mais antigos.

Resposta

Para falar direto ao ponto da pergunta , e o que o autor estava tentando realizar.

Nenhum desses códigos realmente funciona como um todo. Os dados seriam sobrescritos e continuariam em loop continuamente … de qualquer maneira, aqui está um exemplo funcional do código original.

Este método eu prefiro limpar um array:

 for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0; 

Aqui está um exemplo prático. (Certifique-se de selecionar Retorno de carro no monitor serial)

 char message[32]; uint8_t incomingByte = 0; uint8_t BufferPos = 0; int clearbyte = 0; void setup() { Serial.begin(9600); Serial.println("\n String conversion testing"); } void loop() { if (BufferPos >= 32) { Serial.print("Buffer Full\n"); BufferPos = 00; incomingByte = 0; } if (Serial.available()) { incomingByte = Serial.read(); message[BufferPos++]= incomingByte; switch(incomingByte) { case "\n": case " ": break; case "\r": Serial.println(message); for( int i = 0; i < sizeof(message); ++i ) message[i] = (char)0; BufferPos= 0; incomingByte= 0; } } } 

Resposta

Todos os comentários sobre esta questão foram lidos, mas todos os códigos foram compartilhados de forma verbosa. Depois disso, crio um código com funções simples e menos de linha. neste caso, acho que este código funcionará bem

se você definir a taxa de transmissão abaixo de 115200, deve ser adicionado delay () para salvar a mensagem na matriz de caracteres

void loop() { char data[255]; uint8_t k = 0; while (Serial.available()) { data[k] = Serial.read(); k++; } for (int i = 0; i < k; i++) { Serial.print(data[i]); data [i] = "\0"; } //delay(50); } 

Comentários

  • char data[] = {}; fornecerá uma matriz de comprimento zero. Tentar colocar dados nele é uma má ideia.
  • Eu concordo com @NickGammon.Edite sua resposta para substituir ” Eu acho … funcionará bem ” por um sim / não definitivo, depois de testar o código.
  • @NickGammon obrigado pela correção, fui revisar meu código

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *