De la Strings la int problem

Creez aplicații pentru un computer care urmează să fie utilizat pentru a controla brațul robotului. Am vrut să fac prima încercare de a rula aplicația nu pe motor, ci pe diodă și să verific dacă își va schimba luminozitatea în funcție de poziția glisorului. Am scris o aplicație în Qt care trimite tanga la Arduino, iar Arduino am citit și convertește în int. Problema este că, deși glisorul este setat la 0, Arduino nu îl afișează, de multe ori cifrele nu sunt de acord prea des (adesea prea mici), de asemenea, atunci când mișc brusc glisorul numeric tot timpul contează spre față în loc de înapoi.

Cod Arduino:

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

Cod Qt:

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

introduceți descrierea imaginii aici

Comentarii

  • Serial.readString () este profund defect și ar trebui evitat. Citiți acest lucru: majenko.co.uk/blog/reading-serial-arduino
  • Și sunt sigur ați intenționat să adăugați \n la mesajele dvs. de ieșire, nu n
  • atunci când depanați o problemă precum a ta pune Serial.println(br); înainte de analogWrite() pentru a vedea ce se primește

Răspuns

După cum a scris Majenko în comentariul său, problema dvs. rezidă în Serial.readString(). În general, nu este o modalitate bună de a gestiona datele seriale. Citește date din interfața Serial, până când intervine timeout-ul (1s implicit). Deci, va încerca să citească până la 1 secundă după ultima modificare a glisorului și să returneze toate datele ca un singur șir. String.toInt() va începe apoi să citească șirul din primul caracter și să le convertească într-un număr întreg, până când citește un caracter fără cifre (adică n, pe care îl trimiteți). Se oprește acolo și returnează valoarea deja convertită.

Aceasta înseamnă că, din toate datele, care au fost trimise către Arduino, va fi utilizată doar prima valoare. Restul se aruncă.

Mai bine ar trebui să utilizați un cod care nu blochează, care gestionează corect mesajele (numerele în cazul dvs.). Acest lucru se face citind datele seriale de intrare octet cu octet, adăugându-le într-un buffer, până când se primește un caracter special delimitator. Apoi mesajul va fi procesat ca întreg. După aceea, următorul mesaj poate fi citit și procesat. Astfel nu pierdeți niciuna dintre valorile de trimitere.

Caracterul special delimitator este arbitrar; puteți utiliza orice caracter care nu apare în datele valide. Așadar, utilizarea caracterului n este ok aici. Dar, în cea mai mare parte, este folosit caracterul de linie nouă \n, astfel încât să puteți trimite și mesaje cu caractere alfanumerice. Cel mai probabil ați intenționat deja să utilizați \n.

Ca exemplu al acestui cod serial, puteți lua readline() funcție din postarea de pe Majenko :

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

Puteți converti bufferul de caractere la un int cu atoi() în instrucțiunea if din void loop() și folosiți-l pentru ´analogWrite () `.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *