Skocz do zawartości
Komentator

Kurs Qt – #2 – komunikacja z Arduino przez UART

Pomocna odpowiedź

Kurs Qt – #2 – komunikacja z Arduino przez UART

Pora na kolejny artykuł omawiający podstawy Qt. Tym razem zajmiemy się komunikacją przez port szeregowy. Dzięki temu połączymy komputer PC z Arduino (lub innym mikrokontrolerem). W ramach ćwiczeń stworzymy własny monitor portu szeregowego, który będzie mógł sterować pracą Arduino.

UWAGA, to tylko wstęp! Dalsza część artykułu dostępna jest na blogu.

Przeczytaj całość »

Poniżej znajdują się komentarze powiązane z tym wpisem.

Udostępnij ten post


Link to post
Share on other sites

Bardzo fajny poradnik 🙂

Znalazłem jednak jedną rzecz, mianowicie nie usuwasz nigdzie QSerialPort. Najprościej zamienić ten fragment kodu:

//this->device = new QSerialPort;
this->device = new QSerialPort(this); //Ustawiamy rodzica obiektu

Dzięki temu w momencie usunięcia obiektu klasy MainWindow zostanie usunięty obiekt device.

pozdrawiam i czekam na kolejne części 🙂

  • Lubię! 2

Udostępnij ten post


Link to post
Share on other sites

Bardzo przydatny poradnik :D

Czekam z niecierpliwością na kolejne części!

Super robota

Pozdrawiam :)

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Bardzo cenna uwaga (y). Dla czytelników, którzy bedą to czytać - zawsze zwalniajcie poprawnie pamięć w swoich programach niezależne od sytuacji - w tym przykładzie akurat taki memory leak to jeszcze nie jest nic złego. Tworzymy obiekt QSerialPort raz i żyje on sobie do momentu aż proces naszej aplikacji się zakończy, wtedy pamięć po naszym obiekcie powinien zwolnić system (powinien jeśli to obsługuje - dyskusja na stacku). Sprawa przybrałaby bardzo nieprzyjemny obrót gdybyśmy tworzyli nowe obiekty cyklicznie i nie zwalniali po nich pamięci, a nasz program miałby pracować przez długi czas. Więc szanujmy naszą pamięć. 

Jest tutaj jeszcze jeden wysublimowany problem: gdybyśmy otworzyli port i zamknęli aplikację (wcześniej tego portu nie zamykając) to nie wywoła się destruktor obiektu QSerialPort, który między innymi ten port zamyka gdy jest otwarty. Wtedy przy ponownym uruchomieniu aplikacji moglibyśmy się bardzo zirytować niemogąc otworzyć portu ponownie (kto miał taki problem ten wie).


Poprawka powinna się niedługo pojawić na stronie.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Skoro masz uwagi do czytelników, pozwól że ja będę miał uwagę do pisarzy. Alokowane zasoby należy zawsze zwalniać. Poleganie na systemie świadczy o słabej jakości programu i nawet jeśli nie doprowadzi do katastrofy, należałoby tego unikać.

Jak dla mnie wystarczyłoby napisać - w przykładzie pojawił się błąd, każdemu się zdarza i koniec.

Edit: Trochę przesadziłem ze złośliwością w pierwszej wersji, dokonałem autocenzury, przepraszam.

Edytowano przez Elvis

Udostępnij ten post


Link to post
Share on other sites
5 minut temu, Elvis napisał:

Alokowane zasoby należy zawsze zwalniać

To już jako offtopicowa ciekawostka - cytat z jakiekośtam podręcznika do PHP z początku tysiąclecia (niedokładny bo z pamięci):

"Nie należy wywoływać funkcji mysql_result_free, zasoby zostaną zwolnione automatycznie po wykonaniu skryptu."

Niestety - wśród starszych "programistów" tego "języka programowania" do dziś jest to chyba dogmatem 😞

 

Udostępnij ten post


Link to post
Share on other sites
17 godzin temu, erulission napisał:

