Źle wysyłane dane przez RS232 - uC [Qt, OpenGL]

0

Witam,
mam problem z aplikacją. Krótko mówiąc porozumiewa się z mikrokontrolerem AVR.
Na uC zapalam diodę, jeśli przychodzi mi odpowiednia dana. Mam też inny program, który obsługę portu ma taką samą jak peirwszy i w nim dioda się pali ciągle (dane prawidłowo przesyłane).

Natomiast w tej pierwszej aplikacji, dioda miga, co oznacza, że dane są przesyłane raz dobrze a raz źle.

Czy jest możliwe, żeby w Qt była taka różnica jakości, jeśli w tym pierwszym programie (co działa źle) jest jeszcze obsługa obrazu w OpenGL? Czy może to powodować błędy? Fakt, chodzi wolniej, jednak czy to może być przyczyna?

Krótki opis kodu (bo nie będę wrzucał całego programu, za dużo miejsca):
funkcją connect() mam połączone sygnał, że dane oczekują do odebrania. Odbieram je w slot'cie (dane przesyła uC i mówi który bajt wysłać z tablicy).
W tej funkcji wywołuję funkcję wysyłającą odpowiedni bajt.

Tak jak już mówiłem, w identycznym programie pod względem wysyłania danych, jest ok. Tylko tutaj dane przychodzą raz dobre raz złe.

0

Przy wysyłaniu danych dodawaj do nich modulo wartości tych danych i po drugiej stronie sprawdzaj czy modulo z danej liczby daje odpowiedni hash, przy dużych liczbach jest bardzo małe prawdopodobieństwo błędu weryfikacji, no i w przypadku błędu prześlij ponownie dane.

0

Pokaż kod.

0

No dobra, postaram się to jakoś sensownie pokazać.

W klasie głównej odpalam Timer na 200 ms.
W slocie mam

 void MainWindow::UptadeFrameAndGUI()
{
/*
operacje na obrazie
*/
    tmrTimer->stop();
    // jezeli dziala uart, wysylamy dane
    if(isUART)
        WyslijDane();
    tmrTimer->start();
}

W funkcji WyslijDane():

    // sterowanie katami
    if(ui->tabSterowaniePlatforma->isActiveWindow())
    {
        SerialPort::RamkaDanych r;
        r.tab_serw[0] = 30;
        r.tab_serw[1] = 50;
        r.tab_serw[2] = 80;
        r.tab_serw[3] = 130;
        r.tab_serw[4] = 140;
        r.tab_serw[5] = 170;
        //r.ZapiszRamke(platforma->LiczSerwa(zadane_gamma, zadane_beta, zadane_alfa,
                                           //zadane_x_platformy, zadane_x_platformy, zadane_z_platformy));
        port->UstawAktualnaRamke(r);
    }

W klasie SerialPort w SLOCIE jeśli jest do odebrania dana:

void SerialPort::OdebranoDane()
{
    this->read(&odebrana_dana, 1);

    // zebyzapobiec zmianie danej zapisanej w pamieci podczs przesuwania suwaka
    // moze wtedy bajt starszy o mlodszy byc inny
    // narazie jest tylko bajt mlodszy, czyli dana 0 ... 180
    if(odebrana_dana == 'a') // bajt mlodszy
    {
        for(int i = 0; i < 6; i++)
        {
            tab_do_wyslania[i] = akt_ramka.tab_serw[i];
        }
    }
    WyslijDane();
}

I sama funkcja wysyłająca

     switch(odebrana_dana)
    {
    case 'a':
        dana_do = tab_do_wyslania[0];
        break;
    case 'b':
        dana_do = tab_do_wyslania[1];
        break;
    case 'c':
        dana_do = tab_do_wyslania[2];
        break;
    case 'd':
        dana_do = tab_do_wyslania[3];
        break;
    case 'e':
        dana_do = tab_do_wyslania[4];
        break;
    case 'f':
        dana_do = tab_do_wyslania[5];
        break;
    case 's':
        break;
    }

    // w obecnej wersji jesty tylko wysylany mlodszy, bo jest 0..180
    // mlodszy bajt
    if(odebrana_dana >= 'a' && odebrana_dana <= 'f')
    {
        bajt_mlodszy = dana_do & 0x000000FF;
        this->write(&bajt_mlodszy);
    }

Nazwami bajt_mlodszy proszę sięnie sugerować, bo przedem robiłem wysyłanie int'ow, ale zrezygnowałem z tego, więc teraz są same char'y.

I jak już pisałem, identyczny kod, w programie bez OpenGL działa.

0

Chodziło mi o kod na AVR. Pytanie: czy na pewno dioda pali się bo dane są zawsze ok czy po prostu przychodzą one tak gęsto?

0

Dane są tam na pewno dobre, bo potem to przetwarzam na impulsy dla serwomechanizmów. I jak dioda świeci (dane dobre), serwo ładnie trzyma poziom), natomiast w drugim przypadku kręci się raz w jedną raz w drugą stronę.

W ogóle udało mi się naprawić program :D
Tylko teraz pytanie czy to przypadek, czy nie.
Otóż zmienną "dana_do" (na której potem dokonywąłem opracji bitowych, zmieniłem z char na int, jak było w dobrym programie (musiałem to przeoczyć).
I niby jest już ok, ale czasem mam wrażenie z Qt, że rzeczy tam się dzieją przypadkowo :/

kod AVR:

ISR(TIMER2_OVF_vect)
{
	TCNT2 = 150;
	if(odebrano_dane)
	{
		odebrano_dane = 0;
		UDR = tab_indexow_serw[numer_serwa_odebranego];
	}
} 
 ISR(USART_RXC_vect)
{
	//przerwanie generowane po odebraniu bajtu

	rec_data = UDR;   //zapamiętaj odebraną liczbę

	tiki_dla_serw[numer_serwa_odebranego] = tiki_dla_katow[(unsigned char)rec_data];
	if(++numer_serwa_odebranego == 6)
		numer_serwa_odebranego = 0;

	if(tiki_dla_serw[3] == tiki_dla_katow[130])
		LED_2_ON;
	else
		LED_2_OFF;

	odebrano_dane = 1;
}

Pierwszy kod to przerwanie od Timera, on wysyła żądanie do komputera w postaci literek a-f, które bajty ma wysłać.
Drugi to przerwanie od przyjścia bajtu do UART. Widać w nim warunek z diodą. W programie na komputerze, właśnie w indeksie 3 tablicy tiki, zapisałem 130. W tu się okazuje w uC, że raz jest ta wartość a raz nie ma.

0

Jeżeli to ten write http://doc.qt.io/qt-5/qiodevice.html#write to generalnie cosik poknociłeś, ale zmiana w kodzie może nieco tłumaczyć.

EDIT: a jakbyś to wysłał tak this->write(std::addressof(bajt_mlodszy), sizeof(bajt_mlodszy)) ?

No i sprawdzaj co ten write zwrócił...

0
alagner napisał(a):

EDIT: a jakbyś to wysłał tak this->write(std::addressof(bajt_mlodszy), sizeof(bajt_mlodszy)) ?

Z tego co przeczytałem to std::adressof jest to w nowszym standardzie C++ i miałem błędy przy użyciu tego.

W każdym razie, program po wprowadzonej tamtej zmiany śmiga jak na razie:)

Dziękuję bardzo za poświęcony czas!

1 użytkowników online, w tym zalogowanych: 0, gości: 1