Programowanie portu COM - GPS

  • 15 Odpowiedzi
  • 21840 Wyświetleń

0 użytkowników i 1 Gość przegląda ten wątek.

*

Offline PiKNew

  • ***
  • 437
  • Płeć: Mężczyzna
  • Sprzęt: iPaq h5550, Loox n560
Programowanie portu COM - GPS
« dnia: Październik 24, 2007, 11:24:21 »
W czasie implementowania odczytu sekwencji NMEA (by zapewnić obsługę GPS w MobileGadu) napotkałem dosyc powazny problem.

1. Otworam port "CreateFile"
2. Sekwencyjny odczyt - "ReadFile"
3. Zamkniecie portu "CloseHandle"

Funckja "ReadFile" w pewnych sytuacjach staje się całkowicie blokująca tj. załóżmy, ze w czasie odczytu GPS uruchomimy drugi program korzystający z tej usługi (u mnie jest to np. GPSLocator w n560). Program ten bezproblemowo czyta z GPS, jednak "mój" wątek zostaje całkowicie zablokowany na ReadFile (2). Jak zapobiec takiej sytuacji?

Tzn. rozpatruję 2 rozwiązania
- port w pełni dzielony (wg mnie to powinien zapenić OS "GPS Intermediate Driver", jesli nie zapewni, to przecież zawłaszczenie "exclusive" następuje przy CreateFile, druga aplikacja nie powinna otrzymac dostępu)

- ustawienie timeout - jak? Probowałem następująco:

COMMTIMEOUTS cto = {0};
cto.ReadIntervalTimeout = 0;
cto.ReadTotalTimeoutMultiplier = 0;
cto.ReadTotalTimeoutConstant = 5000;
cto.WriteTotalTimeoutMultiplier = 0;
cto.WriteTotalTimeoutConstant = 0;

Bez efektu, tzn. blokowanie trwa, mimo upływu np. 5 sek.

Bardzo proszę o sugestie... Blokowanie na ReadFile powoduje, iż:
- w pełni nie moge kontrolowac synchronizacji wątków i np. sygnalizacja mojemu wątkowi GPS, by ma np. zakończyć działanie nie przynosi skutku, wątek sygnalizujący czeka po zasygnalizowaniu na efekt w postaci zakonczenia watku roboczego. No i mamy klasyczny deadlock.
- mimo zatrzymania na ReadFile - port chyba juz nie działa, nawet po zamknieciu drugiej aplikacji, gps jest już wyłączony...

Jeśli ktoś byłby skłonny pomóć, jestem gotów przesłać kod źródłowy wątku roboczego "gps".

*

Offline PiKNew

  • ***
  • 437
  • Płeć: Mężczyzna
  • Sprzęt: iPaq h5550, Loox n560
Odp: Programowanie portu COM - GPS
« Odpowiedź #1 dnia: Październik 25, 2007, 10:14:35 »
Dodatkowo zauważyłem ciekawe zjawisko, "ReadFile" przestaje blokować, gdy uruchomię "inny program gps" ponownie, jakby GPS był uruchamiany??? Dziwne, gdyż MSDN mówi, iż każda referencja do sterownika jest liczona, niezależnie, czy odczyt jest za pomoca nowego API, czy standardowego "CreateFile". Ale tu wygląda, jakby uruchomienie drugiego programu i zamknięcie odcinało MG od (wyłączało) GPS... Ponowne uruchomienie włącza GPS, wygląda, iż MG także na tym "korzysta".

Prosiłbym chętne osoby do wykonania testu, potrzebowałbym 3 wariantów sprzętowych.

1. WM2003, GPS zewnętrzny np. na BT
2. WM5/6, GPS zewnętrzny np. na BT (czyli skonfigurowany poprzez GPS Intermediate Driver)
3. WM5/6, n560 BEZ wgranego QuickGPS

Osoby chętne, jeśli się takie znajdą ;) proszę o kontakt na gg

Odp: Programowanie portu COM - GPS
« Odpowiedź #2 dnia: Listopad 16, 2010, 00:55:06 »
Hmmm przeszukałem forum i ze swoim pytaniem wczepiam się w ten wątek.
Nie mam odpowiedzi na pytanie autora, ale zająłem się kwestią zbliżoną.

