"Nakładanie" się funkcji - komunikacja przez BT - Wersja do druku +- Arduino Polska Forum (https://forum.arduinopolska.pl) +-- Dział: Korzystanie z Arduino (https://forum.arduinopolska.pl/dzial-korzystanie-z-arduino) +--- Dział: Programowanie w Arduino (https://forum.arduinopolska.pl/dzial-programowanie-w-arduino) +--- Wątek: "Nakładanie" się funkcji - komunikacja przez BT (/watek-nak%C5%82adanie-si%C4%99-funkcji-komunikacja-przez-bt) |
"Nakładanie" się funkcji - komunikacja przez BT - Baltosz - 07-02-2018 Witajcie, przygotowuję sobie urządzenie do odczytu informacji z gniazda OBDII, które gromadzi dane a w późniejszym czasie służyć będzie do analizy "stylu" jazdy kierowcy i eliminowaniu złych nawyków. Aktualnie potrzebuję danych odnośnie aktualnych obrotów silnika i aktualnej prędkości samochodu. Do gniazda OBD wpięty jest ELM327 w wersji bluetooth. Natomiast Arduino współgra z modułem HC-05 poprzez Serial(38400). Wszystko jest zgodnie z oczekiwaniami, gdy aktywna jest tylko jedna funkcja odczytu. Natomiast, gdy uruchamiam dwie funkcje jednocześnie następuje chaos. Po kolei przedstawię jakie próby wykonałem, aby wyeliminować problem. Wartości są wywoływane wysłaniem odpowiedniej komendy do modułu ELM327 (010C lub 010D). W odpowiedzi otrzymuję ciąg znaków (010C1410CXXXX lub 010D1410DXX). W przypadku, gdy obie funkcje są wykonywane ciągi znaków zaczynają na siebie nachodzić. Jednak czasami zdarza się, że działa to prawidłowo i odczyty są poprawne, jednak jest to mniej niż 1% odpowiedzi na zapytanie. Próbowałem zmniejszyć częstotliwość wywoływania funkcji (kolejne zapytanie co sekundę) - bez efektów. Utworzyłem z dwóch jedną funkcję - bez rezultatów. W obrębie jednej funkcji wprowadziłem zmienną indeksującą, która zmieniała stan po ustaleniu wartości np. obrotów na 1, a warunek if (index==1) zezwalał na wywołanie funkcji sprawdzającej prędkość samochodu - również bez zmian. Wywołanie przez timer funkcji pośredniej, w której szeregowo wywoływane były funkcje obliczające z użyciem delay w formie void obd_check(){ rpm_calc(); delay(10); velo_calc(); } Również bez zmian. Czy możecie naprowadzić mnie co tutaj jest nie tak i dlaczego te funkcje działą, ale w mniej niż jednym przypadku na 100 wykonań? Czy może jest coś takiego jak wysłanie "pustego" zapytania do ELM327? Poniżej umieszczam kod funkcji dla obrotów (kod dla prędkości jest bliźniaczy). Kod bazuje na dostępnym w internecie wzorze: Kod: void rpm_calc(){ RE: "Nakładanie" się funkcji - komunikacja przez BT - kaczakat - 08-02-2018 W Arduino nie da się uruchomić dwóch funkcji na raz. Przynajmniej w takim znaczeniu, że jak na komputerze odpalamy muzykę to w drugim okienku piszemy na forum. Dodawanie delay miałoby sens..., no prawie nigdy nie ma sensu. Procesor na tę chwilę działania delay nie robi nic poza obsługą przerwań (jest ślepy i głuchy), nie daje to urządzeniu żadnego dodatkowego czasu na obsługę zwykłych funkcji. Jeśli wywołujesz "co sekundę" dzięki delay(1000) to zamień sobie zgodnie z przykładami arduino wg szkicu 02.Digital BlinkWithoutDelay. Coś więcej można powiedzieć jak wkleisz jakiś kawałek kodu, który można skompilować. Spróbowałbym też podłączyć HC-05 pod zwykły UART, bo jeśli jest pod softserial i ustawiony na więcej niż 9600 to możesz gubić literki. Z kolei HC-05 też jest ciekawy, ma duży bufor na dane, i nie jest tak, że Ty tych danych sobie nie odczytasz, o nie nie. On poczeka i Ci je wrzuci w pierwszej kolejności do następnej transmisji. Więc jeśli dane po np. 15 znaku chcesz ignorować to je odbierasz, tworzysz zmienną i do niej wrzucasz, potem ją zerujesz/zapominasz o niej. Może na tym polega mieszanie? RE: "Nakładanie" się funkcji - komunikacja przez BT - krn78 - 08-02-2018 Poczytaj sobie o wątkach, choćby tutaj. W przypadku Arduino są trochę sztuczne, ale coś tam da się zrobić. RE: "Nakładanie" się funkcji - komunikacja przez BT - Baltosz - 08-02-2018 Dziękuję za odpowiedzi, mam pewne przypuszczenia, które sprawdzę wieczorem. Cytat:W Arduino nie da się uruchomić dwóch funkcji na raz. Przynajmniej w takim znaczeniu, że jak na komputerze odpalamy muzykę to w drugim okienku piszemy na forum.Rozumiem, dlatego kombinowałem z uruchamianiem szeregowym. Cytat:Dodawanie delay miałoby sens..., no prawie nigdy nie ma sensu. Procesor na tę chwilę działania delay nie robi nic poza obsługą przerwań (jest ślepy i głuchy), nie daje to urządzeniu żadnego dodatkowego czasu na obsługę zwykłych funkcji. Jeśli wywołujesz "co sekundę" dzięki delay(1000) to zamień sobie zgodnie z przykładami arduino wg szkicu 02.Digital BlinkWithoutDelay. Coś więcej można powiedzieć jak wkleisz jakiś kawałek kodu, który można skompilować.Działanie funckji delay() również rozumiem. Zastosowałem to, bo myślałem o opóźnieniu uruchomienia kolejnej funkcji. Cytat:Spróbowałbym też podłączyć HC-05 pod zwykły UART, bo jeśli jest pod softserial i ustawiony na więcej niż 9600 to możesz gubić literki.To będzie kolejny trop. Cytat:Z kolei HC-05 też jest ciekawy, ma duży bufor na dane, i nie jest tak, że Ty tych danych sobie nie odczytasz, o nie nie. On poczeka i Ci je wrzuci w pierwszej kolejności do następnej transmisji. Więc jeśli dane po np. 15 znaku chcesz ignorować to je odbierasz, tworzysz zmienną i do niej wrzucasz, potem ją zerujesz/zapominasz o niej. Może na tym polega mieszanie?Cenna uwaga, również do sprawdzenia. Z tym, że zmienne mają odpowiedni rozmiar, odbierane są jakieś znaki końcowe. Jednak jeżeli zmienna "nie mieściłaby" całej odpowiedzi to wnioskuję, że również przy wywoływaniu tej samej funkcji dawałaby podobne objawy, a takich nie ma. Cytat:Poczytaj sobie o wątkach, choćby tutaj. W przypadku Arduino są trochę sztuczne, ale coś tam da się zrobić.Nie wiedziałem o takiej funkcji jak timer.attach(nr wątku, ...). Spróbuję to wykorzystać, bo wydaje mi się, że muszę "poustawiać" funkcje w osobnych wątkach. Do tej pory miałem to zdefiniowane jako: Kod: Timer t; Kod: Timer <2> t; Cytat: napisał(a):Niestety nic się nie dzieje...Zawsze coś się dzieje ... Kod: Kod: akcja.attach (0, 500, dioda1); Kod: Kod: Dwie funkcje wywoływane są w tym samym czasie jedno 500 zmień np na 1000 RE: "Nakładanie" się funkcji - komunikacja przez BT - kaczakat - 08-02-2018 (08-02-2018, 11:21)krn78 napisał(a): Poczytaj sobie o wątkach, choćby tutaj. W przypadku Arduino są trochę sztuczne, ale coś tam da się zrobić.Akurat biblioteka timers jest OK, o tyle że nie używa przerwań, co tu byłoby niewskazane, bo gdyby jakaś czynność odczytu była wywoływana cyklicznie co 1000ms, a jej czas trwania byłby znacząco długi to często dochodziłoby do przerywania odczytu na czas wywołania innej funkcji odczytu. A dodatkowo mocno nie zalecane jest używanie przerwań do funkcji długich, np. Serial.println(), a tym bardziej jak oczekujemy na odpowiedź. Przerwanie funkcji odczytu by zmienić np. stan portu dla led, zmienić wartość zmiennej - byłoby OK. Dokładnie w tej bibliotece zostały użyte mechanizmy z przykładu blinkwithoutdelay - zliczanie ms, sprawdzanie czy zadany okres czasu upłynął i zamiana ostatniej wartości millis() na początkową. Bardzo ładnie poukładane w funkcje/obiekty. Kod: akcja.attach (0, 500, dioda1); Dalej od programisty zależy jak tego użyje. Tak na piechotę można zrobić lepsze zarządzanie obciążeniem procesora, gdzie jeden odczyt będzie wykonywany w każdej parzystej sekundzie, a drugi odczyt innej wartości w nieparzystej, czy w setkach ms parzystych i nieparzystych gdy chcemy to robić z częstotliwością 10Hz, a się da(nie będzie tak, że dwa odczyty obok siebie zablokują działanie urządzenia na 15s, jak np. może być gdy rozmawiamy z modemem GSM). A jak ktoś umie to i bibliotekę można z tego zrobić by pętla wyglądała bardziej elegancko (przykład zmodyfikowany blinkwithioutdelay): Kod: /* "Rozmowa" z innym urządzeniem powinna być tak realizowana, że wysyła się zapytanie, ustawia jakąś flagę oczekiwania na odpowiedź i wychodzi z funkcji. Może raczej osobna funkcja do wysyłania, a inna do zbierania danych i ich obróbki. Ustawienie flagi powoduje sprawdzanie w pętli głównej czy przyszła cała odpowiedź (przerwanie UART odbiera znaki i ładuje do bufora, na koniec ustawia flagę żeby to brać) lub upłynął timeout, nie odpali się ponownie komunikacja dopóki flaga nie pozwoli. Jeśli timeout to kasujemy flagę i pytamy ponownie, informujemy użytkownika o braku komunikacji, możemy zliczać nieudane próby, itp. Jeśli odpowiedź przyszła to możemy coś z nią zrobić, skasować flagę i wysłać kolejne pytanie. No chyba, że odpowiedź jest natychmiastowa - na odpowiedzi z czujników (DS18B20), modemów itp. lepiej nie czekać. Niestety przerwanie UART, event z przykładów dla UART nie są dla softserial. Jeśli komunikujemy się z urządzeniem, a chcemy mieć jakiś podgląd co się dzieje w programie to lepiej jest softserialem wysyłać na jakiś terminal np. Putty (również przez BT HC-05), a sprzętowy UART wykorzystać do odczytu - większa prędkość, stabilność i więcej możliwości. Takie tam przemyślenia filozoficzne . RE: "Nakładanie" się funkcji - komunikacja przez BT - Baltosz - 10-02-2018 Zamieniłem bibliotekę Timer.h na Timers.h i wprowadziłem wątki. Niestety bez efektu. Edytowałem funkcje i sprawdziłem jakie dane otrzymuję po każdym zapytaniu. Może analizując odpowiedź dacie mi podpowiedź co jest winne za "mieszanie". Odpowiedzi przy wywoływaniu tylko funkcji sprawdzającej obroty: Kod: RPM_BUFIN: 010C1410C110A 11 E7 >ING... 41 0C 11 6D >010C1 41 0C 11 0A >010C1 41 0CM? Kod: RPM_BUFIN: 010C1410C0CA1010C1010D1D141 0C 0C B2 >1407F 01 12 >010C141 0C 0C A1 >010C1010+?? RE: "Nakładanie" się funkcji - komunikacja przez BT - kaczakat - 19-02-2018 Muszę znaleźć swoją magiczną kulę... Wkleisz ten kod cały, wraz z linkami do bibliotek, tak by można go było skompilować? |