• 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
Zmiana stanów logicznych oświetlenia
#11
(25-11-2019, 12:06)Krzaczek napisał(a): Jeżeli chodzi o aplikację to wszystko działa dobrze. Problem mam tylko z tym manualnym włączeniem i wyłączeniem.
Źle rozwiązałeś porównywanie czasu włączenia i wyłączenia o zadanym czasie. Używasz ">" i "<" a to rodzi problemy. Powinno być "==" ale jak loop wykonuje się długo to będą problemy. Najlepiej obsługiwać RTC na przerwaniu, wtedy warunek "==" na pewno kiedyś wsie wykona (nie będzie pominięty) i co ważne, wykona się raz (zakładam przerwania RTC co sekundę). To rozwiązanie jest najlepsze.
Inna opcja to np porównywać przez > i < oraz ustawianie flagi aby porównanie wykonało się raz, tyle, że to komplikuje kod.

Zmiana PWM dla ściemniania i rozjaśniania też powinna być zrealizowana na przerwaniach. W tym wypadku wystarczy przerwanie 1ms. Można skorzystać z przerwania "systemowego" od T0 (nie napisałeś co to za Arduino, zakładam, że na AVR).

Zrób RTC na przerwaniach, problemy znikną a kod będzie prostszy. Manualne załączenie lampki to ustawienie/skasowanie flagi, która w przerwaniu 1ms rozjaśni/ściemni oświetlenie. Tak samo porównanie RTC operuje na fladze. Prosto i skutecznie.
 
Odpowiedź
#12
Semi bardzo Ci dziękuję za odpowiedź. Zagłębię się w temat przerwań i spróbuję zrobić tak jak mi zasugerowałeś. Jeżeli już zrobię to oczywiście w odpowiedzi udostępnię program Smile
 
Odpowiedź
#13
A może tak.
zadeklarować zmienną "lampa", jak ma wartość 0 to nie świeci a jak ma wartość 1 to świeci, ogólnie dla 1 przebiega proces włączania czyli rozjaśnianie lub wyłączania dla 0 czyli ściemnianie.

byte lampa = 0;

void Timer ()
{
dt = clock.getDateTime();

if ( t1HOn == dt.hour && t1MOn ==dt.minute)
{
lampa = 1;
}
if ( t1HOff == dt.hour && t1MOff ==dt.minute)
{

lampa = 0;
}

}

void Przyciski ()
{
if (jeżeli naciśnięty przycisk załącz lampę )
{
lampa = 1;
}
if (jeżeli naciśnięty przycisk wyłącz lampę )
{
lampa = 1;
}
}
 Powyżej podprogramy, które wywołujesz w pętli loop. Jest jeden mankament, jak mi się zdaje, to przez minutę jak przyjdzie czas załączania lub wyłączania nie będzie można przyciskami gasić lub zapalać lampy. Można to skrócić, ale nie wiem czy jest to konieczne.
Wydaje się proste, w każdej chwili (bez 2 minut na dobę) możesz zmienną "lampa" przyciskami i nie wpływa to na programowe załączanie i wyłączanie.
Przerwanie można wykorzystać do sterowania rozjaśnianiem i ściemnianiem ale ja bym w pierwszej wersji zastosował delay (10).
Mało eleganckie ale jak program tylko to robi co opisałeś to wystarczy. 
 
Odpowiedź
#14
(25-11-2019, 12:51)Krzaczek napisał(a): Semi bardzo Ci dziękuję za odpowiedź. Zagłębię się w temat przerwań i spróbuję zrobić tak jak mi zasugerowałeś. Jeżeli już zrobię to oczywiście w odpowiedzi udostępnię program Smile
Jak chcesz aby program był bardziej pro (na Arduino to raczej niemożliwe) to RTC powinien byc w uC (programowy) synchronizowany zewnętrzym RTC. W razie problemów z zewnętrznym RTC, wewnętrzny nadal działa a program sygnalizuje problem.
Obsługa I2C na AVR też wymagała by zmiany. W praktyce arduinowe libs won i trzeba napisać swoje, odporne na status F8 i dodać funkcję "reanimacji" blokady I2C przez slave.
Te dwie modyfikacje (tak z 1 dzień roboty) zbliżą program do bardziej niezawodnego.


(25-11-2019, 17:19)Agregacik napisał(a): to przez minutę jak przyjdzie czas załączania lub wyłączania nie będzie można przyciskami gasić lub zapalać lampy.
Jak dla mnie nie do zaakceptowania. Modyfikuje soft, w którym czasem (przez arduinowe libs) program nie reaguje przez ponad 5 sekund. To potrafi człowieka doprowadzić do wściekłości a co dopiero 60 sekund.


(25-11-2019, 17:19)Agregacik napisał(a): Przerwanie można wykorzystać do sterowania rozjaśnianiem i ściemnianiem ale ja bym w pierwszej wersji zastosował delay (10). Mało eleganckie ale jak program tylko to robi co opisałeś to wystarczy.
Delay można zrobić na początku, jak działa, to jak najszybciej wywalić to.
Niestety, w Arduino nie da się (nie jest łatwo) wywalić wszystkie delay i "while ( zdarzenie ), bo są one w bibliotekach :-( Taki wątpliwy urok Arduino.

Nawet tak prosty projekt, jak sterowanie światełkiem w akwarium może być dużym wyzwaniem na Arduino jeśli ma to działać pewnie. Gdyby przyszło dodać nadzór przez ETH, rejestrację parametrów jak temp wody w czasie i inne bajery, to projekt jest praktycznie nie do zrealizowania na Arduino z wykorzystaniem jednego uC a jak już na pewno pochłonie bardzo ale to bardzo dużo czasu więc szybciej i lepiej zrobić odcinając się od Arduino.
 
Odpowiedź
#15
Mogę się mylić, ale wydaje mi się że kolega @Krzaczek jest raczej początkującym programistą. Więc może zanim wykona mega profesjonalny program, warto przećwiczyć coś prostego. Rozwiązanie kolegi @Agregacik wydaje mi się łatwiejsze na początek, chociaż mogę się mylić. Proponowałbym zacząć od czegoś co działa, a później udoskonalać. Bo tak dokładając coraz to nowe udoskonalenia po prostu nic z tego nie wyjdzie, a szkoda.
 
Odpowiedź
#16
Krzaczek zleć robotę semi, nie masz szans zrobić dobrego programu, rybki Ci pozdychają, z resztą ja ani tyle nie potrafię pomóc i "zamilkam" w temacie.
 
Odpowiedź
#17
Póki co walczę ze stanami prawda i fałsz, trochę przerobiłem kod timera, prawie udaje mi się osiągnąć to co chciałem, no właśnie prawie. Załóżmy że Godzina ON to 10:00 a godzina OFF to godzina 20:00, mam aktualnie godzinę 15:00 czyli mieszczę się  w przedziale. W tej sytuacji mogę bez problemu zapalać i gasić lampkę przyciskami. Wystarczy że aktualny czas przekroczy godzinę 20:00 i już lampka się sama nie wyłączy bo podczas jej pracy ją wyłączyłem przyciskiem czyli ustawiłem stan na false a potem włączyłem i ustawiłem stan na true. Właśnie te ponowne włączenie przyciskiem spowodowało to że program ignoruje już godzinę wyłączenia a jako priorytet traktuje stan true podyktowany przez naciśnięcie przycisku. Tego właśnie nie mogę obejść. Jeżeli rozwiązałbym problem w przypadku gdzie mieszczę się z aktualną godziną w przedziale włączenia i wyłączenia to pozostaje jeszcze przypadek gdzie aktualny czas jest już poza zakresem przedziału działania lampki oraz przypadek gdzie czas włączenia jest większy od czasu wyłączenia.

Niestety nie dam rady zrobić jak polecił mi kolega Semi, mogę spróbować metodą kolegi Agregacika. Tak czy inaczej, bardzo dziękuję Wam za odpowiedzi do mojego posta.

Aktualnie przerobiony kod timera z problemem opisanym wyżej to:

