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



Teraz jest 23 mar 2026, o 21:19


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 11 ] 
Autor Wiadomość
PostNapisane: 19 sie 2014, o 18:30 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 19 cze 2014
Posty: 11
Lokalizacja: Nowy Sącz
Pomógł: 0

Witam,

Jakiś czas temu zakupiłem trzy czujniki HC-SR04 i postanowiłem napisać program do ich obsługi. Na początek zabrałem się za testy na jednym czujniku. Procesor jakiego używam to AtTinny2313. Z racji tego, że mam zamiar używać trzech czujników jednocześnie, badanie długości trwania impulsu Echo za pomocą przerwania ICP odpada, gdyż AtTinny2313 posiada tylko jedno wejście ICP, INT też odpada. Postanowiłem więc pobawić się z przerwaniami PCINT. Oto programik jaki udało mi się wymęczyć :P

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


Przeczytałem już kilka wątków o obsłudze HC-SR04 na tym forum ale nie natknąłem się na kod posługujący sie przerwaniami PCINT (chyba że źle szukałem ;d). Moje pytanie jest następujące; co złego jest w tym kodzie? Na wyświetlaczu w miejscu gdzie powinna wyświetlić się odległość cały czas jest zero. Nie jestem pewien gdzie może być błąd, więc proszę Was o pomoc. Dodam tylko, że wyświetlacz LCD podłączony jest do Pinów, odpowiednio; D7-PB0, D6-PB2, D5-PB4, D4-PB6, RS-PD0, RS-PD1, E-PA1.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 sie 2014, o 20:22 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 07 kwi 2013
Posty: 418
Lokalizacja: Rzeszów
Pomógł: 102

Co prawda nie powinno to stanowić problemu, ale ten zapis jest dość nietypowy dla tego programu:

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

Powinno być raczej:

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

Jeszcze jedna uwaga odnośnie sprawdzania warunków. Nie ma potrzeby dodawania zanegowanego wyrażenia w kolejnej instrukcji warunkowej, od tego jest słówko "else" (niepotrzebny "if"):

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

Właściwie cały kod objęty w ciało funkcji "ISR(PCINT_vect)" można uprościć do:

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

To samo tyczy się kolejnego fragmentu:

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: 21 sie 2014, o 20:23 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 19 cze 2014
Posty: 11
Lokalizacja: Nowy Sącz
Pomógł: 0

