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



Teraz jest 2 gru 2024, o 20:54


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 13 ] 
Autor Wiadomość
PostNapisane: 8 sie 2014, o 21:59 
Offline
Nowy

Dołączył(a): 11 lip 2014
Posty: 6
Pomógł: 0

Witam. Mam problem z napisaniem programu, który by co określony czas wł i wył port i przy tym samym, żeby można było sterować PWM. Jestem dopiero początkujący w pisaniu programów w języku C.
Program, który napisałem wykonuje tylko tą czynność która jest pierwsza w poleceniu " int main(void) ". Jak jest na początku " miganie " to steruje portami, a gdy daje na początek " jasnosc " to działa tylko PWM.
Prosiłbym o podpowiedź jak to można połączyć aby działało wszystko razem. Pozdrawiam.

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


Proszę poprawić post .... kody umieszczamy w znacznikach SYNTAX -SunRiver



Ostatnio edytowano 20 sie 2014, o 06:43 przez Aress, łącznie edytowano 2 razy

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

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

Trudno się dziwić, skoro program "wpada" w nieskończoną pętle.
Umieść pętle "while" z obu funkcji jako jedną obejmującą wywołania tych funkcji. Funkcja "inicjalizacja" powinna być wywoływana tylko raz przed główną pętlą programu.

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


Nie zamieszczam całego kodu, a tylko ten fragment, bo z funkcji "miganie" oraz "jasnosc" wystarczy usunąć pętle "while" oraz wywołanie funkcji "inicjalizacja".

Rozumiem, że chciałeś zrobić coś na wzór zadań (wątków), ale do takich działań niezbędny jest tzw "scheduler z dispatcher'em" (system operacyjny [jakiś RTOS]), albo chociaż obsługa timerów (również programowych).
W związku z czym zapewne nie będziesz miał zakładanych rezultatów, ponieważ program przez funkcję "miganie" zostanie wstrzymany na 400ms...

Aha i tak na przyszłość umieszczaj kod na forum w znacznikach SYNTAX a nie Code.


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 sie 2014, o 22:31 
Offline
Nowy

Dołączył(a): 11 lip 2014
Posty: 6
Pomógł: 0

Ogólnie działa tylko to PWM nie zawsze reaguje na przycisk. Wiesz może czemu? I dzięki wielkie za pomoc.



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

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

Sądzę że z tego powodu o którym pisałem tzn. opóźnienie 400ms powoduje bardzo rzadkie "odpytywanie" przycisku, co w efekcie może dać odczucie braku płynności działania. Dla testu spróbuj zakomentować linie z wywołaniem funkcji "miganie" i spróbować czy będzie ok. Jeśli tak to masz co najmniej dwa proste wyjścia:
1. Zmianę stanu portu C zrealizować w przerwaniu od któregoś timer'a.
2. Przycisk obsługiwać poprzez przerwanie zewnętrzne (INTx).

Jest oczywiście jeszcze całe mnóstwo sposobów, ale podaje te, które się "nie zemszczą", bo z doświadczenia wiem, że chcąc zrobić coś na szybko "na około" to w najmniej odpowiednim momencie da o sobie znać. Mimo tej zasady i raczej bezkompromisowego zwolennika przerwań, podam sposób, który powinien działać, ale nie polecam go na dłuższą metę.
Oczywiście jeśli jest to finalny program i wszystko działa jak należy oraz nie planujesz jego późniejszej rozbudowy to poniższy kod może być jak najbardziej ok ;)

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


Ma to oczywiście tę wadę, że przy naciśnięciu przycisku ten czas dodatkowo wydłuży się o 60ms (swoją drogą trochę zbyt dużo, spokojnie wystarczy 20-30ms), ale to już pozostawiam Tobie do dalszych rozważań nad tym, czy jest to wogóle dobra droga, bo moim zdaniem NIE i radzę zastosowanie przerwań.


Autor postu otrzymał pochwałę


Ostatnio edytowano 8 sie 2014, o 23:04 przez atmel, łącznie edytowano 2 razy

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

Dołączył(a): 18 maja 2014
Posty: 126
Pomógł: 12

Ja bym doradził jeszcze nie pisanie w ten sposób:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


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


Wtedy łatwiej innym analizować kod ;)

atmel napisał(a):
"scheduler z dispatcher'em" (system operacyjny [jakiś RTOS])


