Skocz do zawartości

Atmega32 - sterowanie 5 serwami


Panicz74

Pomocna odpowiedź

Witam,

Mam taki problem. Muszę złożyć manipulator o 5 stopniach swobody. Prosty układ złożyłem na płytce Atmega32 i serwo PowerHD AR-3603HB zasilane 5V. Podłączyłem serwo do PD5(OC1A) i działa elegancko 🙂

Ale jest problem... Takich wejść jest tylko 2: PD5(OC1A) i PD4(OC1B).

Pytanie brzmi: Czy da się zrobić tak aby podłączyć 5 serw do całego portu, np. A żeby te serwa były w pełni sterowalne?

Link do komentarza
Share on other sites

Rozumiem, czyli jest to możliwe. Nie mogę znaleźć jakiegoś przykładu. Pomoże ktoś?

[ Dodano: 19-04-2015, 17:08 ]

Albo taki problem. Napisałem taki program:


#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
DDRD |= 0xff;
TCCR1A |= 1<<WGM11 | 1<<COM1A1 | 1<<COM1A0;
TCCR1B |= 1<<WGM12 | 1<<WGM13 | 1<<CS10;
ICR1 = 19999;

while(1)
{
OCR1A = ICR1 - 8;
_delay_ms(5000); //obrót o 180s

OCR1A = 0;
_delay_ms(1000);

OCR1A = ICR1 - 4000;
_delay_ms(5000); //obrót o 180s

OCR1A = 0;
_delay_ms(1000);

}
}

Działa on na porcie PD5(0C1A). Chciałbym żeby to samo działało na porcie PD4(0C1B) lub PB3(OC0) / PD7(OC2). Zmiana OCR1A na OCR1B nic nie daje.

Bardzo proszę pomóżcie.

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

Tak jak podpowiada kolega post wyżej.

1. Ustaw timer, gdy doliczy do 20 ms uruchomi się przerwanie

2. W przerwaniu ustaw stan wysoki na zainteresowanych portach

3. Ustaw drugi timer, który będzie uruchamiał przerwanie np. co 10 us (chodzi o rozdzielczość)

4. W przerwaniu drugiego timera sprawdzaj czy porty są już odpowiednio długo w stanie wysokim, jeśli tak to ustaw stan niski

5. Możesz teraz nacieszyć oczy jak wszystko pięknie działa 🙂

Poniżej przykład:

//--------------------------PRZERWANIA------------------------------
ISR(TIMER1_COMPA_vect)		//przerwanie co 20ms
{
PORTC |= (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4);	//ustawienie stanu wysokiego dla serw

TCCR2B |= (1<<CS20);														//start Timer 2
}
//------------------------------------------------------------------
ISR(TIMER2_COMPA_vect)		//przerwanie co 0.01ms
{
counterT2++;
T2_flag = 1;                     //tutaj możesz sprawdzać czas stanu wysokiego, ale zrobimy tak, aby przerwanie trwało jak najkrócej
}
while(1)
{
	if(T2_flag) {

		if(counterT2 >= serwo1) { PORTC &= ~(1<<PC0); }		//sprawdzanie czy impuls trwa odpowiednio długo
		if(counterT2 >= serwo2) { PORTC &= ~(1<<PC1); }		//jesli tak, ustaw stan niski
		if(counterT2 >= serwo3) { PORTC &= ~(1<<PC2); }		//maksymalna wartosc to 250 -> 2.5ms

		if(counterT2 >= serwo4) { PORTC &= ~(1<<PC3); }
		if(counterT2 >= serwo5) { PORTC &= ~(1<<PC4); }

		if(counterT2 >= 250) {									//zatrzymaj Timer2, gdy counterT2 odliczy od 0 do 250

			TCCR2B &= ~(1<<CS20);
			counterT2 = 0;
		}

		T2_flag = 0;
	}

Proste, prawda? 😋

Link do komentarza
Share on other sites

Wieczorem niezwłocznie to uruchomię 🙂 O to mi właśnie chodziło, konkretny przykład na bazie którego można zrozumieć istotę działania 😃

[ Dodano: 20-04-2015, 22:40 ]

Jeszcze takie pytanie. W Atmega32 są 4 wyjścia PWM: OC1A, OC1B, OC0 i OC1. O ile wysterowanie za pomocą kodu OC1A i OC1B jest możliwe:

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
DDRD |= 0xff;
    TCCR1A |= 1<<WGM11 | 1<<COM1A1 | 1<<COM1A0 | 1<<COM1B1 | 1<<COM1B0;
    TCCR1B |= 1<<WGM12 | 1<<WGM13 | 1<<CS10;
    ICR1 = 19999;
while(1)
{
OCR1A = ICR1 - 10;
_delay_ms(5000); //obrót o 180s

OCR1A = 0;
_delay_ms(1000);

OCR1B = ICR1 - 2000;
_delay_ms(5000); //obrót o 180s

OCR1A = 0;
_delay_ms(1000);

	OCR1A = ICR1 - 10;
	_delay_ms(5000); //obrót o 180s

	OCR1A = 0;
	_delay_ms(1000);

	OCR1B = ICR1 - 2000;
	_delay_ms(5000); //obrót o 180s

	OCR1B = 0;
	_delay_ms(1000);
}
}

To nie wiem jak uruchomić OC0 i OC1. Powinno być tak samo, tymczasem dodając do rejestru te piny te dwa serwa nie działają...

Wie ktoś może co dopisać do kodu?

Link do komentarza
Share on other sites

To nie wiem jak uruchomić OC0 i OC1.

Te piny to OC0 i OC2. Te cyferki '0' i '2' informują, który timer może zarządzać danym pinem.

Musisz więc skonfigurować timery 0 i 2 do generowania PWM analogicznie jak timer 1, czyli odpowiednio ustawić rejestry kontrolne TCCR0 i TCCR2. Pamiętaj, że te timery są 8-bitowe i nie mają podziału rejestru kontrolnego na części A i B

Link do komentarza
Share on other sites

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!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • 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.