BlackJack 88 Luty 6, 2018 Kurcze a w mich czasach robiło się to na TIMERze i liczniku. Wielozadaniowość bez jawnych przerwań. Wykonalne, ale pełne pułapek. . Cytuj Udostępnij ten post Link to post Share on other sites
mmuha 13 Kwiecień 17, 2018 Witam,Właśnie borykam się z problemem millis() i (prawie) 50 dni. Bo jeżeli chcę obliczyć różnicę: różnica = czasAktualny - czasZapamiętany to przy zmiennych unsigned long po czasie (2^32)-1 czas aktualny robi się mniejszy od zapamiętanego i różnica jest ujemna. Ogólnie dobrym sposobem na to jest podzielenie różnicy czasu modulo (2^32) czyli: różnica = (czasAktualny - czasZapamiętany) % (2^32) W excelu to działa bez zarzutu i zawsze pokazuje prawidłową różnicę czasu (funkcja excela MOD(różnica, 2^32)). Symulacja wygląda następująco: Ale Arduino daje jakieś dziwne wyniki. Sprawdzałem z innymi rodzajami zmiennych (double, signed long) ale nie wylicza prawidłowej różnicy czasu. Korzystanie z funkcji abs() także nie pomaga. Czy przykład podany w artykule (tzn. zwykła różnica bez kombinowania) na pewno zadziała, bo nie chce mi się czekać 50 dni żeby sprawdzić BTW jest jakiś sposób na zasymulowanie końcowych wartości funkcji millis(), tak żeby to przetestować? Cytuj Udostępnij ten post Link to post Share on other sites
Treker 1729 Kwiecień 17, 2018 BTW jest jakiś sposób na zasymulowanie końcowych wartości funkcji millis(), tak żeby to przetestować? Ciężko będzie nadpisać wartości zwracane przez tę funkcję. Najszybciej byłoby pewnie przygotować funkcję millisTest(), która będzie zwracała jakieś inne, większe wartości. Wewnątrz tej funkcji możesz mieć przykładowo coś w rodzaju return 4294960000 + milis(); Wtedy zmienna przepełni się po około 7 sekundach 1 Cytuj Udostępnij ten post Link to post Share on other sites
ethanak 1004 Kwiecień 17, 2018 Po pierwsze: różnica dwóch liczb unsigned będzie również unsigned, czyli z założenia nie może być ujemna. Po drugie: nie ma konieczności jakichkolwiek modulo - liczba unsigned long jest 32-bitowa i raczej większa niż 2^32 nie będzie. Po trzecie: Excel to nie Arduino. Ergo: zwykłą różnica bez kombinowania wystarczy. Jeśli nie wierzysz, poodejmuj sobie parę większych liczb. Cytuj Udostępnij ten post Link to post Share on other sites
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Szukasz producenta PCB?Sprawdź przetestowaną firmę JLCPCB. Dlaczego warto? • Prototypy PCB za 2$ (gotowe w 24 godziny) • Kody zniżkowe dla nowych klientów (po rejestracji) • Produkcja w profesjonalnej fabryce (zobacz film) Sprawdź też » Jak powstaje PCB? Wycieczka po fabryce
OG 0 Czerwiec 17, 2018 A ja mam takie pytanie zmieniłem swój kod tzn wyrzuciłem gdzie się dało delay a wstawiłem millis. program ładnie działa tylko ze tylko raz (za sterowanie diodami odpowiada czujni ruchu ) jak dalej nim ruszam to nie załączają się diody jak w ostatnim przykładzie tylko wszystko miga. może ktoś pomógłby mi pomóc #include <OneWire.h> //dodaj biblitekę LiquidCrystal.h #include <DallasTemperature.h> //dodaj biblitekę LiquidCrystal.h #include <LiquidCrystal.h> //dodaj biblitekę LiquidCrystal.h #define one_wire 2 //Transmisja 1-Wire na pinie 10 #define temp 12 //pin 12 jako led wyjscie #define ruchLED 13 //wyjscie czujnika wibracji led #define ruchINPUT 3 //wejscie czujnika wibracji unsigned char state = 0; int stantemp = LOW; int stanruchLed = LOW; unsigned long zapamientanyczastemp = 0; unsigned long aktualnyCzas = 0; unsigned long zapamientanyczasled = 0; OneWire oneWire(one_wire); //wywołujemy transmisję 1-Wire na pinie 10 DallasTemperature sensors(&oneWire); //informujemy Arduino, ze przy pomocy 1-Wire //chcemy komunikowac sie z czujnikiem void setup(void){ pinMode(ruchLED, OUTPUT); //ustawian ruchled na wyjsciu danych pinMode(ruchINPUT, INPUT); //ustawian ruchinput jako wejscie danych //Trigger the blink function when the falling edge is detected attachInterrupt(0, blink, FALLING); Serial.begin(9600); //odczyt danych pinMode(temp,OUTPUT); //ustawiamy led od temp jako wyjscie sensors.begin(); //rozpocznij odczyt z czujnika } void loop(void){ //Pobierz liczbe milisekund od startu aktualnyCzas = millis(); sensors.requestTemperatures(); while (state != 0 && sensors.getTempCByIndex(0) >= 20 && sensors.getTempCByIndex(0) <= 30 ) { state = 0; zapamientanyczastemp = aktualnyCzas; stantemp = !stantemp; digitalWrite(temp, stantemp); digitalWrite(ruchLED, HIGH); //jesli jest ruch i miesci sie w przedziale załącza led } sensors.requestTemperatures(); if (state != 0 && sensors.getTempCByIndex(0) <= 18) { // jezeli jest temp dobre wszytskie led włączone zminilem na 18 state = 0; digitalWrite(ruchLED, HIGH); //jesli jest ruch załacz diody spełniony warunek digitalWrite(temp, HIGH); } else if (aktualnyCzas - zapamientanyczasled >= 8000UL) { // w przeciwnym wypadku (brak ruchu) zgaś wszystko digitalWrite(ruchLED, LOW); digitalWrite(temp, LOW); } } void blink() { state++; } Cytuj Udostępnij ten post Link to post Share on other sites
Treker 1729 Czerwiec 18, 2018 OG, witam na forum! Ciężko do razu znaleźć przyczynę Twojego problemu, jeśli jednocześnie zmieniłeś kilka rzeczy w programie. Jeśli kod działa raz poprawnie, to pewnie w złym miejscu przypisujesz dane do zmiennych odpowiadających za zliczanie czasu i nie są później aktualizowane. Spróbuj wyświetlać sobie np. przez UART wartości aktualnyCzas oraz zapamientanyczasled i zobacz co się z nimi dzieje Cytuj Udostępnij ten post Link to post Share on other sites
OG 0 Czerwiec 18, 2018 no kurde dzięki kolego, problem rozwiązany- pomyliłem zmienne, przez pomyłkę albo z nie wiedzy wpisałem zmienną która nigdzie nie ma odniesienia. Teraz jeszcze jedno pytanie jak za pomocą mills przyspieszyć miganie led chciałbym żeby 3 s świeciła a 1 nie. Proszę o podpowiedz tylko co muszę zmienić . Cytuj Udostępnij ten post Link to post Share on other sites
Treker 1729 Czerwiec 18, 2018 OG, możesz np. napisać program w taki sposób, aby zwiększał wartość jakiejś zmiennej licznikowej co sekundę. Wtedy w pętli głównej wystarczy zrobić coś w stylu: jeśli wartość licznika równa się 1, 2 lub 3 to dioda ma być włączona, a przy wartości wynoszącej 4 wyłączamy diodą i zerujemy zmienną licznikową Cytuj Udostępnij ten post Link to post Share on other sites
KarolKarol 1 Październik 7, 2018 // pierwszy wpis. Cześć! (nie bijcie) Jestem bardzo początkujący, ale wydaje mi się (i mój excel to potwierdza), że po 50 dniach, kiedy millis() zacznie naliczać od zera- szkic z kursu przestaje działać poprawnie. Tabela w załączniku. 1 Cytuj Udostępnij ten post Link to post Share on other sites
Treker 1729 Październik 7, 2018 @KarolKarol, witam na forum Widzę, że to Twoje pierwsze kroki na Forbocie, oto najważniejsze informacje na start: Chcesz przywitać się z innymi członkami naszej społeczności? Skorzystaj z tematu powitania użytkowników. Opis najciekawszych funkcji, które ułatwiają korzystanie z forum znajdziesz w temacie instrukcja korzystania z forum - co warto wiedzieć? Poszczególne posty możesz oceniać (pozytywnie i negatywnie) za pomocą reakcji - ikona serca w prawym dolnym rogu każdej wiadomości. 17 godzin temu, KarolKarol napisał: Jestem bardzo początkujący, ale wydaje mi się (i mój excel to potwierdza), że po 50 dniach, kiedy millis() zacznie naliczać od zera- szkic z kursu przestaje działać poprawnie. Tabela w załączniku. Super, że nie wierzysz na słowo i próbujesz to dokładniej sprawdzić. Nie analizowałem dokładnie Twojego Excela, ale na początek rzuca mi się w oczy od raz pewien błąd. W kolumnie "różnica czasu" masz od pewnego momentu ujemne wartości. W programie byłoby to niemożliwe. Zwróć uwagę, że zmienna ta jest zadeklarowana jako "unsigned long", czyli zmienna bez znaku. Oznacza to, że nie może ona przyjąć wartości ujemnej. Nawet jeśli taką wartość do niej wpiszesz to w wyniku otrzymasz wartość dodatnią. Jaką? Sprawdź najlepiej prostym programem, w którym przypiszesz taką wartość "na sztywno" do zmiennej, a później wyświetl ją sobie np. w monitorze portu szeregowego. Cytuj Udostępnij ten post Link to post Share on other sites
KarolKarol 1 Październik 7, 2018 (edytowany) Pięknie dziękuję za odpowiedź. Czyli będzie wartość bezwzględna z różnicy. Wtedy kiedy millis() dochodzi do maxa i się zeruje - wynik różnicy jest ogromny, dużo większy niż nasze 1000UL - wtedy program zrobi "skok w czasie" i wyświetli napis wcześniej. Czy rozwiązaniem jest tylko zewnętrzny zegar czasu rzeczywistego? Edytowano Październik 7, 2018 przez KarolKarol Cytuj Udostępnij ten post Link to post Share on other sites
ethanak 1004 Październik 8, 2018 Używasz niewłaściwego narzędzia. Arytmetyka liczb bez znaku o określonej długości to nie jest ta sama arytmetyka której używa Excel i której uczyliśmy się w podstawówce. Piszesz że wynik jest ogromny... owszem, ale zbyt ogromny by zmieścić się w 32 bitach - i po obcięciu otrzymamy prawidłowy wynik. W skrócie - wyniki wszystkich operacji musisz potraktować modulo 2^32. 2 Cytuj Udostępnij ten post Link to post Share on other sites
Treker 1729 Październik 8, 2018 14 godzin temu, KarolKarol napisał: Czyli będzie wartość bezwzględna z różnicy. Nie. Tak jak pisałem: 16 godzin temu, Treker napisał: Nawet jeśli taką wartość do niej wpiszesz to w wyniku otrzymasz wartość dodatnią. Jaką? Sprawdź najlepiej prostym programem, w którym przypiszesz taką wartość "na sztywno" do zmiennej, a później wyświetl ją sobie np. w monitorze portu szeregowego. Naprawdę warto sprawdzać takie rzeczy w praktyce i nie zakładać, że coś musi być tak jak nam się wydaje 1 Cytuj Udostępnij ten post Link to post Share on other sites
Madaulpe 2 Listopad 23, 2018 Witam Wszystkich, Dzięki za objaśnienie tematu wielozadaniowości, dzięki temu udało mi się zrobić kolejny krok do przodu. Obecnie próbuję zrobić własną funkcje do migania diodami. Funkcja 1 działa tak jak tego oczekuje dla jednej diody. Jednak kiedy próbuję ją zastosować do kolejnej diody to już nie działa. Jest to dla mnie zrozumiałe (jest tam stan diody który nie może być taki sam dla różnych diod oraz zapamiętany czas który też będzie się różnił dla każdej następnej diody. Poradziłem sobie z tym pisząc drugą funkcje która różni się tymi parametrami i wszystko działa. Nie chcę jednak tworzyć nowych funkcji dla każdej następnej diody. Próbuję zastosować tablice ale nie bardzo mi to wychodzi i już trochę zwątpiłem czy idę w odpowiednim kierunku. Mój kod z dwoma funkcjami: unsigned long prv_T_1 = 0; unsigned long prv_T_2 = 0; unsigned long curren_T = 0; int stanLED_1 = LOW; int stanLED_2 = LOW; void setup() {} void loop() { curren_T = millis(); LED_BLINK_1 (300, 30, 2); //czas LED OFF / czas LED ON / pin LED_BLINK_2 (100, 500, 3); //czas LED OFF / czas LED ON / pin } //------------------ FUNKCJA 1 ----------------------- void LED_BLINK_1(unsigned long interval, unsigned long blink_T, int pin) { pinMode(pin, OUTPUT); if (stanLED_1 == LOW) { if (curren_T - prv_T_1 >= interval) { stanLED_1 = HIGH; digitalWrite(pin, stanLED_1); prv_T_1 = curren_T; } } else { if (curren_T - prv_T_1 >= blink_T) { stanLED_1 = LOW; digitalWrite(pin, stanLED_1); prv_T_1 = curren_T; } } } //------------------ FUNKCJA 2 ----------------------- void LED_BLINK_2(unsigned long interval, unsigned long blink_T, int pin) { pinMode(pin, OUTPUT); if (stanLED_2 == LOW) { if (curren_T - prv_T_2 >= interval) { stanLED_2 = HIGH; digitalWrite(pin, stanLED_2); prv_T_2 = curren_T; } } else { if (curren_T - prv_T_2 >= blink_T) { stanLED_2 = LOW; digitalWrite(pin, stanLED_2); prv_T_2 = curren_T; } } } Cytuj Udostępnij ten post Link to post Share on other sites
D3binski 10 Listopad 25, 2018 (edytowany) #define kontaktron 4 #define pir 7 #define led_r 5 #define led_g 6 #define led_b 9 #define foto_rez A0 #define potencjometr A5 unsigned long aktualnyCzas = 0; //Zmiene pomocnicze do obslugiwania f. miilis() unsigned long zapamietanyCzas = 0; unsigned long timerLED = 10000; boolean czyCiemno = false; //zmienna infomujaca o oswietleniu boolean czyWlaczyc = false; //zmienna pomocnicza do f. wlacznik() boolean zapamietanyTryb = czyWlaczyc; int progJasnosci = 0; //zmienne do obslugiwania progu jasnosci int wartoscPotencjometru = 0; int jakJasno = 0; void setup() { Serial.begin(9600); pinMode(kontaktron, INPUT_PULLUP); //Ustawienie pinow pinMode(pir, INPUT); pinMode(led_r, OUTPUT); pinMode(led_g, OUTPUT); pinMode(led_b, OUTPUT); } void loop() { aktualnyCzas = millis(); //pobranie czasu ktory uplynal od wlaczenia plytki progJasnosci = analogRead(potencjometr); jakJasno = map(analogRead(foto_rez), 0, 1023, 200, 1100); if(jakJasno < progJasnosci){ //sprawdzenie poziomu jasnosci czyCiemno = true; //jesli ciemno, to zmien watosc zmiennej na pawde } else{ czyCiemno = false; //jesli jasno, zmien wartosc funkci na true czyWlaczyc = false; } if(czyCiemno){ //jesli jest ciemno if(digitalRead(kontaktron) == HIGH){ czyWlaczyc = false; } else if(digitalRead(pir) == HIGH){ //jesli wykryto takze ruch zapamietanyCzas = aktualnyCzas; //zapamietaj czas w ktorym ostatnio wykryles ruch czyWlaczyc = true; } } else{ czyWlaczyc = false; //jesli jest jasno to wylacz swiatlo } if(aktualnyCzas - zapamietanyCzas >= timerLED){ //jesli minie wyznaczony czas czyWlaczyc = false; //wylacz swiatlo } if(zapamietanyTryb == !czyWlaczyc){ //jesli zmieni sie tryb swiecenia zapamietanyTryb = czyWlaczyc; //zapamietaj aktualny tryb wlacznik(czyWlaczyc); //pzekaz aktualny tryb do f. wlacznik } } void wlacznik(boolean tryb){ //Funkcja obslugujaca wlaczanie/wylaczanie swiatla if(tryb){ digitalWrite(led_r, HIGH); digitalWrite(led_g, HIGH); digitalWrite(led_b, HIGH); } else{ digitalWrite(led_r, LOW); digitalWrite(led_g, LOW); digitalWrite(led_b, LOW); } } Program rozbudowany o fotorezystor i potencjometr to ustawienia maksymalnej wartości natężenia światła. Funkcja map do zneutralizowania problemu ze zbyt małą wartością napięcia na fotorezystorze przy zgaszonym świetle. Uwagi mile widziane, może uda się coś skrócić. @Treker, ogromne podziękowania i ukłony w Twoją stronę. Świetnie się bawiłem już od pierwszego poziomu kursu. Edytowano Listopad 25, 2018 przez D3binski Cytuj Udostępnij ten post Link to post Share on other sites
Polecacz 101 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