piotrek038 Napisano Sierpień 28, 2012 Udostępnij Napisano Sierpień 28, 2012 Witem, Mam pewien problem z serwami. Otóż zacinają się. Nie wiem czy to kwestia programu czy układu (chociaż ten jest mega prosty). #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> //------------ F_CPU 8MHz -----------// #define LICZBA_SERW 8 #define SERWPORT PORTB #define SERWDIR DDRB #define SERW_PWMMIN 600 #define SERW_PWMMAX 2400 #define SERW_PWMSRODEK ((SERW_PWMMAX + SERW_PWMMIN)/2) #define LEDPORT PORTD #define LEDDIR DDRD #define BUTTPORT PORTC #define BUTTDIR DDRC #define BUTTPIN PINC #define BUTT_1 PC0 #define BUTT_2 PC1 #define BUTT_3 PC2 #define BUTT_4 PC3 #define BUTT_5 PC4 #define BUTT_6 PC5 #define BUTT_7 PC6 #define WOLNE SERW_TablicaPwm[4] #define WOLNE2 SERW_TablicaPwm[5] #define UCHO_PG SERW_TablicaPwm[0] //2200 MAX DÓŁ //1300 MAX GÓRA #define UCHO_PD SERW_TablicaPwm[1] #define UCHO_LG SERW_TablicaPwm[2] //800 MAX DÓŁ //1700 MAX GÓRA #define UCHO_LD SERW_TablicaPwm[3] // 2500 LEWO //500 PRAWO int SERW_TablicaPwm[LICZBA_SERW]; int SERW_Numer=0; int SERW_NumerOdbior=0; void SERW_TablicaPwmInit() //Inicjalizacja tabeli przechowującej pozycje serw { for(int i=0;i<LICZBA_SERW;i++) SERW_TablicaPwm[i]=SERW_PWMSRODEK; } void SERW_PortInit() //Inicjalizacja portu do którego podłączono serwa { SERWDIR = 0xFF; SERWPORT = 0x00; } void LED_PortInit() //Inicjalizacja portu do którego podłączono diody { LEDDIR = 0xFF; LEDPORT = 0x00; } void BUTT_PortInit() //Inicjalizacja portu do którego podłączono przyciski { BUTTDIR = 0x00; BUTTPORT = 0xFF; } void TIMER1_Init() { TCCR1B |= _BV(WGM12); //Tryb CTC OCR1A = SERW_PWMSRODEK; //Ustawienie wstępne serw w pozycji środkowej } void TIMER2_Init() { TCCR2 |= _BV(WGM21) | _BV(CS21) | _BV(CS22); //Tryb CTC, preskaler przez 256 OCR2 = 78; //Odmierzanie 2,5 ms TIMSK |= _BV(OCIE2); //Zezwolenie na przerwanie CTC } void Przyciski() //Funkcja zmiany wartoci tablicy za pomocą przycisków { if(bit_is_clear(BUTTPIN,BUTT_1)) //LEWO { UCHO_PG=1800; UCHO_PD=1650; UCHO_LG=1700; UCHO_LD=2100; _delay_ms(20); } if(bit_is_clear(BUTTPIN,BUTT_2)) //ŚRODEK { UCHO_PG=1700; UCHO_PD=1500; UCHO_LG=1300; UCHO_LD=1500; _delay_ms(20); } if(bit_is_clear(BUTTPIN,BUTT_3)) //PRAWO { UCHO_PG=1250; UCHO_PD=800; UCHO_LG=1200; UCHO_LD=1350; _delay_ms(20); } if(bit_is_clear(BUTTPIN,BUTT_4)) { UCHO_PG=1400; UCHO_PD=1500; UCHO_LG=1600; UCHO_LD=1500; _delay_ms(20); } if(bit_is_clear(BUTTPIN,BUTT_5)) { UCHO_PG=2100; UCHO_PD=800; UCHO_LG=900; UCHO_LD=2300; _delay_ms(20); } } ISR(TIMER1_COMPA_vect) { TCCR1B &= ~_BV(CS11); //Włączenie TIMER1 SERWPORT = 0x00; //Wyzerowanie portu serw TIMSK &= ~_BV(OCIE1A); //Wyłączenie zezwolenia na przerwanie COMP od TIMER1 if(++SERW_Numer >= LICZBA_SERW) SERW_Numer=0; } ISR(TIMER2_COMP_vect) { TCNT1=0; //Zerowanie TIMER1 OCR1A = SERW_TablicaPwm[SERW_Numer]; //Podanie wypełnienia dla danego serwa TCCR1B |= _BV(CS11); //Uruchomienie TIMER1 z preskalerem 8 SERWPORT |= _BV(SERW_Numer); //Ustawienie odpowiedniego pinu TIMSK |= _BV(OCIE1A); //Zezwolenie na przerwanie COMP od TIMER1 } int main() { SERW_PortInit(); LED_PortInit(); BUTT_PortInit(); SERW_TablicaPwmInit(); TIMER1_Init(); TIMER2_Init(); sei(); while(1) { Przyciski(); } return 0; } Serwa zacinają się losowo, ale zauważyłem że najczęściej w pozycji wywołanej przyciskiem 5: if(bit_is_clear(BUTTPIN,BUTT_5)) { UCHO_PG=2100; UCHO_PD=800; UCHO_LG=900; UCHO_LD=2300; _delay_ms(20); } I teraz pojawia się moje pytanie, czy to wina kodu czy układu. Wszystko na AtMedze8. Zasilanie podłączone zgodnie ze wskazówkami ze strony. Oczywiście wystarczy reset i wracają do normy. Drugie co mi przyszło do głowy to może za niskie napięcie? Czy może to być spowodowane zbytni rozładowaniem się akumulatora? Tylko że serwa po resecie działają normalnie. Czasem zdarza się że zacina się dosłownie co 30s a czasem przez godzinę można się bawić. Może ma ktoś pomysł o co chodzi? Pozdrawiam! Link do komentarza Share on other sites More sharing options...
Aramis Sierpień 28, 2012 Udostępnij Sierpień 28, 2012 A co się dzieje, jak podłączysz je prosto do zasilania? Link do komentarza Share on other sites More sharing options...
Tolo Sierpień 28, 2012 Udostępnij Sierpień 28, 2012 Moim zdaniem przyczyną mogą być dwie rzeczy. ➡️ Zbyt słabe źródło zasilania kiedy serwo działa napięcie może przysiąść przez układ działa niestabilnie. ➡️ Nie dokładny zegar procesora... Link do komentarza Share on other sites More sharing options...
piotrek038 Sierpień 28, 2012 Autor tematu Udostępnij Sierpień 28, 2012 to znaczy serwa są w na 100% sprawne, wyciągnąłem je ze swojego akrobata wiec nie ma szans żeby coś im było 😉 Jeśli chodzi o zasilanie to właśnie jestem w trakcie manualnego sprawdzania 😉 faktycznie napięcie trochę przygasa ale zastanawia mnie dlaczego po tym jak już się zatrzymają trzeba je zrestartować a nie da się zmienić położenia przyciskiem, w końcu w jakieś tam określonej pozycji pobierany przez nie prąd jest minimalny (oczywiście nie są zblokowane) a one po prostu się zatrzymają i nic, nie reagują. Z dwa razy zdarzyło mi się że zaczęły drgać tak jakby serwo otrzymywało 2 sygnały, czyli niby wychodziło by na to że przycisk się zaciął ale to jest niemożliwe bo w takim przypadku reset by nie pomógł... czy się mylę? Jeśli serwo podłączam do zasilania, bez sygnału to normalnie drgnie i tyle, tak jak to zwykle bywa. ( nie wiem czy o to chodziło ;/ ) Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
marek1707 Sierpień 28, 2012 Udostępnij Sierpień 28, 2012 Piotrek, zanim zaczniesz rozbierać serwa, spróbuj zweryfikować sygnał PPM jaki dla nich generujesz. Jeśli nie masz oscyloskopu, weź jakąś diodę LED szeregowo z opornikiem kilkaset omów i podłącz to do wyjścia sterującego serwem. Powinna dość słabo świecić a tak naprawdę mrugać 50Hz, sam wiesz. W zależności od wypełnienia sygnału PPM powinna być trochę jaśniejsza lub ciemniejsza ale nigdy nie może zgasnąć ani zapalić się na full. Sprawdź w ten sposób wszystkie wyjścia gdy jest dobrze a następnie poczekaj aż coś się zatnie i wtedy powtórz test z diodką. Może Twój program gdzieś zwisa albo któreś wyjście jest źle obsługiwane i "zostaje" w stanie 0 lub 1? Czy mógłbyś w kilku słowach (ale jednak w miarę dokładnie) opisać swoją ideę generacji PPM? Jeszcze przyszło mi do głowy to, że Twoja tablica przechowująca długości impulsów jest 16-bitowa. To oznacza, że do zmiany zawartości jednej pozycji procesor musi wykonać dwa zapisy do pamięci. Jeżeli przerwanie (które akurat będzie tej pozycji używać) przyjdzie w chwili gdy jeden bajt już został zapisany a drugi jeszcze nie, to cała liczba 16-bitowa w czasie obsługi przerwania będzie niespójna. Jeśli dodatkowo to co było tam wcześniej będzie jakieś pechowe, całość może np. przekroczyć zakres długości 2.5ms. Spróbuj ciągi instrukcji modyfikujące "USZY" zamknąć w blokach sekcji krytycznych cli() / sei(). Link do komentarza Share on other sites More sharing options...
davidpi Sierpień 28, 2012 Udostępnij Sierpień 28, 2012 Podłącz dobre źródło zasilania bo często serwa potrafią pociągnąć sporo prądu. Hmm kod wygląda ok. A jakie masz serwa?? W przycisku piątym wprowadzasz wartość 2300. Być może jest to już poza zakresem serwa?? Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »