Vymazat stávající pole při získávání nového sériového příkazu

Začínám stavět svůj první projekt Arduino, ale narážím na problémy se sériovou komunikací.

Získávám sériová data z konzoly a ukládám je do pole char s názvem „data“.

Potom, když pošlu novou zprávu z konzoly do Arduina, chci, aby vymazala existující pole „data“ a do tohoto pole ukládat pouze nová data.

Nerozumím přesně, co je s mým kódem špatně: věřím, že vnořené příkazy Serial.available () nefungují ale nemám žádné nápady, jak kód opravit.

Data jsou správně ukládána Arduinem, ale spojuje novější řetězec se starým.

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); } 

Předem děkujeme!

Odpovědět

Chcete-li vymazat pole, postupujte takto:

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

nebo

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

, který dělá totéž pomocí funkce knihovny.

Nicméně, protože řetězce znaků (bez odkazu na objekty „String“ zde) je ukončeno nulovým bajtem, pouze první bajt musí být vynulován:

data[0] = (char)0; 

to udělá .

Odpověď

Nejdříve je to vynikající příklad, proč jsou mezery důležité. Váš kód se opravdu těžko čte tak, jak je, protože při procházení se zdá, že je to druhý příkaz if, pokud je mimo první.

Opravený kód:

Také se zdá, že tiskne„ Příkaz obdržel: “každou iteraci, bez ohledu na to, zda existují nová data nebo ne (i když to může být zamýšlená funkce).

Jak již bylo uvedeno, proměnnou nevymažete , pouze vytvoříte novou. Chcete-li tento problém vyřešit, musíte a resetovat count. Jen resetování počtu však nebude fungovat, pokud je druhý příkaz kratší než ten dříve.

Proč také komplikujete kód pomocí proměnné dataComplete? Níže uvedený kód jsem zjednodušil:

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); } 

Odpovědět

Toto pravděpodobně není udělejte, co chcete:

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

Váš výstup říká, že mazáte pole data, ale vy „nic takového nedělám. Ve skutečnosti deklarujete novou místní proměnnou nazvanou data, která je nezávislá na globálním data již byly deklarovány v horní části vašeho programu. Místní proměnné existují pouze v rozsahu, ve kterém jsou deklarovány (uvnitř jejich nejbližšího { }).

Proměnná count místo toho sleduje, kolik dat jste obdrželi. Možná tedy udělejte toto:

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

To není jediná věc, která může způsobit neočekávané fungování vašeho programu, ale měla by alespoň vyřešit problém uvedený v vaše otázka.

Komentáře

  • Pro data je také zapotřebí nulový zakončovací člen: Přidat data[count]='\0'; za dataComplete = true;
  • Ano, ‚ je to pravda, ale větší problém je v tom, že odesílatel nemůže označte konec datového přenosu jiný než pauza. A protože jde o seriál, mezi každým přeneseným znakem bude dostatečně dlouhá pauza.
  • Díky vám oběma. Můj kód byl špatný a jeho změna na “ count = 0 “ fungovala. Také jsem přidal oddělovač, který označuje konec vstupního příkazu a nyní funguje tak, jak bylo zamýšleno. Jediným způsobem, který fungoval k vyprázdnění “ dat “ pole, bylo použití smyčky for, jak uvádí @JRobert: tímto způsobem novější příkazy fungují, i když jsou kratší než starší.

Odpověď

Hovořit k otázce a co se autor pokoušel dosáhnout.

Žádný z těchto kódů ve skutečnosti nefunguje jako celek. Data by se dostala přes zapsaná a jen by se neustále opakovala … každopádně zde je funkční příklad původního kódu.

Tuto metodu dávám přednost vymazání pole:

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

Zde je funkční příklad. (Na sériovém monitoru vyberte Carriage Return)

 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; } } } 

Odpovědět

Přečetly jsem si všechny komentáře k této otázce, ale všechny kódy byly sdíleny tak podrobně. Poté vytvořím kód s jednoduchými funkcemi a méně řádků. v tomto případě si myslím, že tento kód bude fungovat dobře

pokud nastavíte přenosovou rychlost pod 115200, je nutné přidat delay () pro uložení zprávy do char pole

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); } 

Komentáře

  • char data[] = {}; vám poskytne pole nulové délky. Pokus o vložení dat je špatný nápad.
  • Souhlasím s @NickGammon.Upravte prosím svou odpověď a nahraďte “ Myslím, že … bude fungovat dobře “ definitivním ano / ne, jakmile otestujete kód.
  • @NickGammon díky za opravu, revidoval jsem svůj kód

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *