Skocz do zawartości

Serwo + potencjometr - problem ze sterowaniem


Panicz74

Pomocna odpowiedź

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.... 🙁

Link do komentarza
Share on other sites

Ź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

Link do komentarza
Share on other sites

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ę 🙁

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

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

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

  • Pomogłeś! 1
Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

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ę???

Link do komentarza
Share on other sites

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ę »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.