Mam zrobione czytanie NMEA z COM i działa mi to od dawna na wszystkich odmianach PC, PPC, WM itp.
Dla WM6 nie było problemu z HTC HD Mini, stary kod ruszył.
Natomiast w przypadku Omni 2 - znaki z ReadFile wpadają jak z telegrafu, z 8 czy 10 na sekundę.
Po pewnym czasie wwn. bufory się przepełniają i dostaję sieczkę.
Próbowałem wszelkich kombinacji w COMMTIMEOUTS  i COMMCONFIG... i nic.
Także wszystkie znane mi sposoby czytania COMa, tj używanie eventów, cbInQue, bruteforce itp itd... i nic.
Ciągle ten sam objaw, znaki z RS lecą jak woły.

Początkowo podejrzewałem, że Omnia jest padnięta - ale AM radzi sobie na tym samym COM 4800bps bez problemu, więc to nie Omnia.

?
« Ostatnia zmiana: Listopad 16, 2010, 00:57:21 wysłana przez marek_b »

*

Offline joker77

  • *
  • 51
  • Płeć: Mężczyzna
  • Sprzęt: Samsung I600, Toshiba G910, htc magic
Odp: Programowanie portu COM - GPS
« Odpowiedź #3 dnia: Listopad 17, 2010, 21:31:50 »
A musisz otwierać port COM ?

Ja do tego użyłem standardowej funkcji odczytu pozycji gps, działa jako callback i jest bardzo prosty w stosowaniu.

*

Offline PiKNew

  • ***
  • 437
  • Płeć: Mężczyzna
  • Sprzęt: iPaq h5550, Loox n560
Odp: Programowanie portu COM - GPS
« Odpowiedź #4 dnia: Listopad 24, 2010, 08:17:05 »
Zależy na jaką platformę programuje :). To, o czym piszesz jest na WM5 wzwyż.

Ja mimo wszystko MG (teraz 3.x) piszę na WM2003 (chociaż pewnie już nikt tego nie ma).


Co do swojego problemu to rozwiązałem go następująco:

1. Z wątku roboczego "A" startuję dodatkowy wątek "B". W parametrach przekazuję uchwyt com, uchwyt zdarzenia "start czytania", uchwyt zdarzenia "koniec czytania", uchwyt zdarzenia "koniec watki".

2. W wątku "B" - czekam na zdarzenia "start czytania" i "zakończ watki", po nim czekam 5 sekund (parametr) na zdarzenie "koniec czytania". Jeśli "koniec czytania" zostanie zasygnalizowany - ok, jeśli nie (czyli mam WAIT_TIMEOUT) - odpalam "CloseHandle(com)". Wszystko w pętli.

3. W wątku "A" przed "ReadFile" sygnalizuję "start czytania", po zakończeniu "koniec czytania". Okazuje się, ze ew. zablokowanie na ReadFile, trwające więcej niż 5 sekund spowoduje, iż watek "B" zamknie port. I wtedy... ReadyFile się odblokowuje (oczywiście z błędem, ale to jest nieistotne).



*

Offline miba

  • *****
  • 4050
  • Płeć: Mężczyzna
  • Sprzęt: Toshiba G900, doszedł x51v
Odp: Programowanie portu COM - GPS
« Odpowiedź #5 dnia: Listopad 25, 2010, 08:34:19 »
Trochę to pokombinowane. Ale mam pytanie - bo masz zasadniczo dwie opcje: a) otworzyć bezpośredni port sprzętowy (chyba multipekser tylko musi być nieaktywny tzn nic z niego nie korzysta ), b) podłączyć się do emulowanego portu com mutipleksera. Testowałeś oba warianty czy tylko jeden na występowanie problemu?

*

Offline PiKNew

  • ***
  • 437
  • Płeć: Mężczyzna
  • Sprzęt: iPaq h5550, Loox n560
Odp: Programowanie portu COM - GPS
« Odpowiedź #6 dnia: Listopad 25, 2010, 13:53:00 »
Te opcje opisałem w pierwszym mailu. Jak nie dam FILE_SHARE_READ (tylko 0) to createfile otworzy port w trybie exclusive (i tak w gruncie rzeczy powinno się otwierać port sprzętowy). Jak nie otworzy to znaczy, że inny proces już sobie port zawłaszczył i z niego czyta.

Mój problem z blokowaniem dotyczył multiplexera (i de facto nawet w MG2.x masz opcję "wykryj port automatycznie"). Ten problem zgłaszałem do MS, coś tam namierzyli, ale najprawdopodobniej nic nie poprawiali (bo już WM6 miał zdobywać rynek).


Połączone: [time]Listopad 25, 2010, 13:56:40[/time]
Początkowo podejrzewałem, że Omnia jest padnięta - ale AM radzi sobie na tym samym COM 4800bps bez problemu, więc to nie Omnia.

A spróbuj uruchomić MG z opcją "GPS", w ustawieniach ustaw konkretnie ten port + logowanie do pliku. Następnie sprawdź co w tym pliku się zapisało...
« Ostatnia zmiana: Listopad 25, 2010, 13:58:20 wysłana przez PiKNew »

*

Offline miba

  • *****
  • 4050
  • Płeć: Mężczyzna
  • Sprzęt: Toshiba G900, doszedł x51v
Odp: Programowanie portu COM - GPS
« Odpowiedź #7 dnia: Listopad 25, 2010, 15:51:14 »
PiKNew: sorry odebrałem Twój ostatni post jako post marka_b. Coś mi mózg szwankuje.  :-| Ale na dobre wyszło, bo pytanie i Twoim przypadku ma sens. Mam pytanie czy próbowałeś po otwarciu uchwytu robić coś takiego:

SetCommMask (h, EV_RXCHAR |EV_RXFLAG| EV_ERR );
WaitCommEvent (h, &dwPortStat, 0);

wywołania ReadFile

?
Mi się port na multiplekserze nie blokował jak AM odpalałem dodatkowo.
Na emu szło i kod był testowany przez parę osób jako część programiku - nikt nie zgłaszał problemów tego typu.

A z multiplekserem to MS ma problem, bo w PB każdy OEM może sobie zmodyfikować jego kod i dla niektórych urządzeń ( np: z wbudowanym gps) go modyfikują.

*

Offline PiKNew

  • ***
  • 437
  • Płeć: Mężczyzna
  • Sprzęt: iPaq h5550, Loox n560
Odp: Programowanie portu COM - GPS
« Odpowiedź #8 dnia: Listopad 26, 2010, 03:47:34 »
Mam pytanie czy próbowałeś po otwarciu uchwytu robić coś takiego:

SetCommMask (h, EV_RXCHAR |EV_RXFLAG| EV_ERR );
WaitCommEvent (h, &dwPortStat, 0);



Nie próbowałem z bardzo prostej przyczyny. WaitCommEvent jest blokujące. A muszę zasygnalizalizować koniec wątku roboczego.

Teraz jednak patrzę i ew. rozwiązaniem byłoby użycie "FILE_FLAG_OVERLAPPED"... Eleganckie (wg. założeń) i umozliwi użycie WaitForMultipleObjects (zdarzenia "zakończ wątek" i "czytanie zakończone"). Nie wiem jednak, czy jeśli "gdzień w tle" system wykonuje operację to czy się najzwyklej w świecie ta operacja nie zblokuje (identycznie jak przy synchronicznym ReadFile). Jest jednak CancelIo. Wracamy jednak do problemu... "Overapped" nie jest obługiwany przez WM2003... :)


A z multiplekserem to MS ma problem, bo w PB każdy OEM może sobie zmodyfikować jego kod i dla niektórych urządzeń ( np: z wbudowanym gps) go modyfikują.

Jasne. I być może problem dotyczył tylko n560 z oryginalnym WM5 (teraz mam ugotowany 6.1), ale jak czas pozwoli to sprawdzę...

*

Offline miba

  • *****
  • 4050
  • Płeć: Mężczyzna
  • Sprzęt: Toshiba G900, doszedł x51v
Odp: Programowanie portu COM - GPS
« Odpowiedź #9 dnia: Listopad 26, 2010, 11:45:20 »
To, że jest to operacja blokująca to chyba raczej nie argument - ReadFile jest nią również a musisz z niej skorzystać i tak. Z drugiej strony jak w buforze połączenia masz dane (to wiesz po powrocie z tej funkcji) to nie zablokujesz się na ReadFile a co najwyżej dostaniesz mniej bajtów niż chciałeś.

Ale z innej beczki - próbowałeś tego:

COMMTIMEOUTS cto         = {0};
cto.ReadTotalTimeoutConstant   = MAXDWORD;
cto.ReadIntervalTimeout      = 0;
cto.ReadTotalTimeoutMultiplier   = 0;

