Panicz74 Napisano Maj 6, 2015 Udostępnij Napisano Maj 6, 2015 Witam, Sprzęt: -Atmega644P + kwarc 16mgh,-Serwo TowerPro GS-5010, (na pinie PD5/OC1A) -potencjometr A10k. (na pinie PA0/ADC0) -środowisko Eclipse Luna, Problem: Za pomocą załączonego kodu, gdy steruje potencjometrem, ciężko ustawić je w zadanej pozycji. Albo szarpie i nie może się ustawić albo od razu przesuwa się do końca i szarpie. Pewnie coś źle zrobiłem w kodzie. Takie problemy mam zarówno na taktowaniu obecnym 16mgh jak i na fabrycznym 1mgh. Pewnie coś źle obliczyłem. Może ktoś mądrzejszy ode mnie poradzi co tu jest nie tak? Oto kod: #include <avr/io.h> #include <avr/interrupt.h> static volatile uint16_t rezultat10bit; int main(void) { DDRD |= 0xFF; TCCR1A |= 1<<WGM11 | 1<<COM1A1 | 1<<COM1A0; TCCR1B |= 1<<WGM12 | 1<<WGM13 | 1<<CS10; ICR1 = 10000; ADCSRA |= 1<<ADPS2; ADMUX |= (1<<REFS0) | (1<<REFS1); ADCSRA |= 1<<ADIE; ADCSRA |= 1<<ADEN; sei(); ADCSRA |= 1<<ADSC; float y1 = 100; float y2 = 8000; float m = (y2 - y1)/1023; while (1) { OCR1A = ICR1 - (m * rezultat10bit) + 800; } } ISR(ADC_vect) { uint8_t theLowADC = ADCL; rezultat10bit = ADCH<<8 | theLowADC; ADCSRA |= 1<<ADSC; } [ Dodano: 06-05-2015, 23:03 ] Oto filmy jak działa ten program. Gdy zatrzymuje serwo w danym położeniu nie może ono wypośrodkować położenia. Na pewno coś zmaściłem w kodzie, tylko właśnie nie wiem co.... 🙁 Cytuj Link do komentarza Share on other sites More sharing options...
deshipu Maj 7, 2015 Udostępnij Maj 7, 2015 Takie głupie pytanie: jak zasilasz serwo? Spadki napięcia mogą powodować taki efekt. Cytuj Link do komentarza Share on other sites More sharing options...
Wojciech Maj 7, 2015 Udostępnij Maj 7, 2015 Źle ustawiasz timer - masz prescaler 1 (patrz datasheet: Table 14-6) i źle ustawiasz ICR1. Muszą one być ustawione tak aby zachodziła równość: F_CPU / prescaler / ICR1 = 50 Wartość OCR1A powinna być dobierana od 5% do 10% ICR1 (1ms - 2ms). datasheet Cytuj Link do komentarza Share on other sites More sharing options...
Panicz74 Maj 7, 2015 Autor tematu Udostępnij Maj 7, 2015 Zasilanie mam 5V z zasilacza sieciowego D-Link. Mam podłączone tylko to serwo do układu więc tylko ono może generować spadek napięcia. [ Dodano: 07-05-2015, 21:46 ] Wojciechu, to znaczy, że przykładowo dla 1mgh jak by te obliczenia wygladały? Wiem, że dla was to proste ale ja się dopiero tego uczę 🙁 Cytuj 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
Wojciech Maj 7, 2015 Udostępnij Maj 7, 2015 Z tabelki "Table 14-6" odczytujemy możliwe wartości prescalera, są to: 1, 8, 64, 256, 1024. Z datasheet dowiadujemy się także, że Timer1 jest 16-bitowy, czyli wartość ICR1 musi się mieścić w przedziale: 0..65535. Przekształcamy wzór: F_CPU / prescaler / ICR1 = 50 do postaci takiej aby wyliczyć jedną z niewiadomych (niewiadome to: prescaler i ICR1) przy zgadywaniu drugiej z nich. Łatwiej jest zgadywać z pośród 5 wartości niż 65536-u, więc wyprowadzamy wzór na ICR1. Wygląda on następująco: ICR1 = F_CPU / prescaler / 50 Dla przykładowego F_CPU = 1MHz (tak się zapisuje megaherc) wygląda to następująco: prescaler = 1 -> ICR1 = 1000000 / 1 / 50 = 20000 prescaler = 8 -> ICR1 = 1000000 / 8 / 50 = 2500 prescaler = 64 -> ICR1 = 1000000 / 64 / 50 = 312,5 prescaler = 256 -> ICR1 = 1000000 / 256 / 50 = 78,125 prescaler = 1024 -> ICR1 = 1000000 / 1024 / 50 = 19,53125 Następnie sprawdzamy, które wyliczone ICR1 są mniejsze od 65536 i wybieramy największe z nich aby mieć jak największą rozdzielczość ustawiania OCR1A. Mamy więc: prescaler = 1 i ICR1 = 20000, teraz wyznaczamy już tylko 5% i 10% z ICR1, co powie nam jak mamy zmieniać OCR1A aby uzyskać na wyjściu impuls w przedziale 1ms - 2ms. Ten zakres to: od 1000 do 2000 Podsumowując dla F_CPU = 1MHz otrzymujemy: prescaler = 1 - ustawiamy tylko bit CS10 ICR1 = 20000 OCR1A od 1000 do 2000 1 Cytuj Link do komentarza Share on other sites More sharing options...
marek1707 Maj 8, 2015 Udostępnij Maj 8, 2015 No i warto zwrócić uwagę, że ani pobranie wartości zmiennej "rezultat10bit" ani operacja zapisu do OCR1A nie są atomowe (niepodzielne) a to znaczy, że przerwanie może wejść pomiędzy dwoma 8-bitowymi dostępami do obiektów 16-bitowych (do zmiennej lub do rejestru). Tak więc program główny może np. wziąć do obliczeń jedną "połowę" ze starej wartości zmiennej rezultat10bit a drugą z nowej. Jeżeli np. poprzednia wartość tej zmiennej wynosiła 0x01FE a zmieniła się na 0x0202 (zmiana o 4) a program pobrał młodszy bajt tuż przed zmianą (czyli 0xFE) a starszy już po (czyli 0x02) to w rezultacie "zobaczy" wartość 0x02FE - z błędem aż 0x00FC. W takich przypadkach trzeba synchronizować dostępy albo "producenta" danych albo ich "konsumenta" do wspólnego zasobu jakim w tym przypadku jest zmienna rezultat10bit. Najprościej to zrobić wprowadzając 1-bitowy znacznik (tzw. semafor). Przerwanie (producent danych): 1. Odczytaj wynik z ADC. 2. Jeśli semafor jest wyzerowany to wpisz wynik do zmiennej rezultat i ustaw semafor. 3. Wróć z przerwania. Program obliczeniowy (konsument danych): 1. Jeżeli semafor jest ustawiony to oblicz nowy OCR1A na podstawie wartości zmiennej rezultat po czym (dopiero wtedy) wyzeruj semafor. W tym algorytmie przerwanie nigdy nie zapisze nowej wartości do zmiennej (tj. nie wygeneruje nowych danych i nie ustawi semafora) dopóki program nie skorzysta z poprzednich wyników i nie potwierdzi tego wyzerowaniem semafora. Cytuj Link do komentarza Share on other sites More sharing options...
Panicz74 Maj 22, 2015 Autor tematu Udostępnij Maj 22, 2015 A możecie mi wytłumaczyć jeszcze jedną kwestię prescalera? prescaler = 1 - ustawiamy tylko bit CS10 Rozumiem, że ustawienie tego bitu daje nam prescaler = 1. A jeśli chciałbym ustawić prescaler = 8 lub prescaler = 16? Jakie bity wtedy ustawić? CS11? CS12? Rozumuje to tak, że jeśli mam prescaler = 1, to serwo będzie szukało jak najbardziej bliskiego miejsca pomiędzy liczbami całkowitymi. Czyli jeśli zwiększę na prescaler = 8 to serwo zatrzyma się między, np. 0 - 8, ale też przestanie drgać bo nie będzie musiało już szukać tego bardzo wąskiego zakresu prescaler = 1 (0 - 1). Czy dobrze rozumuję??? Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!