Wprowadziłem niektóre z Twoich poprawek. Dodałem również warunek mający zapalić diodę LED jeśli odległość jest mniejsza od 10
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Niestety dioda nie świeci :( . Gdzieś popełniam błąd ale nie wiem gdzie. Macie jakieś pomysły?

Jak tylko będę miał czas potestuje trochę z przerwaniami INT i ICP. Może będą jakieś rezultaty.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 22 sie 2014, o 19:42 
Offline
Uzytkownik zasłużony dla forum.atnel.pl
Avatar użytkownika

Dołączył(a): 16 lip 2012
Posty: 2088
Lokalizacja: Leżajsk / Kraków
Pomógł: 411

Może pokaż aktualny kod, bo mogę powiedzieć, że PA0 jest wejściem i dlatego dioda nie świeci. Jak do OCR0A i OCR0B wpisujesz to samo to po co ci 2 przerwania?

_________________
Dragonus Cracovus: Biomagia



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 23 sie 2014, o 11:50 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 19 cze 2014
Posty: 11
Lokalizacja: Nowy Sącz
Pomógł: 0

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


Wyrzuciłem przerwanie z OCR0B i połączyłem z OCR0A i faktycznie coś zaczęło się dziać, dzięki Krauser :D . Szkoda tylko ze wyświetlacz pokazuje głupoty, a dioda świeci losowo mniej więcej około 30 cm od czujnika. Zauważyłem że zmienna rezultat była typu uint_8, i na wyświetlaczu wyświetlały się liczby od 0 do 4, zmieniłem na uint_16 ale dalej są głupoty.

Edit:
Wyświetla się tylko cyfra dziesiątek centymetrów i to niedokładnie. Np. przy około 20 cm wyświetla się 2, przy mniej niż 10 cm 0 itd.



Ostatnio edytowano 23 sie 2014, o 13:55 przez Pajda, łącznie edytowano 1 raz

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 23 sie 2014, o 13:53 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 07 kwi 2013
Posty: 418
Lokalizacja: Rzeszów
Pomógł: 102

Być może spowodowane jest to nieatomowym dostępem do zmiennej "rezultat1"...

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: 23 sie 2014, o 14:05 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 19 cze 2014
Posty: 11
Lokalizacja: Nowy Sącz
Pomógł: 0

W Eclipsie wywala mi błąd "ATOMIC_RESTORESTATE could not be resolved", pewnie przyczyną jest to że nic jeszcze nie wiem o ATOMIC_BLOCK :(

------------------------ [ Dodano po: 16 minutach ]

Dobra, dodałem nagłówek <util/atomic.h>, nie wywala błędu. Wyświetlacz dalej wyświetla głupoty, dioda zapala się po odległości około 1 metra czyli 10 razy większej niż powinna; czyżby zła podstawa czasowa timera, czy coś w tym rodzaju?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 23 sie 2014, o 19:21 
Offline
Uzytkownik zasłużony dla forum.atnel.pl
Avatar użytkownika

Dołączył(a): 16 lip 2012
Posty: 2088
Lokalizacja: Leżajsk / Kraków
Pomógł: 411

Dobrze kombinujesz. Za często masz to przerwanie od timera. Jak masz kwarc 8 MHz to jedna instrukcja trwa 1/8 us i w ciągu jednej mikrosekundy wykona się ich 8. Jak sobie popatrzysz na kod asemblera w pliku *.lss w folderze Release to zobaczysz, że pusta funkcja obsługi przerwania zajmuje 10 instrukcji asemblera, a i tak zajmie więcej niż 10 taktów zegara, bo dochodzą skoki. Twoje przerwanie nie wykonuje się co 1us. Na pewno jest to dłuższy okres czasu. Możesz to sprawdzić jak sobie zamiast tego kodu wrzucisz dwa liczniki po 1000 i będziesz zmieniał stan LED co 1 sekundę. Drugi test: wrzuć sobie do pętli głównej tylko _delay_ms(1000); i również miganie LED. Zobaczysz, że czas się wydłuży a to dlatego, że przez zbyt częste przerwanie procesor będzie co chwila opuszczać główną pętlę i zajmował się wykonywaniem funkcji obsługi przerwania.

_________________
Dragonus Cracovus: Biomagia



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 23 sie 2014, o 20:07 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 19 cze 2014
Posty: 11
Lokalizacja: Nowy Sącz
Pomógł: 0

A czy można by zrobić tak, że użyję trybu NORMAL, wyłącze przerwanie w rejestrze TIMSK (przepełnienie TCNT dalej po 1 us) i zmienna licznik1 będzie się zwiększała nie w procedurze obsługi przerwań a w pętli głównej np tak;
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

A potem to już analogiczne. Ma to jakiś sens czy wyjdzie na to samo?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 23 sie 2014, o 20:48 
Offline
Uzytkownik zasłużony dla forum.atnel.pl
Avatar użytkownika

Dołączył(a): 16 lip 2012
Posty: 2088
Lokalizacja: Leżajsk / Kraków
Pomógł: 411

Nie bardzo wiem do czego zmierzasz i napiszę na czym to polega.
Jak masz wejście ICP i sobie to skonfigurujesz to odpowiednie zbocze powoduje sprzętowe skopiowanie wartości licznika timera, który sobie zlicza w kółko do rejestru przechwytywania. Podglądnij taki program opary na ICP mimo, że nie będziesz wykorzystywał takiego sposobu. Tam w procedurze przerwania od przechwycenia dla jednego zbocza licznik timera jest zerowany, a przy drugim wynik jest gotowy. Przerwanie od przepełnienia włącza się, bo w czasie pomiaru licznik może przekręcić się parę razy. Przerwania ICP zależą od odległości czujnika od przeszkody, a przerwania timera są co 256 cykli zegara.

Jak nie korzystasz z ICP tylko przerwania od zmiany stanu na wejściu (PCINT) to tracisz na dokładności, bo licznik timera nie jest automatycznie kopiowany i sam to musisz zrobić. Tylko tym to się różni.


Autor postu otrzymał pochwałę

_________________
Dragonus Cracovus: Biomagia



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 25 sie 2014, o 14:56 
Offline
Nowy
Avatar użytkownika

Dołączył(a): 19 cze 2014
Posty: 11
Lokalizacja: Nowy Sącz
Pomógł: 0

Trochę pokombinowałem i można powiedzieć że się udało :D Oto końcowy kod:

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


Kilka słów wyjaśnień;
Zamiast dzielić zmienną rezultat1 przez 58 znalazłem inny wzór -> dystans1 = (rezultat1*34)/100/2, w orginale dzielenie było przez 1000 ale dalej coś jest nie tak z podstawą czasu więc dziele przez 100. Wyniki są w zadowalającym stopniu dokładne :) Może kod nie jest super zoptymalizowany ale jak dla mnie (początkującego) to i tak duży sukces :P. Potem wrzuce jeszcze wyniki moich eksperymentów z trzema czujnikami (o ile sie uda XD ). Narazie dzięki wszystkim za pomoc :)



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

Strefa czasowa: UTC + 1


Kto przegląda forum

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


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:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO