Forum Elektroniki Praktycznej Strona Główna

Elektronika PraktycznaElektronika Praktyczna    FAQFAQ    SzukajSzukaj    StatystykiStatystyki    UżytkownicyUżytkownicy    GrupyGrupy    RangiRangi
RejestracjaRejestracja    ProfilProfil    Zaloguj się, by sprawdzić wiadomościZaloguj się, by sprawdzić wiadomości    ZalogujZaloguj
Użytkownik:    Hasło:      Zaloguj mnie automatycznie przy każdej wizycie    

Poprzedni temat «» Następny temat
[Atmega8] Problem ze zmiennym okresem dzialania pętli
Autor Wiadomość
Serwik


Poland

Dołączył: 10 Mar 2010
Posty: 4
Skąd: Warszawa
Wysłany: 10-03-2010, 23:08   [Atmega8] Problem ze zmiennym okresem dzialania pętli

Próbowałem zrobić prosty program do sterowania serwem (Hitec HS311). Kod miał działać tak aby generować na wyjściu D procesora impuls o określonej szerokości a po nim 0 tak aby okres (impuls i zero) był stały (period=20ms)
Impuls jest sterowany przez zmienną t, która waha się w przedziale od 0.6 do 2.4ms co jest zgodne ze specyfikacja serwa i powinno powodować jego wychylenie od -90 do 90 stopni. t jest zwiększane i zmniejszane o stałą offset (tu: 0.05)
Problem polega na tym ze sygnal wyjsciowy na D jest inny niz zaprogramowany.

Kod:
#define F_CPU 4000000L
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  double t = 1.5;
  double offset = 0.05;
  double period = 20.0;
   
    /* Wszystkie linie portu D będą wyjściami */
    DDRD = 0xFF;
(1)    //t = t + offset; <- -- INSTRUKCJA DODAWANIA W TYM MIEJSCU DZIALA POPRAWNIE

    /* Początek nieskończonej pętli */
    while(1)
    {
      if ((t<=0.6)||(t>=2.4)) offset = -offset;
       
      PORTD = 0xAA; //1010 1010
      _delay_ms(t);
   
      PORTD = 0x55; //0101 0101
      _delay_ms(period-t);
   
(2)      t = t + offset;   <--- TA INSTRUKCJA ZMIENIA OKRES PETLI
    }
}


Wg powyższego programu okres sygnału powinien trwać równo 20ms. Niestety trwa on dłużej a zmienna t (impuls na wyjściu) nie przyjmuje wartości z przedziału 0.6-2.4 tylko ok 1.5-3.3. Problem znika gdy w pętli zakomentuje się instrukcje (2). t jest wówczas niezmienne i wynosi 1.5 co idealnie widać na oscyloskopie a serwo ustawia sie w pozycji 0. Zmiana wartości t na 0.6 skutkuje przechyleniem serwa o -90stopni a 2.4 o +90 (i to jest OK)
Program prawidłowo dodaje offset w miejscu (1). Po odkomentowaniu instrukcji (1) t zostaje zwiększone prawidłowo.
Problem pojawia się natomiast gdy t jest zmieniane w pętli np. w miejscu (2). Wówczas występuje to "przesunięcie" i rozciągniecie okresów.
Procesor ustawiony jest na zewnętrzny kwarc o częstotliwości 4MHz.
Stawiam pierwsze kroki w programowaniu AVR i będę wdzięczny za wyjaśnienie tej anomalii :)
 
     
Serwik


Poland

Dołączył: 10 Mar 2010
Posty: 4
Skąd: Warszawa
Wysłany: 11-03-2010, 19:16   

No prosze znalazlem odpowiedz w delay.h
\note In order for these functions to work as intended, compiler
optimizations <em>must</em> be enabled, and the delay time
<em>must</em> be an expression that is a known constant at
compile-time. If these requirements are not met, the resulting
delay will be much longer (and basically unpredictable), and
applications that otherwise do not use floating-point calculations
will experience severe code bloat by the floating-point library
routines linked into the application.

Okazuje sie ze _delay dziala poprawnie tylko gdy jako parametr poda sie wartość stałą. W innym przypadku funkcja dziala w sposob nieprzewidywalny :)

W zwiazku z tym pytanie:
Jak inaczej moge osiagnac efekt ktory zaplanowalem? Prosze o nakierowanie na jakies rozwiazania
 
     
Tomasz Gumny


Dołączył: 04 Lut 2004
Posty: 141
Skąd: Trzcianka/Poznań
Wysłany: 11-03-2010, 19:48   

Napisz własną funkcję delay() - na przerwaniach lub po prostu w pętli. No i wyrzuć tą całą matematykę zmiennoprzecinkową - wystarczy wszystkie wartości przemnożyć przez 10.
_________________
TomG
 
     
pajaczek
Moderator
Ulubieniec Lloth



Poland

Dołączył: 24 Sty 2005
Posty: 1973
Skąd: Winny grod
Wysłany: 11-03-2010, 19:52   

A to ciekawe z dealy'em...

ale do rzeczy. A może by tak zastosować zwykły timer w trybie PWM ;) (zmieniając wypełnienie, osiągniesz właśnie swój efekt).
_________________
NASA wydala miliony $ na zaprojektowanie dlugopisu, ktory mozna by uzywac w przestrzeni kosmicznej...

... Rosjanie uzywaja olowkow.
 
     
Serwik


Poland

Dołączył: 10 Mar 2010
Posty: 4
Skąd: Warszawa
Wysłany: 11-03-2010, 21:46   

Pożądany efekt uzyskałem w poniższy sposób. Niemniej delay'e są na tyle uciążliwe ze trzeba będzie sprawdzić co to jest to PWM :597:
Kod:
#define F_CPU 4000000L
#include <avr/io.h>
#include <util/delay.h>

void my_delay_us(int us)
{
  while(us>0)
  {
    us-=100;
    _delay_us(100.0);
  }
}

int main(void)
{
  int t = 1500;
  int offset = 50;
  int period = 20000;
 
    /* Wszystkie linie portu D będą wyjściami */
    DDRD = 0xFF;

    /* Początek nieskończonej pętli */
    while(1)
    {
      if ((t<=600)||(t>=2400)) offset = -offset;
      t = t + offset;
   
      PORTD = 0xAA;
      my_delay_us(t);
   
      PORTD = 0x55;
      my_delay_us(period-t);
    }
}
 
     
pajaczek
Moderator
Ulubieniec Lloth



Poland

Dołączył: 24 Sty 2005
Posty: 1973
Skąd: Winny grod
Wysłany: 11-03-2010, 23:00   

Serwik napisał/a:
Niemniej delay'e są na tyle uciążliwe ze trzeba będzie sprawdzić co to jest to PWM


To trochę skrót myślowy, bo w klasycznym PWM (pulse width modulation) regulujesz jedynie szerokością (a dokładniej wypełnieniem) sygnału, zwykle puls zaczyna się w "zerze" okresu, lub wokół połowy okresu. Jednak w niektórych trybach jest możliwość ustalenie również momentu startu i końca "1", przy stałej szerokości okresu. W ATMega o ile pamiętam dostępne jest to w timerach 16 bitowych, wygląda to m/w tak, że licznik liczy od 0 do ustalonej wartości po osiągnięciu tej wartości się automatycznie zeruje. Są jeszcze 2 wartości, startu i stopu "1", pierwsza oczywiście niższa od drugiej. Doliczenie licznika do pierwszej ustawia powiązane wyjście, doliczenie do drugiej zeruje. Dzięki czemu możesz wysterować nie tylko szerokość impulsu, ale również moment startu i stopu. W niektórych rozwiązaniach możesz również odwrócić "0" z "1".
Mam nadzieję, że jasno opisałem, poszukaj w opisach timera. Jak nie znajdziesz postaram się odświeżyć nieco, bo dawno nie używałem tego trybu.

Aaa... będziesz miał jeszcze tą przewagę, że wszystko łatwo wykonasz w przerwaniach, a więc wykonywać się będzie niejako samo, bez uzależnienia od aktualnie wykonywanego fragmentu głównego programu.
_________________
NASA wydala miliony $ na zaprojektowanie dlugopisu, ktory mozna by uzywac w przestrzeni kosmicznej...

... Rosjanie uzywaja olowkow.
 
     
j_bravo 
J_Bravo



Poland

Wiek: 32
Dołączył: 14 Wrz 2005
Posty: 164
Skąd: Lublin
Wysłany: 13-03-2010, 07:30   

Fakt. Troszkę szkoda całego czasu procesora na generowanie impulsów. Może nie łatwiej, ale lepiej było by to zrobić na przerwaniu. Będzie czas na inne zadania np. miganie diodką ;P
_________________
gdy diesel nie chce odpalic http://www.diesel.serwis.tv
serwis konsol http://www.konsole.serwis.tv
miniatury allegro: http://www.allemini.pl

<b>nie polecane nie polecani: http://www.nie-polecam.pl - Czyli ucz się na cudzych błędach</b>
 
 
     
Serwik


Poland

Dołączył: 10 Mar 2010
Posty: 4
Skąd: Warszawa
Wysłany: 14-04-2010, 21:32   PWM na atmega162

Troszkę się męczę z uruchomieniem PWM
Kod:
#include <avr/interrupt.h>
#include <avr/io.h>

int main(void)
{
PORTD=0x00;
DDRD=0x00;

//PWM, phase correct, 8-bit | Prescaler /8
TCCR3B = _BV(WGM30) | _BV(CS31);
TCNT3 = 0x00;
ICR3 = 20000;
OCR3A = 1000;

//sei();
while (1) { };
}


Ten prosty kod powinien (?) uruchomic timer 3 z sygnalem pwm na wyjsciu OC3A (Port PD4 na atmega162), jednak na wyjciu jest tylko 0. Czego tu brakuje?
 
     
Tomasz Gumny


Dołączył: 04 Lut 2004
Posty: 141
Skąd: Trzcianka/Poznań
Wysłany: 15-04-2010, 11:13   Re: PWM na atmega162

Załączenie trybu PWM chyba "nadpisuje" standardowe rejestry portu, ale na wszelki wypadek ustaw PD4 jako wyjście: DDRD=0x10;
_________________
TomG
 
     
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Nie możesz załączać plików na tym forum
Możesz ściągać załączniki na tym forum
Dodaj temat do Ulubionych
Wersja do druku

Skocz do:  

Powered by phpBB modified by Przemo © 2003 phpBB Group