To całkowicie powinno wyeliminować blokowanie, przy czym możliwe jest, że dostaniesz 0 bajtów czyli trzeba sobie zasypiać na przykładowo 250ms i po obudzeniu sprawdzać sygnały i wywoływać readfile ponownie w pętli.
Może ta kombinacja akurat działa dobrze, bo ścieżka kodu systemowego jest pewnie różna od tej z definiowanym czasem przekroczenia.


*

Offline PiKNew

  • ***
  • 437
  • Płeć: Mężczyzna
  • Sprzęt: iPaq h5550, Loox n560
Odp: Programowanie portu COM - GPS
« Odpowiedź #10 dnia: Listopad 27, 2010, 06:35:27 »
Czy na pewno dobrze napisałeś? Z MSDN:

Cytuj
ReadIntervalTimeout
The maximum time allowed to elapse between the arrival of two bytes on the communications line, in milliseconds. During a ReadFile operation, the time period begins when the first byte is received. If the interval between the arrival of any two bytes exceeds this amount, the ReadFile operation is completed and any buffered data is returned. A value of zero indicates that interval time-outs are not used.

A value of MAXDWORD, combined with zero values for both the ReadTotalTimeoutConstant and ReadTotalTimeoutMultiplier members, specifies that the read operation is to return immediately with the bytes that have already been received, even if no bytes have been received.

Czyli powinno być:

COMMTIMEOUTS cto         = {0};
cto.ReadTotalTimeoutConstant   = 0;
cto.ReadIntervalTimeout      = MAXDWORD;
cto.ReadTotalTimeoutMultiplier   = 0;

*

Offline miba

  • *****
  • 4050
  • Płeć: Mężczyzna
  • Sprzęt: Toshiba G900, doszedł x51v
Odp: Programowanie portu COM - GPS
« Odpowiedź #11 dnia: Listopad 27, 2010, 06:49:56 »
Przy wpisywaniu zrobiłem oczywiście błąd. MAXDWORD idzie do stałęj ogólnej a nie do tych dotyczących przeterminowania pojedynczych znaków. Słuszna korekta, choć akurat pomyliłem się po prostu przy wpisywaniu.
Ale głównie chodziło mi, że jest możliwość (przynajmniej w założeniu) wywalenia blokowania z operacji readfile, więc dlatego nie wkleiłem przetestowanego kodu.

*

Offline PiKNew

  • ***
  • 437
  • Płeć: Mężczyzna
  • Sprzęt: iPaq h5550, Loox n560
Odp: Programowanie portu COM - GPS
« Odpowiedź #12 dnia: Listopad 28, 2010, 08:09:23 »
Ok, sprawdziłem - rzeczywiście ReadFile już nie blokuje, czasami jednak czyta 0 znaków. Obsłużyłem tę sytuację jako dodatkowe wyczekanie (tutaj na zdarzeniu "zakończ aplikację") ok. 1 sek. i ponowny read file.

Na razie przetestowałem swój kod zarówno na multiplexerze jak i porcie sprzętowym. W tym przypadku trzeba dodatkowo ustawiać prędkość - to odnośnie:

Natomiast w przypadku Omni 2 - znaki z ReadFile wpadają jak z telegrafu

(...)

Próbowałem wszelkich kombinacji w COMMTIMEOUTS  i COMMCONFIG... i nic.

U mnie (na n560) jest to 57600. Sugestia do marek_b - użyj SetCommState.

U mnie jest teraz:

if(mgAppDataPtr->GetOptionBool(mgAppData::OPTION_PARAM_GPS_MANUAL,FALSE,FALSE))
{
     DCB dcb = {0};
     dcb.DCBlength = sizeof(DCB);
     if(::GetCommState(hGpsPort,&dcb))
     {
          dcb.BaudRate = mgAppDataPtr->GetOptionIntT<DWORD>(mgAppData::OPTION_PARAM_GPS_PORT_BAUD_RATE,FALSE,CBR_9600);
          bSuccess = ::SetCommState(hGpsPort,&dcb);
     }
     else
     {
          bSuccess = FALSE;
     }
}

*

Offline miba

  • *****
  • 4050
  • Płeć: Mężczyzna
  • Sprzęt: Toshiba G900, doszedł x51v
