Tworzę aplikacje na komputer, który ma być używany do sterowania ramieniem robota. Chciałem podjąć pierwszą próbę uruchomienia aplikacji nie na silniku, a na diodzie i sprawdzić, czy zmieni ona swoją jasność w zależności od położenia suwaka. Napisałem aplikację w Qt, która wysyła stringi do Arduino, a Arduino czytam i konwertuje na int. Problem w tym, że chociaż suwak jest ustawiony na 0, Arduino go nie pokazuje, często liczby nie zgadzają się zbyt często (często za małe), również gdy nagle przesuwam suwak liczby cały czas licząc do przodu zamiast wstecz.
Kod 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()); } }
Kod 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!"); } }
Komentarze
Odpowiedź
Jak napisał Majenko w swoim komentarzu, twój problem dotyczy Serial.readString()
. Zwykle nie jest to dobry sposób obsługi danych szeregowych. Odczytuje dane z interfejsu szeregowego, aż do upływu limitu czasu (domyślnie 1 s). Więc spróbuje odczytać do 1 sekundy po ostatniej zmianie suwaka i zwróci całe dane jako jeden ciąg. String.toInt()
zacznie odczytywać ciąg od pierwszego znaku i konwertować je na liczbę całkowitą, aż odczyta znak niebędący cyfrą (czyli n
, które wysyłasz). Zatrzymuje się w tym miejscu i zwraca już przekonwertowaną wartość.
Oznacza to, że ze wszystkich danych, które zostały wysłane do Arduino, zostanie użyta tylko pierwsza wartość. Reszta zostaje wyrzucona.
Lepiej użyj kodu nieblokującego, który poprawnie obsługuje wiadomości (w twoim przypadku liczby). Odbywa się to poprzez odczytywanie przychodzących danych szeregowych bajt po bajcie, dodając je do bufora, aż do otrzymania specjalnego separatora. Następnie wiadomość jest przetwarzana w całości. Następnie można odczytać i przetworzyć następną wiadomość. W ten sposób nie przegapisz żadnej z wysyłanych wartości.
Specjalny znak separatora jest dowolny; możesz użyć dowolnego znaku, który nie występuje w prawidłowych danych. Zatem użycie znaku n
jest tutaj w porządku. Ale głównie używany jest znak nowego wiersza \n
, dzięki czemu można również wysyłać wiadomości zawierające znaki alfanumeryczne. Najprawdopodobniej miałeś już zamiar użyć \n
.
Jako przykład tego kodu seryjnego możesz wziąć readline()
funkcja z posta na blogu 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("<"); } }
Możesz przekonwertować bufor znaków do int z atoi()
w instrukcji if w void loop()
i użyj go jako ´analogWrite () `.
\n
do swoich wiadomości wychodzących, a nien
…Serial.println(br);
przedanalogWrite()
, aby zobaczyć, co jest odbierane.