To chyba aż zrobię kiedyś podobny test u siebie na ARM - masz jakiś przykładowy kod który mógłbym od razu wrzucić? (;
4\/3!!
4\/3!!
Czy wolisz polską wersję strony elektroda?
Nie, dziękuję Przekieruj mnie tamTomq napisał:
Ok. Tylko dla mnie wygląda to jak automatyczne przechodzenie z jednego stanu w inny. A co jeśli chciałbym, żeby ta maszyna reagowała na rzeczywiste wydarzenia, np odczytano wartość ADC poniżej wyznaczonego progu, albo wciśnięto przycisk?
Cytat:Po prostu trzeba dodać warunki, które muszą zostać sprawdzone przed zmianą stanu maszyny
Cytat:Przy jednym klawiszu to można zrobić w ten sposób, ale przy większej ilości (a zwłaszcza z podmenus) to robi się oddzielną maszynę stanów na obsługę klawiszy.
Tomq napisał:Cytat:Po prostu trzeba dodać warunki, które muszą zostać sprawdzone przed zmianą stanu maszyny
Czyli musimy użyć zmiennych globalnych (klawisz, ADC_value).
Tomq napisał:A jak skomunikować ze sobą kilka maszyn stanu? Zmiennymi globalnymi? Czy po prostu używać wskaźników na te same funkcje? Wiem, że to wiele zależy od konkretnego projektu, ale chciałbym zobaczyć jakieś przykładowe powiązania między np dwiema różnymi maszynami stanu.
Tomq napisał:
Ewentualnie można robić jedną dużą maszynę stanu (klawiatura). Stanami byłyby różne odczyty klawiszy. Dany stan zawierałby tekst który należy wyświetlić na wyświetlaczu i parametr który należałoby zmienić (poprzez wskaźnik), lub funkcja jaką należałoby wywołać (np. wyślij poprzez rs232/gsm, włącz_coś_tam). Stan Idle wtedy gdy żaden klawisz nie wciśnięty i w tym idlu oczekwiało by się na wciśnięcie klawisza oraz można by przełączać inne funkcje (np przelicz_temperature, zapisz okresowy log na kartę pamięci, etc). W tym wypadku Idle też musiałoby być maszyną stanu (wewnątrz większej maszyny jaką jest klawiatura).
Ma sens powyższa konstrukcja?
Tomq napisał:Pętla która dziesięć razy przypisuje do pola state funkcję, której argument pobiera ze struktury mySuperDuperBlower.
Tomq napisał:Jak to możliwe, że "BlowerState" jest zmienną strukturalną (bo po zamknięciu definicji struktury możemy deklarować jej zmienne i tak właśnie tu jest zrobione, za nawiasem "}" stoi nazwa BlowerState)
Freddie Chopin napisał:Tam nie ma żadnego przypisania.
Tomq napisał:A jak skomunikować ze sobą kilka maszyn stanu? Zmiennymi globalnymi? Czy po prostu używać wskaźników na te same funkcje? Wiem, że to wiele zależy od konkretnego projektu, ale chciałbym zobaczyć jakieś przykładowe powiązania między np dwiema różnymi maszynami stanu.
Tomq napisał:Ewentualnie można robić jedną dużą maszynę stanu (klawiatura). Stanami byłyby różne odczyty klawiszy. Dany stan zawierałby tekst który należy wyświetlić na wyświetlaczu i parametr który należałoby zmienić (poprzez wskaźnik), lub funkcja jaką należałoby wywołać (np. wyślij poprzez rs232/gsm, włącz_coś_tam). Stan Idle wtedy gdy żaden klawisz nie wciśnięty i w tym idlu oczekwiało by się na wciśnięcie klawisza oraz można by przełączać inne funkcje (np przelicz_temperature, zapisz okresowy log na kartę pamięci, etc). W tym wypadku Idle też musiałoby być maszyną stanu (wewnątrz większej maszyny jaką jest klawiatura).
Ma sens powyższa konstrukcja?
Tomq napisał:Tu jest ładna, prosta maszynka stanów z wykorzystaniem struktur: https://www.elektroda.pl/rtvforum/topic1088003.html#5491796
Tomq napisał:Jak to możliwe, że "BlowerState" jest zmienną strukturalną (bo po zamknięciu definicji struktury możemy deklarować jej zmienne i tak właśnie tu jest zrobione, za nawiasem "}" stoi nazwa BlowerState)Kod: C / C++Zaloguj się, aby zobaczyć kod
A jednocześnie jest ono strukturą (bo za pomocą nazwy BlowerState deklarujemy inne struktury):Kod: C / C++Zaloguj się, aby zobaczyć kod
Jak dla mnie to powinno to wyglądać tak...
Cytat:To utworzenie zmiennej globalnej o typie BlowerState (czyli takiej struktury jaką widzisz w typedefie) o nazwie idleState z przypisaniem jej wartości domyślnej do jedynego pola tej struktury -> wskaźnika na funkcje handle.
Cytat:Co znaczy skomunikować maszyny stanu? Pytanie jakie powinno paść to chyba raczej - jak dany stan nakarmić danymi zewnętrznymi np, temperatura ?
Cytat:Klawiatura to nie maszyna stanu, tylko obiekt posiadający swój własny kontekst, którym jest między innymi jej stan. Nie ma sensu też wciskać bez sensu maszynę stanów gdzie popadnie.
Cytat:Do klawiatury (też zależy w sumie jakiej) lepsze jest coś w stylu event source. Naciskasz klawisz -> wywołujesz event "naciśnięto klawisz detonacji urządzenia" -> łapiesz event i wołasz jego obsługę.
Cytat:Równie dobrze można nie robić żadnych struktur, tylko zrobić 500 zmiennych globalnych (w tym wskaźniki na funkcje ;]).
Tomq napisał:Przewagę struktur nad moimi wskaźnikami na funkcje jednak dostrzegam w tym, że w moim przypadku funkcja robi coś na zmiennych globalnych, a w Twoim funkcja działa "na swoim podwórku", tzn w obrębie własnej struktury.
Tomq napisał:"Ifa" tak czy inaczej należałoby dodać w Twoim przykładzie, bo jest on na tyle uproszczony (co jest zrozumiałe, bo jak widać nawet takiego uproszczonego przykładu nie byłem w stanie szybko ogarnąć), że maszyna automatycznie przechodzi z jednego stanu w drugi.
Cytat:Można zaimplementować bardzo uproszczoną wersję:
-> wykrywasz naciśnięcie przycisku (jakkolwiek: ify, porównanie poprzedniego stanu na porcie, przerwanie, etc)
-> "zgłaszasz event" - na uC w języku C najprościej to zrobić wywołując po prostu metodę, która jako parametr przyjmuje rodzaj eventu + jakieś ewentualne dane.
-> W metodzie masz handlery, które obsługują konkretny typ eventu. Nie trzeba tutaj robić switch-case'a, wystarczy mapa, która mapuje typ eventu na handler.
Cytat:Jeśli nie chcesz uwierzyć na słowo, to jak trochę dłużej poprogramujesz, to sam dojdziesz do wniosku, że używanie i operowanie na zmiennych globalnych w cale nie jest takie fajne.
Cytat:No tak, ale nie służy on do sprawdzania stanu w jakim się znajdujesz (bo to jest przecież nieważne), tylko do sprawdzenia jakiegoś zewnętrznego czynnika, od którego zależy następny stan.
Cytat:Generalnie wzorzec stanu wywodzi się z języków obiektowych. Jeśli chcesz pisać czystszy i bardziej uporządkowany kod to polecam przesiadkę. Nie jest ona łatwa, programiści często używają obiektów jak struktur, ale wiele rzeczy można napisać łatwiej. Np wzorzec stanu, który gdzieś tam podałem dla języka C, jest w C++ łatwiejszy do napisania. Eventbus też jest prostszy do zrobienia w C++ (tak po prawdzie to jest trudniejszy, ale da się go zrobić ładniej i bardziej uniwersalnie).
Cytat:Żeby nie było - co kto lubi, nie neguję niczyjego rozwiązania. Chcecie to róbcie switch casy, ale takie rozwiązania są mało elastyczne. Przy większym projekcie, w którym klient (kórym możecie być wy sami) często robi zmiany, jest to tragedia.
gaskoin napisał:Eventbus też jest prostszy do zrobienia w C++ (tak po prawdzie to jest trudniejszy, ale da się go zrobić ładniej i bardziej uniwersalnie).
Freddie Chopin napisał:natomiast nie ma czegoś takiego, że jakaś akcja wywoływana jest w kółko tylko dlatego że HSM jest w danym stanie
4\/3!!
Tomq napisał:Ale IMHo jeśli trzeba przerzucić kilka poziomów to trochę to zajmie.
Freddie Chopin napisał:
Wcześniej prezentowałem "wysłanie" zdarzenia do maszyny stanów, a teraz funkcja dispatch() (uprzedzam, że dla niektórych składnia może być przytłaczająca (; ):
Jado_one napisał:Może ktoś ma lepszy pomysł - o ile to co piszę jest zrozumiałe przez innych
TWl napisał:Freddie, a podzieliłbyś się może przykładowym kodem kompletnej maszyny stanów (jeśli to nie ściśle tajne/poufne)? Łatwiej byłoby zrozumieć całość niż wycinki
TWl napisał:Czy cała klasa HSM jest template'm a STATE i ARG to jego parametry?
Freddie Chopin napisał:gaskoin napisał:Eventbus też jest prostszy do zrobienia w C++ (tak po prawdzie to jest trudniejszy, ale da się go zrobić ładniej i bardziej uniwersalnie).
Zapodaj lepiej jakiś fajny kod (np. link) (;
4\/3!!
gaskoin napisał:Nie mam za bardzo czasu nic pisaćhttps://github.com/danquist/EventBus to wygląda nawet w miarę.
typedef std::list<EventRegistration*> Registrations;
typedef std::unordered_map<std::type_index, std::list<EventRegistration*>*> TypeMap;
TypeMap handlers;Freddie Chopin napisał:No naprawdę, ale próbujesz teraz wymyślić coś co już zostało wymyślone dawno temu, tyle że chcesz koniecznie zrobić to inaczej niż "się to robi" (;
Jado_one napisał:Każdą rzecz można rozwiązać na 100 sposobów - ale jak widzę jest "jedynie słuszna droga"