• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Przekaźnik czasowy na attiny13
#11
(17-04-2024, 08:58)Spinus napisał(a): Witam, potrzebuje zaprogramować przekaźnik pompy na attiny13 w następujący sposób:
1. Wyłączona 20min
2. Włączona 90s
3. Wyłączona 60min
Punkt 2 i 3 w pętli

Próbowałem funkcją delay ale maksymalny czas mi wychodził około 1min, a millis coś mi nie wychodzi.

Czy ktoś był by mi w stanie pomóc ?

kolejny pomysł to własna fukcja delay

Kod:
void customDelay(unsigned long czas_opoznienia) {
  unsigned long czas_startu = millis();
 
  while (millis() - czas_startu < czas_opoznienia) {
    delay(10);
  }
}
 
Odpowiedź
#12
(17-04-2024, 14:10)Łowiczak napisał(a): może zamiast delay użyj cykle zegara systemowego,  coś w tym stylu

Kod:
#define CZAS_WYLACZONA 20 * 60 * 1000  // 20 minut w milisekundach
#define CZAS_WLACZONA 90 * 1000         // 90 sekund w milisekundach
#define CZAS_POMIEDZY 60 * 60 * 1000   // 60 minut w milisekundach

enum Stan { WYLACZONA, WLACZONA, POMIEDZY };
Stan obecny_stan = WYLACZONA;

unsigned long czas_startu = 0;

void setup() {
  // Konfiguracja pinów i przekaźnika
}

void loop() {
  switch (obecny_stan) {
    case WYLACZONA:
      if (millis() - czas_startu >= CZAS_WYLACZONA) {
        czas_startu = millis();
        obecny_stan = WLACZONA;
      }
      break;
    case WLACZONA:
      if (millis() - czas_startu >= CZAS_WLACZONA) {
        czas_startu = millis();
        obecny_stan = POMIEDZY;
      }
      break;
    case POMIEDZY:
      if (millis() - czas_startu >= CZAS_POMIEDZY) {
        czas_startu = millis();
        obecny_stan = WYLACZONA;
      }
      break;
  }
}
Chyba jeszcze nie ogarniam. Wybaczcie ale jestem początkującym. Konfiguracja to mam wpisać: pinMode(4, OUTPUT); ?Czy coś jeszcze bo coś mi nie chce wcale zadziałać.
 
Odpowiedź
#13
(18-04-2024, 07:48)Łowiczak napisał(a):
(18-04-2024, 07:32)oscarX napisał(a): Tylko trzeba pamiętać, że millis też się zeruje co jakiś czas - kilkadziesiąt dni, co generuje taki problem, ...

to że się zeruje nie ma żadnego znaczenie bo jest w pętli pobierane za każdym razem pdczas zmiany stanu, czyli tak jakby program zaczął działanie od nowa, podobnie jak podczas zaniku zasilania

PS. Funkcja millis() w mikrokontrolerach Arduino (w tym ESP8266 używanym w NodeMCU) zwraca liczbę milisekund od czasu uruchomienia urządzenia. Oznacza to, że wartość zwracana przez millis() zwiększa się w miarę upływu czasu od momentu uruchomienia urządzenia i nie jest zerowana automatycznie.

Jednakże, wartość zwracana przez millis() jest liczbą typu unsigned long, która ma ograniczenie górne. Po przekroczeniu maksymalnej wartości (4294967295 milisekund, czyli około 50 dni), wartość ta przepełnia się i zaczyna od zera. To oznacza, że z powodu przepełnienia millis() zacznie zwracać wartości od zera i liczyć czas od now
Wszystko i tak będzie codziennie resetowane więc żaden problem
 
Odpowiedź
#14
pisałem w pierwszej wiadomości abyś wkleił kod programu, pokaż co sam napisałeś
 
