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
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
data[count]='\0';
zadataComplete = true;