Skocz do zawartości

Atmega644 - pozycjonowanie serwa


Panicz74

Pomocna odpowiedź

Witam,

Pewnie sprawa będzie dla was banalna ale ja się z nią zmagam już jakiś czas. Poniższy kod steruje 5 serwami:

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

#define KEY1    (1<<PA0)				// definicja przycików
#define KEY2    (1<<PA1)
#define KEY3    (1<<PA3)

#define KEY1_DOWN ( !(PINA & KEY1) )	// definicja wciśniętego przycisku
#define KEY2_DOWN ( !(PINA & KEY2) )
#define KEY3_DOWN ( !(PINA & KEY3) )

#define SERVO1 (1<<PB0)					// definicja silników
#define SERVO2 (1<<PB1)
#define SERVO3 (1<<PB2)
#define SERVO4 (1<<PB3)
#define SERVO5 (1<<PB4)


#define SERVO_MID       1500			// definicja położenia silnika
#define SERVO_MIN       1000
#define SERVO_MAX       2000


uint16_t servo1, servo2, servo3, servo4, servo5;
volatile uint8_t key_flag;				// zmienna pomijana przez kompilator

int main(void)
{
servo1 = servo2 = servo3 = servo4 = servo5 = SERVO_MID;		// ustawienie początkowe silników
PORTA |= KEY1 | KEY2 | KEY3;				// wyjścia - przyciski
DDRB |= SERVO1 | SERVO2 | SERVO3 | SERVO4 | SERVO5; 			// wyjścia do silników
TCCR1A |= 1<<WGM11;
TCCR1B |= 1<<WGM12 | 1<<WGM13 | 1<<CS10;//rejestry odpowiedzialne za PWM
TIMSK1 |= 1<<OCIE1A;					// timer dla TCCR1B & TCCR1A

ICR1 = 19999;//rozciagnij, zawez okres

sei();//uruchomienie przerwań

while(1)
        {
                if(key_flag) // jeśli flaga = 0, wykonaj program
                {
                        key_flag = 0;
                        if (KEY1_DOWN) //klawisz 1 wcisniety
                        {

                                servo1 = SERVO_MAX;
                                servo2 = SERVO_MIN;
                                servo3 = SERVO_MAX;
                                servo4 = SERVO_MIN;
                                servo5 = SERVO_MAX;

                        }
                        if (KEY2_DOWN) //klawisz 2 wcisniety
                        {
                                servo1 = SERVO_MIN;
                                servo2 = SERVO_MAX;
                                servo3 = SERVO_MIN;
                                servo4 = SERVO_MAX;
                                servo5 = SERVO_MIN;

                        }
                        if (KEY3_DOWN) //klawisz 2 wcisniety
                        {
                                servo1 = SERVO_MID;
                                servo2 = SERVO_MID;
                                servo3 = SERVO_MID;
                                servo4 = SERVO_MID;
                                servo5 = SERVO_MID;

                        }

                }
                if(TCNT1 >= servo1) PORTB &= ~SERVO1; //nakierowanie mechanizmu przerwania
                if(TCNT1 >= servo2) PORTB &= ~SERVO2;
                if(TCNT1 >= servo3) PORTB &= ~SERVO3;
                if(TCNT1 >= servo4) PORTB &= ~SERVO4;
                if(TCNT1 >= servo5) PORTB &= ~SERVO5;

        }
}
ISR (TIMER1_COMPA_vect)
{
       PORTB |= SERVO1 | SERVO2 | SERVO3 | SERVO4 | SERVO5;
       key_flag = 1;						 // jeśli flaga = 1, program sie wykonał
}

Wszystko działa dobrze, tylko chciałbym aby serwa ruszały po kolei, od SERVO1 do SERVO5. W tym momencie wszystkie wykonują zadany ruch jednocześnie. Zabiegi z "delay" nic nie pomagają.

Czy mogę liczyć na wasza pomoc?

Link do komentarza
Share on other sites

M. in. tak:

while(1)
        {
                if(key_flag) // jeśli flaga = 0, wykonaj program
                {
                        key_flag = 0;
                        if (KEY1_DOWN) //klawisz 1 wcisniety
                        {

                                servo1 = SERVO_MAX;
                                _delay_ms(50);
                                servo2 = SERVO_MIN;
                                _delay_ms(50);
                                servo3 = SERVO_MAX;
                                _delay_ms(50);
                                servo4 = SERVO_MIN;
                                _delay_ms(50);
                                servo5 = SERVO_MAX;

                        }
                        if (KEY2_DOWN) //klawisz 2 wcisniety
                        {
                                servo1 = SERVO_MIN;
                                _delay_ms(50);
                                servo2 = SERVO_MAX;
                                _delay_ms(50);
                                servo3 = SERVO_MIN;
                                _delay_ms(50);
                                servo4 = SERVO_MAX;
                                _delay_ms(50);
                                servo5 = SERVO_MIN;

                        }
                        if (KEY3_DOWN) //klawisz 3 wcisniety
                        {
                                servo1 = SERVO_MID;
                                _delay_ms(50);
                                servo2 = SERVO_MID;
                                _delay_ms(50);
                                servo3 = SERVO_MID;
                                _delay_ms(50);
                                servo4 = SERVO_MID;
                                _delay_ms(50);
                                servo5 = SERVO_MID;

                        }

                }
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

Przepraszam was, że tak długo. Uruchomiłem program. Jedyne co należało zrobić to zwiększyć ilość warunków i w ten sposób puszczać serwa po kolei 🙂 Jak nie spełnia jednego warunku to nie jedzie. Jeśli ktoś będzie potrzebował to udostępnię cały kod.

Tymczasem jest problem z zakłóceniami. To jest dopiero ciekawa sprawa. Patrzcie na wyniki z oscyloskopu. Dźwięk i obraz idealnie oddają postać rzeczy:

Może ktoś wie jak ten problem rozwiązać???

Link do komentarza
Share on other sites

Błędem w kodzie, a raczej w fusbitach był fus CKDIV8... Spowalniał procka x8. Potem już zmiana bitów z CS10 na CS11, ICR1 na 40000, trochę przeliczania... i śmiga.

Jak pupa niemowlęcia 🙂

Innymi słowy, 100Hz to niedobry pomysł dla serwomechanizmów 😉

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.