logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Jak zrealizować pętlę sterującą w programie (deltatime-crucial)

valarian 20 Mar 2012 09:16 1488 11
REKLAMA
  • #1 10698707
    valarian
    Poziom 22  
    Posty: 647
    Pomógł: 33
    Ocena: 112
    Witajcie,

    Pytanie w sumie niezależne od architektury (z ukłonem w stronę ARM7)- w jaki sposób realizuje się pętle sterujące w programach pisanych na mikrokontrolery?
    Chodzi mi o sytuację, gdzie pewien fragment kodu wykonywanu jest co ściśle określoną ilość czasu lub wykonywany jest w różnych odstępach, jednak z dokładnie znaną różnicą czasów między dwoma kolejnymi wywołaniami (potrzebne np. przy całkowaniu etc.).
    W jaki sposób można zrealizować coś takiego, nie blokując możliwie kontrolera (np. nie wrzucając kodu w przerwania timera itp.), jego peryferiów itp.
    Jak mają się w tej kwestii wynalazki wielowątkowe typu FreeRTOS itp.

    Dodam, że chodzi mi głownie o zastosowania, gdzie znajomość czasu między kolejnymi wywołaniami jest krytyczna i raczej niezbędna do prawidłowego działania(wspomniane wyżej obliczenia matematyczne itp.).
  • REKLAMA
  • #2 10698900
    Jado_one
    Poziom 22  
    Posty: 650
    Pomógł: 43
    Ocena: 12
    Witam,

    Moim zdaniem, to nie unikniesz oparcia się o zasoby sprzętowe mikrokontrolera - zresztą nie należy się tego bać - po to one są.
    Jeżeli potrzebujesz scisłego momentu wyzwolenia się jakiejs procedury (zakładając, że jej czas wykonania jest krótszy niż interwał czasowy jaki masz do dyspozycji pomiędzy dwoma kolejnymi wywołaniami tej procedury), to własnie naprościej oprzeć się jest o zasoby sprzętowe.
    Przykładowo - mam urządzenie które musi obliczyć parametry PID w czasie pomiędzy kolejnymi odwołaniami do np. układu PWM sterującego jakimś procesem.
    Powiedzmy, że dane pobieram z przetwornika A/D, który jest wyzwalany raz na jakiś czas.
    Najprościej więc będzie stworzyć flagę ustawianą po zakończeniu procedury konwersji A/D, zezwalającą na wykonanie się programu obliczającego - który czeka na to zezwolenie kręcąc się w pętli głównej.
    Albo moża zrobić to wywołując bezpośrednio procedurę obliczeń - po zakończeniu konwersji A/D.
    RTOS'y też synchronizują sobie zarządzanie procesami korzystając z cyklicznego przerwania od jakiegoś licznika systemowego.
    Współczesne mikrokontrolery typu ARM mają do dyspozycji po 5+ liczników, więc aż się prosi o użycie któregoś z nich :-)
  • #3 10698941
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    Jado - PIDa nie trzeba liczyć co konkretny czas, wystarczy znać czas próbkowania i tyle. Jeśli chodzi o RTOS to w zależności czy czas jest bardzo krytyczny, taski mają swoje priorytety i różnego typu mechanizmy synchronizacyjne.

    Wszystko zależy od złożoności i typu problemu. Ciężko dać jakieś uniwersalne rady.
  • #4 10699037
    Jado_one
    Poziom 22  
    Posty: 650
    Pomógł: 43
    Ocena: 12
    Ja akurat wysyłam do PWM dane ze stałym interwałem czasowym, więc muszę się zmieścic w okienku czasowym.
    I dobrze, że to okienko jest :-)
  • REKLAMA
  • #5 10699129
    valarian
    Poziom 22  
    Posty: 647
    Pomógł: 33
    Ocena: 112
    Mój schemat wygląda raczej standardowo (ARM - lpc1769):

    Elementy o stałym (mniej-więcej) czasie wykonania i określonej częstotliwości:
    * Odczyt danych z ADC
    * Odczyt stanów niektórych pinów
    * Wykonanie różnych obliczeń stałych (PID, Kalman etc. - docelowo może to być dość złożone, jednak o relatywnie przewidywalnym czasie - tak myślę)
    * Wysłanie wyników sterowania do rejestrów PWM i niektórych pinów

    Elementy mniej przewidywalne lub o różnym czasie/częstotliwości wykonania:
    * Wysyłanie raportów poprzez UART - może być raz na sekundę, a może być dużo więcej, zależy od stanu urządzenia
    * Odbiór wiadomości sterujących i danych telemetrycznych z dwóch innych UARTów - tu również ilość oraz częstotliwość danych jest bardzo ruchoma, na pewno nie mniej niż 10Hz
    * Wykonanie pewnych dodatkowych obliczeń/operacji/odwołań do peryferiów, w zależności od otrzymanej wiadomości sterującej - tu już jest kompletna dowolność

    Elementy, co do których nie jestem pewien:
    * Pomiar szerokości impulsów za pomocą timera/przerwań zewnętrznych (to jeszcze planowany ficzer)
    * Zapis danych na kartę microSD (SPI)

    Zastanawiam się, jak to wszystko sensownie poukładać i zorganizować, żeby zostawić sobie jak najwięcej mocy układu oraz zachować pewną elastyczność - oczywiście nie mam nic przeciwku używaniu peryferiów (timery, dma etc.), po to one są :) Będę wdzięczny za każdą poradę.
  • REKLAMA
  • #6 10699510
    Jado_one
    Poziom 22  
    Posty: 650
    Pomógł: 43
    Ocena: 12
    Ja ostatnio testuję program zorganizowany w postaci maszyn stanów - coś w rodzaju programowania współbieżnego. Do końca jeszcze nie jestem przekonany o słuszności tej drogi vs RTOS choć generalnie na razie się to sprawdza. Zobaczymy co będzie jak program się bardziej skomplikuje. Zwłaszcza denerwujące jest przyrastanie czasami współzależności jednych 'wątków' od drugich - jeżeli walczymy o te same zasoby, trzeba sprawdzać coraz więcej flag zezwoleń przed wywołaniem, żeby jedno nie zakłóciło drugiego.
    Przy asynchronicznie pojawiających się zdarzeniach największym problemem są spiętrzenia czyli jednoczesne żądania obsługi kilku zdarzeń.
    Procesor sobie z tym w końcu poradzi, ale czy wyrobi się w czasie.
    Pytanie - które procesy są krytyczne czasowo, a które mniej. Co trzeba obsłużyć natychmiast, a co może się trochę spóźnić?
    Buforowanie danych - tych do wysłania i tych odebranych może pozwolić nam na stworzenie systemu "retencyjnego" który bedzie napełniany i opróżniany w "wolniejszych chwilach procesora", itp...
    Na pewno procek musi być odp. szybki, żeby poradził sobie w najgorszym możliwym momencie :-)
  • #7 10701344
    lucasgg
    Poziom 11  
    Posty: 20
    Pomógł: 1
    Witam,

    valarian napisał:
    Jak mają się w tej kwestii wynalazki wielowątkowe typu FreeRTOS itp.


    Najwygodniej użyć jakiś OS. Teraz każdą, nawet drobną-testową rzecz, wykonuje z użyciem OS'a (CoOS) - przynajmniej jeden wątek do interfejsu z użytkownikiem (LED/LCD/Przyciski), kolejny(-e) do funkcjonalności. Sensowne rozdzielenie aplikacji wpływa korzystnie na przejrzystość kodu (mniej błędów, łatwiej utrzymać).

    valarian napisał:
    Mój schemat wygląda raczej standardowo (ARM - lpc1769):
    Elementy o stałym (mniej-więcej) czasie wykonania i określonej częstotliwości:
    * Odczyt danych z ADC
    * Odczyt stanów niektórych pinów
    * Wykonanie różnych obliczeń stałych (PID, Kalman etc. - docelowo może to być dość złożone, jednak o relatywnie przewidywalnym czasie - tak myślę)
    * Wysłanie wyników sterowania do rejestrów PWM i niektórych pinów


    Do tego, jak wcześniej wspomniano, dobrze wykorzystać timery. Przykładowo:
    - w przerwaniu trigger ADC
    - zakończenie konwersji kolejne przerwanie (zapisanie do zmiennej/tablicy wartości)
    - w wątku już przetwarzanie i zapis

    valarian napisał:

    Elementy mniej przewidywalne lub o różnym czasie/częstotliwości wykonania:
    * Wysyłanie raportów poprzez UART - może być raz na sekundę, a może być dużo więcej, zależy od stanu urządzenia
    * Odbiór wiadomości sterujących i danych telemetrycznych z dwóch innych UARTów - tu również ilość oraz częstotliwość danych jest bardzo ruchoma, na pewno nie mniej niż 10Hz
    * Wykonanie pewnych dodatkowych obliczeń/operacji/odwołań do peryferiów, w zależności od otrzymanej wiadomości sterującej - tu już jest kompletna dowolność

    Elementy, co do których nie jestem pewien:
    * Pomiar szerokości impulsów za pomocą timera/przerwań zewnętrznych (to jeszcze planowany ficzer)
    * Zapis danych na kartę microSD (SPI)


    Też się prosi o OS. Dodatkowo możliwość korzystania z priorytetów (wątki/mutexy).


    valarian napisał:

    Zastanawiam się, jak to wszystko sensownie poukładać i zorganizować, żeby zostawić sobie jak najwięcej mocy układu oraz zachować pewną elastyczność - oczywiście nie mam nic przeciwku używaniu peryferiów (timery, dma etc.), po to one są :) Będę wdzięczny za każdą poradę.


    Do dobrego ułożenia potrzebujesz chociaż przybliżonych czasów (próbkowania, raportów), ilości zapisywanych danych. Nie wiem jak Ty do tego podchodzisz - ale może warto narysować diagram (forma obrazkowa często ułatwia planowanie).

    --
    Pozdrawiam,
    Łukasz Gryka
  • REKLAMA
  • #8 10702585
    valarian
    Poziom 22  
    Posty: 647
    Pomógł: 33
    Ocena: 112
    Zainteresowałem się FreeRTOS, wydaje mi się, że w ten sposób możnaby chyba ogarnąć to wszystko tak, jak sobie mniej-więcej planuję.
  • #9 10702609
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    Niewątpliwą zaletą jest, tak jak Łukasz napisał, że zadania są podzielone, i nie masz jednego wielkiego syfu. Nie wiem jak z ARM7 bo programowałem raz kiedyś tam na studiach, nie wgłębiając się w szczegóły, ale ARMv7 czy ARMv7-me ARMv6-M itd maja peryferia pod OS (jak chociażby SysTick) przez co narzut, związany z "instalacją" samego systemu jest naprawdę niewielki.
  • #10 10702663
    Ostry23
    Poziom 18  
    Posty: 296
    Pomógł: 25
    Ocena: 30
    Jado_one napisał:
    Ja ostatnio testuję program zorganizowany w postaci maszyn stanów - coś w rodzaju programowania współbieżnego. Do końca jeszcze nie jestem przekonany o słuszności tej drogi vs RTOS choć generalnie na razie się to sprawdza. Zobaczymy co będzie jak program się bardziej skomplikuje. Zwłaszcza denerwujące jest przyrastanie czasami współzależności jednych 'wątków' od drugich - jeżeli walczymy o te same zasoby, trzeba sprawdzać coraz więcej flag zezwoleń przed wywołaniem, żeby jedno nie zakłóciło drugiego.
    Przy asynchronicznie pojawiających się zdarzeniach największym problemem są spiętrzenia czyli jednoczesne żądania obsługi kilku zdarzeń.


    Lepiej bym tego nie ujął. Mam dokładnie taki sam problem obecnie. Nie używam żadnego RTOSa mam za to parę maszyn stanów, które chcą używać jednego zasobu, EEPROMu, a jak wiadomo, zapis do niego trwa niemiłosiernie długo z perspektywy cykli uC.
    Jedna maszyna stanów obrabia polecenia przychodzące po rs'ie. Nie robię tego w jednym kroku, bo trzeba najpierw telegram sparsować, sprawdzić rodzaj rozkazu, poprawność danych, poprawność CRC, potem wyzwolić wykonywanie - niektóre komendy to zapis czegoś do EEPROMu, potem trzeba przygotować i wysłać raport. Maszyna stanów wykonuje więc po jednym fragmencie w 1 cyklu głównej pętli. W niektórych swoich stanach musi czekać na flagę od innej maszyny (np. od maszyny realizującej zapis tablicy uint8_t do EEPROMu), powiadamiającej tę pierwszą, że coś się zakończyło i ew. przekazującą status (np. czy udało się poprawnie zapisać, stwierdzane na bazie crc).

    Z kolei inny wątek, zupełnie asynchroniczny do tamtego, też chce zapisywać do EEPROMu.
    Muszę podnosić globalne flagi zajętości oraz kolejkować te cholerstwa (właśnie z powodu asynchroniczności drugiego wątku względem pierwszego).
    Trochę się to komplikuje, ale póki co działa.
    Też zaczynam dochodzić do wniosku, że może lepiej byłoby użyć RTOSa ale póki co nie znam żadnego a w tym projekcie jest już na to za późno.

    Myślę, że RTOSy przydają się, kiedy mamy w programie dużo zadań i część z nich jest dużo wolniejsza od innych a nie chcemy sobie wstrzymywać tych szybszych i nie chcemy też komplikować sprawy koniecznością obsługi dziesiątek różnych przerwań albo wielu maszyn stanów.
  • #11 10702831
    valarian
    Poziom 22  
    Posty: 647
    Pomógł: 33
    Ocena: 112
    Po rozplanowaniu, jak mniej-więcej miałoby to wyglądać, też zacząłem dochodzić do sytuacji, gdzie pojawia się coraz większa liczba flag, statusów, powiadomień i kolejek. Głównie przez to, że zadań jest sporo i wiele z nich może mieć bardzo różny czas wykonania oraz częstotliwość.
    Dam szansę RTOS'owi i zobaczę, co z tego wyniknie.
  • #12 10703382
    Jado_one
    Poziom 22  
    Posty: 650
    Pomógł: 43
    Ocena: 12
    Przy maszynach stanów ja często sprawdzam tylko status "sąsiedniej" maszyny stanów - jeśli jest różny od zera, znaczy się, maszyna w ruchu - nie wolno wywoływać działania, jeśli zero - wolne, można działać...
    Ale flag i tak nie uniknie - ....i trzeba z nimi uważać ;-)

Podsumowanie tematu

✨ W dyskusji poruszono kwestie realizacji pętli sterujących w programach dla mikrokontrolerów, szczególnie w kontekście architektury ARM7. Uczestnicy podkreślili znaczenie wykorzystania zasobów sprzętowych, takich jak timery i przerwania, do precyzyjnego wyzwalania procedur obliczeniowych, np. PID. Wskazano na zalety stosowania systemów operacyjnych czasu rzeczywistego (RTOS), takich jak FreeRTOS, które umożliwiają lepsze zarządzanie zadaniami i synchronizację. Zauważono również, że w przypadku bardziej złożonych aplikacji, maszyn stanów mogą prowadzić do problemów z zarządzaniem zasobami i synchronizacją, co może wymagać wprowadzenia dodatkowych flag i mechanizmów powiadamiania. Uczestnicy podzielili się doświadczeniami związanymi z implementacją różnych podejść, w tym programowaniem współbieżnym oraz organizowaniem kodu w postaci maszyn stanów.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA