• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Niskie taktowanie na PWM Atmega8

Mały hosting, OGROMNE możliwości
0 głosów
1,218 wizyt
pytanie zadane 6 lutego 2020 w Mikrokontrolery przez Mavimix Dyskutant (8,490 p.)
Chcę aby uC był taktowany na 8MHz, a jednocześnie potrzebuję uzyskać taktowanie 50Hz na zegarze PWM (programowanie serwomechanizmu). Nie mam pomysłu jak mogę zyskać taki efekt, pomógłby ktoś?

2 odpowiedzi

0 głosów
odpowiedź 6 lutego 2020 przez mokrowski Mędrzec (158,960 p.)
Masz 3 wyjścia:

1. Timery programowe

2. Timery sprzętowe

3. Zewnętrzny kontroler PWM

Ostatnie pewnie odpada bo to dodatkowy koszt. Najłatwiej będzie programowym.

Leciwe ale przydatne: http://hobby.abxyz.bplaced.net/index.php?pid=3&aid=20

Jeśli dalej nie zrozumiesz, zapytaj.
0 głosów
odpowiedź 6 lutego 2020 przez adrian17 Mentor (354,880 p.)
edycja 6 lutego 2020 przez adrian17

Na przykład (w tym stylu skonfigurowałem to w swoim projekcie lata temu, na oba kanały na raz, atmega16, 1MHz zegar):

// piny PWMa
DDRD = (1<<PD5) | (1<<PD4);

// PWM
TCCR1A =(1<<COM1A1)|   //tryb komparatora bez inwersji kanału OC1A
        (1<<COM1B1)|   //tryb komparatora bez inwersji kanału OC2B
        (1<<WGM10);    //wybor trybu (Fast PWM 8-bit)
TCCR1B =(1<<WGM12)|    //wybor trybu (Fast PWM 8-bit)
        (1<<CS10)|     //uruchomienie timera z prescalerem 64
        (1<<CS11);
        
OCR1A = 60; // 60/256 duty cycle -> ~25% dłgość pulsu
OCR1B = 120; // 120/256 duty cycle -> ~50% długość pulsu

U mnie z taktowaniem 1MHz to dawało 1MHz / 64 prescaler / 256 (bo 8-bit PWM) == 61Hz. Nie równo 50Hz, ale współczesne serwa akceptują duże zakresy częstotliwości (bardziej interesuje je szerokość pulsu).

Wrzuciłem ten kod u siebie na początek programu i potem tylko edytowałem OCR1A i OCR1B żeby kontrolować moc silników.

Z 8MHz można na przykład użyć prescaler 256 i tryb 9-bitowy PWMa żeby dostać analogicznie 61Hz. Albo można użyć Fast PWM z "customowym" maxem i ustawiając ICR1 dostać niemal dokładnie 50Hz (np: 8MHz / prescaler 8 / 20000 ICR1 == 50MHz). Jak chcesz to mogę Ci spróbować na sucho napisać konfigurację do tego.

Po szczegóły polecam zajrzeć do specyfikacji atmegi, rozdział "16-bit Timer/Counter1", przede wszystkim podrozdziały "Modes of Operation" i "16-bit Timer/Counter Register Description"; ładnie opisują wszystkie tryby w których może działać PWM i jak je włączyć.

komentarz 6 lutego 2020 przez Mavimix Dyskutant (8,490 p.)
edycja 6 lutego 2020 przez Mavimix
I serwo podłączam do PD4 lub PD5 tak? A to: OCR1A = 60; oznacza, że dziele OCR1A na 60, tak?
komentarz 6 lutego 2020 przez adrian17 Mentor (354,880 p.)
edycja 6 lutego 2020 przez adrian17

Tak jak mówiłem, to był przykład na atmegę16, więc dla atmegi8 trzeba by go trochę zaadaptować - na przykład pin OC1A jest na porcie B, nie D.

A to: OCR1A = 60; oznacza, że dziele OCR1A na 60, tak?

A tego tak szczerze to nie zrozumiałem. W trybie Fast PWM to działa tak, że, że dla wartości rejestru timera od 0 do 60 na pinie jest wysoki sygnał, a potem spada na niski sygnał. W trybie 8-bitowym rejestr liczy do 255 i się zawija, więc wysoki sygnał masz przez 60/256 czasu. W trybie "elastyczniejszym" (#14 na tabeli 39 z datasheetu) rejestr liczy do wartości ICR1.

komentarz 6 lutego 2020 przez adrian17 Mentor (354,880 p.)

Przykład bardziej zaadaptowany pod Twój use case - na sucho, więc może nie działać ;)