Ja ostatnio uruchomiłem na avrach Super Simple Tasker. Tylko, że trochę to zasobożerne w porównaniu do timera, ale zadania można kolejkować i jest też coś w stylu wywłaszczania.

Z prostszych rozwiązań z timerami programowymi, można np tak:

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.


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


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


Autor postu otrzymał pochwałę

_________________
Pozdrawiam, Adrian.



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

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

O to jest właśnie to czego Koledze Aress potrzeba :)

SPAM:
Ja z kolei na potrzeby dość rozbudowanego projektu musiałem dynamicznie tworzyć zadania oraz funkcje, które będą im przyporządkowywane, dodatkowo z wywłaszczeniem. Niestety nie znalazłem żadnego gotowego rozwiązania i myślałem żeby całkiem przejść na ASM'a, ale przy tak świetnych poradnikach Mirka o wstawkach asemblerowych postanowiłem wszystko napisać w C, a jedynie krytyczne modyfikacje stosu umieścić w takich właśnie procedurkach :D

Problem autora tematu nie wymaga jednak aż tak złożonego podejścia, dlatego z pewnością z przedstawionym powyższym kodem wszystko będzie działać jak należy ;)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 sie 2014, o 00:04 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 18 maja 2014
Posty: 126
Pomógł: 12

No tu nie ma niestety priorytetów i wywłaszczania a funkcje są wykonywane w przerwaniu, więc nie należy przesadzać z objętością, bo będziemy gubić milisekundy jeżeli funkcja się nie wyrobi. W razie czego można zmniejszyć rozdzielczość timera do 10 ms, lub w przerwaniu odblokowywać przerwania, co pozwoli na ich zagnieżdżanie. Jeśli by następnie dodać do funkcji priorytety to dostaniemy właśnie Super Simple Taskera. Mam gdzieś uruchomiony przykład z wykorzystaniem bibliotek stworzonych przez Artura Lipowskiego. Przy ustawieniu najwyższego priorytetu dla obsługi timera wywoływanego co 1 ms można nawet w innej funkcji wrzucić _delay_ms albo nieskończoną pętlę a system co 1 ms sprawdzi czy nie ma czegoś ważniejszego do roboty, wykona to i wróci do mielenia delayem ;) a jeśli nie ma nic do roboty to uśpi procesor do następnego przerwania od timera. Jutro wrzucę i opiszę, bo myślę, że koncepcja jest dość ciekawa, a nie znalazłem w sieci przykładów zastosowania. Jedyne co, to trzeba pilnować użycia stosu, bo jak "się zagnieździmy" za bardzo to program pójdzie w maliny ;)

_________________
Pozdrawiam, Adrian.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 sie 2014, o 07:44 
Offline
Nowy

Dołączył(a): 11 lip 2014
Posty: 6
Pomógł: 0

OK. Dzięki wielkie Wam za pomoc. :)

Federerer jak to nie stwarza Ci żadnego problemu to chętnie zobaczę jaki jest jeszcze na to sposób.



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

Dołączył(a): 18 maja 2014
Posty: 126
Pomógł: 12

Tak jak pisałem wcześniej, do wywoływania zadań z określonym interwałem czasowym można użyć systemu który nazywa się Super Simple Tasker, taki trochę RTOS, z jednym stosem. Opis jest tu:
http://www.embedded.com/design/prototyping-and-development/4025691/Build-a-Super-Simple-Tasker
Biblioteki autorstwa Artura Lipowskiego tu (wymaga zalogowania):
http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=725&item_type=project

Tak w ramach zabawy uruchomiłem kiedyś przykład z tej paczki na attiny2313 i atmedze8. Na attiny można było tylko pomigać diodą, za mało flasha i ramu ;) Na atmedze wyświetlałem sobie wartości timerów na LCD i bawiłem się dodając w funkcjach delaye i zmieniając ich priorytety, patrząc czy się zawiesi :D. Np dając duże opóźnienie w funkcji wyświetlania na LCD spadała częstotliwość odświeżania, ale timer mierzył czas poprawnie, bo miał wyższy priorytet. Gdy zamieniłem priorytety, timer gubił impulsy, bo procesor mielił delayem, który miał wyższy priorytet niż obsługa timera. Nic poważniejszego nie testowałem. Kod przykładu przerobiony przeze mnie wyglądał tak:

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.