Odpowiedź
#15
Millis się przepełnia, ale działania zrobione na liczbach bez znaku typu uint32_t powodują, że nie ma żadnego końca działania i nic się nie "psuje" po tych 54 dniach, można to sobie przetrenować na liczbach typu uint8_t czy uint16_t wprost inkrementując je w każdym obiegu loop, porównując warunki i wykonując jakieś działania co określoną wartość.
Przykładowy kod przetestuj na zwykłym UNO, potem ewentualnie na attiny13, niektóre core mogą wyłączyć millis by oszczędzać zasoby tak małych uC.
Możesz mieć też źle ustawiony Attiny13.
Fabrycznie uC jest ustawiony na 1MHz, trzeba wypalić bootloader by go ustawić na takie MHz jak w Arduino IDE, czyli np. 9.6 MHz. Bez tego 90s będzie trwało z 900s. W Attiny13 wypalenie bootloadera tylko ustawia fusebity.

Jak to jedyna funkcja programu to można zrobić na delay, duże delay nie zadziałają, ale jak masz rozdzielczość działania 1s to można zrobić np. 90 x delay 1000:

Kod:
#define CZAS_WYLACZONA 20 * 60    // 20 minut 
#define CZAS_WLACZONA 90           // 90s 
#define CZAS_POMIEDZY 60 * 60    // 60s

#define pompa 4

void setup() {
  // Konfiguracja pinów i przekaźnika
digitalWrite(pompa, 0); 
pinMode(pompa, OUTPUT);
for (int i=0;i< CZAS_WYLACZONA;i++)
{
  delay(1000);
}
}

void loop() {

  digitalWrite(pompa, 1); 
for (int i=0;i< CZAS_WLACZONA;i++)
{
  delay(1000);
}
  digitalWrite(pompa, 0); 
for (int i=0;i< CZAS_POMIEDZY;i++)
{
  delay(1000);
}


}

Niektóre przekaźniki są aktywowane zerem, trzeb zamienić 1 i 0.
Oczywiście millis, czy choćby ten sam kod z delay 1000 i  switch case byłby lepszy, bo można wtedy uruchomić WDT ustawiony na >1000ms i będzie pilnował, czy nie wydarzyło się coś niezwykłego i wtedy zresetuje uC, przy delay 90x60 to nie bardzo idzie zastosować, max czas WDT to 8s. Ale w celach edukacyjnych można zastosować i takie proste rozwiązanie jako pierwsze przybliżenie.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#16
... to jak doczekamy się kodu aby Ci pomóc?
 
Odpowiedź
#17
Zawsze można użyć sprzętowy timer i ustawić przerwanie na 1 lub 10 s bez zbędnych jakiś dziwacznych wyliczeń millis
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#18
(18-04-2024, 22:29)Łowiczak napisał(a): ... to jak doczekamy się kodu aby Ci pomóc?
Przepraszam że tak długo, ale pracuje. To jest jeden z kodów który zaczął jakoś działać, tylko problem jest taki że jak na próbę dałem leda to po tych 20min i 100s led przygasa ale nie gaśnie. dopiero jak minie następne 40min to gaśnie.
Czasy też są zaniżone, ale podejrzewam że prędkości zegarów się nie zgadzają. Ale to nie jest problemem.

Kod:
#define LED_1 4

bool stan_LED_1 = false;

unsigned long now = 0;

unsigned long timer_LED_1 = 0;

void setup() {
  pinMode(LED_1, OUTPUT);

}

void loop() {
   now = millis();

  if(now - timer_LED_1 >= 20*60*1000UL){
    digitalWrite(LED_1, HIGH);
  }
 if(now - timer_LED_1 >= 100*1000UL){
    digitalWrite(LED_1, LOW);
  }
   if(now - timer_LED_1 >= 40*60*1000UL){
    timer_LED_1 = now;
  }
}
 
Odpowiedź
#19
zobacz czy to zadziała jak trzeba

Kod:
#define LED_1 4

bool stan_LED_1 = false;

unsigned long now = 0;