Odp: Programowanie portu COM - GPS
« Odpowiedź #13 dnia: Listopad 28, 2010, 09:54:42 »
Dlaczego piszesz, że "jednak" - "czasami jednak czyta 0 znaków"? Tak musi być. To jest pooling tak na prawdę. Zresztą z punktu widzenia programisty API systemu op. nie da się tego inaczej zaimplementować z opcją nieblokującą.
Ja bym dał odstęp czekania w przypadku pustego bufora trochę mniejszy niż 1s. Proponuję jakieś t > 1/4s i jednocześnie t<=1/2s. GPS-y najczęściej wysyłają paczki danych w odstępach 1s.
Zauważ, że problem z gps jest takiej natury - mamy układ (gps) definiowany zestawem parametrów zmiennych w czasie. Chcielibyśmy znać kolejne stany(zestawy parametrów) S1, S2, S3, w następujących po sobie chwilach czasu. Jednak protokół nmea nie definiuje operacji przesyłów całych stanów (a raczej informacji je definiującej) tylko wartości poszczególnych parametrów. Zatem jeśli utrzymujesz w pda strukturę mającą odzwierciedlać najbardziej aktualny stan to jesteś narażony na takie kwiatki, że parametr p1 pochodzi ze stanu w chwili t1 i jednocześnie inny parametr p2 pochodzi od stanu w chwili wcześniejszej t2 = t1- delta. Im większe opóźnienia w obróbce informacji z bufora portu gps, tym te desynchronizację są większe. Oczywiście sytuację ratuje trochę to, że najważniejsze parametry ( informacja o pozycji ) są niejako ciągłą funkcją czasu o niezbyt dużej zmienności. Jednak trochę jest problem z hdop czy vdop jako, że one już tak regularnie nie muszą się zachowywać, a są przydatne w ocenie jakości sygnału.

*

Offline PiKNew

  • ***
  • 437
  • Płeć: Mężczyzna
  • Sprzęt: iPaq h5550, Loox n560
Odp: Programowanie portu COM - GPS
« Odpowiedź #14 dnia: Listopad 29, 2010, 03:57:42 »
Wydaje mi się, że z tym nie będzie problemu. W skrócie - czytam paczki za pomocą readfile i jeśli są dane to "doklejam" do bufora. Następnie zdarzeniem triggerującym przetwarzanie jest pojawienie się znaków z sekwencji "\r\n". Czyli de facto maksymalnym opóźnieniem w procesie będzie właśnie to ew. 1 sek (to jednak jest szczegół).

Jest drugi problem - im szybciej będę próbkował tym bardziej obciążę system. Tak więc w tym przypadku (czyli w przypadku mojej aplikacji) lepiej jest dać czas większy. Bo MG to nie jest mapa a tylko wrzucanie opisu do gg. I trzeba zauważyć, że tam raczej zdefiniuje się czas w okolicach 30 sekund.
« Ostatnia zmiana: Listopad 29, 2010, 07:36:39 wysłana przez PiKNew »

*

Offline miba

  • *****
  • 4050
  • Płeć: Mężczyzna
  • Sprzęt: Toshiba G900, doszedł x51v
Odp: Programowanie portu COM - GPS
« Odpowiedź #15 dnia: Listopad 29, 2010, 07:49:45 »
Paczka to kilka komend nmea opisujących  stan urządzenia. GPS-y wypluwają takie ciągi co 1s mniej więcej.

Scenariusz:
t1: Czytasz dane (dużą część paczki) i usypiasz na minute
t1+ 10ms:  reszta danych opisująca stan gps-u w chwili  t1 kończy transmisją z modułu BT do bufora w jądrze i czeka na twój odczyt bo usnąłeś.
t1+1s: czytasz resztę paczki i dodatkowo początek albo i całość albo część następnej i przetwarzasz dane opisujące stan w chwili t1 (mniej więcej ) z danym opisującymi stan t1+1s

Obciążenie to byś wygenerował jakbyś 100 razy na sek czytał i to takie dopiero troszkę zauważalne. Taki pooling w jądrze to normalka i jakoś stanowi tylko ułameczek prawdziwego źródła obciążenia proca. Powiem tak - 1 wariant czytasz 1raz/sek ,drugi czytasz 3razy/sek Teza - nie zauważysz skróconego czasu pracy na baterii uwzględniając błąd pomiaru.