Skocz do zawartości

Kurs Qt – #2 – komunikacja z Arduino przez UART


Komentator

Pomocna odpowiedź

26 minut temu, Matthew11 napisał:

@Filip4444 Strzelałbym, że problem leży prawdopodobnie w tym, że port pod którym masz Arduino jest już otwarty, albo system otworzył i nie zamknął go poprawie, gdy używałeś go np. do wgrania programu. Natomiast... analizując Twój zrzut ekranu widać tam, że system znalazł dwa urządzenia, a Ty nie wybrałeś portu COM3 gdzie faktycznie jest Arduino, tylko wybrałeś COM1.

Tak, na zrzucie jest wybrany com1, ale gdy chce się podłączyć do arduino wyskakuje taki sam błąd. Przepiszę program i zobaczę czy po porostu nie mam jakiejś literówki.

Link do komentarza
Share on other sites

Cześć @kulfi27 Na drugiej stronie komentarzy w tym wątku, kilka osób sygnalizowało podobne/same problemy jak Ty opisujesz. Sprawdź proszę tamte sugestie - niektórzy wskazywali na błędy w biblioteki QSerialPort na niektórych wersjach. Jest też przykład Terminal Example - https://doc.qt.io/qt-5/qtserialport-terminal-example.html uruchom go u siebie i sprawdź czy to działa poprawnie - od razu mówię, że nigdy z niego nie korzystałem ale jest to dobre źródło do weryfikacji co nie działa. Sprawdź też swoją wersję Qt i poszukaj czy anglojęzyczni koledzy nie mają podobnego problemu co Ty - polecam w tym celu przeszukać forum Qt https://forum.qt.io/

Daj znać po testach czy coś się udało.

Link do komentarza
Share on other sites

Wiem, że trochę nie na temat ale jak zrobić aby móc wywoływać skrypty pythona z wnętrza slotów pisząc na widgetach? @Matthew11 masz jakąś metodę do tego? Próbowałem stosować api pythona dla c++ ale wykorzystanie całego gotowego skryptu było by chyba łatwiejsze. Jedyny problem to przekazywanie danych pomiędzy modułem pythona i Qt inaczej jak za pośrednictwem plików tymczasowych. Dzięki temu oprócz uarta można by było wykorzystać inne sterowniki z pythona. Pozdrawiam

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

Witam ponownie, odpaliłem terminal z przykładów w Qt i działa mogę odbierać dane. wersja Qt jaką posiadam to 5.14 więc teraz pytanie co jest nie tak? Mam jeszcze takie pytanie z racji iż nigdy nie programowałem na PC tylko uC czy mógł byś trochę nakreślić jak działa taki program  nie chodzi mi o wykonywanie zdarzeń po kliknięci przycisku bo to zostało opisane w kursie a o strukturę takiego programu czy również tutaj występuje coś w rodzaju głównej funkcji jak się to ma w uC.

Link do komentarza
Share on other sites

1 godzinę temu, kulfi27 napisał:

Witam ponownie, odpaliłem terminal z przykładów w Qt i działa mogę odbierać dane. wersja Qt jaką posiadam to 5.14 więc teraz pytanie co jest nie tak?

Wygląda na to, że problem leży w kodzie, który używasz. Stosujesz swój własny, czy ten dołączony do kursu? Jeśli nie działa Twój własny, no to musisz porównać Twoją implementację z implementacją z przykładu. Natomiast jeśli ten załączony do kursu nie działa, a oficjalny przykład Qt już tak, to w takim prosiłbym Cię o porównanie obu programów i poszukanie różnic ostatecznie możesz podesłać mi w wiadomości prywatnej źródła obu tych wersji - mógłbym to zrobić u siebie, ale mam inną wersję Qt, stąd przykład w mojej wersji może być zmieniony. 

1 godzinę temu, kulfi27 napisał:

Mam jeszcze takie pytanie z racji iż nigdy nie programowałem na PC tylko uC czy mógł byś trochę nakreślić jak działa taki program  nie chodzi mi o wykonywanie zdarzeń po kliknięci przycisku bo to zostało opisane w kursie a o strukturę takiego programu czy również tutaj występuje coś w rodzaju głównej funkcji jak się to ma w uC.

Zakładam że na uC piszesz w C lub C++. Każdy program napisany w C lub C++ niezależne czy jest pisany na uC czy PC będzie miał funkcję main() - czy przez nią rozumiesz "funkcję główną"? My programujemy w Qt w C++, więc też mamy taką funkcję - i mamy ją zawsze w projekcie w pliku o nazwie main.cpp. Dla czystego projektu QtWidgets ma ona taką formę:

