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



Teraz jest 16 mar 2026, o 13:00


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 14 ] 
Autor Wiadomość
PostNapisane: 9 gru 2016, o 09:40 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 28 sie 2013
Posty: 165
Lokalizacja: Sycyna Południowa
Pomógł: 4

Witam. Mam pytanie, czy jest możliwość wybudzenia procesora ze śpiączki za pomocą konkretnego przerwania PCINTX?
Na PCB mam podłączony RTC PCF8583. Odczytuję go przez I2C i przerwanie PCINT8. Z kolei pod PCINT2 mam podłączony transoptor który po podaniu sygnału na wejście wybudza procesor ale nie poprzez przerwanie tylko przez sprawdzenie stanu na pinie... I chyba mam problem bo każde "zdarzenie" RTC wybudza na ułamek sekundy procesor.
Czy jest na to jakieś rozwiązanie?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 gru 2016, o 10:01 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 28 lis 2011
Posty: 156
Pomógł: 12

Cześć przejrzyj to może pomoże
https://sites.google.com/site/qeewiki/b ... -atmega328



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 gru 2016, o 11:02 
Offline
Moderator
Avatar użytkownika

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

hopek napisał(a):
Mam pytanie, czy jest możliwość wybudzenia procesora ze śpiączki za pomocą konkretnego przerwania PCINTX?

a dlaczego miałoby nie być jak jest ... nie rozumiem wręcz pytania - bo w nocie jest mowa o tym że można więc w czym problem ?

_________________
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: 9 gru 2016, o 12:03 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 28 sie 2013
Posty: 165
Lokalizacja: Sycyna Południowa
Pomógł: 4

To chyba coś robię źle bo uśpić mogę ale wybudzić się już nie chce. Więc tak odpaliłem sobie na PCINT2 osobne przerwanie i w środku sprawdzam sobie stan na pinie czy niski czy wysoki za pomocą makra i instrukcji sleep_mode(); i sleep_cpu(); gdy pin w stanie niskim usypiam procesor. Chcąc wybudzić sprawdzam czy stan pinu wysoki i odpalam instrukcje sleep_disable();
Co w tym przypadku robię źle?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 gru 2016, o 14:17 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

hopek napisał(a):
Więc tak odpaliłem sobie na PCINT2 osobne przerwanie i w środku sprawdzam sobie stan na pinie czy niski czy wysoki za pomocą makra i instrukcji sleep_mode(); i sleep_cpu(); gdy pin w stanie niskim usypiam procesor.

Jeśli usypiasz mikrokontroler wewnątrz procedury obsługi przerwania, to obawiam się, że już go nie wybudzisz, ponieważ flaga I w SREG jest wtedy wyłączona. Globalne zezwolenie na przerwania musi być włączone, aby wybudzić mikrokontroler z uśpienia.

hopek napisał(a):
wybudza procesor ale nie poprzez przerwanie tylko przez sprawdzenie stanu na pinie...

Nie bardzo to rozumiem. Jak sprawdzasz stan pinu w trybie uśpienia?

hopek napisał(a):
I chyba mam problem bo każde "zdarzenie" RTC wybudza na ułamek sekundy procesor.

Sprecyzuj jakiej funkcjonalności oczekujesz.

No i dobrze by było, gdybyś pokazał kod, jeśli to nie tajemnica.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 gru 2016, o 15:52 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 28 sie 2013
Posty: 165
Lokalizacja: Sycyna Południowa
Pomógł: 4

andrews napisał(a):
Nie bardzo to rozumiem. Jak sprawdzasz stan pinu w trybie uśpienia?


No jasne przecież to nie możliwe... Mój błąd, przepraszam.

To wybudzanie procesora poprzez sprawdzenie stanu pinu to jednak zakomentowałem tą część kodu żeby nie robić bałaganu bo to i tak nie działało ale do testu w osobnym przerwaniu PCINT2 umieściłem coś takiego:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Ogólnie próbuję zaprogramować mikrokontroler tak, żeby był usypiany i wybudzany jednym pinem PCINT2 (PB2). Do tej pory robiłem to tak że sprawdzałem stan pinu PCINT2 i jeśli był stan niski to uruchamiałem timer który po 10 sekundach usypiał mi mikrokontroler, ale wybudzanie następowało samoczynnie zaraz po uśpieniu i podejrzewam że przez przerwanie od RTC na pinie PCINT8 co skutkowało wyświetleniem na ułamek sekundy treści na wyświetlaczu OLED. Kod zamieszczę później bo nie mam teraz przy sobie projektu.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 gru 2016, o 18:32 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

