Skocz do zawartości

Millis - co nie działa z resetowaniem czasu ?


OLi_m

Pomocna odpowiedź

Witajcie, 

pewnie jako kolejny mam problem z użyciem funkcji millis.  W złożonym szkicu którym się zajmuję, muszę używać kilkusekundowych zwłok czasowych. Delay nie wchodzi w grę. Oparłem się na znalezionych materiałach włącznie z kursem nr 9.

Dla przejrzystości napisałem krótko oddzielny malutki szkic: ( założenie tutaj to: po 3 sekundach od wciśnięcia przycisku ma zaświecić się dioda ).

#define LED1 12   
#define PRZYCISK 11

unsigned long aktualnyCzas = 0;
unsigned long zapamietanyCzas = 0;
unsigned long roznicaCzasu = 0;

void setup(){
  Serial.begin(9600);
  pinMode(LED1, OUTPUT);
  digitalWrite(LED1, LOW);
  pinMode(PRZYCISK, INPUT);
 
}

void loop() {

if (digitalRead(PRZYCISK) == LOW)    
//Pobierz liczbe milisekund od startu
 { 
   aktualnyCzas = millis();  
  roznicaCzasu = aktualnyCzas - zapamietanyCzas;
  zapamietanyCzas = aktualnyCzas;
  }
  
  //Jeśli różnica wynosi ponad 3 sekund
  if (roznicaCzasu >= 3000UL) {

    Serial.println(roznicaCzasu);
    digitalWrite(LED1, HIGH);       // zaświeć diodę
  }
} 

Problem z drganiem styków rozwiązałem użyciem układu RC i wykorzystując bibliotekę <Bounce2.h> ( tutaj nie zamieszczam, żeby nie zaciemniać treści ).

Problemem przed którym stoję to krótsza w czasie reakcja LED na przycisk. Zasięgnąłem pomocy u sztucznej inteligencji - https://chat.openai.com/chat , ale odpowiedź nic nie pomogła  , cytuję: 

Cytat

Powodem dlaczego dioda świeci się w różnym czasie od naciśnięcia klawisza, jest to, że zmienna "zapamietanyCzas" jest ustawiana tylko raz przed pętlą w funkcji "setup()", a nie jest ustawiana ponownie po każdym naciśnięciu klawisza w funkcji "loop()".

Aby poprawić to, można dodać linijkę kodu do aktualizowanie zmiennej "zapamietanyCzas" po każdym naciśnięciu klawisza, tak aby zawsze zapisywała ona bieżący czas:

Copy code
if (digitalRead(PRZYCISK) == LOW) {
    aktualnyCzas = millis();
    roznicaCzasu = aktualnyCzas - zapamietanyCzas;
    zapamietanyCzas = aktualnyCzas;                                  // Dodanie tej linii
}
Takie rozwiązanie pozwoli na zresetowanie odliczania czasu po każdym naciśnięciu klawisza, a dioda będzie świecić się po upływie 3 sekund od momentu naciśnięcia klawisza.

Jak wspomniałem dodanie tej linii nic to nie daje, a obserwując dane wysyłane na Serial.println(roznicaCzasu) widać, że jednak czas nie resetuje się po naciśnięciu klawisza i stąd świecenie LED bezpośrednio po wciśnięciu klawisza, jeśli czas od resetu wynosił ponad 3 sekundy.

Jak to naprawić ?

Link do komentarza
Share on other sites

Co za czasy, że człowiek pyta się AI o radę 😁

Spróbuj coś takiego (zadeklaruj sobie najpierw zmienną bool):

if (!zapamietany_czas_wcisniecia && digitalRead(PRZYCISK) == LOW)

{

aktualnyCzas = millis();

zapamietany_czas_wcisniecia = true;

}

if ((millis() - aktualnyCzas >= 3000UL) && (digitalRead(PRZYCISK) == LOW)) digitalWrite(LED1, HIGH); // zaświeć diodę

 

Logikę oczywiście można/trzeba rozbudować w zależności od wymagań. Np tutaj można wcisnąć guzik, potem go puścić i znowu wcisnąć, żeby zapalił się led nie wcześniej niż po 3sek.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

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

14 godzin temu, OLi_m napisał:

założenie tutaj to: po 3 sekundach od wciśnięcia przycisku ma zaświecić się dioda

I co dalej?

Czy ma tak świecić aż do wyłączenia zasilania, czy do puszczenia przycisku, czy może coś innego?

