Skocz do zawartości

Millis - co nie działa z resetowaniem czasu ?


Pomocna odpowiedź

Napisano

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ć ?

40 minut temu, OLi_m napisał:

Jak to naprawić ?

Używasz Bounce2, tak? No to przecież tam masz funkcje currentDuration i previousDuration. 

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

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.

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

Dzięki wielkie za rozwiązanie  🙂 .  Dla mnie początkującego to bardzo wiele .

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

Pozdrawiam 

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ę();

 

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.

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

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
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?

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.

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 👍

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...