boolean timer(int tPin, byte hOn, byte mOn, byte sOn, byte hOff, byte mOff, byte sOff) {

  long czWL = (long(hOn) * 3600) + (long(mOn) * 60) + long(sOn);
  long czWYL = (long(hOff) * 3600) + (long(mOff) * 60) + long(sOff);

  boolean Stan = false;

  if (zmierzch == true) {
    Stan = false;
  }
  if (swit == true) {
    Stan = true;
  }

  // Przypadek gdzie czas wlaczenia jest mniejszy od wylaczenia ale aktualny czas miesci sie w tym przedziale

  if (czWL < czWYL) {
    if (AktualnyCzas >= czWL && AktualnyCzas < czWYL) {
      Stan = true;
      if (zmierzch == true) {
        Stan = false;
      }
      if (zmierzch == false) {
        Stan = true;
      }
      if (swit == true) {
        Stan = true;
      }
     
    }
  }

  //przypadek gdzie czas wlaczenia jest mniejszy od wylaczenia ale aktualny cza jest juz poza zakresem wlaczenia i wylaczenia

  if (czWL < czWYL) {
    if (AktualnyCzas >= czWL && AktualnyCzas >= czWYL) {
      Stan = false;
      if(swit == true){
        Stan = true;
      }
     
      if(zmierzch == true){
        Stan = false;
      }
    }
  }


  if (czWL > czWYL) {
    if (AktualnyCzas >= czWL && AktualnyCzas <= 86399) {
      Stan = true;
      if (zmierzch == true) {
        Stan = false;
      } else {
        Stan = true;
      }
    }
    if (AktualnyCzas >= 0 && AktualnyCzas < czWYL) {
      Stan = true;
    }
  }

  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  if (Stan == true) {
    analogWrite(led, jasnosc); // wejscie pwm jest deklarowane na pin leda o okreslonej jasnosci rownej 0
    jasnosc += wypelnienie;
    if (jasnosc > 255) //jesli jest powyzej 255, to ustalamy spowrotem 255
      jasnosc = 255;
  }

  if (Stan == false) {
    analogWrite(led, jasnosc); // wejscie pwm deklarowane na pin led o jasnosci rownej 0
    jasnosc -= wypelnienie;
    if (jasnosc < 0) //jesli spadlo nam ponizej zera, to wracamy na wartosc 0.
      jasnosc = 0;
  }

}
 
Odpowiedź
#18
(25-11-2019, 17:19)Agregacik napisał(a): if ( t1HOn == dt.hour && t1MOn ==dt.minute)
{
lampa = 1;
}
if ( t1HOff == dt.hour && t1MOff ==dt.minute)
{

lampa = 0;
}

}
Funkcja włączenia i wyłączenia wygląda fajnie, ale co jeżeli podczas uruchamiania arduino aktualny czas będzie np. mieścił się w przedziale pomiędzy godziną włączenia i wyłączenia? to wtedy chyba lampka według Twojej funkcji nie będzie świecić? 
 
Odpowiedź
#19
(25-11-2019, 19:04)Krzaczek napisał(a): Niestety nie dam rady zrobić jak polecił mi kolega Semi,
Nie nie dasz tylko nie masz ochoty. Podłącz wyjście przerwań z RTC na pin uC. Obsługa tego przerwania to banał. Skonfiguruje RTC aby generował przerwania co sekundę. Masz już więc przerwania co 1 sekundę.
Można tez inaczej, "podpinasz" sie pod IRQ 1ms, co 1000 przerwań (w praktyce nie - taki urok Arduino) obsługujesz RTC.
Na I2C nie masz nic poza RTC a liczba danych nie przekracza 32, więc możesz w przerwaniu 1 sek czytać RTC po I2C bez problemu.
Teraz porównanie czasu on/off nie jest juz problemem. Nie bedzie "blokady" manualnego on/off przez 1 minutę.


(25-11-2019, 18:59)Agregacik napisał(a): Krzaczek zleć robotę semi,
Aby program napisać dobrze to pewnie min miesiąc roboty a z dokładnymi testami zdecydowanie dłużej. Sam policz ile by to kosztował gdyby to miał robić sprzedawca z dyskontu. Trochę jest? Niestety, dyskontowiec nie zrobi więc przemnóż kwotę przez 5..10.
 
Odpowiedź
#20
W sumie zamiast płacić takiemu marudzie, to lepiej wystawić zlecenie na freelancerze - Hindusi zrobią projekt za grosze, a pan maruda pójdzie pracować w dyskoncie Big Grin
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości