Ik maak applicaties voor een computer die gebruikt worden om de robotarm te besturen. Ik wilde de eerste poging doen om de applicatie niet op de motor maar op de diode uit te voeren en te controleren of de helderheid verandert afhankelijk van de positie van de schuifregelaar. Ik heb een applicatie geschreven in Qt die strings naar Arduino stuurt, en Arduino las ik en converteert naar int. Het probleem is dat hoewel de schuifregelaar op 0 staat, de Arduino het niet laat zien, vaak komen de cijfers niet te vaak overeen (vaak te klein), ook als ik ineens de schuifregelaar met cijfers beweeg, tel naar voren in plaats van terug.
Arduino-code:
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-code:
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!"); } }
Opmerkingen
Antwoord
Zoals Majenko in zijn commentaar schreef, ligt uw probleem bij Serial.readString()
. Het is over het algemeen geen goede manier om met seriële gegevens om te gaan. Het leest gegevens van de seriële interface, totdat de time-out (standaard 1s) optreedt. Het zal dus proberen te lezen tot 1 seconde na uw laatste wijziging van de schuifregelaar en de volledige gegevens als één reeks retourneren. String.toInt()
begint dan met het lezen van de tekenreeks vanaf het eerste teken en converteert deze naar een geheel getal, totdat het een niet-cijferig teken leest (dit betekent de n
, die u verzendt). Het stopt daar en retourneert de reeds geconverteerde waarde.
Dit betekent dat van alle gegevens die naar de Arduino zijn gestuurd, alleen de eerste waarde wordt gebruikt. De rest wordt weggegooid.
Je kunt beter een niet-blokkerende code gebruiken, die de berichten (in jouw geval cijfers) correct verwerkt. Dit wordt gedaan door de inkomende seriële gegevens byte voor byte te lezen, ze aan een buffer toe te voegen, totdat een speciaal scheidingsteken wordt ontvangen. Dan wordt het bericht in zijn geheel verwerkt. Daarna kan het volgende bericht worden gelezen en verwerkt. Op deze manier mist u geen enkele verzendwaarde.
Het speciale scheidingsteken is willekeurig; u kunt elk teken gebruiken dat niet voorkomt in de geldige gegevens. Dus het gebruik van het teken n
is hier ok. Maar meestal wordt het newline-teken \n
gebruikt, zodat u ook berichten met alfanumerieke tekens kunt verzenden. Waarschijnlijk wilde u \n
al gebruiken.
Als voorbeeld van deze seriële code kunt u de readline()
functie uit Majenko “s blogpost :
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("<"); } }
U kunt de karakterbuffer converteren naar een int met atoi()
in het if statement in void loop()
en gebruik het voor ´analogWrite () `.
\n
toevoegen aan je uitgaande berichten, nietn
…Serial.println(br);
voor deanalogWrite()
om te zien wat er wordt ontvangen