Witam. Posiadam inkubator i sterownik do niego. Wszystko jest okej gdy program działa na wait'ach. Chcę przepisać go do przerwania na timerze ale program mi się zawiesza po wgraniu. Po uruchomieniu nie zawsze pokaże temperaturę, po wyjściu z "menu" również czysty ekran zamiast pomiarów.
Cała konstrukcja składa się z:
*czterech przycisków Sw1-Sw4
*dwóch czujników temperatury DS18B20 1wire na jednej linii
*wyświetlacza 2x16
*dwa przekaźniki opisane jako "Przekaźnik1" i Przekaźnik2"
Gdzie w programie popełniłem błąd?
Liczę na pomoc z waszej strony.
Nie wiem czy chcesz się nauczyć czy potrzebujesz program.
Na początek te uwagi:
1. Nie wiem co tam robi dyrektywa $eeprom. Jest niepotrzebna w tym kodzie
2. Zmienna Ds jest zwiększana w przerwaniu niezależnie od tego czy jesteś w Menu czy nie. Tak więc po powrocie z Menu już na pewno nie zdążysz załapać się na warunek If Ds = 2 i wyzerować jej wartość.
3. Korzystasz z GoTo to bardzo nierozważne. GoTo używa się tylko do przeskoczenia linii kodu które nie chcesz żeby się wykonały jeśli zaszedł jakiś warunek.
Poniżej przepisany program.
Używa CTC i zapisuje do eeproma. Przy starcie czyta z eeproma.
Bardzo dziękuje! Wczoraj walczyłem z eeprom'em i dlatego został wpis na początku. Przekaźniki same mi pstrykały co ułamek sekundy i przy zapisie, odczycie miałem tylko "-0.0".
Poczytam helpa i postaram się zrozumieć jak działa program poprawiony przez Ciebie.
Dodano po 6 [minuty]:
Tylko jedna sprawa. Zmienna Termostat i Histereza potrzebne są z przecinkiem. Jak to osiągnąć? Być może miałem problemy bo chciałem zapisać zmienną single do eeprom'u
Kod wydaje się sprawować prawidłowo. Przecinek jest względny.
Operacje na zmiennych z przecinkiem są męczące dla mikrokontrolera. Jesli nie jest to konieczne to należy ich unikać. Zauważ że sam DS nie wysyła Single tylko Integer. Każda zmienna z jednym miejscem po przecinku pomnożona przez dziesięć da liczbę całkowitą.
Tutaj przecinek jest "wirtualny" i domalowany przez funkcję FORMAT
Z przykładowej wartości 371 zrobi na wyświetlaczu 37,1
Dlatego regulacja o 1/10 stopnia czyli 0,1st realizowana jest przez dodanie albo odjęcie jednynki.
Jeśli zmienna Termostat ma być regulowana z dokładnością 0,1st to ten zapis
Code: basic4gl
Log in, to see the code
trzeba zamienić na
Code: basic4gl
Log in, to see the code
To samo z odejmowaniem.
Uznałem że regulacja taka byłaby długotrwała.
Dodatkowo kilka cyferek możesz dostosować do swoich potrzeb.
Bez problemu można zrobić szybsze przestawianie o stopień przy dłuższym naciśnięciu a o 0,1st przy krótkim naciśnięciu, ale zostawiłem coś Autorowi Nie ruszałem też drugiego przekaźnika.
Mój kod jest nawet o 10% mniejszy mimo iż ma więcej funkcji wiec możesz dopisać co tam potrzebujesz.
Pod tym linkiem możesz zobaczyć też inny kod do termostatu wylęgarni który pomagałem przerobić Link (na samym końcu jest w pełni działający kod)
Super, w najbliższym czasie przeanalizuje dokładnie program. Drugi przekaźnik jest jako alarmowy, załącza syrenę po przekroczeniu zadanych temperatur, ale z tym dam radę Jeszcze raz dziękuje Sterownik zyskał obudowę to program też by się przydał https://www.elektroda.pl/rtvforum/viewtopic.php?p=14586825#14586825
Po Pierwsze:
Dlaczego zostały użyte funkcje jeśli? Nie można ich pominąć? Przy okazji, jak to jest zrobione, że na końcu warunku nie ma "end if"? Piszę programy amatorsko, z tego co potrafię.
Code: basic4gl
Log in, to see the code
Po Drugie:
Na początek powiem jak to rozumiem:
Code: basic4gl
Log in, to see the code
Jest zmienna "Status" od której zależy gdzie znajdziemy się w programie. Jeśli będzie ona wynosiła 0 to ujrzymy pierwszy, główny program odczytu temperatury.
Po Trzecie:
Nie rozumiem tej części i dalej. Mianowicie, dlaczego reszta tego się nie wyświetla? To tylko i wyłącznie dlatego że zmienna "Status" jest równa 0?
Code: basic4gl
Log in, to see the code
Widzę że wszystko się kręci wokół zmiennej Status. Nie mogę tego załapać Jeśli uda się jakoś wyjaśnić wyżej przedstawione zagadki, myślę że włączy się u mnie bardziej logiczne myślenie (W programie dopisałem wg wzorów ustawienie temperatury maksymalnej i minimalnej przy jakich ma się załączyć alarm)
Gdybym opisał program wszystko stałoby się oczywiste
Użycie IF ELSE bez END IF zawsze warte jest omówienia bo potem nikt nie może się doliczyć END IF
Chodzi o to że jeśli tylko jedna instrukcja jest od jakiegoś warunku zależna to można ją zapisać w jednej linii. Jeśli z powodu jakiegoś warunku musza juz być zmienione dwie zmienne lub wykonać się dwie instrukcje to już musisz to rozpisać w wielu liniach. Tak więc możesz napisać
Code: basic4gl
Log in, to see the code
Jest to jednak niepotrzebne bo można to zapisać tak:
Code: basic4gl
Log in, to see the code
Jeśli jednak A ma być wyzerowane i ma się stać coś jeszcze to juz musisz to rozpisać na wiecej linii.
Code: basic4gl
Log in, to see the code
Teraz dopiero dodam że można jeszcze coś dodać w tej jednej linii jeśli warunek nie jest spełniony. I również można tam zapisać tylko jedną instrukcję.
Można więc zapisać coś takiego
Code: basic4gl
Log in, to see the code
Co oznacza zwiększaj A jeśli mniejsze od 4
Jeśli jednak jest dużo IF to można się gubić...Jest na to sposób
Jeśli cokolwiek jest zapisane za wyrażeniem "Then" znaczy ze jest to zapis w jednej linii i nie potrzebuje "End If" oraz...co jest ważniejsze, instrukcje pod tą linią nie są już objęte IF`em
Wracając do pierwszego pytania
Code: basic4gl
Log in, to see the code
Ten zapis tworzy granicę do której można podnieść wartośc zmiennej.
Znaczy "Tylko jeśli jeszcze zmienna nie ma 400 to dodaj jeden" Jeśli juz ma 400 to nic się nie doda.
Takie zabezpieczenie stosje się tym częściej im mniejsza jest zmienna. Na przykład Bajt
Code: basic4gl
Log in, to see the code
Stosuje się dlatego że po dodaniu 1 do 255 wartość wynosiłaby znów 0.
Moim zdaniem dużo ciekawszy jest ten zapis
Code: basic4gl
Log in, to see the code
Pomyśl jakie wartości sa w komórkach Eeproma po programowaniu.
Cała pamięć ma wartości FF FF FF FF FF
Czyli po włączeniu pierwszy raz czytana jest temperatura i wynosi....65535 (FF FF)
Dlatego zapis że jeśli temperatura odczytana z Eeproma wieksza niż "typowa" to przyjmij bezpieczna wartość.
To samo jest dla wartości typu Byte. Odczytana ze "świeżego" Eeproma wynosi 255.
Nie chcę zaciemniać, ale dla Integer trzeba innego zapisu
Wracając do pytań. Status to sposób na rozpoznanie w każdym miejscu programu co akurat się dzieje w programie. Ciekawsze są jednak te stałe
Kiedy napiszesz że
Code: basic4gl
Log in, to see the code
..to w całym programie możesz używać "Normal" albo "Term"
Ty wiesz dokładnie w jakim stanie jest program, możesz też w każdym miejscu programu zmienić stan na jakiś z tych wcześniej zapisanych...a mikrokontroler widzie to tak : Status = 2
Ty piszesz If Status = Normal a mikrokontroler widzi If Status = 0 Piszesz Status = Hist a mikrokontroler sobie zapisuje Status = 1
Nie do końca wiem co Ci się nie wyświetla ale napiszę że nie wysyła się ciągle tego samego w pętli na wyświetlacz jeśli nic się nie zmieniło. To byłby bezsens.
Stosuje się więc zabieg:
Jeśli coś jest do wyświetlenia to to wyświetl i gotowe. To że cos jest do wyświetlenia pokazuje zmienna Refresh.
W przypadku zegarków, na przykład, taka Refresh jest ustawiana co sekundę i wtedy zmieniają się sekundy na LCD ale tylko raz na sekundę..bo po co częściej.
..ale gdy jesteś w menu to odświeżanie co sekundę mogło by być zbyt wolne. Dlatego gdy jakaś wartosć się zmieniła bo ją ustawiasz to ustawiasz też zmienną Refresh = 1
Wtedy od razu nowa wartość pokaże się na LCD.
Czyli wyświetlacz jest odświeżany kiedy coś się zmieniło i musi być pokazane.
Jesli Refresh = 1 to jest od razu kasowane Refresh = 0 ..ale dalej program analizuje co ma pokazać. patrzy jaki jest Status i wybiera co pokazać.
W zależności co chcesz osiągnąć czasem potrzebne jest Cls ale pod przyciskiem nie w pętli.
To nie jest jakiś superprogram tylko przerobiony troche Twój
Można go jednak rozbudowywać dalej w ten sposób. Prawdopodobnie to co chcesz osiągnąć da się zrobić dopisując
Code: basic4gl
Log in, to see the code
..pewnie o czyms zapomniałem ale dokombinujesz
EDIT: Nie wszystkie przykłady są trafione. czasem żeby cos wytłumaczyć trzeba się zastanowic jak to powiedzieć.
Kazdy kod można zoptymalizować.
Przedtem pisało If Zmienna < 400 Then Zmienna = Zmienna + 10 i dlatego taki zapis.
W przypadku jedynki można po prostu napisać
If Zmienna < 400 Then Incr Zmienna
Tak samo przykład dla Else
If A = 1 Then Idź tam Else Idź gdzieś indziej i takie tam niuanse
Dobra, skończyłem jak na razie "pracę" nad programem. Więcej było gapienia się w niezrozumiałe funkcje i polecenia ale już prawie program czaje w całości Oznaczyłem go jako V.2.2 ^^
Zmiany:
*Możliwość ustawienia skrajnych temperatur uruchamiających alarm
*kasowanie alarmu poprzez wejście do menu i zapisanie zmiennych
*zmiana stopnia regulacji zmiennych
*poprawiona histereza bo jakoś dziwnie była zapisana i nie wyłączało się przy zadanej temperaturze tylko jakoś inaczej
*liczenie czasu załączonego przekaźnika (ogrzewania) z liczeniem zużycia w kilowatogodzinach [i tu jest pewien problem z niedokładnością, śpieszy o 1,5 sekundy, a nie chce uruchamiać kolejnego timera czy coś bo w innych projektach miałem problem z szalejącymi pomiarami z czujników w czasie przerwań]
Code: basic4gl
Log in, to see the code
Proszę o sprawdzenie czy nie ma jakichś poważnych błędów. Nie umiem pisać poprawnie. Umiem pisać tak żeby działało. Jak coś jest nie tak, wrzucam do pętli głównej.
Napisałeś że spieszy o 1,5s ale nie w jakim czasie. Jeśli 1,5s na minutę to zobacz obliczenia pod Timerem. Coś tam poprawiłem. Rezonator i tak będzie czuły na zmiany temperatur, ale możesz próbować to dostroić.
Zmieniłem lekko obliczanie watogodzin. Powinno już po 5 min pokazać 0,01kWh
Dodałem też szybkie kasowanie alarmu z automatycznym powrotem jeśli temperatura wróci do normy.
Code: basic4gl
Log in, to see the code
Nie testowałem Może coś trzeba poprawić.
EDIT. Wsród wiekszej ilości projektów można zapomnieć który pracuje na wewnetrznym oscylatorze. Tam można regulować OSCCAL
Wszystko pięknie działa, ale myślę nad jedną opcją. Inkubator będzie trzebalo chłodzić. Chciałbym z menu wywołać program, który odliczal by 15 min i przez ten czas nie grzać. Jest to wykonalne?
Proszę. Takie rzeczy to przy kawie. Masz nawet możliwość przerwania odliczania Na samym końcu wpadłem na pomysł żeby dodać ikony termometrów przed odczytami, ale zostawiłem coś Tobie
Bardzo dziękuję Mam pewność że kurczaki mi się nie ugotują. Jak mogę się Panu odwdzięczyć? Teraz sterownik będzie wykorzystywany w 99% Mam jeszcze pytanie. W jakich okolicznościach nieulotna pamięć eeprom może mi się ulotnić?
Drugie pytanie to bardziej sprzętowe. Zasilam to zasilaczem impulsowym 12V i stabilizuje na 5V. Czasem mam tak, że atmega nie wystartuje poprawnie, tzn. na lcd wyświetla się pasek, zdarzało się że temperatury zmieniły się na 85*C. Zawsze pomaga wyjęcie wtyczki zasilającej i ponowne podłączenie.
Pamięć Eeprom może się wysypać przy zasilaniu nie gwarantującym poprawnej pracy mikrokontrolera.
Raz w moim sterowniku też Eeprom się posypał podczas burzy kiedy napięcie sieciowe przerywało bo wiatr szarpał przewody.
Wtedy dopiero doczytałem o bitach konfiguracyjnych BODLEVEL i BODEN
Można je tak ustawić, że mikrokontroler będzie utrzymywany w stanie RESET jeśli napięcie jest niższe niż 2,7V albo 4V - piszę o Atmega8.
Tak wiec po włączeniu zasilania mikrokontroler poczeka aż napięcie będzie wynosić 4V i to powinno rozwiązać obydwa Twoje problemy/pytania.
Bity BODEN i BODLEVEL powinno się ustawiać zawsze gdy pracuje się z pamięcią Eeprom.
Co do bezpieczeństwa kurczaków..sprawdziłbym co się stanie jeśli zaszwankuje okablowanie któregoś z czujników Mogę to oprogramować w wolnej chwili łącznie z Watchdogiem
W jakich okolicznościach nieulotna pamięć eeprom może mi się ulotnić?
Drugie pytanie to bardziej sprzętowe. Zasilam to zasilaczem impulsowym 12V i stabilizuje na 5V. Czasem mam tak, że atmega nie wystartuje poprawnie, tzn. na lcd wyświetla się pasek, zdarzało się że temperatury zmieniły się na 85*C. Zawsze pomaga wyjęcie wtyczki zasilającej i ponowne podłączenie.
Objawy, które opisujesz to z reguły problem schematu lub nieodpowiednio zabezpieczonych urządzeń współpracujących z mikrokontrolerem, ale także i programu pod kątem tzw. dobrych praktyk.
Przeczytaj w szczególności artykuł: Zakłócenia w pracy mikrokontrolerów
Każdy punkt przeanalizuj pod swoim kątem.