Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki

KURS HOME ASSISTANT

Chcesz zautomatyzować swój dom bez skomplikowanego kodowania?
Zastanawiasz się nad wyborem sprzętu, oprogramowania i aplikacji?
Od czego zacząć przygodę z HA? Co będzie najlepsze na start?

Nasz kurs Home Assistant nauczy Cię krok po kroku, jak łatwo zautomatyzować swój dom i oszczędzić na rachunkach za prąd i ogrzewanie. Bez chmur, bez zbędnych abonamentów. Twoja przygoda z Home Assistant zaczyna się tutaj!

↓↓↓

    Szanujemy Twoją prywatność. Możesz wypisać się w dowolnym momencie.




    Teraz jest 26 lip 2025, o 12:58


    Strefa czasowa: UTC + 1





    Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 8 ] 
    Autor Wiadomość
    PostNapisane: 4 kwi 2021, o 12:03 
    Offline
    Użytkownik

    Dołączył(a): 10 cze 2020
    Posty: 29
    Pomógł: 0

    Cześć! Na początku chciałem życzyć wszystkim spokojnych, zdrowych i wesołych świąt! Dla niektórych mogą to być już 2 święta w samotności przez pandemię, ale spokojnie, w końcu wszystko się ułoży! A teraz przechodząc do tematu wątku...

    Jestem w trakcie budowy własnego zegarka na rękę z wyświetlaczem OLED opartym na sterowniku SSD1306. Całe oprogramowanie piszę na zestawie uruchomieniowym ATB 1.05a. Program co sekundę otrzymuje przerwanie z RTC PCF8583 umieszczonym na zestawie. Przerwanie podłączyłem do pinu PD3, tak aby wykorzystać INT1. Chciałem na tym mechanizmie oprzeć całe działanie zegarka, czyli co sekundę aktualizowany jest wyświetlacz oraz wykonywany jest pomiar ADC naładowania baterii (na razie wykorzystuję potencjometr dodany w zestawie). Na osobnym Timerze oparty jest odczyt temperatury z DS18B20 (kod wzorowany na tym z bluebooka). Do tego momentu wszystko działa poprawnie. Chciałem dodać obsługę zegarka bazując na 3 micro switchach. Postanowiłem wykorzystać rozwiązanie, które Mirek przedstawił przy okazji tworzenia własnego pilota IR w bluebooku. Jedno wyprowadzenie przycisku podłączone jest do PORTu C, a drugie bezpośrednio do PD2, ponieważ znajduję się tam przerwanie INT0. Z mojego rozumowania i noty ATmegi 32 wynika, że przerwanie INT0 ma większy priorytet niż INT1, a więc wciśnięcie przycisku powinno spowodować natychmiastowe przejście do przerwania INT0_vect i wykonać zawarte w nim operację. Na początku chciałem wykorzystać funkcję SuperDebounce umieszczoną w przerwaniu INT0_vect, jednak program nie działał poprawnie, ponieważ nie reagował na każde wciśnięcie przycisku, a tylko na niektóre. Zrezygnowałem więc z tego rozwiązania i wykorzystałem kod do pilota podczerwieni z bluebooka. Efekt niestety jest ten sam... Gdzieś wyczytałem, że w momencie w którym program już wejdzie w jakieś przerwanie wyłączane jest globalne zezwolenie na przerwanie, więc skoro co sekundę mam przerwanie z RTC, to czy właśnie ono blokuje działanie przerwania INT0? Jeżeli tak to w takim razie po co priorytet przerwań w AVRce, skoro i tak jedno przerwanie blokowałoby inne? Pomyślałem, żeby ten odczyt co sekundę oprzeć na jakimś timerze programowym zamiast na zewnętrznym przerwaniu z RTC, jednak nie jestem przekonany czy to rozwiąże mój problem... Poniżej zamieszczam kod z maina i kilku innych funkcji. Proszę o pomoc i życzę jeszcze raz zdrówka :)

    P.S. Od razu napiszę, że wykorzystuję aż 4 bitmapy, ponieważ w mojej wersji wyświetlacza SSD1306 nie działa częściowe odświeżanie ekranu oraz przesuwanie tekstu, które Mirek przedstawiał w swojej serii poradników właśnie na temat tego wyświetlacza. Niestety moje próby naprawy tego okazały się nieskuteczne, najprawdopodobniej przez to, że wykorzystywane są tam komendy: mk_ssd1306_cmd(SSD1306_SETLOWCOLUMN | (col_start & 0x0F)); mk_ssd1306_cmd(SSD1306_SETHIGHCOLUMN | col_start >> 4); mk_ssd1306_cmd(0xB0 + page_cnt); // ustawienie strony

    Cytuj:
    Składnia: [ Pobierz ] [ Ukryj ] [ Zaznacz wszystko ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    Miałem też z nimi problem w wątku "SSD1306 - Przesuwanie się bitmap". Jak ktoś ma pomysł jak to rozwiązać to chętnie przeczytam :D.

    MAIN:
    Cytuj:
    Składnia: [ Pobierz ] [ Ukryj ] [ Zaznacz wszystko ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    INICJALIZACJA PRZYCISKOW:
    Cytuj:
    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    INICJALIZACJA RTC:
    Cytuj:
    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    RTC_EVENT:
    Cytuj:
    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    INT0_vect:
    Cytuj:
    Składnia: [ Pobierz ] [ Ukryj ] [ Zaznacz wszystko ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 6 kwi 2021, o 19:21 
    Offline
    Użytkownik

    Dołączył(a): 11 sty 2015
    Posty: 166
    Pomógł: 24

    Popełniłeś dwa błędy

    1. W przerwaniu INT0_vect używasz delay. Nie idź tą drogą. Skoro używasz przerwań to nie blokuj ich delay'ami.

    2. Źle kasujesz flagę przerwań:

    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

    W ten sposób kasujesz wszystkie aktywne flagi ustawione w rejestrze GIFR a nie tylko tą od INT1.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 6 kwi 2021, o 20:58 
    Offline
    Moderator
    Avatar użytkownika

    Dołączył(a): 03 paź 2011
    Posty: 27416
    Lokalizacja: Szczecin
    Pomógł: 1043

    auers napisał(a):
    2. Źle kasujesz flagę przerwań:

    Dokładnie, dlatego kasowanie flagi powinno wyglądać w tym wypadku tak

    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

    _________________
    zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 7 kwi 2021, o 16:01 
    Offline
    Użytkownik

    Dołączył(a): 10 cze 2020
    Posty: 29
    Pomógł: 0

    Zastosowałem się do waszych rad i zmieniłem sposób kasowania flagi przerwania oraz usunąłem delaya z przerwania (dodałem go dlatego, ze służył do wyeliminowania drgań styków w projekcie pilota IR w bluebooku). Niestety działanie programu nie poprawiło się... Z tego co widzę to jednak muszę zrezygnować z cyklicznego przerwania od RTC. Wydaje mi się, że to on blokuje działanie przycisków pod INT0.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 7 kwi 2021, o 18:57 
    Offline
    Użytkownik

    Dołączył(a): 11 sty 2015
    Posty: 166
    Pomógł: 24

    Przerwanie od RTC nie może blokować przerwań od przycisków.
    Obsługę RTC masz w RTC_event w pętli głównej. Każde przerwanie w tym to od INT0 przerwie tą funkcję i wejdzie w kod umieszczony w "sekcji ISR".
    To nie RTC blokuje Ci klawisze, prędzej kod z INT0_vect blokuje resztę programu i pozostałe przerwania.
    Chyba że kod INT0_vect: masz poza ISR.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 8 kwi 2021, o 21:06 
    Offline
    Użytkownik

    Dołączył(a): 10 cze 2020
    Posty: 29
    Pomógł: 0

    No i racja. Przemodelowałem funkcję. Teraz obsługa przycisków jest w while'u, a przerwanie INT0 wystawia tylko flagę. Układ działa lepiej, jednak nadal mam dwa dziwne problemy... Pierwszy to to, że zawsze wykonuje mi się pierwszy warunek IF w obsłudze przycisków, nie ważne jak je zamaskuje i jaki przycisk wcisnę... Drugi to zaczynają reagować dopiero po kilkukrotnym wciśnięcia na początku uruchomienia zegarka. Później już każde kliknięcie jest poprawnie wykonywane. Zmienna, która ma się inkrementować wraz z wciśnięciem nie zmienia swojego stanu przez jakieś 4-5-6 wciśnięć, po czym zaczyna działać poprawnie xd. Strasznie dziwne są te dwa błędy... Składniowo nie widzę problemu, dlatego może ktoś z was coś zauważy. Reszta funkcji się nie zmieniła...

    P.S Ogólnie to nie muszę używać tych warunków if, ponieważ sama funkcja SuperDebounce powinna być już w stanie rozpoznać jaki dokładnie przycisk został wciśnięty. Niestety ona tak nie działa :/

    Cytuj:
    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    Cytuj:
    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    Cytuj:
    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



    Cytuj:
    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 9 kwi 2021, o 20:27 
    Offline
    Użytkownik

    Dołączył(a): 11 sty 2015
    Posty: 166
    Pomógł: 24

    Cytuj:
    Pierwszy to to, że zawsze wykonuje mi się pierwszy warunek IF w obsłudze przycisków, nie ważne jak je zamaskuje i jaki przycisk wcisnę...

    A jak masz te przyciski podłączone? Nie masz ich zwartych ze sobą?

    Cytuj:
    Drugi to zaczynają reagować dopiero po kilkukrotnym wciśnięcia na początku uruchomienia zegarka.

    Jeżeli tego nie zmieniłeś to na początku programu miałeś delay'a 3s wykonanego przy pomocy pętli while(Timer2);
    W tym czasie przyciski jak i cała reszta programu nie będą działać.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 15 kwi 2021, o 21:59 
    Offline
    Użytkownik

    Dołączył(a): 10 cze 2020
    Posty: 29
    Pomógł: 0

    Miałem chwilę przerwy od tego tematu... Dzisiaj wróciłem do zabawy. Jeżeli chodzi o połączenie przycisków, to wykonałem je w takim sposób jak Mirek pokazywał w rozdziale dotyczącym budowy własnego pilota IR. Jedna nóżka przycisku jest podłączona do INT0, a druga do konkretnego portu np, PC6. Zauwazyłem, że nawet jeżeli zmienie podlączenie przycisków (z portu C na port D) a nie zmienie portu z PINC na PIND w funkcji superdebounce, to przyciski i tak będą reagować tak samo, czyli po uruchomieniu zegarka, 3-4 wciśnięcia nic nie robią, a później każde kolejne wykonuje wywołanie pierwszego superdebounce, czyli tego z funkcja switch1_command.

    Pozwoliłem sobie wrzucić to przycięte zdjęcie z książki. Mam nadzieję, że w takim przypadku jest to dozwolone :).

    Cytuj:
    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    Obrazek



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    Wyświetl posty nie starsze niż:  Sortuj wg  
    Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 8 ] 

    Strefa czasowa: UTC + 1


    Kto przegląda forum

    Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 5 gości


    Nie możesz rozpoczynać nowych wątków
    Nie możesz odpowiadać w wątkach
    Nie możesz edytować swoich postów
    Nie możesz usuwać swoich postów
    Nie możesz dodawać załączników

    Szukaj:
    Skocz do:  
    cron
    Sitemap
    Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
    phpBB SEO