unsigned long timer_LED_1 = 0;

enum LED_State { OFF, ON_SHORT, OFF_SHORT, ON_LONG };

LED_State ledState = OFF;

void setup() {
  pinMode(LED_1, OUTPUT);
}

void loop() {
  now = millis();

  switch (ledState) {
    case OFF:
      if (now - timer_LED_1 >= 20 * 60 * 1000UL) {
        digitalWrite(LED_1, HIGH);
        ledState = ON_SHORT;
        timer_LED_1 = now;
      }
      break;

    case ON_SHORT:
      if (now - timer_LED_1 >= 90 * 1000UL) {
        digitalWrite(LED_1, LOW);
        ledState = OFF_SHORT;
        timer_LED_1 = now;
      }
      break;

    case OFF_SHORT:
      if (now - timer_LED_1 >= 20 * 60 * 1000UL) {
        digitalWrite(LED_1, HIGH);
        ledState = ON_LONG;
        timer_LED_1 = now;
      }
      break;

    case ON_LONG:
      if (now - timer_LED_1 >= 60 * 60 * 1000UL) {
        digitalWrite(LED_1, LOW);
        ledState = OFF;
        timer_LED_1 = now;
      }
      break;
  }
}
 
Odpowiedź
#20
(18-04-2024, 14:03)kaczakat napisał(a): Millis się przepełnia, ale działania zrobione na liczbach bez znaku typu uint32_t powodują, że nie ma żadnego końca działania i nic się nie "psuje" po tych 54 dniach, można to sobie przetrenować na liczbach typu uint8_t czy uint16_t wprost inkrementując je w każdym obiegu loop, porównując warunki i wykonując jakieś działania co określoną wartość.
Przykładowy kod przetestuj na zwykłym UNO, potem ewentualnie na attiny13, niektóre core mogą wyłączyć millis by oszczędzać zasoby tak małych uC.
Możesz mieć też źle ustawiony Attiny13.
Fabrycznie uC jest ustawiony na 1MHz, trzeba wypalić bootloader by go ustawić na takie MHz jak w Arduino IDE, czyli np. 9.6 MHz. Bez tego 90s będzie trwało z 900s. W Attiny13 wypalenie bootloadera tylko ustawia fusebity.

Jak to jedyna funkcja programu to można zrobić na delay, duże delay nie zadziałają, ale jak masz rozdzielczość działania 1s to można zrobić np. 90 x delay 1000:

Kod:
#define CZAS_WYLACZONA 20 * 60    // 20 minut 
#define CZAS_WLACZONA 90           // 90s 
#define CZAS_POMIEDZY 60 * 60    // 60s

#define pompa 4

void setup() {
  // Konfiguracja pinów i przekaźnika
digitalWrite(pompa, 0); 
pinMode(pompa, OUTPUT);
for (int i=0;i< CZAS_WYLACZONA;i++)
{
  delay(1000);
}
}

void loop() {

  digitalWrite(pompa, 1); 
for (int i=0;i< CZAS_WLACZONA;i++)
{
  delay(1000);
}
  digitalWrite(pompa, 0); 
for (int i=0;i< CZAS_POMIEDZY;i++)
{
  delay(1000);
}


}

Niektóre przekaźniki są aktywowane zerem, trzeb zamienić 1 i 0.
Oczywiście millis, czy choćby ten sam kod z delay 1000 i  switch case byłby lepszy, bo można wtedy uruchomić WDT ustawiony na >1000ms i będzie pilnował, czy nie wydarzyło się coś niezwykłego i wtedy zresetuje uC, przy delay 90x60 to nie bardzo idzie zastosować, max czas WDT to 8s. Ale w celach edukacyjnych można zastosować i takie proste rozwiązanie jako pierwsze przybliżenie.
Wszystko działa jak należy, dziękuję bardzo.
Jeszcze zostało mi rozpracować jak to działa bo nie do końca rozumiem, ale wszystko przede mną
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości