logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

ATmega8535 - PWM, serwonapęd - język C

ProgramerAG 11 Sty 2009 15:45 1829 3
REKLAMA
  • #1 5982988
    ProgramerAG
    Poziom 10  
    Dzień dobry, mam problem z uruchomieniem serwonapędu na ATmega8535, prosiłbym was o ustosunkowanie się do mojego kodu. Pisząc go posiłkowałem się stronami:
    Idea sterowania serwonapędu
    Przykłady - licznik/czasomierz na AVR
    Używam serwonapędu HSR-8499HB Opis serwa, serwo to ma możliwość wyboru trzech trybów sterowania. Ja chcę zrealizować to, przy pomocy wypełnienia pwm, czyli standard pulse mode.
    Tak jak na początku postu napisałem, używam ATmega8535, z 10MHz kwarcem. Zgodnie ze wzorem znajdującym się na stronie Idea sterowania serwonapędu do ICR1 powinienem wpisać 12500, tymczasem muszę tą wartość pomnożyć przez 2, aby na nóżce OC1A mikrokontrolera pojawiła się częstotliwość 50 Hz, inaczej jest 100Hz (mierzę prostym miernikiem uniwersalnym). Mimo tego program nie działa tak jak bym się tego spodziewał, to znaczy serwo wogóle nie reaguje na stan portów, do któych podłączone są przyciski.
    (PORTA.0 i PORTA.1). Jednocześnie serwo chyba jest sprawne, ponieważ wychylone z położenia pierwotnego, po załączeniu napięcia wraca do swojego pierwotnego stanu (-90 stopni).
    Oto kod, którego używam:
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include <string.h>
    
    int main(void)
    {
      int p = 1500;  //zmienna
      DDRA = 0x00;  //przyciski
      PORTA =0X03;  //przyciski sa podlaczone do masy (ustawiam stan wysoki)
      DDRD|=(1<<5); //PORTD.5 to OC1A w ATmega8535
      ICR1=12500*2;  //z obliczeń wynika, że powinno być 12500
      OCR1A = p; //określenie wypełnienia
    
      TCCR1A |= (0<<COM1A0)|(1<<COM1A1)|(0<<COM1B0)|(0<<COM1B1)|(0<<FOC1A)|(0<<FOC1B)|(1<<WGM11)|(0<<WGM10);
      TCCR1B |= (0<<ICNC1)|(0<<ICES1)|(1<<WGM13)|(1<<WGM12)|(0<<CS12)|(1<<CS11)|(0<<CS10);
      for (;;)
      {
    
         if(bit_is_clear(PINA, 0))
         {
             p+=50;
          //   if(p > 2000) p=2000;
            OCR1A=p;
    	loop_until_bit_is_set(PINA, 0);
         }
         if(bit_is_clear(PINA, 1))
         {
             p-=50;
            // if(p < 1000) p=1000;
             OCR1A=p;
             loop_until_bit_is_set(PINA, 1);
         }
    
      }
    }
    


    Proszę o pomoc.
  • REKLAMA
  • #2 5983353
    d3zerter
    Poziom 12  
    mi wyszło że żeby częstotliwość była równa 50hz należy wpisać 25000, tj. 10000000 hz/8 (prescaler)/50hz. Więc tutaj by to się zgadzało.

    a nie powinno być loop_until_bit_is_clear zamiast
    loop_until_bit_is_set(PINA, 0); 
  • REKLAMA
  • #3 5983672
    ProgramerAG
    Poziom 10  
    Witam, zgodnie ze wzorem znajdującym się na pierwszej stronie tzn. TOP=fclk/(2*N*f) a nie TOP=fclk/(N*f) jednakże dziwne jest to, że mimo wpisania 25000 częstotliwość wyjściowa na nóżce nadal jest równa 50 Hz. Co do loop_until_bit_is_set to wydaje się prawidłowe, ponieważ bit is set, gdy puszczam przycisk, czyli wtedy nie powinna zmieniać się wartość.
  • #4 6040863
    ProgramerAG
    Poziom 10  
    Po sprawdzeniu na oscyloskopie program okazał się prawidłowy. Problem tkwił w serwonapędzie, który miał przepalony sterownik.
REKLAMA