Znalazłem jednak jedną rzecz, mianowicie nie usuwasz nigdzie QSerialPort. Najprościej zamienić ten fragment kodu:


//this->device = new QSerialPort;
this->device = new QSerialPort(this); //Ustawiamy rodzica obiektu

Dzięki temu w momencie usunięcia obiektu klasy MainWindow zostanie usunięty obiekt device.

Poprawka i opis do niej znajduje się już w artykule.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

W przypadku testowania programu z Arduino Due spotkałem się z dziwnym zjawiskiem:

Przesyłanie danych do Arduino odbywa się bez przeszkód, ale nie mogę odczytać informacji z płytki. Problem rozwiązuje się po wcześniejszym uruchomieniu Arduino IDE i włączeniu i wyłączeniu w nim monitora portu szeregowego.

Sprawdzałem program na Arduino Uno i wszystko działało bez problemu. (między programami w Arduino Uno i Due zmieniałem Serial -> SerialUSB oraz dodałem dla DUE funkcję SerialEvent, bo z tego co wiem to ta płytka takowej nie posiada).

Ktoś ma może jakiś pomysł z czego to może wynikać?

Udostępnij ten post


Link to post
Share on other sites

@klarec 

Sprawdziłem właśnie u siebie korzystając z Due - wgrałem identyczny soft jak w kursie - korzystam z Serial (Serial0) i nie mam żadnych problemów z komunikacją w obie strony. 

Czy Qt otworzyło Ci port bez problemu? Możesz wykorzystać sygnał QSerialPort::errorOccurred żeby zobaczyć błąd jeśli jakiś się pojawi:

//mainwindow.h:
private slots:
	//...
    void onErrorOccurred(QSerialPort::SerialPortError error);

// mianwindow.cpp:
MainWindow::MainWindow(QWidget *parent) :
    //...
{
    //...
    connect(device, SIGNAL(errorOccurred(QSerialPort::SerialPortError)), this, SLOT(onErrorOccurred(QSerialPort::SerialPortError)));
}

void MainWindow::onErrorOccurred(QSerialPort::SerialPortError error)
{
    qDebug() << error << device->error();
}

Może sprawa dotyczy dostępu do portu? Może np. IDE otworzyło port i go nie zamknęło, wtedy ponowne otwarcie i zamknięcie portu go odblokowało? Może problem wynika z tego, że korzystasz z SerialUSB - na Serial jest to samo?

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@klarec dla formalności dopytam - to oryginalne Arduino czy jakiś klon? 😉

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@Matthew11 Sprawdziłem czy występują błędy Twoją metodą, błędów nie ma: QSerialPort::NoError QSerialPort::NoError.

Spróbowałem też użyć Serial, ale wtedy nie działa komunikacja w żadną stronę, nie pokazuje też w monitorze portu szeregowego.

Kod, który użyłem na Arduino (podmienione na Serial):

const uint8_t ledPin = LED_BUILTIN;
uint32_t interval = 1000;
uint32_t previousMillis = 0;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
}

void loop() {
  uint32_t currentMillis = millis();
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    Serial.println("Czas procesora = " + String(currentMillis));
  }
  while (Serial.available()) {
    
    char state = (char)Serial.read();
    if(state == '0') {
      digitalWrite(ledPin, 0);
    } else if(state == '1') {
      digitalWrite(ledPin, 1);
    }

    Serial.println("Potwierdzam odbior. Status diody = " + String(state));
  
}
}

 

Myślę, że to też nie jest kwestia niezamknięcia portu przez Arduino IDE, testowałem program po wgraniu i resecie Arduino, na wszelki wypadek też przy wyłączonym IDE i nadal było to samo.

 

@Treker Moje Due to klon. Może faktycznie to decyduje o działaniu programu. ( klon na CH340)

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

@klarec W takim razie problemem może być CH340. Więc pozostaje Ci faktycznie opcja z natywnym Serialem - SerialUSB. 

Edytowano przez Matthew11
  • Lubię! 1
  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Napisz odpowiedź...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...