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

Atmega32 [c] - Jak generować podaną ilość impulsów w czasie?

takilogin 29 Lis 2009 23:50 1451 3
  • #1 7326100
    takilogin
    Poziom 15  
    Witajcie!
    Wiem że na Was zawsze mogę liczyć więc jestem pewien że i tym razem się nie zawiodę :-)

    A więc:

    Mam układ zbudowany na bazie uc Atmega32 (8MHz). Do niego mam podłączonych kilka przycisków i cztery sterowniki silników krokowych. Ogólnie można powiedzieć że jest to coś w rodzaju maszyny CNC.
    Program pisze w C i jego pierwszą wersję mam już praktycznie skończoną za wyjątkiem głównej pętli generującej impulsy kroku na silniki.
    Pętla ta ma wygenerować podane ilości impulsów na każdy silnik (liA, liB, liC, liD) w stałym przedziale czasowym (czas_kr).
    Impulsy te mają być równo "rozłożone" a wypełnienie przebiegów nie ma znaczenia, wystarczy tylko zbocze narastające.

    Atmega32 [c] - Jak generować podaną ilość impulsów w czasie?

    Czyli jeszcze raz: podaje liA, liB, liC, liD i czas_kr i na wyjściu Atmegi mam na czterech oddzielnych pinach wygenerowaną odpowiednią liczbę impulsów w odpowiednim czasie, równo rozłożone.

    Stworzyłem coś takiego:


    
    // Tutak szukam Najmniejszego Wspólnego Dzielnika NWW
    // Jest to potrzebne do równego rozłożenia impulsów:
    
    a=li_A;
    b=li_B;
    c=li_C;
    d=li_D;
    
    iloczyn = a*b;
     while(a!=b) if(a>b) a-=b; else b-=a;  
    b =iloczyn/a;
    
    
    iloczyn = c*d;
     while(c!=d) if(c>d) c-=d; else d-=c;  
    d =iloczyn/c;
    
    
    iloczyn = b*d;
     while(b!=d) if(b>d) b-=d; else d-=b;  
    NWW =iloczyn/b;
    
    
    
    // główna pętla generująca impulsy na silniki w przedziale czasowym "czas_kr"
    
    
    for (i=1 ; i<=NWW; i++)
    
    	{	
    	
    		if (i%(NWW/li_A)== 0) PORTC |=0x02;
    								
    		if (i%(NWW/li_B)== 0) PORTC |=0x08;
    								
    		if (i%(NWW/li_C)== 0) PORTC |=0x20;
    								
    		if (i%(NWW/li_D)== 0) PORTC |=0x80;
    
                 // zerowanie pinów ABCD						
    	PORTC &=0x55; 
                 // opóźnienie
    	_delay_ms(czas_kr/NWW);
    	}
    


    Wszystko ładnie dział z małym wyjątkiem: pętla for daje bardzo duże opóźnienie!
    Zwłaszcza jak NWW wyjdzie dosyć wysoki np 1000.
    Macie może jakiś pomysł na ten mój "generator"
    liA, liB, liC, liD wahają się w granicach 1 do 50 a czas_kr to ok 0.1 - 0.2s.

    Pozdrawiam Wszystkich :)
  • Pomocny post
    #2 7326453
    Konto nie istnieje
    Konto nie istnieje  
  • Pomocny post
    #3 7327277
    ktrot
    Poziom 20  
    Cytat:
    Zwłaszcza jak NWW wyjdzie dosyć wysoki np 1000.

    Jesteś optymistą. Przy podanych parametrach (50 i 0,1s) Maksymalne NWW (najmniejsza wspólna wielokrotność a nie dzielnik) to NWW=47*43*41*37= ponad 3000000.

    Cytat:
    Zastanowiłbym się także nad użyciem przerwania od timera zamiast pętli z delayem.

    Nie ma się nad czym zastanawiać. Użycie timera to konieczność.

    @takilogin
    Ustaw raster czasowy na sztywno i zbocza generuj w przerwaniu.
  • #4 7346649
    takilogin
    Poziom 15  
    Po pierwsze to dzielenie, faktycznie miało duży wpływ na prędkość
    po drugie to miałem źle ustawione fusebity i zamiast 8MHz miałem 1 wewnętrzny ;) co też miało duży wpływ hehe
    po trzecie te NWW, przez co pętla miała różną długość dla każdego kroku. zmieniłem to tworząc jedną tablice 1000 wymiarową i w miarę równo rozkładam w niej sygnały. Dzięki temu opóźnienie z for-a jest zawsze takie same.
    Teraz wszystko działa nawet z delayem :)
    Dziekuje za pomoc.
REKLAMA