Komentator Napisano Grudzień 31, 2017 Udostępnij Napisano Grudzień 31, 2017 Funkcja delay (do wprowadzania opóźnień) to jedna z pierwszych rzeczy, której uczymy się podczas poznawania Arduino. Jej działanie może jednak generować wiele kłopotów.Na szczęście z pomocą przychodzi nam bardziej rozbudowane rozwiązanie bazujące na funkcji millis. Dzięki niej Arduino może wykonywać kilka zadań "jednocześnie". UWAGA, to tylko wstęp! Dalsza część artykułu dostępna jest na blogu.Przeczytaj całość »Poniżej znajdują się komentarze powiązane z tym wpisem. Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 Jeszcze raz przepraszam wszystkich, którzy musieli czekać na kolejną część tak długo. Niestety plany związane z tym artykułem miałem zupełnie inne i wszystko przeciągało się w nieskończoność. W końcu wpadłem w pułapkę, bo chciałem „za dobrze” i ciągle przekładałem ten artykuł. Ostatecznie postanowiłem zmienić tematykę na millis(). Myślę, że będzie to korzystne dla wszystkich, bo warto znać tę funkcję. W kolejnym artykule krótkie podsumowanie kursu + plany na przyszłość 🙂 Cytuj Link do komentarza Share on other sites More sharing options...
Elvis Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 Mam takie dwie drobne uwagi. Przełączanie zadań odbywa się raczej tysiące razy na sekundę, niż miliardy - to dość czasochłonny proces wbrew pozorom. Druga sprawa to animacja przy miganiu dwóch diodek (jedna 0,5s, druga 1s) - może warto byłoby zmienić długość filmu, bo teraz dioda migająca co 0,5s ma taki dziwny przeskok. Dość długo próbowałem zrozumieć skąd w tym programie to dodatkowe, szybki mrugnięcie 🙂 Cytuj Link do komentarza Share on other sites More sharing options...
SOYER Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 Teraz o millis?!?!? 😅😅 Trzeba było 2 miechy temu to by zaoszczędziło Elvisovi żmudnego uczenia mojej skromnej osoby 😋 . Artykuł bardzo przydatny, choć dla mnie teraz już mniej(dzięki forum Forbota 😃 ). Dziękuję za ogrom włożonej pracy. Mała uwaga, uważam, że lepiej pisać takie artykuły z nauką podstaw i uczenia kodowania, podawanie niuansów i sztuczek, niż skupianie się na praktyce. Wydaje się, że powyższy artykuł jest idealnie wyważony, podaje to co ważne w teorii i jakiś przykład dla zrozumienia, ew. podpowiedzi co do innego wykorzystania zdobytej wiedzy niż tylko jak w przykładzie. Do artykułu jak bym jeszcze dopisał sposób millis()-poprzedniZapisanyMillis[zwał jak zwał]>2000 korzystamy tylko z jednej zmiennej co przynajmniej, jak dla mnie, znacznie upraszcza całą robotę 🙂 Pozdrawiam Cytuj Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
Treker (Damian Szymański) Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 Elvis, dzięki za uwagi! Już poprawione, faktycznie animacja była źle złożona. SOYER, nie ukrywam, że Wasza dyskusja była też trochę inspiracją do tego artykułu. Dzięki za miłe słowa 😉 Jeśli chodzi o zaproponowane przez Ciebie rozwiązanie: millis()-poprzedniZapisanyMillis > 2000 To mam mieszane uczucia. Na pewno jest to poprawne, gdy mamy jedno opóźnienie w programie i potrzebujemy sprawdzić aktualny czas tylko raz. Jeśli takich wątków będzie 50, to w Twojej metodzie wywołasz 50 razy funkcję millis(), a w mojej tylko raz. W tym przypadku nie zrobi to wielkiej różnicy, ale obawiam się, że takie podejście wykształca nawyk, aby za każdym razem wywoływać funkcję (nawet jeśli wynik będzie taki sam). Jeśli zamiast millisa mielibyśmy bardziej rozbudowaną funkcję, to lepiej byłoby wykonać ją raz, zapisać wynik do zmiennej i później się do niej odwoływać - zamiast 50x wywoływać funkcję, która może być "zasobożerna", a zawsze zwróci ten sam wynik (w danym obiegu pętli). Jednak tak jak mówię, to tylko mój nawyk i nie jest on związany bezpośrednio z millis. Cytuj Link do komentarza Share on other sites More sharing options...
Elvis Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 Ja widzę co najmniej dwie zalety wersji opisanej w kursie. Po pierwsze, każde wywołanie millis() może zwrócić inną wartość. W opisywanym przypadku to nie problem, ale lepiej sobie wyrabiać "odruch" używania tej samej wartości. Druga sprawa to typ ze znakiem. Kod w kursie używał typu unsigned long. Natomiast jeśli użyjemy odejmowania jak w kodzie zaproponowanym przez SOYER-a, kompilator ma pełne prawo użyć typu long. Niestety wtedy pojawią się problemy w przypadku przepełnienia typu (czyli po 50 dniach). Wesja z kursu działa za to poprawnie nawet wtedy. 1 Cytuj Link do komentarza Share on other sites More sharing options...
nse Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 Ja widzę co najmniej dwie zalety wersji opisanej w kursie. Po pierwsze, każde wywołanie millis() może zwrócić inną wartość. W opisywanym przypadku to nie problem, ale lepiej sobie wyrabiać "odruch" używania tej samej wartości.Druga sprawa to typ ze znakiem. Kod w kursie używał typu unsigned long. Natomiast jeśli użyjemy odejmowania jak w kodzie zaproponowanym przez SOYER-a, kompilator ma pełne prawo użyć typu long. Niestety wtedy pojawią się problemy w przypadku przepełnienia typu (czyli po 50 dniach). Wesja z kursu działa za to poprawnie nawet wtedy. Ja kiedyś wielowątkowość na AVR rozwiązałem za pośrednictwen zadeklarowanego rejestru flagowego sterowanego w przerwaniu z timera1, z flagami 1ms,10ms,100ms,1 ... , potem w pętli głównej podpinałem funkcje które mały być wykonywane w odpowiednich odstępach czasowych. Pozdrawiam i Zdrowego Sylwestra 😉 Cytuj Link do komentarza Share on other sites More sharing options...
SOYER Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 Ok, czyli twierdzicie, że lepiej jak wrócę do currentMillis i previousMillis, w sumie macie rację, tylko, że wtedy trzeba pamiętać o aktualizowaniu w odpowiednim momencie obu zmiennych, co wiem, że początkującemu sprawia trochę problemu w momencie kiedy tych stoperów jest więcej niż dwa, trzy jednocześnie. Wtedy łatwiej jest stosować pojedynczą zmienną i traktować ją jako start odliczania. Ale oczywiście zgadzam się, że nadpisana currentMillis jest stała i kropka. A millis() nawet wywołana jedną linijkę kodu niżej będzie się różnić od tej linijkę wyżej... bo chyba o to wam chodziło tak? Cytuj Link do komentarza Share on other sites More sharing options...
Belferek Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 Wielu początkującym będzie sprawiać trudność zapanowanie nad zmiennymi określonymi przez millis() i dlatego w/g mnie szkoda, że nie wspomniano w artykule o bibliotekach ułatwiających "wielozadaniowość" w Arduino jak np. Timers czy leOS. Korzystając np. z leOS wystarczy raz zaplanować przedziały czasowe wykonywanych zadań (wątków) i tyle. W sumie artykuł ciekawy i powinien być obowiązkową lekturą, każdego rozpoczynającego przygodę z Arduino. Pozdrawiam, Cytuj Link do komentarza Share on other sites More sharing options...
Elvis Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 Nadmiar bibliotek bywa problematyczny, co już na tym forum się przewijało: biblioteka X działa pięknie ale nic mi nie działa jak dodam bibliotekę Y... Jeśli Timers to ta biblioteka, którą znalazłem, to w niej właściwie nie ma kodu - taki cienki wrapper w C++ do wywołania millis(). Moim zdaniem lepiej zrozumieć jak millis() działa. Natomiast IeOS to jakiś koszmarek. Wywoływanie funkcji z poziomu przerwań powinno być karane. Lepiej już uruchmić "prawdziwy" RTOS, chociażby FreeRTOS działa na Arduino. Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 Tak w kwestii formalnej: Oba rozwiązania porównania - zarówno SOYERa: millis()-poprzedniZapisanyMillis > 2000 jak i użyte w kursie: roznicaCzasu > 1000 są co najmniej nieprawidłowe (a przynajmniej kompilator swoje zdanie na ten temat powinien wypluć - chyba że ktoś ma wyłączone wyświetlanie ostrzeżeń). Prawidłowo w kursie powinno być: roznicaCzasu > 1000UL 1 Cytuj Link do komentarza Share on other sites More sharing options...
Belferek Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 Nadmiar bibliotek bywa problematyczny, co już na tym forum się przewijało: biblioteka X działa pięknie ale nic mi nie działa jak dodam bibliotekę Y... Święta racja, sam się o tym przekonałem i super przydatnym byłoby zestawienie timerów Arduino wykorzystywanych przez popularne biblioteki. Szukałem i ... nie znalazłem, ale szukam takiego zestawienia dalej. Natomiast IeOS to jakiś koszmarek. Wywoływanie funkcji z poziomu przerwań powinno być karane. Z pewnością masz rację. Należy pamiętać, że procedury obsługi przerwań nie mogą być czasochłonne, ale uważam, że dla prostych zastosowań leOS nie jest zły, a może wiele uprościć. No ale to moje zdanie - początkującego. Pozdrawiam, Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 Belferek, specjalnie nie zajmowałem się tutaj bibliotekami, bo obawiam się, że część osób od razu ominęłaby "ręczne eksperymenty" z millis(). Bez zrozumienia tego tematu nie ma sensu brać się za jakieś gotowce. Może w przyszłości zrobię takie zestawienie - zobaczymy 😉 ethanak, słusznie, już dopisuję! Ciężko mi teraz stwierdzić jak dokładnie radzi sobie z tym tematem Arduino, bo wygląda na to, że wszystko działa bez dopisku UL poprawnie, ale dla formalności zaraz dodam taką informację. Dzięki! Cytuj Link do komentarza Share on other sites More sharing options...
SOYER Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 O co chodzi z tym UL-em?? 🤯 Cytuj Link do komentarza Share on other sites More sharing options...
Belferek Grudzień 31, 2017 Udostępnij Grudzień 31, 2017 W reference znajdziemy: Notes and WarningsU & L formatters: By default, an integer constant is treated as an int with the attendant limitations in values. To specify an integer constant with another data type, follow it with: a 'u' or 'U' to force the constant into an unsigned data format. Example: 33u a 'l' or 'L' to force the constant into a long data format. Example: 100000L a 'ul' or 'UL' to force the constant into an unsigned long constant. Example: 32767ul Więc pisząc np. 1000UL odwołujemy się do wartości unsigned long, a takiego typu wartość (unsigned long) zwraca millis() ReturnsNumber of milliseconds since the program started (unsigned long) Pozdrawiam, Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!