Skocz do zawartości

Kurs Qt – #2 – komunikacja z Arduino przez UART


Komentator

Pomocna odpowiedź

@dernis W takim razie musisz dokładnie prześledzić co wysyłasz z Qt, a co faktycznie odbierasz na STM - czyli sprawdzić zawartość Receivedatoi(&Received). Sprawdź też najpierw opcję z dwoma możliwościami w switch'u : 1) case 1: zapal(); 2) default: zgas(); skoro udaje się diodę zapalić to Qt przynajmniej raz wysłało "1".

Edytowano przez Matthew11
Link do komentarza
Share on other sites

Więc tak po wysłaniu 1 lub 0 za pierwszym razem wysteruje mi port następnie przestaje nadawać i tylko po ponownym podłączeniu urządzenia mogę cokolwiek zrobić tak jakby nie mogło zresetować tego co wystawiam na początku. Nic nie trafia do Received po tym tym pierwszym razie jak gdyby go blokowało.. Jeśli odpalę aplikacje Qt  Block Master Example wszystko jest ok.

Link do komentarza
Share on other sites

dla tych którzy mają problem z portem a mianowicie z zapisem:)

Nie jest to wina bug-a.

Musimy zaimplementować:

this->device->waitForBytesWritten();

wszystko wtedy działa.

Edytowano przez dernis
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

@Lukasz1996 Miałeś okazje sprawdzić na nowej wersji czy problem nadal występuje? 

@dernis Nadal to jest bardzo podejrzane. Wykorzystanie funkcji blokujących jak w tym przypadku waitForBytesWritten() nie jest najszczęśliwszym rozwiązaniem (nieco więcej info tutaj) jeśli obsługujemy jeszcze GUI w tym samym wątku. Generalnie jedna z możliwych metod write(x) powinna działać bez problemu - wysyłając zawartość, którą chcieliśmy wysłać:

Cytat

Before accessing the device, open() must be called to set the correct OpenMode (such as ReadOnly or ReadWrite). You can then write to the device with write() or putChar(), and read by calling either read(), readLine(), or readAll(). Call close() when you are done with the device.

Identycznie wygląda sprawa w przykładowym projekcie: https://doc.qt.io/qt-5/qtserialport-terminal-example.html, gdzie wywołane jest zwyczajnie write() w MainWindow::writeData().

Mogę się mylić, ale nadal wygląda to jak bug w Qt... Albo bardzo specyficzny przypadek.

Edytowano przez Matthew11
mała poprawka
  • Lubię! 2
Link do komentarza
Share on other sites

Panowie jednak coś jest na rzeczy...

Dostałem odpowiedz na Qt:

Nonono. If You use Windows && Qt 5.13.1/5.12.5 then it is a bug in QSP (just update Qt to latest version 5.13.2/5.12.6 or to use a previous version 5.13.0/5.12.4).

waitForBytesWritten()

Don't do that.

więc gdyby ktoś miał podobny problem to można użyć w/w funkcji na potwierdzenie błędu od strony naszej wersji Qt.

instaluje wszystko offline i myślę że rozwiąże to mój problem.

  • Lubię! 2
Link do komentarza
Share on other sites

A skromnie podpytam. Ogarnąłem sygnał clear() obiektu TextEdit zasugerowany przez autora artykułu i inne sygnały czyli kopiuj, wklej, usuń, cofnij ... takie pierdołki. Jednak jestem cienki jak nicień i jeszcze długo tak pozostanie więc nie ogarniam jak zmodyfikować ten program z przykładu by móc wysyłać tekst do Arduino, przysłowiowe "imię". Na razie podmieniłem tekst na przycisku służącym do kontroli led ale chciałbym wysyłać dowolne imię a nie tylko zdeklarowane programowo. A druga sprawa to jakaś funkcja "Save as" czyli jak zrobić by po naciśnięciu "buttona" zapisać całą zawartość okna Logs? Coś pokombinowałem, okienko zapisu się uruchamia ale po wybraniu folderu docelowego i nazwy pliku nic się nie zapisuje, ale prawda jest taka że zrobiłem to wzorując się na innym projekcie którego w zasadzie nie rozumiem, a chce w prosty sposób zapisywać dane z sesji pomiarowej czujników podłączonych do Arduino. Podpowiedzcie coś, może załapie, a jak nie to wracam do CoolTerm i nie porywam się na cos co mnie przerasta 🙂 Pozdrawiam 

Link do komentarza
Share on other sites

Cześć @Wrona 

26 minut temu, Wrona napisał:

Jednak jestem cienki jak nicień i jeszcze długo tak pozostanie więc nie ogarniam jak zmodyfikować ten program z przykładu by móc wysyłać tekst do Arduino, przysłowiowe "imię".

Metoda MainWindow::sendMessageToDevice(QString message) właśnie zapewnia, Ci taką funkcjonalność, mamy na sztywno w kodzie:

this->sendMessageToDevice("1");

a możesz zrobić w slocie pod dowolnym przyciskiem (generalnie możesz tam wysłać to co chcesz):

this->sendMessageToDevice("Mateusz");

wtedy powinieneś po drugiej stronie odebrać cały string.

26 minut temu, Wrona napisał:

A druga sprawa to jakaś funkcja "Save as" czyli jak zrobić by po naciśnięciu "buttona" zapisać całą zawartość okna Logs?

Okej, to można zrobić na wiele sposobów w zależności od celu jaki chcesz osiągnąć, chyba najprostszy moim zdaniem to zapisanie zawartości okna z logami do pliku. QTextEdit daje Ci dwie metody: toPlainText() i toHtml() obie zwracają QString'a. W twoim przypadku chyba odpowiedniejsza będzie toPlainText(),  wtedy używając klasy QFile, możesz takiego QStringa, wcześniej konwertując do QByteArray zapisać do pliku, przykład poniżej:

#include <QCoreApplication>
#include <QFile>
#include <QString>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QFile file("logs.txt"); // Uwaga! Plik będzie stworzony w katalogu, gdzie znajdują się pliki wynikowe programu (build dir)
    if(!file.open(QIODevice::WriteOnly))
    {
        qDebug() << "Could not open!";
    }
    else
    {
        const QString dataToWrite("Mateusz");
        file.write(dataToWrite.toUtf8());
        file.close();
    }

    return a.exec();
}

W twoim programie, musisz wydostać zawartość okna z logami i wykorzystać powyższe. Więcej info znajdziesz w dokumentacji.

Edytowano przez Matthew11
  • Lubię! 1
  • Pomogłeś! 1
Link do komentarza
Share on other sites

Dzięki za pomoc

1 godzinę temu, Matthew11 napisał:

 


this->sendMessageToDevice("Mateusz");

wtedy powinieneś po drugiej stronie odebrać cały string.

To mam właśnie w taki sam sposób ogarnięte czyli podmieniłem w kodzie z artykułu "1" na "Mateusz". Tylko mnie to nie urządza, bo zawsze wysyła się to samo. Przykładowo moje Arduino mierzy tętno. Na początek cały program czeka na informacje z portu i nic nie mierzy. Wysyłam imię "Mateusz"  i program w Arduino wie że ma zacząć pomiary i wysyłać je do monitora zatytułowane w pierwszym wierszu "Pomiary gościa o imieniu Mateusz". Jednak za chwilkę będę do pomiarów wykorzystywał inny obiekt badawczy czyli "Mikołaja". W monitorze portu załączonym do Arduino IDE, działa to doskonale, tylko jak dla mnie, to brakuje jednej kluczowej użyteczności czyli zapisywania do pliku. Właśnie ten niedostatek skłonił mnie to samodzielnej próby stworzenia czegoś takiego. Musze to zrobić tak że albo podaje dowolne imię w obecnym polu tekstowym dokładnie tak jak w Arduinowym monitorze portu  albo może podaje tekst do wysłania w nowym "okienku". Zabrałem się do tego ze świadomością że kompletnie błądzę po omacku i albo kwestie ogarnę albo przynajmniej przekonam się gdzie jest moja granica. W ambitnych planach myślałem o takim monitorze portu które ściąga dane tekstowe a równolegle tworzy wykres czyli taka równoległa kreślarka. Jednak na razie dostałem kubeł zimnego kodu na głowę i się opanowałem 🙂

 

Cytat

W twoim programie, musisz wydostać zawartość okna z logami i wykorzystać powyższe. Więcej info znajdziesz w dokumentacji.

Przestudiuje to sobie jutro ze świeżą głową. Parę drobnostek udało mi się dokumentacji wyciągnąć ale generalnie nie znając w zasadzie języka C++ patrzę na to jak na tekst po Japońsku. Jaką funkcją odwołać się do tekstu w logach a innymi słowy jak "wyciągać zawartość okna z logami".

Dzięki za już i dobrej nocy.

Link do komentarza
Share on other sites

Proponuję na początek porzucić marzycielstwo i zapoznać się choćby z podstawami języka do którego frameworka chcesz używać bo inaczej będziesz próbowała pisać chińską poezję po japońsku, którego, jak twierdzisz nie znasz.

Do obsługi plików w Qt służy klasa QFile. Wszystko jest pięknie opisane we wbudowanym manualu łącznie z przykładami użycia. 

Link do komentarza
Share on other sites

6 godzin temu, atMegaTona napisał:

Proponuję na początek porzucić marzycielstwo i zapoznać się choćby z podstawami języka

W zasadzie masz racje. Brak wolnego czasu związany z obowiązkami zupełnie z innej bajki powoduje że pozostaje że jestem skazany na naukę od tyłka strony czyli poprzez naśladownictwa. Najpierw powielam mały fragment prezentowanego w przykładzie kodu a dopiero potem go próbuje rozgryźć i zmienić do własnych potrzeb. Na inna drogę i systematyczność nie ma szans, takie życie. Ale dzięki bo faktycznie nie otworzyłem jeszcze samouczków Qt a tam pewnie jest wszystko łopatologicznie pokazane. Na razie :)

