Skocz do zawartości

[c][atmega128]problem z przerwaniem


sobal44

Pomocna odpowiedź

dobra przerwanie działa super. w pętli głównej wprowadze jakieś wartości to serwo sie zachowuje jak ja tego chce.

tylko jest jeszcze problem który na 100% był przyczyną nie działającego poprzedniego przerwania i programu, natomiast napisałem program w pętli nieskonczonej

C1 = 100;

_delay_ms(1000);

C1 = 10;

_delay_ms(1000);

by sprawdzić czy serwo sie porusza raz w jedną a raz w drugą strone, ku mojemu zdziwieniu program zawiesił sie, chyba na funkcji delay, po prostu nic nie robi.

co może być powodem takiej anomali ??

czytałem że może to być włączonyc watch dog, ustawiłem fus bit i jet wyłączony i nadal nic.

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

Jest to przyczyną zawieszania się programu, trudniej odpowiedzieć na pytanie co jest tego przyczyną 🙂 Napisz może ten program tak, ze jak już wykorzystujesz timer to nie używane delay, tylko zliczaj cykle timera odpowiedniej długości, zwykle jest to do wykonania.

Link do komentarza
Share on other sites

O ile dobrze rozumie to chcesz sterować do 20 serw synchronicznie ale niezależnie.

(synchronicznie rozumie, że jednym sygnałem zegarowym,
niezależnie rozumie jako, że mogą przybierać niezależne pozycje)

Proponuję zmienić kod na coś takiego.

Jaką chcesz dokładność pojedynczego impulsu (działki ,skoku) jak zwał tak zwał ??

Załóżmy, że skoro masz 16MHz, chcesz uzyskać dokładność 0,128ms.

W takim przypadku korzystasz z przerwania prostego (na przepełnienie)

preskaler = 8, wtedy uzyskujesz przerwanie co 0,128 (16MHz / 8/256)

Jeśli chcesz inną działkę musisz skorzystać z przerwania CTC (Clear Timer on Compare).

Wewnątrz przerwania deklarujesz zmienną oznaczoną jako static (counter) liczącą kolejne przerwania,
jak osiągnie ona zadaną wartość maksymalną MAX (załóżmy 100), to jest zerowana.

Podczas zerowania zmiennej counter ustawiasz wszystkie wyjścia serw w stan wysoki.

Deklarujesz tablicową zmienną globalną np SERPOS[20], w której przechowujesz pozycje serwa, przy czym muszą one spełniać warunek SERPOS[x] < MAX.

I w przerwaniu seria warunków

 if(SERPOS[x]==counter) WY_SERWO_x = 0; 

Jak widać warunki te da się łatwo zrobić w pętli for, gdzie inkrementujesz zmienną x.

Nie potrzeba żadnego delaya w przerwaniu!

Kod masz elegancki i zwięzły.

Link do komentarza
Share on other sites

/*
************************************************************************  
 Nazwa pliku -  pajak.c
 Autor - Mateusz Sobalski.
 sobal44@op.pl
 Data -  24-04-2010
 Procesor Atmel ATmega16  
 Program do sterowania robotem Hexapod
 wykorzystywanie kinematyki odwrotnej
************************************************************************ 
*/


#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h> 
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <math.h>


#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))


volatile uint8_t C0 = 90;  
volatile uint8_t C1 = 90;  
volatile uint8_t C2 = 90;  
volatile uint8_t C3 = 90;
volatile uint8_t C4 = 90;
volatile uint8_t C5 = 90;
volatile uint8_t C6 = 90;
volatile uint8_t C7 = 90; 



//--------------------------------------------------------------------------------------

//------------------------------------ OBSŁUGA SERW ---------------------------------------

//-----------------------------------------------------------------------------------------
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


SIGNAL(SIG_OUTPUT_COMPARE1A)
//Przerwanie obsługi serw) 
{ 


   static int counter = (-6); 

if (C0==counter) {PORTC &= 0b11111110;} 
if (C1==counter) {PORTC &= 0b11111101;} 
if (C2==counter) {PORTC &= 0b11111011;} 
if (C3==counter) {PORTC &= 0b11110111;} 
if (C4==counter) {PORTC &= 0b11101111;} 
if (C5==counter) {PORTC &= 0b11011111;} 
if (C6==counter) {PORTC &= 0b10111111;} 
if (C7==counter) {PORTC &= 0b01111111;} 

   if (++counter>=1994){counter = (-6); PORTC = 0xff;} 


}






void serwo(void)//Inicjacja serw
{

DDRD = 0xFF;//Włączenie serw
DDRC = 0xFF;
DDRA = 0xFF;
PORTD = 0X00;//"resetowanie" serw
PORTC = 0x00;
PORTA = 0x00;



   TIMSK = (1<<OCIE1A);//|(1<<OCIE1B);        
   OCR1A = 0x0014;  
   TCCR1A = 0x00;        
   TCCR1B = _BV(CS11)|_BV(WGM12);







}

//----------------------------------------------------------------------------------------------------------





int main(void)                        // program główny
{


 serwo();

 sei();



while(1)                     // pętla nieskończona
 {







C1 = 50; 
_delay_ms(100);   
C1 = 90;     
_delay_ms(100);




 }

}

oto część kodu, serwo numer C1 przyjmuje tylko wartość 50 i dalej nic, przerwanie działa cały czas bo serwo trzyma w tej pozycji, a program główny stoi przy pierwszy delay i dalej niechce isc

Link do komentarza
Share on other sites

Jesteś pewny że wpiąłeś serwo do właściwego pinu??

Masz dostęp do oscyloskopu żeby sprawdzić to wyjście ??

Proponowałbym trochę wydłużyć czas w delayu do np 2 sek.

Zmienne Cx ładnie wyglądałyby jako jedna tablica - dałoby się zrobić to w pętli for.

W jakim celu counter przyjmuje wartości od -6 a nie np od 0 ??

Jaki powinien być kąt obrotu między sygnałem 50 a 90 ??

A poza tym informacja sterująca zawarta jest w długości trwania "1" a nie wypełnieniu PWM.

Możesz spokojnie zmniejszyć zakres zmiennej count (do 3-5ms)

Link do komentarza
Share on other sites

serwa moge wpinac do jakiego portu chce, na C0,C2,C3-C7 mam ustawione stałą wartość 90 i wiem że na C1 jest to wartość 50. Nie mam oscyloskopu by sprawdzić co tam sie dziaje ale widać po zachowaniu serwa że na wyjsciu jest pwm 50Hz i wypełnienie około trwające 560us.

wydłużenie czasu nic nie da, program sie zawiesza na tej funkcji gdyz serwo przyjmuje tylko tą wartość 50 niechce przeskoczyć tej funkcji delay.

counrter przyjmuje wartość -6 gdyż zmienne Cn przyjmują wartość kąta gdzie 60us to 0stopni a 240us to 180 stopni.

przerwanie działa wyśmienicie, tylko ta głupia funkcja delay wszystko psuje

Link do komentarza
Share on other sites

to może sprawdź funkcję delay w prostym programie migania diodami.

Po czym wnioskujesz, że się zawiesiło ??

Masz może jakiś sprzętowy debugger (dragon, JTAGice, itp.)??

Spróbuj, w ramach testu, zamienić delaya na jakiegoś pustego fora.

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.