logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ATmega16 C] przerwania od licznika

nelik1987 24 Lis 2009 18:12 2442 18
  • #1 7303481
    nelik1987
    Poziom 31  
    Witam.
    Pisze program sterujący pracą silników krokowych. Pisałem cały czas tak program by mieć konktrolę nad prędkością każdego z silników osobno (chodzi o to że silniki mają różne przekładnie a chce by wszytskie elementy poruszały się z tą samą prędkością obrotową więc prędkość ustala się raz w programie i się jej później nie zmienia)

    Zastosowałem przerwanie w którym są 4 wartości są to takie liczniki które liczą w górę i jeden za każdym przerwaniem jeżeli konkretny licznik osiągnie założoną wartość mozna wykonać przełączenie tranzystorów i tym samym poruszyć silnikiem. Na początek przerwania wpisuję liczbę do licznika który wywołuje to przerwanie luczniki jest 8-bitowy więc żeby przerwanie wywoływało się przykładowo co 200 µs wpisałem na początek do licznika TCNT0 = 54; niestety jeżeli ustawię wartość mniejszą niż 218 program nie działa to znaczy przerwanie się wykonuje ale chyba nie wykonywana jest dalsza część programu nie wiem dlaczego? podajce cały kod programu:

    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h> 
    #include <avr/signal.h>
    
    /////// SILNIK 1 ////////////////
    
    #define TRA0_ON PORTB |= _BV(0);
    #define TRA0_OFF PORTB &= ~_BV(0);
    
    #define TRA1_ON PORTB |= _BV(1);
    #define TRA1_OFF PORTB &= ~_BV(1);
    
    #define TRA2_ON PORTB |= _BV(2);
    #define TRA2_OFF PORTB &= ~_BV(2);
    
    #define TRA3_ON PORTB |= _BV(3);
    #define TRA3_OFF PORTB &= ~_BV(3);
    
    /////// SILNIK 2 ////////////////
    
    #define TRA4_ON PORTB |= _BV(4);
    #define TRA4_OFF PORTB &= ~_BV(4);
    
    #define TRA5_ON PORTB |= _BV(5);
    #define TRA5_OFF PORTB &= ~_BV(5);
    
    #define TRA6_ON PORTB |= _BV(6);
    #define TRA6_OFF PORTB &= ~_BV(6);
    
    #define TRA7_ON PORTB |= _BV(7);
    #define TRA7_OFF PORTB &= ~_BV(7);
    
    
    /////// SILNIK 3 ////////////////
    
    #define TRA8_ON PORTD |= _BV(0);
    #define TRA8_OFF PORTD &= ~_BV(0);
    
    #define TRA9_ON PORTD |= _BV(1);
    #define TRA9_OFF PORTD &= ~_BV(1);
    
    #define TRA10_ON PORTD |= _BV(2);
    #define TRA10_OFF PORTD &= ~_BV(2);
    
    #define TRA11_ON PORTD |= _BV(3);
    #define TRA11_OFF PORTD &= ~_BV(3);
    
    ///// LEDY //////
    
    #define LED_ON PORTC |= _BV(0);
    #define LED_OFF PORTC &= ~_BV(0);
    #define LED_TOGGLE PORTC ^= _BV(0);
    
    
    volatile uint16_t overflow_ADC=0;
    volatile uint8_t overflow1=0;
    volatile uint8_t overflow2=0;
    volatile uint8_t overflow3=0;
    
    volatile uint16_t overflow_ADC_max=500;
    volatile uint8_t overflow1_max=200;
    volatile uint8_t overflow2_max=10;
    volatile uint8_t overflow3_max=30;
    
    volatile char sw0=0;
    volatile char sw1=0;
    
    volatile char sw2=0;
    volatile char sw3=0;
    
    volatile char sw4=0;
    volatile char sw5=0;
    
    volatile uint16_t value;
    
    SIGNAL (SIG_OVERFLOW0)
    {
      TCNT0 = 54;                // Załaduj wartość początkową do timera0 218
        overflow1++;
    	overflow2++;
    	overflow3++;
    	overflow_ADC++;
    	LED_TOGGLE;
    	
    }
    
    
    int main (void)
    {
    
    ADCSRA = _BV(ADEN)|_BV(ADIE)|_BV(ADSC)|_BV(ADPS0)|_BV(ADPS1)|_BV(ADATE); // ustaw przetwornik ADC
    
    DDRA = 0; // Ustawienie rejestru A jako wejście (PRZYCISKI)
    DDRB = 255; // Ustawienie rejestru B jako wyjście na silnik
    DDRD = 255; // Ustawienie rejestru D jako wyjście na silniki
    DDRC = 255; // Ustawienie rejestru C jako wyjście LED
    
    
    TIMSK = _BV(TOIE0);        // włącz obsługę przerwań wywołane timerem 0
    
    
    unsigned char stan1 = 3;
    unsigned char stan2 = 3;
    unsigned char stan3 = 3;
    
    unsigned int value;			// zmienna przechowująca stan wyjścia przetwornika ADC
    unsigned int zakres=150; 	// wartośc po jakiej ma nastąpić załączenie
    
    TCCR0  |= (1 << CS00);			//Ustawia timer0 bez preskalera
    
    ADMUX = 0;    		// wybierz kanał 0 przetwornika ADC
    
    sei();                        // włącz obsługę przerwań
    
    
    
    while(1)  // Program główny
    {
    
    //////////////////////////////////////////////////// Sprawdzanie przetwornika ADC ///////////////////////
    
    if(overflow_ADC>=overflow_ADC_max)
    {
    
    ADMUX = 0;    		// wybierz kanał 0 przetwornika ADC
    	value = ADCW;
    	if(value<=zakres)
    		{
    		sw0=1;
    		sw1=0;
    		}
    	else
    		{
    		if(value>=1023-zakres)
    			{
    			sw0=0;
    			sw1=1;
    			}
    		else
    			{
    			sw0=0;
    			sw1=0;
    			}
    		}
    	
    	
    ADMUX = 1;    		// wybierz kanał 1 przetwornika ADC
    	value = ADCW;
    	if(value<=zakres)
    		{
    		sw2=1;
    		sw3=0;
    		}
    	else
    		{
    		if(value>=1023-zakres)
    			{
    
    			sw2=0;
    			sw3=1;
    			}
    		else
    			{
    
    			sw2=0;
    			sw3=0;
    			}
    		}		
    
    ADMUX = 2;    		// wybierz kanał 2 przetwornika ADC
    	value = ADCW;
    	if(value<=zakres)
    		{
    
    		sw4=1;
    		sw5=0;
    		}
    	else
    		{
    		if(value>=1023-zakres)
    			{
    			sw4=0;
    			sw5=1;
    			}
    		else
    			{
    			sw4=0;
    			sw5=0;
    			}
    		}
    		
    		
    overflow_ADC=0;
    
    }
    
    
    
    
    //////////////////////////////////////////////////// SILNIK 1 ///////////////////////
    
    if(overflow1>=overflow1_max) // silnik 1
    {
    	if(sw1 != 0)  //jeżeli przycisk 1 wciśnięty  //jeżeli przycisk 1 wciśnięty
    	{
    		stan1++;
    		if(stan1==5)
    		stan1=1;
    	}
    
    	if(sw0 != 0)  //jeżeli przycisk 1 wciśnięty  //jeżeli przycisk 1 wciśnięty 
    	{
    		stan1--;
    		if(stan1==0)
    		stan1=4;
    	}
    
    switch(stan1)
    	{
    	case 1 :
    	TRA0_ON;
    	TRA1_OFF;
    	TRA2_OFF;
    	TRA3_OFF;
    
    	break;
    	
    	case 2 :
    	TRA0_OFF;
    	TRA1_OFF;
    	TRA2_ON;
    	TRA3_OFF;
    	break;
    	
    	case 3 :
    	TRA0_OFF;
    	TRA1_ON;
    	TRA2_OFF;
    	TRA3_OFF;
    	break;		
    	
    	case 4 :
    	TRA0_OFF;
    	TRA1_OFF;
    	TRA2_OFF;
    	TRA3_ON;
    	break;	
    	}
    	overflow1=0;
    
    }
    
    //////////////////////////////////////////////////// SILNIK 2 ///////////////////////
    
    if(overflow2>=overflow2_max) // silnik 2
    {
    	if(sw2 != 0)  //jeżeli przycisk 1 wciśnięty
    	{
    		stan2++;
    		if(stan2==5)
    		stan2=1;
    	}
    
    	if(sw3 != 0)  //jeżeli przycisk 1 wciśnięty 
    	{
    		stan2--;
    		if(stan2==0)
    		stan2=4;
    	}
    
    switch(stan2)
    	{
    	case 1 :
    	TRA4_ON;
    	TRA5_OFF;
    	TRA6_OFF;
    	TRA7_OFF;
    	break;
    	
    	case 2 :
    	TRA4_OFF;
    	TRA5_OFF;
    	TRA6_ON;
    	TRA7_OFF;
    	break;
    	
    	case 3 :
    	TRA4_OFF;
    	TRA5_ON;
    	TRA6_OFF;
    	TRA7_OFF;
    	break;		
    	
    	case 4 :
    	TRA4_OFF;
    	TRA5_OFF;
    	TRA6_OFF;
    	TRA7_ON;
    	break;	
    	}
    	overflow2=0;
    
    }	
    
    //////////////////////////////////////////////////// SILNIK 3 ///////////////////////
    
    if(overflow3>=overflow3_max) // silnik 3
    {
    	if(sw4 != 0) 
    	{
    		stan3++;
    		if(stan3==5)
    		stan3=1;
    	}
    
    	if(sw5 != 0) 
    	{
    		stan3--;
    		if(stan3==0)
    		stan3=4;
    	}
    
    switch(stan3)
    	{
    	case 1 :
    	TRA8_ON;
    	TRA9_OFF;
    	TRA10_OFF;
    	TRA11_OFF;
    	break;
    	
    	case 2 :
    	TRA8_OFF;
    	TRA9_OFF;
    	TRA10_ON;
    	TRA11_OFF;
    	break;
    	
    	case 3 :
    	TRA8_OFF;
    	TRA9_ON;
    	TRA10_OFF;
    	TRA11_OFF;
    	break;		
    	
    	case 4 :
    	TRA8_OFF;
    	TRA9_OFF;
    	TRA10_OFF;
    	TRA11_ON;
    	break;	
    	}
    	overflow3=0;
    
    }	
    
    
    	
    } 	//zamyka while
    }	//zamyka main
    


    Dodano po 1 [godziny] 36 [minuty]:

    Odkryłem coś jeszcze bardziej dziwnego, podłączyłem sobie oscyloskop by sprawdzić co się dzieje wewnątrz tego przerwania. Wstawiłem do wewnątrz przerwania komendę odpowiedzialną za zmianę stanu jednego z wyjść nazwałem to LED_TOGGLE , bo początkowo była tam dioda :) ale ja podłaczyłem tam oscyloskop i dla powtewierdzenia wyniki również częstotliwościomierz. I wyniki są bardzo dziwne !!

    SIGNAL (SIG_OVERFLOW0)
    {
      TCNT0 = 54;                // Załaduj wartość początkową do timera0 218
        overflow1++;
       overflow2++;
       overflow3++;
       overflow_ADC++;
       LED_TOGGLE;
       
    } 


    Zmianiałem początkową wartość timera czyli wpisywałem różne wartości do TCNT0, no i tu wielkie zaskoczenie bo wraz ze wzrostem wartośi poczatkowej licznika przerwanie powinno wykonywać się coraz częściej bo bliżej było do przepełnienia a tu zaskoczenie bo zmieniałem wartość TCNT0 i nic się nie zmieniało zawsze wychodziło że stan wysoki (lub niski nieważne) trwa 255&micro;s aż do wartości TCNT0=211 jak wpisałem TCNT0=212 to wartość ta od razu zmniejszyła się do 65&micro;s czy ktoś możne mi wyjaśnić dlaczego tak się dzieje? 65&micro;s nie zmieniało się aż do wartości maksymalnej czyli TCNT0=255
  • #2 7304258
    walek33
    Poziom 29  
    Ze swoich własnych (niewielkich)doświadczeń wiem, że symulator to nie najlepsze rozwiązanie, ale może wrzuć swój kod do jakiegoś i sprawdź jak zachowują się Twoje zmienne. Tak na marginesie, to czy nie dałoby się tego kodu skrócić? Zauważyłem, że sekwencje włączania są dla wszystkich silników jednakowe?
  • #3 7304289
    nelik1987
    Poziom 31  
    no nie są jednakowe bo załączają inne wyjścia :)
    wiem wiem można to zrobić na zasadzie funkcji i wybierać odpowiednie wyjścia ale jak na razie to jest wersja testowa programu tak by wszystko działało bo będzie tam znacznie więcej procedur ale jak na razie poległem na tym przerwaniu i nie mogę ruszyć dalej. Jak już zrobię wszystko to będę optymalizował kod
  • #4 7304785
    janbernat
    Poziom 38  
    If both ADATE and ADEN is written to one, an interrupt event can occur at any time. If the ADMUX Register is changed in this period, the user cannot tell if the next conversion is based on the old or the new settings. ADMUX can be safely updated in the following ways:
    1. When ADATE or ADEN is cleared.
    2. During conversion, minimum one ADC clock cycle after the trigger event.
    3. After a conversion, before the Interrupt Flag used as trigger source is cleared.
    When updating ADMUX in one of these conditions, the new settings will affect the next ADC conversion.
    Czyli masz dwa przerwania- od Timer0 i od ADC.
    A jak to jest optymalizowane przez kompilator- nie wiem.
    A jakie są priorytety tych przerwań?
    Używasz starej wersji AVRGCC czy starych przyzwyczajeń?
  • #6 7304950
    janbernat
    Poziom 38  
    Strona 214 dokumentacji.
    Jak wpisałeś bity 1 do tego co wytłuściłem- to zgodziłeś się na przerwanie w dowolnym momencie z ADC.
    Co z tym robi kompilator- jak napisałem- nie wiem.
    Nie znam się na C- może robi z tym coś sensownego- ale masz dwa przerwania.
    Każde zajmuje jakiś czas.
    Odkładanie na stos->obsługa-> zdejmowanie ze stosu.
    Poza tym: "Używasz starej wersji AVRGCC czy starych przyzwyczajeń?"
    I daj schemat bo patrząc na te "switche" trochę się niepokoję czy to będzie działać.
  • #8 7305252
    janbernat
    Poziom 38  
    Masz, tylko ich nie obsługujesz jawnie.
    I nie wiem co kompilator z nimi robi.
  • #10 7308272
    nelik1987
    Poziom 31  
    rzeczywiście bit ADIE nie powinien być ustawiony bo nie korzystam z przerwania od przetwornika, chociaż teraz pojawiło się coś jeszcze dziwnego. Mianowicie gdy ustawię rożne wartości TCNT0 to rzeczywiście mam różne czasy zmiany tego wyjścia LED_TOGGLE, czyli wychodzi że przerwanie działa prawidłowo, sprawdzałem oscyloskopem i częstotliwościomierzem. ale teraz poruszenie jednego joysticka (joysticki potencjometryczne podłączone są do przetwornika ADC i tym samym sprawdzam w którą stronę jest taki joystick wychylony) ruszają mi się wszystkie silniki?? problem polega chyba na tym że nie jest odpowiednio zmieniana wartość ADMUX od 0 do 2 tylko jak to rozwiązać? no i silniki nadal nie pracują równo tzn czasy między przełączeniami nie są równe, to nawet słychać bo jak silnik się kręci to co chwila zmienia dźwięk podczas pracy

    Dodano po 3 [minuty]:

    a może by zrobić tak, że przełączenia tranzystorów odbywać się będzie w przerwaniu wtedy będę miał pewność że przełączenia będą odbywać się zawsze o tym samym czasie, bo te nierówne przełączenia wynikają zapewne z tego ze niektóre operacje trwają dłużej a niektóre krócej i czasami też występuje sprawdzanie stanu ADC i to też zajmuje czas ale jak by te przełączenia wrzucić do przerwania to by zawsze były wykonywane w określonym czasie, problem w tym ze w ten sposób muszę obsłużyć 6 silników a 6 liczników nie mam :)
  • #11 7308595
    janbernat
    Poziom 38  
    W zależności od ustawienia bitów ADPS w rejestrze ADCSRA otrzymasz częstotliwość taktowania przetwornika ADC.
    Powinna być 50-200kHz.
    Ponieważ podejrzewam że taktujesz zegarem 1MHz to powinieneś go podzielić na 8 i wtedy masz taktowanie ADC 125kHz.
    Pomiar ADC trwa normalnie 13 cykli czyli w Twoim przypadku 104us.
    Ale pierwszy pomiar (po przełączeniu na inny kanał jest to pierwszy pomiar) trwa 25 cykli czyli 200us.
    To są zależności czasowe od których nie uciekniesz.
    Można sprawdzać flagę ADIF- znacznik zakończenia konwersji.
    Bo ADMUX (czyli kanał) zmieni się dopiero po zakończeniu poprzedniej konwersji.
  • #12 7308622
    nelik1987
    Poziom 31  
    tak taktuje to na razie 1MHz, a czyli rozumiem po prosty za szybko przełączam kanały zanim skończy się przetwarzanie ja już zmieniam kanał i dlatego inne silniki reagują?

    Dodano po 2 [minuty]:

    później będę korzystał z innego procesora (atmega128) i ustawie to na 16MHz więc wtedy nie powinno być problemu ale dla pewności, że konwersja została zakończona można wstawić tam while który będzie sprawdzał czy konwersja została zakończona a dopiero potem pozwalał przejść dalej czyli zmienić kanał przetwornika i znów to samo czyli while do sprawdzenie zakończenie konwersji?

    Dodano po 9 [minuty]:

    Czyli powinno to wyglądać tak, że program powinien zatrzasnąć się w pętli robiącej nic :) do czasu aż bit ADIF zostanie skasowany??

      
    
    
    ADMUX = 0;    		// wybierz kanał 0 przetwornika ADC
    	value = ADCW;
    	if(value<=zakres)
    		{
    		sw0=1;
    		sw1=0;
    		}
    	else
    		{
    		if(value>=1023-zakres)
    			{
    			sw0=0;
    			sw1=1;
    			}
    		else
    			{
    			sw0=0;
    			sw1=0;
    			}
    		}
    	
    While (~_BV(ADIF)) {}
    	
    ADMUX = 1;    		// wybierz kanał 1 przetwornika ADC
    	value = ADCW;
    	if(value<=zakres)
    		{
    		sw2=1;
    		sw3=0;
    		}
    	else
    		{
    		if(value>=1023-zakres)
    			{
    
    			sw2=0;
    			sw3=1;
    			}
    		else
    			{
    
    			sw2=0;
    			sw3=0;
    			}
    		}
    		
    While (~_BV(ADIF)) {}
    
    ADMUX = 2;    		// wybierz kanał 2 przetwornika ADC
    	value = ADCW;
    	if(value<=zakres)
    		{
    
    		sw4=1;
    		sw5=0;
    		}
    	else
    		{
    		if(value>=1023-zakres)
    			{
    			sw4=0;
    			sw5=1;
    			}
    		else
    			{
    			sw4=0;
    			sw5=0;
    			}
    		}
    
    While (~_BV(ADIF)) {}		
    		
    overflow_ADC=0;
  • #13 7308779
    janbernat
    Poziom 38  
    Atmega16 też można ustawić na 16MHz.
    Ale przetworniki ADC muszą chodzić na 50-200kHz.
    Po prostu trzeba dać większy dzielnik -inaczej ustawić ADPS.
    W Twoim programie nie widać ustawiania tych bitów- czyli ADC chodzi na 500kHz.
    Może chodzić ale Atmel nie gwarantuje że dobrze.
    Zamiana na ATmega128 nic nie pomoże na szybkość przetwarzania ADC- tam są takie same przetworniki.
    A sprawdzanie czy konwersja została zakończona chyba jest w tym wypadku konieczne.
    W rejestrach ADC jest pamiętany wynik ostatniej konwersji.
    Czyli-> zmieniasz kanał -> poprzednia konwersja jeszcze trwa-> czyli kanał jeszcze się nie zmienił->sterujesz kolejny silnik wynikami z poprzedniego kanału.
    P.S.
    W czasie kiedy pisałem wkleiłeś nowy program.
    "procesor w pustej pętli"- to jest taki sobie pomysł.
    Szkoda czasu.
    To jest dobry moment aby ustawić ten bit ADIE i napisać procedurę obsługi przerwania- myślę że po wykryciu przerwania ustawić flagę i procedurę napisać w głównej pętli.
    Jak już napisałem - nie potrafię programować w C.
    Ale może zdążę się tego nauczyć...
  • #15 7308885
    janbernat
    Poziom 38  
    Czyli moje wyliczenia są dobre- konwersja po zmianie kanału trwa 200us.
  • #16 7309026
    nelik1987
    Poziom 31  
    czyli po zmianie kanały trzeba by odczekać jakiś czas bo to właśnie mi wygląda na to ze ja ustawiam na przykład kanał 0 - czytana jest wartość i zapisywana, potem powinna nastąpić zmiana kanału na 1 i znów odczyt a następnie podejmowana decyzja a to wygląda tak że jest ustawiony kanał 0 odczytywana jest wartość a potem program leci dalej bez zmiany kanału. Dziwne jest tylko to że wraz ze wzrostem wartości początkowej licznika silniki powinny działać szybciej a działają wolniej, dlaczego?? przy wartości poniżej 209 wszytskie silniki właśnie zaczynają chodzić na raz a przy wartości 210 wszytsko chodzi nawet ładnie a jak ustawię na przykład 220 to silniki tak jak by traciły moc i trzęsą się jak oszalałe ja już nic z tego nie rozumiem może macie jakieś lepsze rozwiązanie?
  • #17 7309449
    janbernat
    Poziom 38  
    To wymaga dogłębnego studiowania PDF dla ATmeg- nie tylko dla 16.
    Jest to kolejna próba sterowania silników krokowych za pomocą sterowania tranzystorów i wykorzystania ADC bezpośrednio z procesora.
    Co prawda nie tak niemożliwa jak sterowanie mikrokrokowe ale jak widać zależności czasowe i w tym przypadku praktycznie to uniemożliwiają.
    Takich prób- zastąpienia dedykowanego sterownika scalonego do silników krokowych przez procesor już było na elektrodzie kilkanaście.
    I nikt się nie pochwalił sukcesem.
    Według mnie- tego nie da się zrobić.
    Można zrobić sterowanie pełnokrokowe albo półkrokowe bez pomiaru prądu silnika.
    Albo mikrokokowe z pomiarem prądu dla bardzo wolnych obrotów silnika.
    Rozwiązaniem jest sterownik dedykowany scalony dla każdego silnika i procesor który wysyła tylko STEP, DIR i ew. ENABLE.
    Taki układ jest bardzo szybki i przetwornik ADC ma mało dokładny- bo po co mu duża dokładność.
    Mam nadzieję że się mylę- może w ASM da się zrobić jednocześnie pomiar prądu i sterowanie tranzystorów choćby dla jednego silnika i żeby kręcił się z pełną prędkością.
    Ale ja tego nie potrafię.
  • #18 7310736
    nelik1987
    Poziom 31  
    ale ja nie chce pomiaru prądu, ten przetwornik ADC bada mi położenie joysticka a nie prąd płynący do silników. Nie chce wykorzystywać ten sterowania mikrokrokowego, wiem ze sterownik był by najlepszym rozwiązaniem ale miałem wykorzystać tranzystory i silniki krokowe, poza tym płytka z układami L293 jest już gotowa.

    Dodano po 50 [minuty]:

    no dobrze a gdyby wykorzystać układ L297 jako sterownik do którego podam sygnał CLK i DIR, czyli częstotliwość przełączeń i kierunek i jaki już pisałeś ewentualnie ENABLE dla wyłączenia silnika i do tego podłączę moje gotowe sterowniki stopnie mocy na L293?? czy to będzie współpracować bo we wszystkich projektach jakie widziałem do układu sterownika L297 z układem L298N (chyba z tego względu że jest mocniejszy i można zrobić pomiar prądu), Jak już mówiliście chyba będzie trzeba to bardziej sprzętowo rozwiązać. Co Wy na to?
  • #19 7311529
    janbernat
    Poziom 38  
    Będzie działać.
    Ten układ ma po prostu mniejszy prąd-600mA a nie 2A.
    W zasadzie sprawdź program "po kawałku".
    Zakomentuj przerwanie INT0 i wartości overflow wstaw na stałe.
    Takie jakie sądzisz że powinny być.
    Sprawdź dla kilku wartości.
    Albo na czas pomiaru z ADC zablokuj przerwania.
    Albo pomiar z ADC robić co jakiś czas- ostatecznie dżojstikiem nie machasz aż tak szybko.
    I trzeba obliczyć zależności czasowe.
    Przetwarzanie ADC trwa 200us.
    Silniki mają swoje obroty.
    Trzeba je zmierzyć.
    Na każdy obrót pewnie 200 lub 180 kroków.(albo inna wartość- zwykle naklejona na obudowie).
    Na każdy krok ileś instrukcji procesora.
    A w każdej chwili w to wszystko może wpakować się przerwanie- trzeba sprawdzić ile trwa.
REKLAMA