Po pierwsze, jak już wcześniej napisałem, nie można usypiać mikrokontrolera wewnątrz procedury obsługi przerwania, ponieważ jest wtedy wyłączona flaga globalnego zezwolenia na przerwania, więc nie uda się wybudzić mikrokontrolera. Z drugiej strony włączenie wewnątrz procedury globalnego zezwolenia na przerwania ( sei(); ) to w takiej sytuacji zdecydowanie zły pomysł.

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

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

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


hopek napisał(a):
wybudzanie następowało samoczynnie zaraz po uśpieniu i podejrzewam że przez przerwanie od RTC na pinie PCINT8 co skutkowało wyświetleniem na ułamek sekundy treści na wyświetlaczu OLED.
Możesz przed uśpieniem mikrokontrolera wyłączyć zezwolenie na przerwanie od PCINT8, a po wybudzeniu włączyć ponownie. Przerwanie PCINT8 przypisane jest do wektora PCINT1_vect, więc:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
To powinno zapobiec wybudzaniu przez PCINT8.

No a w procedurze obsługi przerwania od PCINT2 ( ISR(PCINT0_vect) ) modyfikuj tylko wartość jakiejś zadeklarowanej globalnie zmiennej (z atrybutem volatile), a dopiero w pętli głównej na podstawie wartości tej zmiennej usypiaj lub wybudzaj mikrokontroler.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 gru 2016, o 21:18 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 28 sie 2013
Posty: 165
Lokalizacja: Sycyna Południowa
Pomógł: 4

Więc tak, to jest taki dodatkowy gadżet zamiast fabrycznego zegarka w samochodzie rover 214. Upakowałem w oryginalnej obudowie wyświetlacz 2x8 znaków i jedną płytkę z atmegą. Będzie jeszcze druga mniejsza do reszty zaplanowanych rzeczy.
Na tą chwilę zmodyfikowałem kod i wygląda następująco:

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


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



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


Procedurę przerwania PCINT2 zostawiłem pustą.
Nie wiem czy wszystko jest ok, ale wygląda na to że działa. Proszę o weryfikacje :)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 gru 2016, o 22:04 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

Trudno precyzyjnie ocenić nie widząc całego kodu.

Wydaje mi się, że akurat w Twoim przypadku to zerowanie flagi przerwania PCINT2 nie jest bardzo konieczne, ale skoro już jest, to powinno być raczej zaraz przed włączeniem zezwolenia na przerwanie, a nie zaraz po wyłączeniu zezwolenia.

Zamiast makra sleep_cpu() użyłbym raczej sleep_mode(), ponieważ to drugie włącza zezwolenie na uśpienie bezpośrednio przed uśpieniem i wyłącza zaraz po wybudzeniu. Nie jest to może konieczne, ale jest zalecane, tak "dobra praktyka".

Tyle mogę powiedzieć na podstawie kodu który przedstawiłeś. Musisz teraz po prostu dobrze całość przetestować i w przypadku zauważenia błędów wprowadzić ewentualne korekty.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 gru 2016, o 22:59 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 28 sie 2013
Posty: 165
Lokalizacja: Sycyna Południowa
Pomógł: 4

Zamieszczam pełny kod i uprzedzam że "miszczem" nie jestem co chyba widać ;)
To na razie faza początkowa, jeszcze dużo jest do zrobienia...
main.c
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


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



func.h
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: 10 gru 2016, o 15:33 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

Napisałem, że trudno precyzyjnie ocenić nie widząc całego kodu, ponieważ w przypadku przedstawienia tylko fragmentów:
  • nie wiadomo, z jakiego miejsca programu dany fragment pochodzi, a to może mieć kluczowe znaczenie
  • nie wiadomo, czy w pozostałej części kodu nie ma czegoś, co może spowodować nieprawidłowe działanie pokazanego fragmentu
  • jaka jest ogólna struktura/organizacja programu, ponieważ to też może mieć wpływ na prawidłowość działania przedstawionych fragmentów.

