Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

PWM - które piny mogę użyć?

miccaldo 02 Lis 2012 17:46 3204 30
  • #1 02 Lis 2012 17:46
    miccaldo
    Poziom 12  

    Witam, czy pwm można zastosować jedynie na pinach OC1A i OC1B?

    0 29
  • #2 02 Lis 2012 17:56
    mickpr
    Poziom 39  

    Podaj rodzaj MCU!

    Jeśli to Atmega:
    Z punktu widzenia wyjścia - można zrealizować PWM na każdym pinie.
    Jedyną różnicą będzie fakt, że na pinach - które podałeś masz wyjście PWM realizowane sprzętowo (wystarczy ustawić jego parametry).
    Na pozostałych pinach musiałbyś zrealizować PWM programowo - i zaangażować w tym celu czas i zasoby procesora.
    Zatem piny, które podałeś są niejako dedykowane do celu (m.in.) PWM.

    0
  • #3 04 Lis 2012 16:45
    miccaldo
    Poziom 12  

    Rozumiem, procesor to attiny 2313, a mógł by ktoś podać mi stronę na której dokładnie jest opisane pwm? Realizacja jego, przykłady, co i jak? Bo szukałem dość sporo na internecie ale nie rozumiem za bardzo o co tam chodzi.

    0
  • #5 09 Lis 2012 16:02
    miccaldo
    Poziom 12  

    Ok już trochę bardziej to rozumiem, tylko w tym kodzie:

    Code:
    // program to change brightness of an LED
    
    // demonstration of PWM

    #include <avr/io.h>
    #include <util/delay.h>

    // initialize PWM
    void pwm_init()
    {
        // initialize timer0 in PWM mode
        TCCR0 |= (1<<WGM00)|(1<<COM01)|(1<<WGM01)|(1<<CS00);

        // make sure to make OC0 pin (pin PB3 for atmega32) as output pin
        DDRB |= (1<<PB3);
    }

    void main()
    {
        uint8_t brightness;

        // initialize timer0 in PWM mode
        pwm_init();

        // run forever
        while(1)
        {
            // increasing brightness
            for (brightness = 0; brightness < 255; ++brightness)
            {
                // set the brightness as duty cycle
                OCR0 = brightness;

                // delay so as to make the user "see" the change in brightness
                _delay_ms(10);
            }

            // decreasing brightness
            for (brightness = 255; brightness > 0; --brightness)
            {
                // set the brightness as duty cycle
                OCR0 = brightness;

                // delay so as to make the user "see" the change in brightness
                _delay_ms(10);
            }

        // repeat this forever
        }
    }

    Do którego pinu podpięta jest ta dioda?
    I wracając do mojego pierwszego pytania, chciałbym żeby pwm był powiedzmy na PINie 2 PORTU C, jak mam to programowo zrobić? Zdefiniować na początku programu czy coś? Bo widziałem że w niektórych programach tak jest.
    I jeszcze jedno pytanie: dlaczego w TCCR0 jest ustawiony bit CS00? Nie powinno być zamiast tego COM00?

    0
  • #6 09 Lis 2012 16:44
    mi14chal
    Poziom 28  

    A komentarze w kodzie to się czyta? make sure to make OC0 pin (pin PB3 for atmega32) as output pin Da się też zrobić programowo po prostu robisz to na przerwaniu w którym zmieniasz stan wyjściowy danego pinu.

    0
  • #7 09 Lis 2012 17:33
    miccaldo
    Poziom 12  

    Dobra, mam takie coś:

    Code:


    #define F_CPU 1000000L
    #include <avr/io.h>
    #include <util/delay.h>


    void pwm_init()
    {
       
        TCCR0A |= (1<<WGM10)|(1<<COM0A1)|(1<<COM0A0);
       TCCR0B |= (1<<CS00)|(1<<CS01);
       
        DDRB |= (1<<PB2);
    }
    void main()
    {
        uint8_t jasnosc;
       jasnosc = 180;

        pwm_init();
       
       
        while(1)
        {
           OCR0A = jasnosc;
        }
    }

    Tylko dioda zamiast się ściemnić, jest wrażenie jakby z dużą częstotliwością(jak da oka) mrugała... Co trzeba zmienić aby dioda się ściemniła?

    0
  • #8 09 Lis 2012 17:43
    mi14chal
    Poziom 28  

    No w poprzednim kodzie który tu dałeś jest pokazane jak zrobić żeby rozjaśniać i ściemniać diodę.

    0
  • #9 09 Lis 2012 17:47
    miccaldo
    Poziom 12  

    Na razie chciałbym tylko ją zauważalnie ściemnić, bo teraz to miga mi bardzo szybko nie wiem dlaczego.

    0
  • Pomocny post
    #10 09 Lis 2012 17:59
    Procesor32
    Poziom 12  

    miccaldo napisał:
    jasnosc = 180


    Jest to stała, a powinna być w pętli zwiększana, lub zmniejszana.

    Dodano po 8 [minuty]:

    miccaldo napisał:
    miga mi bardzo szybko nie wiem dlaczego.

    Jeśli umieściłeś w pętli OCR0A = jasność , a jasność = 180 to musi migać.

    0
  • #11 09 Lis 2012 18:27
    miccaldo
    Poziom 12  

    Czyli OCR0A mam umieścić poza pętlą? Nie bardzo wiem co mam zrobić.

    0
  • #12 09 Lis 2012 18:30
    Procesor32
    Poziom 12  

    mi14chal napisał:
    No w poprzednim kodzie który tu dałeś jest pokazane jak zrobić żeby rozjaśniać i ściemniać diodę.

    Czytaj, co piszą inni.
    Przeanalizuj kod, który dodałeś.

    0
  • #13 09 Lis 2012 18:50
    miccaldo
    Poziom 12  

    Powyższy program stopniowo rozjaśnia i zgasza diodę, ja chcę aby świeciła na poziomie powiedzmy 50%, jestem początkujący więc proszę o wyrozumiałość. Mógł by mnie ktoś nakierować jak to zrobić? Bo już próbowałem kilku sposobów ale za każdym razem dioda miga.

    0
  • #14 09 Lis 2012 19:01
    Procesor32
    Poziom 12  

    miccaldo napisał:
    ja chcę aby świeciła na poziomie powiedzmy 50%,


    Maksymalna wartość PWM to 255 ... podziel to na dwa (liczba całkowita) i jest 50 %.

    Dodano po 3 [minuty]:

    miccaldo napisał:
    Czyli OCR0A mam umieścić poza pętlą?


    Brawo

    0
  • Pomocny post
    #15 09 Lis 2012 19:05
    ZbeeGin
    Poziom 38  

    miccaldo napisał:
    Tylko dioda zamiast się ściemnić, jest wrażenie jakby z dużą częstotliwością(jak da oka) mrugała... Co trzeba zmienić aby dioda się ściemniła?

    Preskaler ustaw na 1 (albo na 8) i włącz tryb FastPWM. Obecnie masz preskaler 64 i tryb Phase Correct. Dlatego dioda miga około 30Hz.

    Twoja Biblia: http://www.atmel.com/Images/doc2543.pdf

    0
  • #16 09 Lis 2012 19:50
    miccaldo
    Poziom 12  

    Cytat:
    Preskaler ustaw na 1 (albo na 8) i włącz tryb FastPWM. Obecnie masz preskaler 64 i tryb Phase Correct. Dlatego dioda miga około 30Hz.


    Ustawiłem, teraz jest dużo bardziej dokładne, program gaszący i rozjaśniający diodę jest płynny. Ale wracając, program który ma tylko przygasić diodę:

    Code:

    #define F_CPU 1000000L
    #include <avr/io.h>
    #include <util/delay.h>


    void pwm_init()
    {
       
        TCCR0A |= (1<<WGM10)|(1<<COM0A1)|(1<<COM0A0);
       TCCR0B |= (1<<CS00);
       TCCR1B |= (1<<WGM12);
       
        DDRB |= (1<<PB2);
    }
    void main()
    {
        uint8_t jasnosc;
       jasnosc = 50;
       
       pwm_init();

       OCR0A = jasnosc;
       
    }


    Z ustawieniem Fast PWM, preskaler 1 dioda przestała migać, ale jest w pełni otwarta, macie może jakiś pomysł co zmienić w kodzie żeby ją przyciemnić?

    0
  • #17 09 Lis 2012 19:55
    ZbeeGin
    Poziom 38  

    miccaldo napisał:
        TCCR0A |= (1<<WGM10)|(1<<COM0A1)|(1<<COM0A0);
       TCCR0B |= (1<<CS00);
       TCCR1B |= (1<<WGM12);

    A cóż to za "kwiatek"? Poczytaj sobie jakie bity występują w TCCR0A i TCCR1B i do czego służą. Oraz dlaczego nie powinno się ustawiać bitów w liczniku TIMER1 jak korzysta się z licznika TIMER0.

    0
  • #18 09 Lis 2012 20:38
    miccaldo
    Poziom 12  

    Znalazłem coś. TCCRx, x - numer timera. U mnie jest TCCR0A i TCCR1B, także jeśli korzystam z timera 0, nie mogę ustawiać żadnych bitów w timerze 1. W takim razie czegoś tutaj nie rozumiem. W tabelce Waveform Generation Mode Bit Description aby ustawić 8 - bitowy Fast PWM, muszę ustawić WGM10 oraz WGM12, który znajduje się w TCCR1B, a więc timer 1. Jak w związku z tym ustawić Fast PWM, aby bity znajdowały się w timerze 0?

    0
  • #19 10 Lis 2012 13:17
    miccaldo
    Poziom 12  

    Ustawiłem timer1 i to samo, dioda świeci z pełną mocą...

    Code:
    #define F_CPU 1000000L 
    
    #include <avr/io.h>
    #include <util/delay.h>


    void pwm_init()
    {
       
        TCCR1A |= (1<<WGM10)|(1<<COM1B1)|(1<<COM1B0);
       TCCR1B |= (1<<WGM12)|(1<<CS10);
       
        DDRB |= (1<<PB4);
    }
    void main()
    {
        uint8_t jasnosc;
       jasnosc = 3000;
       
       pwm_init();

       OCR1B = jasnosc;
       
    }

    Nie wiem co z tym zrobić.

    0
  • #20 10 Lis 2012 14:53
    Procesor32
    Poziom 12  

    miccaldo napisał:
    jasnosc = 3000


    Co to jest ?

    0
  • #21 10 Lis 2012 15:20
    McMonster
    Poziom 32  

    Procesor32 napisał:
    miccaldo napisał:
    jasnosc = 3000


    Co to jest ?


    Podpowiem, jasnosc jest typu uint8_t, który jest 8-bitowy. Na 8 bitach maksymalną wartością, jaką możesz zapisać, jest 255. Kompilator powinien w takim wypadku wyprodukować ostrzeżenie, które zignorowałeś.

    0
  • #23 10 Lis 2012 16:42
    miccaldo
    Poziom 12  

    Dodałem ICR1 = 255, dioda ściemnia się prawidłowo. Jednak nie wiem co robi to ICR że PWM zaczął działać prawidłowo, mógłby ktoś podesłać jakąś lekturę gdzie jest to wytłumaczone? Mam jeszcze trzy pytania:

    1. W programie rozjaśniającym i ściemniającym diodę, dioda nie ściemnia się do końca, dlaczego?
    2. Chciałbym, aby dioda była zgaszona, a po naciśnięciu przycisku zaczął działać PWM. Program działa w ten sposób, że dioda jeszcze przed naciśnięciem przycisku jest w pełni otwarta, następnie jest wykonywana instrukcja. Jak ją zgasić przed naciśnięciem?
    3. Chciałbym napisać program PWM, aby pierwsza dioda się rozjaśniała, a druga dioda w tym samym czasie się ściemniała, później druga rozjaśniała, pierwsza ściemniała i zapętlić. Muszę chyba zrobić tak, że dwie pętle jednocześnie się wykonują, tylko jak? to pytanie do Was.

    Oto program:

    Code:


    #define F_CPU 1000000L
    #include <avr/io.h>
    #include <util/delay.h>


    void pwm_init()
    {
       
        TCCR1A |= (1<<WGM10)|(1<<COM1B1)|(1<<COM1B0); // timer1
       TCCR1B |= (1<<WGM12)|(1<<CS10);
       
       ICR1 = 255;
       
        DDRB |= (1<<PB4);
       DDRD |= 0x00;
       
       PORTD |= 0x40;
       PORTB |= 0x00;
    }
    int main(void)
    {
        uint8_t jasnosc;
       
       int i;

        pwm_init();
       
       
        while(1)
       {
          while(!(PIND & 0x40))
             {
             
             for(i=0;i<4;i++)
             {
       
                for (jasnosc = 255; jasnosc > 0; --jasnosc)
                {
                   OCR1B = jasnosc;
                   
                   _delay_ms(9);

                }
             
       if(jasnosc = 0)
       {
          _delay_ms(230);
       }
          
                for (jasnosc = 0; jasnosc < 255; ++jasnosc)
                {
                   OCR1B = jasnosc;
                   _delay_ms(4);
                }
                
       if(jasnosc = 256);
       {
          _delay_ms(230);
       }
       
    }
    }
    }
    }


    Z góry dziękuje za odpowiedzi.

    0
  • #24 10 Lis 2012 17:11
    Procesor32
    Poziom 12  

    McMonster, ja to wiem, było to pytanie do autora wątku.

    Dodano po 24 [minuty]:

    miccaldo napisał:
    mógłby ktoś podesłać jakąś lekturę gdzie jest to wytłumaczone?

    Lektura to PDF twojego procka.
    1) For brightness = 255 To 1 Step -1 = pętla liczy do 1, a nie do zera.
    2) jasność = 0
    3) Przestudiuj dokładnie kod, jaki wkleiłeś jako 1

    Nie wiem jaki masz procek, ale instrukcja po polsku do Atmega16 znajduje się tutaj Link

    0
  • #25 10 Lis 2012 19:18
    miccaldo
    Poziom 12  

    Jednak ICR jest tu nie potrzebne, usunięcie COM0A0 spowodowało przygaszenie diody.

    Cytat:
    jasność = 0


    Mam prosty kod który powinien zgasić diodę, jednak lekko się świeci, a wartość jasność = 0. Więc od czego zależy żeby całkowicie ją gasić PWMem?
    Code:


    #define F_CPU 1000000L
    #include <avr/io.h>
    #include <util/delay.h>


    void pwm_init() // inicjalizacja PWM
    {
       
       TCCR0A |= (1<<WGM01)|(1<<COM0A1)|(1<<WGM00); // timer0
       TCCR0B |= (1<<CS00);
       
       DDRB |=(1<<PB2);

    }

    int main(void)
    {
       
       uint8_t jasnosc;
       jasnosc = 0;

        pwm_init();
       

       OCR0A = jasnosc;
       
    }
       


    Edit: Próbowałem teraz z timerem 1, dioda gasi się w pełni, działa po naciśnięciu przycisku czyli wszystko w porządku. Ale w takim razie dlaczego nie działa w timerze0?

    Dodano po 26 [minuty]:

    W timerze0 dioda bez względu na wartość jaką wpiszę do 'jasnosc' zawsze delikatnie się świeci, dla przykładu,
    Code:

    jasnosc = 100;

        pwm_init();

        while(1)
       {
          while(!(PIND & 0x40))
             {
             
       OCR0A = jasnosc;
    }
    }
    }

    Z początku słabo się pali, po naciśnięciu pali się zdecydowanie mocniej czyli problem tkwi w zgaszeniu tej diody.

    0
  • #26 10 Lis 2012 19:40
    McMonster
    Poziom 32  

    Procesor32 napisał:
    McMonster, ja to wiem, było to pytanie do autora wątku.

    Wiem o tym, moja podpowiedź też była skierowana do autora.

    Dobry poradnik do timerów jest tutaj, tyle że po angielsku.

    0
  • #27 12 Lis 2012 10:12
    Procesor32
    Poziom 12  

    miccaldo napisał:
    Ale w takim razie dlaczego nie działa w timerze0?

    Nie wiem, czy Timer0 obsługuje tryb PWM w Twoim procku, jest to wątpliwe.
    Pomoc Link

    0
  • #28 12 Lis 2012 10:32
    ZbeeGin
    Poziom 38  

    Procesor32 napisał:
    Nie wiem, czy Timer0 obsługuje tryb PWM w Twoim procku, jest to wątpliwe.

    Niestety Attiny2313 obsługuje PWM z TIMER0 i do tego dwa kanały.

    0
  • #29 12 Lis 2012 10:57
    Procesor32
    Poziom 12  

    To teraz już to wiem, dziękuję.
    Osobiście nie używam takich maleństw.

    0
  • #30 12 Lis 2012 11:43
    ZbeeGin
    Poziom 38  

    miccaldo napisał:
    W timerze0 dioda bez względu na wartość jaką wpiszę do 'jasnosc' zawsze delikatnie się świeci, dla przykładu,

    PWM nie jest idealny. Jeśli do OCR0A wpiszesz 0 to i tak na wyjściu pojawia się szpilka. Mój oscyloskop określa tą szpilkę na 0,4% wypełnienia. Przy prawie 4kHz robi się już moc, która podświetla diodę (obecnie diody mają bardzo dobre struktury).
    Tu gdy OCR0A = 0;
    PWM - które piny mogę użyć?
    Tu gdy OCR0A = 200;
    PWM - które piny mogę użyć?

    PWM chodzi poprawnie tylko musisz dobrać rezystor ograniczający prąd diody. Dodatkowo możesz nieco zmienić prescaler by zmniejszyć częstotliwość.

    0