Vytvářím aplikace pro počítač, který má sloužit k ovládání robotického ramene. Chtěl jsem udělat první pokus o spuštění aplikace ne na motoru, ale na diodě a zkontrolovat, zda změní svůj jas v závislosti na poloze jezdce. Napsal jsem aplikaci v Qt, která odesílá tanga do Arduina, a Arduino jsem četl a konvertoval na int. Problém je v tom, že ačkoliv je posuvník nastaven na 0, Arduino to neukazuje, často se čísla příliš často neshodují (často příliš malá), i když najednou celou dobu posuvu posuvníku počítám dopředu místo zpět.
Arduino kód:
String br; void setup() { Serial.begin(9600); pinMode(9, OUTPUT); } void loop() { while (Serial.available()>0) { br = Serial.readString(); analogWrite(9, br.toInt()); Serial.println(br.toInt()); } }
Qt kód:
void MainWindow::on_horizontalSliderGrip_sliderMoved(int position) { this->sendMessageToDevice(QString::number(position) + "n"); qDebug() << "Grip: " << QString::number(position); } void MainWindow::sendMessageToDevice(QString message) { if(this->device->isOpen() && this->device->isWritable()) { //this->addToLogs("Sending information to the device " + message); this->device->write(message.toStdString().c_str()); } else { this->addToLogs("I can not send a message. The port is not open!"); } }
Komentáře
- Serial.readString () je hluboce chybný a je třeba se mu vyhnout. Přečtěte si toto: majenko.co.uk/blog/reading-serial-arduino
- A jsem si jistý chtěli jste přidat
\n
k odchozím zprávám, nikolin
… - při ladění problému, jako je vložte
Serial.println(br);
předanalogWrite()
, abyste zjistili, co je přijímáno
odpověď
Jak napsal Majenko ve svém komentáři, váš problém spočívá v Serial.readString()
. Obecně to není dobrý způsob zpracování sériových dat. Čte data ze sériového rozhraní, dokud nenastane časový limit (výchozí 1 s). Pokusí se tedy číst do 1 sekundy po poslední změně posuvníku a vrátit všechna data jako jeden řetězec. String.toInt()
poté začne číst řetězec od prvního znaku a převede je na celé číslo, dokud nenačte znak, který není číslice (tj. n
, které posíláte). Tím se zastaví a vrátí již převedenou hodnotu.
To znamená, že ze všech dat odeslaných do Arduina bude použita pouze první hodnota. Zbytek bude vyhoden.
Lepší je použít neblokující kód, který správně zachází se zprávami (ve vašem případě čísla). To se provádí čtením příchozích sériových dat po bajtech, jejich přidávání do vyrovnávací paměti, dokud nedostane speciální znak oddělovače. Poté bude zpráva zpracována jako celek. Poté lze přečíst a zpracovat další zprávu. Tímto způsobem nezmeškáte žádnou z hodnot odeslání.
Speciální oddělovač je libovolný; můžete použít libovolný znak, který se v platných datech nevyskytuje. Takže použití znaku n
je v pořádku. Většinou se ale používá znak nového řádku \n
, takže můžete také odesílat zprávy s alfanumerickými znaky. S největší pravděpodobností jste již chtěli použít \n
.
Jako příklad tohoto sériového kódu můžete použít readline()
funkce z Majenkova příspěvku na blogu :
char buf[80]; int readline(int readch, char *buffer, int len) { static int pos = 0; int rpos; if (readch > 0) { switch (readch) { case "\r": // Ignore CR break; case "\n": // Return on new-line rpos = pos; pos = 0; // Reset position index ready for next time return rpos; default: if (pos < len-1) { buffer[pos++] = readch; buffer[pos] = 0; } } } return 0; } void setup() { Serial.begin(115200); } void loop() { if (readline(Serial.read(), buf, 80) > 0) { Serial.print("You entered: >"); Serial.print(buf); Serial.println("<"); } }
Můžete převést vyrovnávací paměť znaků na int s atoi()
v příkazu if v void loop()
a použít jej pro ´analogWrite () `.