Link do komentarza
Share on other sites

1 godzinę temu, Matthew11 napisał:

Nie wiem jaką Ty preferujesz metodę uczenia, ale tutaj masz darmowy kurs od Johna Purcella do podstaw C++ 

Dzięki wielkie. Zderzyłem się ze ścianą i już wiem że musze zrobić większy rozpęd czyli cofnąć się kilka kroków. Mam nadzieje ze znajdę czas na systematyczne zrealizowanie kursu który mi poleciłeś. Jeszcze jest we mnie zapał.

To na razie tyle. Odezwę się jak będę trochę mądrzejszy ... albo głupszy ale po kursie :)

 

Link do komentarza
Share on other sites

Po intensywnym kursie, wiem że nic nie wiem czyli programistą to ja nie zostanę.

Jednak w kontrze do powyższego, program stworzyłem. Nie twierdze, że „napisałem” bo jednak najefektywniejszą metodą przy chronicznym braku czasu jest korzystanie z małego kawałka gotowego kodu i rozkminianie co się w nim dzieje i tworzenie własnej zmodyfikowanej wersji. Rozwiązałem tą metodą kilkanaście problemów i program w zasadzie jest gotowy i elegancko współpracuje z Arduino. Wpisuje w linii tekstowej np. lokalizacje „kuchnia” i naciskam przycisk „Wyślij” a w zamian otrzymuje serie wyników z czujników pod nazwą kuchnia. Wpiszę „łazienka” otrzymam serie wyników opisana jako łazienka. Mogę mierzyć kolejne lokalizacje lub obiekty i wszystkie wyniki są opatrzone stosowanymi etykietami. W oknie logów wszystko ładnie się wyświetla a gdy nacisnę przycisk „Zapisz jako” to (o dziwo) wszystko się zapisuje czyli najpierw otwiera się okienko dialogowe gdzie wpisuje nazwę pliku, program sam dodaje rozszerzenie .txt czyli mam co chciałem. Dzięki za pomoc.

Żeby nie było, że o Was chłopaki i dziewczyny zapomniałem, to pojawiam się z kolejnym pytaniem. W zależności od ustawień czujników  pomiary zbierają się przez minutę lub dwie i cały czas wyświetlają się w okienku logów. W tym czasie nie powinienem móc niczego wysyłać. Pewnie to zmęczenie materiału ale nie mam pomysłu jak to wykombinować w Qt aby zablokować przycisk „Wyślij” do czasu aż zakończy się odbieranie danych z portu szeregowego. Natomiast w zasadzie już 5 sekundowa przerwa w odbieraniu danych może być sygnałem że na powrót można wysyłać dane czyli odblokować "Wyślij". 

Link do komentarza
Share on other sites

3 minuty temu, Wrona napisał:

Żeby nie było, że o Was chłopaki i dziewczyny zapomniałem, to pojawiam się z kolejnym pytaniem. W zależności od ustawień czujników  pomiary zbierają się przez minutę lub dwie i cały czas wyświetlają się w okienku logów. W tym czasie nie powinienem móc niczego wysyłać. Pewnie to zmęczenie materiału ale nie mam pomysłu jak to wykombinować w Qt aby zablokować przycisk „Wyślij” do czasu aż zakończy się odbieranie danych z portu szeregowego. Natomiast w zasadzie już 5 sekundowa przerwa w odbieraniu danych może być sygnałem że na powrót można wysyłać dane czyli odblokować "Wyślij". 

Jak chcesz zablokować przycisk na jakiś określony czas to użyj klasy QTimer i stałego interwału, w dokumentacji, w opisie masz sposób użycia. Przycisk ma możliwość ustawienia opcji enabled. Czyli enabled = true - przycisk można klikać, enabled = false - przycisku nie możesz kliknąć (na interfejsie będzie szary). Sposób działania może być taki: przy kliknięciu wyślij blokujesz przycisk za pomocą setEnabled(false), uruchamiasz w tym samym czasie timer, gdy timer wyemituje sygnał triggered() to w slocie jego obsługi odblokowujesz przycisk przez setEnabled(true). 

Druga opcja to znowu zablokowanie przycisku w momencie jego kliknięcia i uruchomienie timera 5 sekundowego tak jak napisałeś (lub o innym odpowiednim interwale) i resetowanie go w slocie odbioru danych przez wywołanie metody start() - zresetuje to timer. Gdy dane będą odbierane to timer będzie resetowany i przycisk nadal będzie zablokowany, natomiast jak skończy się transmisja to po 5 sekundach timer wyemituje sygnał (bo już nic nie będzie go resetować), następnie w slocie jego obsługi możesz odblokować przycisk co umożliwi ponowne użycie przycisku.

  • Lubię! 1
  • Pomogłeś! 1
Link do komentarza
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!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   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...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.