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



Teraz jest 25 kwi 2024, o 13:00


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 8 ] 
Autor Wiadomość
PostNapisane: 15 cze 2019, o 23:03 
Offline
Nowy

Dołączył(a): 03 sty 2014
Posty: 19
Pomógł: 0

Cześć,
Mózg mi zaraz wyparuje, niewiele zostało ;)

Chciałbym wygenerować PWM na pin PD0 w atmega32u4.

Proszę poprawcie mnie, w którym miejscu coś źle rozumiem:

INT0/SCL/OC0B – Port D, Bit 0
OC.0B: Timer 0 Output Compare B. This pin can be used to generate a PWM signal from the Timer 0 module.

Czyli muszę ustawić Timer0:
TCCR0A = (1<<WGM00);
TCCR0A = (1<<WGM01);
TCCR0B = (1<<CS01);
TCCR0A = (1<<COM0A1);

a następnie ustawić jakąś wartość w

OCR0B ?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 16 cze 2019, o 10:00 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 04 lut 2014
Posty: 164
Pomógł: 3

Jeżeli rejestry są poprawne to tylko wpisać wartość od 0 do 255 i oczywiście nie zapomnieć o
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

_________________
::::::: C ::::::::::
:::::: C++ :::::::::



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 16 cze 2019, o 13:02 
Offline
Użytkownik

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

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

Po pierwsze, jeśli w trybie Fast PWM chcesz uzyskać sygnał PWM na pinie OC0B (PD0), to musisz w rejestrze TCCR0A ustawić bit COM0B1, a nie COM0A1.
Po drugie nie przedstawiłeś całego kodu, więc może to robisz w innym miejscu, ale dla uzyskania na wyjściu OC0B(PD0) sygnału PWM wymagane jest także ustawienie tego pinu jako wyjście:
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 linii 2 Twojego kodu, wpisując nową wartość do rejestru TCCR0A, zerujesz bit WGM00, który wcześniej ustawiłeś w linii 1. Podobnie jest w linii 4. Aby tego uniknąć powinieneś zastosować operator |= lub | w następujący 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.

Później wartość wypełnienia regulujesz poprzez wpisanie odpowiedniej wartości do rejestru OCR0B. Należy jednak pamiętać o tym, że przy takich ustawieniach timera nie da się uzyskać wypełnienia 0%, czyli nawet wpisując do OCR0B wartość 0 nie da się uzyskać ciągłego stanu niskiego na pinie OC0B. Po każdym przepełnieniu licznika na wyjściu OC0B będzie pojawiać się krótkotrwały impuls.

Lex_ napisał(a):
Jeżeli rejestry są poprawne to tylko wpisać wartość od 0 do 255 i oczywiście nie zapomnieć o
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Po pierwsze ten mikrokontroler nie ma rejestru TIMSK, tylko np. (między innymi) TIMSK0.
OCR0B to nazwa rejestru, a nie bitu. Zezwolenie na przerwanie od porównania realizuje bit OCIE0B w rejestrze TIMSK0.
Włączenie przerwań od porównania wcale nie jest konieczne do wygenerowania sygnału PWM.


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 16 cze 2019, o 17:46 
Offline
Nowy

Dołączył(a): 03 sty 2014
Posty: 19
Pomógł: 0

Bardzo Wam dziękuję za pomoc!
Wszystko działa. Niesamowicie dziękuję za tak wyczerpującą odpowiedź.

Czy mogę jeszcze tylko poprosić o informację z czego wynika że nie da się ustawić wypełniania 0%?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 16 cze 2019, o 18:44 
Offline
Użytkownik

Dołączył(a): 25 lip 2013
Posty: 2562
Pomógł: 126

Poczytaj o tzw. glitch. Ale można to obejść stosując 'negację'. Wtedy 0 to max wypełnienia a 255 to idealne 0.


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 16 cze 2019, o 18:47 
Offline
Użytkownik

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

goslawen napisał(a):
Czy mogę jeszcze tylko poprosić o informację z czego wynika że nie da się ustawić wypełniania 0%?

To raczej pytanie do producenta mikrokontrolera ;)

Takie jest z założenia działanie w trybie Fast PWM. Wynika to z tego, że rejestr OCR0B jest ośmiobitowy (inny być nie może, bo timer też jest ośmiobitowy). Może więc przechowywać 256 wartości, czyli od 0 do 255. Odliczanie w tym trybie odbywa się tylko w jednym kierunku, więc zrównanie wartości występuje tylko 1 raz na okres zliczania timera wynoszący 256 taktów. Istnieją więc dwie opcje:
  • wypełnienie będzie miało zakres od 0/256 do 255/256, czyli nie da się uzyskać pełnego wypełnienia 100%,
  • wypełnienie będzie miało zakres od 1/256 do 256/256, czyli nie da się uzyskać wypełnienia 0%.
Można wybrać tylko jedną z tych opcji i producent wybrał akurat tę drugą. Dlaczego? Tego nie wiem ;)

Jeśli jednak lepiej pasowałaby Ci ta pierwsza opcja, możesz odwrócić polaryzację PWM poprzez ustawienie bitów COM0B1=1 i COM0B0=1. Wypełnienie (stanem wysokim) będzie wtedy równe 255-OCR0B. Wtedy jednak nie da się uzyskać wypełnienia 100%.

Inną alternatywą jest użycie innego trybu pracy timera, np. Phase Correct PWM, i wtedy uzyskasz pełen zakres od 0 do 100%, za to częstotliwość będzie o około połowę mniejsza, ponieważ tutaj odliczanie jest dwukierunkowe. Nie będę tutaj już tego tutaj dokładnie wyjaśniał, bo dopuszczalna pojemność postu na forum może być za mała ;) Szczegóły można znaleźć w dokumentacji mikrokontrolera.


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 sie 2019, o 15:39 
Offline
Nowy

Dołączył(a): 03 sty 2014
Posty: 19
Pomógł: 0

Męczę temat dalej, jednak kilku rzeczy nie rozumiem.
Może uda się Wam mi znowu trochę temat rozjaśnić.

W momencie przypisania jakiejkolwiek wartości do rejestru OCR0B program się "resetuje". Tj wraca na początek funkcji
int main(void). Robi tak dokładnie 3 razy po czym mimo wszystko wartość się wpisuje i PWM zaczyna działać.
Miejsce przypisania OCR0B nie ma znaczenia, czy w samej funkcji main czy w innej np. oid parse_nrf_data ( char * buf, uint8_t len ) po otrzymaniu czegoś z NRF24l01.

Kod wygląda jak wygląda bo już sobie włosy z głowy rwałem i zamieniałem 0b na 0x itp ;) i inne tego typu pomysłu, które ostatecznie nic nie dały.
Myślę że ten błąd może powodować również to, że NRF24l01 raz wysyła komunikaty poprawnie a po pewnym czasie ileś z rzędu zgubi i tak w kółko.
Wydawało się, że wszystko "działa poprawnie" do czasu aż zacząłem zatrzymywać program debugerem. (poza tymi ominiętymi komunikatami). Nawet zmiana ilości powtórzeń na 15, czy czasu na oczekiwanie na 3750u niewiele pomogła.

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

}

------------------------ [ Dodano po: 57 minutach ]

// sei(); oczywiście powinno być bez komentarza.

// nie udało mi się zedytować postu



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 19 sie 2019, o 19:04 
Offline
Nowy

Dołączył(a): 03 sty 2014
Posty: 19
Pomógł: 0

Problem rozwiązany. Koledzy z elektrody słusznie zauważyli, że gdy wywalałem z kodu wszystko, żeby sprawdzić na jak najwęższym zakresie co mi nie działa wyrzuciłem też obsługę jednego przerwania. To powodowało dziwne zachowanie przy sei ().



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