#include <QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

Jeśli miałbyś to porównać do main() z projektu dla systemu wbudowanego to pierwsze trzy linie w main() to taka konfiguracja układu, a ostatnia return a.exec() to uruchomienie pętli zdarzeń - dzięki której działają między innymi sygnały i sloty - porównując to do programu uC jest to odpowiednik nieskończonej pętli, w której realizowana jest logika układu. @kulfi27 czy te odpowiedzi Cię satysfakcjonują?

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

Hej, udało mi się po części rozwiązać problem, na początek odpaliłem Qt z opcją Debug postawiłem kilka breakpoint  i zauważyłem że program nie wchodził do funkcji readFromPort, porównałem kod z przykładu Terminal i w miejscu konfiguracji portu podmieniłem tą linijkę kodu

            connect(this->device, &QSerialPort::readyRead, this, &MainWindow::readFromPort);

Po tym zabiegu już program zatrzymywał się w funkcji redFromPort z tym że nie wchodził do funkcji while więc dla testu ja wywaliłem i działa😀

Miałbym do Ciebie jeszcze pytanie czy możesz mi wyjaśnić jak się to odbywa że raz wywołana metoda connect będzie ciągle sprawdzała czy nie nadleciały jakieś dane do odczytu skoro jest wywoływana w funkcji on_pushButtonConect_clicked().

Dziękuje Ci za wszystkie wyjaśnienia i poświęcony czas.

Pozdrawiam

Link do komentarza
Share on other sites

@kulfi27 connect łączy sygnał ze slotem. Jest to realizowane na poziomie meta systemu Qt (w skrócie Qt generuje kod C++, który pozwala na działanie mechanizmu signals & slots). W dużym uproszczeniu connect to rejestracja callbacku znanego z czystego C/C++. Za każdym razem gdy wywołany zostanie sygnał (np. SerialPort::readyRead) wywoływane są wszystkie połączone sloty. Do jednego sygnału może być podłączonych wiele slotów. Połączenie trwa dopóki nie wywołasz funkcji QObject::disconnect

Link do komentarza
Share on other sites

@kulfi27 
Okej w takim razie, jeśli problemem było użycie metody QObject::connect() z Qt4, która używa makr SIGNAL i SLOT:

connect(this->device, SIGNAL(readyRead()), this, SLOT(readFromPort()));

na connect z Qt5,

connect(this->device, &QSerialPort::readyRead, this, &MainWindow::readFromPort);

To sugeruje, że Qt nie mogło rozwiązać tego połączenia w czasie wykonywania programu. connect() z Qt4 jest rozwiązywany w czasie programu, natomiast connect() z Qt5 w czasie kompilacji. Ciężko powiedzieć dlaczego nie działa starsza wersja, ale to tylko znak, że należy używać tej z Qt5. Niestety wtedy kiedy pisałem kurs używałem connect() z Qt4 😞 
@kulfi27 Z ciekawości czy przy connect() z Qt4 po uruchomieniu programu w konsoli nie były drukowane jakieś ostrzeżenia? Jak się connect() z Qt4 nie powiedzie to jest drukowana informacja.

33 minuty temu, kulfi27 napisał:

nie wchodził do funkcji while więc dla testu ja wywaliłem i działa

Program do tego while'a wchodzi wtedy kiedy odczytany ciąg znaków zawiera znak końca linii, z przykładu z dokumentacji np: taką może mieć implementację metoda canReadLine():

bool CustomDevice::canReadLine() const
{
    return buffer.contains('\n') || QIODevice::canReadLine();
}

Czy dane, które wysyłałeś z uC zawierały znak końca linii? 😛 Jeśli nie to masz odpowiedź dlaczego nie wchodziło do while'a.

33 minuty temu, kulfi27 napisał:

Miałbym do Ciebie jeszcze pytanie czy możesz mi wyjaśnić jak się to odbywa że raz wywołana metoda connect będzie ciągle sprawdzała czy nie nadleciały jakieś dane do odczytu skoro jest wywoływana w funkcji on_pushButtonConect_clicked().

Za to odpowiada mechanizm Sygnałów i Slotów Qt. To nie connect() sprawdza czy w buforze odbiorczym są jakieś dane, connect() się wykonuje i zwraca sterowanie od razu - więc jak by mógł to robić? To co robi connect() to rejestruje dane połączenie w mechanizmie sygnałów i slotów. Wtedy w tej pętli zdarzeń:

int main(int argc, char *argv[])
{
    //...
    return a.exec(); // <- która startuje tutaj
}

Jeśli device wyemituje sygnał readyRead() to mechanizm sygnałów i slotów (nie connect()) wywoła w efekcie metodę readFromPort() klasy MainWindow@erulission akurat mnie ubiegł 😛 A jak to działa dokładnie, możesz sprawdzić tutaj

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

Dziękuje wam za odpowiedzi właśnie to chciałem wiedzieć żeby zrozumieć ten mechanizm działania 😁

Nie będę ukrywał to moje kompletne początki więc trochę zabawy i nauki przede mną tym bardziej że uC to tylko w C więc poznanie C++ jak Qt zapewne trochę mi zajmie a że samego C++ jakoś nie miałem potrzeby się uczyć to teraz mam trochę motywacji do tego.

@Matthew11 przyznam szczerze że zapomniałem o końcu lini masz racje dlatego to nie zadziałało.

Jeszcze raz dzięki za pomoc😉

Link do komentarza
Share on other sites

Cześć, znam podstawy C++, więc chciałem zacząć korzystanie z Qt i trafiłem na ten kurs. Mam oryginalną płytkę Arduino Uno.  Próbowałem różnych podanych sposobów, ale ciągle nie mogę otworzyć portu.

W Arduino IDE wszystko działa jak należy ale w Qt nie otwiera portu.

void MainWindow::on_pushButtonConnect_clicked()
{
    static int i;
    if (ui->comboBoxDevices->count() == 0) {
        this->addToLogs("Nie wykryto urządzeń");
        return;
    }

    qDebug() << ++i << " proba polaczenia.";
    QString portName = ui->comboBoxDevices->currentText().split("\t").first();
    this->device->setPortName(portName);

    qDebug() << "Nazwa portu: " << device->portName()
             << "Czy otwarty: " << device->isOpen();

    if (!device->isOpen()) {
        this->addToLogs("test1");
        //OTWORZ I SKONFIGURUJ PORT

        if (this->device->open(QSerialPort::ReadWrite) ) {  // <-- nie otwiera i zwraca błąd
            this->addToLogs("test2");
            this->device->setBaudRate(QSerialPort::Baud9600);
            this->device->setDataBits(QSerialPort::Data8);
            this->device->setParity(QSerialPort::NoParity);
            this->device->setStopBits(QSerialPort::OneStop);
            this->device->setFlowControl(QSerialPort::NoFlowControl);

            this->addToLogs( "otwarto port szeregowy");

            connect(this->device, SIGNAL(readyRead()), this, SLOT(readFromPort()));
        }
        else this->addToLogs("Port nie zostal otwarty");
    }
    else
        this->addToLogs("Port juz otwarty!");
   qDebug() << "test3";

}

Szukaj > Połącz > Rozłącz > Włącz diodę:

okno.thumb.PNG.6e53059eef089fd77988bd92873c7bb4.PNG

Wyjście:

Wyjscie.thumb.PNG.38dad4e76100e6fca10174168e927658.PNG

Link do komentarza
Share on other sites

Witajcie,

Mam nieco powiedzmy błahy problem z C++ i zastosowaniem funkcji QiODevice::Write(). Mianowicie dane (wartości liczbowe 0-255), które chcę wysłać do Xmega są pod zmienną typu unsigned char, a funkcja przyjmuje const char * lub QByteArray.  Korzystam z napisanego przez siebie protokołu (bazującego na DBus, xmodem). Problem pojawia się w drugą stronę - kiedy odbieram dane char i potrzebuję przekonwertować na unsigned char.

Próbowałem na różne sposoby (reinterpret_cast<const char*>, QByteArray::setNum(zmienna, 10)), ale żadna z tych metod nie pozwoliła mi osiągnąć tego co chcę - czyli wysyłam z uC np 0x10 0x15.., a po stronie PC otrzymuję również 0x10 0x15...  

Kodu nie zamieszczam, ponieważ nie ma nic nadzwyczajnego, różniącego się od tego co w artykule. Korzystam z QIODevice::write(const char *) oraz z QIODevice::read(cons char*).

Czy jest ktoś w stanie mi wyjaśnić jak powinienem to zrobić ? Prawdopodobnie problem jest błahy i wynika z mojej niepełnej wiedzy C++.

 

Edit: Dodam tylko, że po stronie uC raczej nie ma problemu, ponieważ gdy wysyłam dane na zwykły terminal (np RealTerm) dane są przesyłane prawidłowo.

Edytowano przez Dejwuch
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.