Nadal nie wszystko jest jasne. Przykładowo masz taką linijkę PCINT8_flag=1;, a nigdzie nie widzę deklaracji, co to jest PCINT8_flag i do czego tej zmiennej używasz...

...ale już to zostawmy, bo nie o to chodzi, żeby tutaj przedstawiać wszystkie moduły programu ;) Teraz już lepiej widać, jak to wszystko jest zorganizowane.

Niestety nie dysponuję wystarczającą ilością czasu, aby szczegółowo przeanalizować cały kod, więc odniosę się tylko do usypiania, które jest tematem tego wątku.

Nadal zerowanie flagi przerwania PCINT8 (PCIF1) masz w nieodpowiednim miejscu. Tak jak wcześniej napisałem, powinno być przed włączeniem zezwolenia na przerwanie, czyli przed PCICR |= (1<<PCIE1); , a nie przed wyłączeniem. Właściwie wygląda na to, że w Twoim przypadku nie trzeba tego robić, więc możesz spróbować to zerowanie flagi w ogóle pominąć. W każdym razie zerowanie w tym miejscu, w jakim jest w tej chwili, i tak nie spełni swojej roli.

Ustawienie bitu SE we funkcji sm_power_down() jest zbędne, a nawet niewskazane (ustawienie bitu SE jest realizowane przez makro sleep_mode() ). W pliku <avr/sleep.h> masz gotowe makro wygodniejsze w użyciu, które robi to, co Twoja funkcja, więc w miejscu wywołania funkcji sm_power_down() zrobiłbym tak:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


To, o czym napisałem, to nie jakieś błędy, które mogą powodować nieprawidłowe działanie. To tylko takie moje uwagi. Ogólnie myślę, że w tej formie usypianie i wybudzanie powinno działać prawidłowo. Reszty szczegółowo nie analizowałem, więc się nie wypowiadam, choć być może też znalazłoby się kilka uwag. Myślę, że powinieneś po prostu solidnie przetestować i w razie problemów zawsze można spróbować poprawić lub pytać na forum.


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 gru 2016, o 18:42 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 28 sie 2013
Posty: 165
Lokalizacja: Sycyna Południowa
Pomógł: 4

Witam i dziękuję za obszerne opisanie problemu, nie każdemu się chce w tych czasach to robić. Ja chyba muszę się nauczyć czytać ze zrozumieniem, albo do okulisty iść ;)

Flaga PCINT8_flag jest używana do odczytu danych z RTC. Kod mam z poradników Mirka, tyle że Mirek używał tam przerwania INT0, ja ten pin miałem już zajęty więc skonfigurowałem i zamieniłem tylko przerwanie z INT0 na PCINT8 i zmieniłem dla czytelności nazwę flagi.

Usypianie teraz działa tak jak chciałem, więc i Pomógł się należy :) Pobór prądu w czasie pracy urządzenia to około 25mA a podczas uśpienia 4mA z czego 2mA pobiera sam stabilizator 7805, reszta to wyświetlacz OLED, pull-upy i dzielniki na PCB.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 gru 2016, o 19:17 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

hopek napisał(a):
podczas uśpienia 4mA z czego 2mA pobiera sam stabilizator 7805

Dlatego do takich zastosowań lepiej używać stabilizatorów z "Low Quiescent Current", np. LM2936-5.0. Podejrzewam, że taki układ przy obciążeniu (prądzie wyjściowym) np. 2mA nie zużyje więcej niż ok. 100uA.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 gru 2016, o 19:25 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 28 sie 2013
Posty: 165
Lokalizacja: Sycyna Południowa
Pomógł: 4

W aucie te 4mA to raczej nie problem nawet ze słabym akumulatorem, ale w przyszłości zapamiętam, zakupię i użyję :) Trochę niski prąd wyjściowy, ale jak do tego typu zastosowań powinien wystarczyć.



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: 14 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 2 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