Merkkijonosta int-ongelmaan

Luon sovelluksia tietokoneelle, jota käytetään robotin käsivarren hallintaan. Halusin ensimmäisen kerran suorittaa sovelluksen ei moottorilla, vaan diodilla ja tarkistaa, muuttaakö se kirkkautta liukusäätimen sijainnista riippuen. Kirjoitin Qt: ssä sovelluksen, joka lähettää hihnat Arduinolle, ja Arduino, jonka luin ja muunnetaan intiksi. Ongelmana on, että vaikka liukusäätimen arvoksi on asetettu 0, Arduino ei näytä sitä, usein luvut eivät sovi liian usein (usein liian pieniksi), myös kun liikutan yhtäkkiä numeroiden liukusäädintä koko ajan eteenpäin eikä takaisin.

Arduino-koodi:

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

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

kirjoita kuvan kuvaus tähän

kommentit

  • Serial.readString () on erittäin puutteellinen ja sitä tulisi välttää. Lue tämä: majenko.co.uk/blog/reading-serial-arduino
  • Ja olen varma halusit lisätä \n lähteviin viesteihisi, et n
  • virheenkorjauksessa esimerkiksi sinun on laitettava Serial.println(br); analogWrite() -koodin eteen nähdäksesi mitä vastaanotetaan

Vastaa

Kuten Majenko kirjoitti kommentissaan, ongelmasi on Serial.readString(). Se ei yleensä ole hyvä tapa käsitellä sarjatietoja. Se lukee tietoja sarjaliitännästä, kunnes aikakatkaisu (oletusarvo 1 s) tapahtuu. Joten se yrittää lukea 1 sekunnin ajan viimeisen liukusäätimen muutoksen jälkeen ja palauttaa koko tiedot yhtenä merkkijonona. String.toInt() alkaa sitten lukea merkkijonoa ensimmäisestä merkistä ja muuntaa ne kokonaislukuksi, kunnes se lukee ei-numeroisen merkin (eli n, jonka lähetät). Se pysähtyy tähän ja palauttaa jo muunnetun arvon.

Tämä tarkoittaa, että kaikista Arduinoon lähetetyistä tiedoista käytetään vain ensimmäistä arvoa. Loput heitetään pois.

Parempi on käyttää estämätöntä koodia, joka käsittelee viestit (tapauksessasi numerot) oikein. Tämä tehdään lukemalla saapuvat sarjatietatavut tavuina, lisäämällä ne puskuriin, kunnes erityinen erotinmerkki tulee vastaan. Sitten viesti käsitellään kokonaisuutena. Sen jälkeen seuraava viesti voidaan lukea ja käsitellä. Tällä tavoin et menetä mitään lähetysarvoja.

Erotinmerkin erikoismerkki on mielivaltainen; Voit käyttää mitä tahansa merkkiä, jota ei ole kelvollisissa tiedoissa. Joten merkin n käyttö on ok. Mutta enimmäkseen käytetään uuden rivin merkkiä \n, joten voit lähettää viestejä myös aakkosnumeerisilla merkeillä. Todennäköisesti olet jo tarkoittanut käyttää \n.

Esimerkkinä tästä sarjakoodista voit ottaa readline() funktio Majenkon blogikirjoituksesta :

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

Voit muuntaa merkkipuskurin intiin, jossa atoi() on if-lausekkeessa void loop(), ja käytä sitä ´analogWrite () `.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *