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

Atmega16 + serwo hs-311 nie dziala

lolcio 15 Lis 2010 20:12 2967 12
  • #1 8748031
    lolcio
    Poziom 16  
    Witam!
    Próbuje uruchomić serwo hs-311 na uC at mega16A...ale nie wychodzi mi :(
    podlaczam linie danych serwa (zolty przewod) do pinu pd.0, mikrokontroler programuje w C takim wsadem:
    #include <avr/io.h>
    #include <util/delay.h>
    #define F_CPU 1200000L
    
    void prawo(){
     for(int i=100; i>=0; i--) //wysyłam 100 impulsów o długości 2,5 ms
    	 { PORTD = 0x01;    
    		_delay_us(2500); 
           PORTD = 0x00;    
             _delay_ms(20); //przerwa miedzy impulsami 20 ms (tak jak w dokumentacji)
    	  }
    
    }
    
    void lewo(){
    for(int i=100; i>=0; i--)
    	 
    	 { PORTD = 0x01;   
        
          _delay_ms(450); 
           PORTD = 0x00;   
            _delay_ms(20);
    	  }
    	
    
    
    }
    
    int main(void)
    { 
    DDRD = 0xFF; 
    
    	 prawo();
    	lewo();  
     }
    

    Impulsy próbuje wysyłać tak jak jest opisane na tej stronie: http://www.henryk.mbapp.com/servo/servo.html
    Czy dobrze robię PWM?? Jeśli nie to jak to powinno wyglądać??
    Kiedy podłączam serwo do mikrokontrolera i zasilam napięciem 5V to serwo się skręca max w lewo i dalej próbuje się kręcić ale ze jest blokada to stoi i tylko słychać jak pracuje, i tak jest cały czas obojętnie co wgram do kontrolera...
    Bardzo proszę o jakieś wskazówki co źle robię, z góry wielkie dzięki :)
  • #2 8748439
    _Robak_
    Poziom 33  
    Pomijając fakt że w lewo masz 450ms delay, to i tak źle sterujesz. Po pierwsze jak Ci coś nie wychodzi to po co robisz jakieś lewo prawo, zrób program z jednym ustawieniem! Po drugie, okres całego impulsu masz 20ms, więc jak najpierw dajesz stan wysoki przez np. 2 ms to potem masz 18ms stanu niskiego a nie 20.
  • #3 8750178
    lolcio
    Poziom 16  
    Poprawiłem kod i teraz wyglada tak:
    
    #include <avr/io.h>
    #include <util/delay.h>
    
    void center(){
    
     for(int i=100; i>=0; i--)
    	 { PORTD = 0x01;    
    		_delay_us(1500);  //1,5 ms mam stan wysoki
           PORTD = 0x00;    
             _delay_us(18500); //18,5 ms stan niski, czyli teraz cały impuls ma 20 ms
    	  }
    }
    
    int main(void)
    { 
    DDRD = 0xFF; 
    	center();
     }
    

    No ale nadal nie chce działać, ciągle kręci się w jedną stronę do oporu...(serwo jest sprawne, mam 4 takie i inne tak samo się zachowują). Proszę o trochę wyrozumiałości, dopiero zaczynam zabawę z uC :)
  • #4 8750289
    jezjacek
    Poziom 14  
    Metodą prób i błędów pozmieniaj czasy impulsów. Też miałem taki problem i impulsy przy których serwo wykonywało poprawne ruchy znacznie różniły się od teoretycznych.
  • #5 8750406
    Andrzej__S
    Poziom 28  
    lolcio napisał:

    
    #define F_CPU 1200000L
    


    Jesteś tego pewien? Na pewno masz odpowiednią ilość zer? Funkcje _delay_ms() i _delay_us() bazują na tej wartości.

    EDIT:
    1,2MHz to raczej nietypowa wartość częstotliwości taktowania. Podejrzewałem, że miało to być 12MHz, ale zauważyłem, że w drugim kodzie, który podałeś, nie masz w ogóle ustawionego F_CPU. Jest to stała potrzebna funkcjom delay do prawidłowego działania. Nie napisałeś, jakiej częstotliwości taktowania używasz, ale jeśli nie jest to 1MHz (takie jest domyślne ustawienie w 'delay.h'), to funkcje _delay_ms() i _delay_us() będą generowały nieprawidłowe czasy.
  • #6 8751834
    _Robak_
    Poziom 33  
    Jeszcze jedna sprawa, masa zasilania silnika i części cyfrowej musi być połączona.
  • #7 8755579
    lolcio
    Poziom 16  
    Teraz tak wygląda kod:
    
    #include <avr/io.h>
    #include <util/delay.h>
    #define F_CPU 8000000L //tudzież mniemam że to jest 8 mhz :P
    void center(){
     for(int i=100; i>=0; i--)
    	 { PORTD = 0x01;    
    		_delay_us(1500); 
           PORTD = 0x00;    
             _delay_us(18500);
    	  }
    }
    int main(void)
    { DDRD = 0xFF; 	center();  }
    

    Ustawiłem atmege na wewnętrzny oscylator 8 mhz
    (fuse bity: hfuse = D9 , lfuse = E4)...no i....nic :P serwo stoi. Połączyłem też przewód sterowania z masa i wyjściem uC, chodź nie wiem po co ten zabieg??
  • Pomocny post
    #8 8755759
    mieczotronix
    Poziom 16  
    znajdź definicje _delay_us i zobacz w komentarzach jaki zakres wartości może przyjmować jej parametr. Pamiętam, że zależy to m.in od wartości F_CPU
    Generalnie zbyt dużych wartości nie można przekazywać, bo ta funkcja to głupie makro, które czasem źle liczy (dochodzi do przepełnień).
    To samo się tyczy _delay_ms też wartość parametru jest mocno ograniczona.
  • Pomocny post
    #9 8756111
    Andrzej__S
    Poziom 28  
    Cytat:

    Połączyłem też przewód sterowania z masa i wyjściem uC...

    Nie miałeś łączyć przewodu sterowania z masą tylko masę zasilania serwa z masą zasilania mikrokontrolera. Jeśli zasilasz to wszystko z tego samego napięcia to taki zabieg nie jest konieczny, aczkolwiek to niezbyt dobre rozwiązanie. Przewód sterowania musi być połączony tylko z wyjściem mikrokontrolera. Najlepiej narysuj, jak to masz połączone.

    #define F_CPU 8000000L proponuję dać przed #include <util/delay.h>
    W opcjach projektu w AVR Studio masz ustawioną taką samą częstotliwość? Po kompilacji nie wyświetla Ci czasami warninga w stylu 'F_CPU redefined'?

    @mieczotronix:
    Jeśli funkcja _delay_us() otrzyma parametr większy od 768us automatycznie wywoływana jest funkcja _delay_ms().
    Jeśli funkcja _delay_ms() otrzyma parametr większy od 262.14ms zmniejszona zostaje precyzja do 0.1ms, ale w tym przypadku takiego nie otrzyma.
    Osobiście nie miałem przypadku, żeby te funkcje działały nieprawidłowo (przynajmniej dopóki program nie korzysta z przerwań), chociaż szczerze mówiąc niezbyt często z tych funkcji korzystam.
  • #10 12241800
    prima89
    Poziom 10  
    Hej,
    trochę stary temat ale może komuś pomogę/ktoś mi pomoże ;)
    Najpierw to co mi się udało uzyskać...
    Deklaracje zmiennych:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Po naciśnięciu guzika robię tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Czas ustalam sobie przyciskami:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    I teraz... Po wstawieniu czasu tak jak ludzie piszą w internecie, czyli ramka (podstawa) 20 000us i sygnały 1500us, 1250us, 1750us czy to z innego źródła 450us, 1500us, 2500us serwo idzie maksymalnie w prawo i chce wyłamać trybiki wychodząc poza skalę ;)

    Po zastosowaniu przycisków i przeleceniu różnych czasów... okazało się że dla czasów 40us idzie maksymalnie do lewej, a dla 140us maksymalnie do prawej. Wszystko fajnie... bo po przechodząc między tymi wartościami mogę uzyskać prawie każdy kąt.
    • 43us :arrow: -90°
    • 50us :arrow: -80°
    • 60us :arrow: -60°
    • 69us :arrow: -50°
    • 70us :arrow: 20°
    • 80us :arrow: 30°
    • 90us :arrow: 50°
    • 100us :arrow: 60°
    • 110us :arrow: 65°
    • 127us :arrow: 90°

    Mógłbym to zaakceptować, ale widoczny jest spory przeskok :cry: macie pomysł jak to rozwiązać?
    Ciekawostką się fakt, że gdy podstawę ustalę na 2000us jest tak samo :) Tylko jak wiadomo szybciej ;)
    Ps. Atmega8515 + serwo hs-311

    Cały program:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #11 12242938
    zumek
    Poziom 39  
    prima89 napisał:
    ... macie pomysł jak to rozwiązać?

    Zrób to, jak nakazuje zdrowy rozsądek :!:
    Wykorzystaj np. timer1 w trybie 14, a serwo podłącz do wyjścia OC1A(PD5), bo to co Ty teraz wyrabiasz, to jest ... tragedia :cry:
  • #12 12243246
    prima89
    Poziom 10  
    Timery wykorzystuje w innym celu... no ale dzięki... spróbuje! Jak to pomoże to będę musiał przeprojektować wszystko...
    No ale i tak dzięki :D
  • #13 12325427
    prima89
    Poziom 10  
    Jeszcze jedna sprawa, po użyciu timera pojawił się następujący problem. Zakres regulacji jest za mały. Mogę uzyskać tylko około 30 kroków (od OCR0=8 do OCR0=38 ) na 180 stopni, a to za mało do mojego projektu. Można jakoś zwiększyć ilość kroków?

    Ustawienia timera:
    Kod: text
    Zaloguj się, aby zobaczyć kod
REKLAMA