void setup() {
    // piny PWMa
    DDRB = (1<<PB1) | (1<<PB2);
     
    // PWM
    TCCR1A =(1<<COM1A1)|   //tryb komparatora bez inwersji kanału OC1A
            (1<<COM1B1)|   //tryb komparatora bez inwersji kanału OC2B
            (1<<WGM11);    //wybor trybu (Fast PWM, TOP w ICR1)
    TCCR1B =(1<<WGM12)|    //wybor trybu (Fast PWM, TOP w ICR1)
            (1<<WGM13)|    //wybor trybu (Fast PWM, TOP w ICR1)
            (1<<CS11);     //uruchomienie timera z prescalerem 8
    ICR1 = 19999; // 0-19999 -> 20000 cykli

    // 8MHz / 8 prescaler / 20000 == 50Hz
}

void set_power() {
    // przykłady mocy
    OCR1A = 0; // 0/19999 -> 0% długość pulsu
    OCR1A = 19999; // 19999/19999 -> 100% długość pulsu
    OCR1B = 2000; // 2000/19999 duty cycle -> ~10% długość pulsu
}

 

komentarz 6 lutego 2020 przez Mavimix Dyskutant (8,490 p.)
Powiem szczerze, że średnio rozumiem dlaczego takie wartości są przypisane do ICR1, OCR1A/B? Trzeba ustawiać 2 rejestry i TCRR1A i TCCR1B? Czy mógłbym 1.?
komentarz 6 lutego 2020 przez adrian17 Mentor (354,880 p.)
edycja 6 lutego 2020 przez adrian17

Dlatego polecam mieć pod ręką datasheet atmegi8 ;)

https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2486-8-bit-AVR-microcontroller-ATmega8_L_datasheet.pdf

Po kolei:

Strona 75 - tu zaczyna się opis działania timera. Pierwszych kilka stron jest mocno technicznych i mało ciekawych.

Strona 89 - pokazuje na diagramie jak działa tryb Fast PWM. Rejestr TCNT1 idzie od 0 do maksymalnej wartości i gdy po drodze przekroczy wartość OCR1, zmienia wyjście pinu na 0 aż do końca cyklu. W praktyce właśnie tak można wysyłać pulsy do serwa ze stałą częstotliwością i zmienną szerokością.

Strona 96 - zaczyna się opis, jak to ustawić w rejestrach.

Tablica 37 - ustawiam COM1A1 (i COM1B1), więc wybieram trzeci tryb, mówiący to co wyżej napisałem: "gdy po drodze przekroczy wartość OCR1, zmienia wyjście pinu na 0 aż do końca cyklu".

Strona 97/8, tablica 39 - ustawiam tryb 14, Fast PWM z konfigurowalną długością cyklu przez ICR1. W tym celu ustawiam WGM11, WGM12, WGM13. Tak się dziwnie składa, że te flagi są rozbite po dwóch rejestrach, TCRR1A i TCCR1B.

Strona 99, tablica 40 - te flagi dopiero włączają zegar timera. Przy okazji ustawiam prescaler 8 (czyli co 8 cykli zegara 8MHz wykonuje się jeden cykl timera).

dlaczego takie wartości są przypisane do ICR1

W ten sposób ustawiam częstotliwość 50MHz. Zegar 8MHz, z prescalerem 8, więc co 8 cykli podnosi timer o 1. Co 20000 cykli timera timer się resetuje, więc końcowa częstotliwość jest 8MHz/8/20000 == 50Hz.

OCR1A/B?

W sensie, dlaczego wartość 2000 to 10% długości pulsu? Wrócę do obrazka z strony 89, może to pomoże: https://puu.sh/F7PdG/fb4b6180bf.png A ogólnie tutaj wartości wpisujesz jakie chcesz, tym właśnie sterujesz serwem.

Ogólnie nie trzeba znać całego tego datasheetu znać żeby móc używać PWMy, sam znam tylko z 2-3 proste tryby które akurat potrzebowałem a z innymi nigdy nic nie robiłem ;)

Tu masz inny przykładowy tutorial po polsku (i raczej łatwiejszym językiem niż ja :P ) opisujący działanie PWMa w Atmedze, może pomoże: https://forbot.pl/blog/wszystko-co-musisz-wiedziec-aby-uruchomic-pwm-id5021

Podobne pytania

0 głosów
1 odpowiedź 370 wizyt
pytanie zadane 11 maja 2016 w C i C++ przez Dorota95 Nowicjusz (210 p.)
0 głosów
1 odpowiedź 706 wizyt
pytanie zadane 9 listopada 2018 w Mikrokontrolery przez Jezel123 Nowicjusz (120 p.)
0 głosów
1 odpowiedź 743 wizyt
pytanie zadane 30 marca 2022 w Mikrokontrolery przez Mavimix Dyskutant (8,490 p.)

93,718 zapytań

142,629 odpowiedzi

323,261 komentarzy

63,265 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...