@kostuch można to zrobić bez dodatkowej zmiennej, w sumie potrzeba tylko jednej zmiennej do przechowywania czasu.

static uint32_t zapamietanyCzas = millis();
if (digitalRead(PRZYCISK) == HIGH) zapamiętanyCzas = millis();
else if (millis() - zapamiętanyCzas > 3000UL) digitalWrite(LED1, HIGH);

 

  • Lubię! 1
Link do komentarza
Share on other sites

2 godziny temu, OLi_m napisał:

Ten wyłącznik to krańcówka , dioda to siłownik, itd. , całość w switch-case. 

 

No to jak najbardziej użycie funkcji z Bounce2, coś w stylu:

if (!przycisk.read() && przycisk.currentDuration() > 3000) włącz_pompę();

 

Link do komentarza
Share on other sites

20 godzin temu, ethanak napisał:

@Belferek timers to nie pacaneum na kaca 😉 Po co komplikujesz?

Dlaczego @Belferek komplikuje?

Merytoryczna odpiwiedź.

Używam tej biblioteki zawsze, jeszcze nie spowodowała problemów. Kiedy spowoduje?

Chyba, że chodzi o nie stosowanie gotowca, a zrozumienie zasady, to ok.

Link do komentarza
Share on other sites

33 minuty temu, SOYER napisał:

Kiedy spowoduje?

Kiedy będziesz jej używać nie do tego co trzeba.

Zauważ: kolega wątkotwórca używa w programie Bounce2. Z wykorzystaniem tej biblioteki rozwiązanie masz w moim poprzednim poście - dokładnie jedna linijka realizująca to, co było potrzebne (wyjaśnienie: biblioteka Bounce2 dokładnie do tego służy).

Zrób to krócej/lepiej za pomocą timers.

Czy to wystarczająca odpowiedź?

  • Lubię! 1
Link do komentarza
Share on other sites

Dokładnie tak. Bounce2 podaje ile czasu trwa bieżący stan przycisku i ile trwwał poprzedni. currentDuration możesz użyć tak jak w moim przykładzie, a previousDuration np. przy puszczeniu przycisku do sprawdzenia krótkie/długie wciśnięcie.

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Dnia 11.01.2023 o 11:35, ethanak napisał:

I co dalej?

Czy ma tak świecić aż do wyłączenia zasilania, czy do puszczenia przycisku, czy może coś innego?

@kostuch można to zrobić bez dodatkowej zmiennej, w sumie potrzeba tylko jednej zmiennej do przechowywania czasu.

static uint32_t zapamietanyCzas = millis();
if (digitalRead(PRZYCISK) == HIGH) zapamiętanyCzas = millis();
else if (millis() - zapamiętanyCzas > 3000UL) digitalWrite(LED1, HIGH);

 

Zadanie ma co najmniej milion poprawnych rozwiązań 😉

Dodatkowa zmienna dla czytelności kodu. Można napisać poprawnego jednolinijkowca, którego początkujący nie zrozumie zupełnie. Równie dobrze można napisać bez dodatkowego bool'a:

static uint32_t zapamietany_czas;

if (!zapamietany_czas && digitalRead(PRZYCISK) == LOW) zapamietany_czas = millis();

 

Ale czy dla początkującego jest to czytelniejsze? Będzie wiedział że na początku zapamietany_czas jest inicjalizowany na zero, zero to false a niezerowa wartość to true?

Link do komentarza
Share on other sites

2 minuty temu, kostuch napisał:

Dodatkowa zmienna dla czytelności kodu.

A po jakiego grzyba jakieś dodatkowe zmienne (i w ogóle jakieś zmienne) jeśli użyta biblioteka realizuje to sama z siebie?

A wprowadzanie dodatkowych zmiennych wcale nie przyczynia się do uczytelnienia kodu.

Link do komentarza
Share on other sites

4 godziny temu, ethanak napisał:

A po jakiego grzyba jakieś dodatkowe zmienne (i w ogóle jakieś zmienne) jeśli użyta biblioteka realizuje to sama z siebie?

A wprowadzanie dodatkowych zmiennych wcale nie przyczynia się do uczytelnienia kodu.

Eeee... To samo można napisać o komentarzach w kodzie - powinien być samodokumentujący 🙂

Akurat do reakcji na przytrzymanie guzika przez trzy sekundy debounce jest "przeinżynieryzowaniem". Jestem zwolennikiem metodologii KISS (Keep It Simple Stupid).

 

Ale najważniejsze, że autorowi już działa 👍

Link do komentarza
Share on other sites

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!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.