Från strängar till int problem

Jag skapar applikationer för en dator som ska användas för att styra robotarmen. Jag ville göra det första försöket att köra applikationen inte på motorn utan på dioden och kontrollera om den ändrar ljusstyrkan beroende på skjutreglage. Jag skrev en applikation i Qt som skickar remmar till Arduino, och Arduino läser jag och konverterar till int. Problemet är att även om skjutreglaget är inställt på 0, visar Arduino det inte, ofta är siffrorna inte överens för ofta (ofta för små), även när jag plötsligt flyttar sifferreglaget hela tiden räknas framåt istället för tillbaka.

Arduino-kod:

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-kod:

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

ange bildbeskrivning här

Kommentarer

  • Serial.readString () är djupt bristfällig och bör undvikas. Läs detta: majenko.co.uk/blog/reading-serial-arduino
  • Och jag är säker du menade att lägga till \n till dina utgående meddelanden, inte n
  • när du felsöker ett problem som din sätt Serial.println(br); före analogWrite() för att se vad som tas emot

Svar

Som Majenko skrev i sin kommentar ligger ditt problem med Serial.readString(). Det är i allmänhet inte ett bra sätt att hantera seriell data. Den läser data från det seriella gränssnittet tills timeout (standard 1s) inträffar. Så det kommer att försöka läsa till 1 sekund efter din senaste ändring av skjutreglaget och returnera hela data som en sträng. String.toInt() börjar sedan läsa strängen från det första tecknet och konvertera dem till ett heltal tills det läser ett icke-siffrigt tecken (vilket betyder n, som du skickar). Det stannar där och returnerar det redan konverterade värdet.

Detta innebär att av alla data som skickades till Arduino kommer endast det första värdet att användas. Resten kastas bort.

Det är bättre att du använder en icke-blockerande kod som hanterar meddelandena (siffror i ditt fall) korrekt. Detta görs genom att läsa inkommande seriell data byte för byte, lägga till dem i en buffert tills ett specialavgränsningstecken mottas. Därefter bearbetas meddelandet som en helhet. Därefter kan nästa meddelande läsas och bearbetas. På så sätt missar du inte något av sändningsvärdena.

Det särskilda avgränsningstecknet är godtyckligt. Du kan använda vilket tecken som helst som inte förekommer i giltiga data. Så att använda tecknet n är ok här. Men oftast används den nya linjetecknet \n så att du också kan skicka meddelanden med alfanumeriska tecken. Troligtvis menade du redan att använda \n.

Som ett exempel på den här seriekoden kan du ta readline() funktion från Majenkos blogginlägg :

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 konvertera teckenbuffert till ett int med atoi() i if-uttalandet i void loop() och använd det för ´analogWrite () `.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *