Jeg lager applikasjoner for en datamaskin som skal brukes til å kontrollere robotarmen. Jeg ønsket å gjøre det første forsøket på å kjøre applikasjonen ikke på motoren, men på dioden og sjekke om den vil endre lysstyrken, avhengig av glidebryteren. Jeg skrev en applikasjon i Qt som sender tanga til Arduino, og Arduino jeg leste og konverterer til int. Problemet er at selv om glidebryteren er satt til 0, viser Arduino det ikke, ofte er ikke figurene enige for ofte (ofte for små), også når jeg plutselig flytter tallsklien hele tiden teller mot fronten i stedet for tilbake.
Arduino-kode:
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-kode:
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!"); } }
Kommentarer
- Serial.readString () er dypt feil og bør unngås. Les dette: majenko.co.uk/blog/reading-serial-arduino
- Og jeg er sikker du mente å legge til
\n
i de utgående meldingene dine, ikken
… - når du feilsøker et problem som din setter
Serial.println(br);
føranalogWrite()
for å se hva som mottas
Svar
Som Majenko skrev i sin kommentar, ligger problemet ditt med Serial.readString()
. Det er vanligvis ikke en god måte å håndtere seriedata på. Den leser data fra det serielle grensesnittet, til timeout (standard 1s) inntreffer. Så det vil prøve å lese til 1 sekund etter den siste endringen av glidebryteren og returnere hele dataene som en streng. String.toInt()
vil da begynne å lese strengen fra det første tegnet og konvertere dem til et heltall, til den leser et ikke-sifret tegn (som betyr n
, som du sender). Den stopper der og returnerer den allerede konverterte verdien.
Dette betyr at av alle dataene som ble sendt til Arduino, vil bare den første verdien bli brukt. Resten blir kastet.
Bedre, du bør bruke en ikke-blokkerende kode som håndterer meldingene (tall i ditt tilfelle) riktig. Dette gjøres ved å lese innkommende seriedata byte for byte, legge dem til en buffer til et spesialtegn mottas. Da blir meldingen behandlet som en helhet. Etter det kan neste melding leses og behandles. På denne måten savner du ikke noen av sendingsverdiene.
Spesiell skilletegn er vilkårlig; du kan bruke hvilket som helst tegn som ikke forekommer i gyldige data. Så å bruke tegnet n
er ok her. Men stort sett brukes den nye linjetegnet \n
, slik at du også kan sende meldinger med alfanumeriske tegn. Mest sannsynlig mente du allerede å bruke \n
.
Som et eksempel på denne seriekoden kan du ta readline()
funksjon fra Majenkos blogginnlegg :
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("<"); } }
Du kan konvertere tegnbufferen til en int med atoi()
i if-setningen i void loop()
og bruk den til ´analogWrite () `.