dodatkowo w pliku sst_base_def.h trzeba sobie ustawić kilka rzeczy. U mnie wyglądało to tak:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Wrzucę na wszelki wypadek w załączniku cały projekt bez bibliotek Mirka, bo nie jestem pewien czy czasem nie edytowałem czegoś w reszcie plików.

Aha, kompilowałem pod toolchainem atmela. W winavr nie znajdzie pliku bool.h, trzeba go dorobić ręcznie i dołączyć.


Autor postu otrzymał pochwałę

Załączniki:

Aby zobaczyć załączniki musisz się zalogować. Tylko zalogowani użytkownicy mogą oglądać i pobierać załączniki.

_________________
Pozdrawiam, Adrian.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 sie 2014, o 08:02 
Offline
Nowy

Dołączył(a): 11 lip 2014
Posty: 6
Pomógł: 0

Ok. Jeszcze raz dzięki za pomoc :)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 20 sie 2014, o 06:29 
Offline
Nowy

Dołączył(a): 11 lip 2014
Posty: 6
Pomógł: 0

Witam ponownie. Jak na razie najłatwiej było mi ogarnąć INTx, ale nie do końca wszystko mi wyszło tak jak bym chciał.
Mam 2 problemy ze swoim programem.
1- Czasami jest tak, że program przełącza PWM na 3 tryby ale prawie cały czas jest tak, że przechodzi tylko przez 2.
2- Jak przełącza się po trybach to jak dojdzie do ostatniego (tego co jest przed "default") to, żeby przejść do początku trzeba wcisnąć dwa razy przycisk.

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: 20 sie 2014, o 12:38 
Offline
Użytkownik
Avatar użytkownika

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

Pierwszym błędem jest wywołanie funkcji "inicjalizacja" w przerwaniu, która powinna zgodnie ze swoją nazwą być wywołana jednokrotnie przed pętlą główną programu.

Kolejny to zupełnie zbędne ciągłe ustawianie "pull-up'a" (PORTB = (1<<PD2);) w funkcji "przycisk". Zapewne chodziło o "pull-up" dla PD2, a nie PB2, dlatego tę linię można zupełnie usunąć, gdyż takowa znajduje się już w funkcji "inicjalizacja".

Następnie kolejna uwaga dotycząca ustawiania kierunku portów. Nie wiem jakie było założenie, ale w tym wypadku wszystkie piny oprócz PD2 będą wyjściami:

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

Nie powinno być w ten sposób?:

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

Podobnie sytuacja wygląda w głównej pętli "while" programu. Tam również warto użyć maskowania (jeżeli zmianie ma ulec stan jedynie niektórych pinów).

"SIGNAL(SIG_INTERRUPT0)" jest to przestarzały zapis i lepiej używać: "ISR(INT0_vect)".

Przechodząc do sedna problemu, przy pierwszym naciśnięciu klawisza wywoływana jest funkcja "tryb2", później "tryb3", a następnie zmianie ulega jedynie zmienna "n" nie wywołując przy tym żadnych akcji. Dobrze byłoby ustawiać jej stan przed instrukcją wyboru "switch". Można to zrobić w dwojaki sposób:
1. Używając reszty z dzielenia
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

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


Cały kod przedstawia się 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.


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 20 sie 2014, o 19:58 
Offline
Nowy

Dołączył(a): 11 lip 2014
Posty: 6
Pomógł: 0

atmel napisał(a):
Pierwszym błędem jest wywołanie funkcji "inicjalizacja" w przerwaniu...

Bez tej inicjalizacji program mi się nie uruchamia na uC.

atmel napisał(a):
Kolejny to zupełnie zbędne ciągłe ustawianie "pull-up'a" (PORTB = (1<<PD2);)...

Program na początku pisałem patrząc na inny i jakoś mi to umknęło.

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

Tu chodziło mi o to, żeby PWM dostał jeden sygnał po podłączeniu zasilania aby się uruchomił bez konieczności przyciskania przycisku.

Mam jeszcze takie pytanie czy maskowanie tutaj zapewnia lepsze działanie czy po prostu tak jest poprawniej?

A tak poza tym to program działa w 100% tak jak chciałem. Dziękuję bardzo za pomoc, omówienie i wyjaśnienie :)



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

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