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

[ATmega128][C] Przypadkowe ustawienie wyjść mikrokontrolera

nelik1987 11 Gru 2009 20:52 1810 11
  • #1 7376029
    nelik1987
    Poziom 31  
    Witam w swoim projekcie do sterowania silnikami krokowymi wykorzystuję joysticki potencjometryczne. By określić, w którą stronę został on wychylony mierzę napięcie na potencjometrze przetwarzając je w przetworniku analogowo cyfrowym. Silniki działają bez zarzutu, tak jak zakładałem. Problem występuje jedynie przy silniku numer 1. Dokładniej po załączeniu zasilania silnik wariuje, trzęsie się jak oszalały. Sprawdziłem stany wyjść na oscyloskopie i podawane są jakieś śmieci, dlatego taka reakcja silnika. Najciekawsze jest to, że jak poruszę jednym z potencjometrów to problem zanika i można normalnie sterować tym silnikiem, ale gdy znów poruszę innym joystickiem znów wracają wariacje. Problem polega zapewne w przetwarzaniu sygnały analogowego, ale niestety nie mogę sobie z tym poradzić. Zmieniałem porty i nic nie pomogło więc to nie wina wyjść. Nie jest to też wina joysticka bo podłączłem na szybko 4 potencjometry i sterowałem wkrętakiem tymi potencjometrami reakcja była taka sama. Dlaczego tylko na tym jednym wyjściu się tak dzieje?

    załączam kod programu:

    
    
    #include <avr/io.h>
    #include <avr/interrupt.h> 
    
    
    /////// SILNIK 1 //////////////// PORT - E
    
    #define OUT1a_ON 	PORTE |= 	 _BV(0);
    #define OUT1a_OFF 	PORTE &= 	~_BV(0);
    
    #define OUT1b_ON 	PORTE |= 	 _BV(1);
    #define OUT1b_OFF 	PORTE &= 	~_BV(1);
    
    #define OUT1c_ON 	PORTE |= 	 _BV(2);
    #define OUT1c_OFF 	PORTE &= 	~_BV(2);
    
    #define OUT1d_ON 	PORTE |= 	 _BV(3);
    #define OUT1d_OFF 	PORTE &= 	~_BV(3);
    
    /////// SILNIK 2 ////////////////  PORT - E
    
    #define OUT2a_ON 	PORTE |= 	 _BV(4);
    #define OUT2a_OFF 	PORTE &= 	~_BV(4);
    
    #define OUT2b_ON 	PORTE |= 	 _BV(5);
    #define OUT2b_OFF 	PORTE &= 	~_BV(5);
    
    #define OUT2c_ON 	PORTE |= 	 _BV(6);
    #define OUT2c_OFF 	PORTE &= 	~_BV(6);
    
    #define OUT2d_ON 	PORTE |= 	 _BV(7);
    #define OUT2d_OFF 	PORTE &= 	~_BV(7);
    
    
    /////// SILNIK 3 ////////////////  PORT - B
    
    #define OUT3a_ON 	PORTB |= 	 _BV(0);
    #define OUT3a_OFF 	PORTB &= 	~_BV(0);
    
    #define OUT3b_ON 	PORTB |= 	 _BV(1);
    #define OUT3b_OFF 	PORTB &= 	~_BV(1);
    
    #define OUT3c_ON 	PORTB |= 	 _BV(2);
    #define OUT3c_OFF 	PORTB &= 	~_BV(2);
    
    #define OUT3d_ON 	PORTB |= 	 _BV(3);
    #define OUT3d_OFF 	PORTB &= 	~_BV(3);
    
    /////// SILNIK 4 ////////////////  PORT - B
    
    #define OUT4a_ON 	PORTB |= 	 _BV(4);
    #define OUT4a_OFF 	PORTB &= 	~_BV(4);
    
    #define OUT4b_ON 	PORTB |= 	 _BV(5);
    #define OUT4b_OFF 	PORTB &= 	~_BV(5);
    
    #define OUT4c_ON 	PORTB |= 	 _BV(6);
    #define OUT4c_OFF 	PORTB &= 	~_BV(6);
    
    #define OUT4d_ON 	PORTB |= 	 _BV(7);
    #define OUT4d_OFF 	PORTB &= 	~_BV(7);
    
    
    /////// SILNIK 5 ////////////////  PORT - D unipolarny
    
    #define OUT5a_ON 	PORTD |= 	 _BV(0);
    #define OUT5a_OFF 	PORTD &= 	~_BV(0);
    
    #define OUT5b_ON 	PORTD |= 	 _BV(1);
    #define OUT5b_OFF 	PORTD &= 	~_BV(1);
    
    #define OUT5c_ON 	PORTD |= 	 _BV(2);
    #define OUT5c_OFF 	PORTD &= 	~_BV(2);
    
    #define OUT5d_ON 	PORTD |= 	 _BV(3);
    #define OUT5d_OFF 	PORTD &= 	~_BV(3);
    
    /////// SILNIK 6 ////////////////  PORT - D unipolarny
    
    #define OUT6a_ON 	PORTD |= 	 _BV(4);
    #define OUT6a_OFF 	PORTD &= 	~_BV(4);
    
    #define OUT6b_ON 	PORTD |= 	 _BV(5);
    #define OUT6b_OFF 	PORTD &= 	~_BV(5);
    
    #define OUT6c_ON 	PORTD |= 	 _BV(6);
    #define OUT6c_OFF 	PORTD &= 	~_BV(6);
    
    #define OUT6d_ON 	PORTD |= 	 _BV(7);
    #define OUT6d_OFF 	PORTD &= 	~_BV(7);
    
    ///// LEDY //////
    #define LED_ON PORTC |= _BV(0);
    #define LED_OFF PORTC &= ~_BV(0);
    #define LED_TOGGLE PORTC ^= _BV(0);
    
    
    volatile uint8_t overflow_ADC=0;
    volatile uint8_t overflow1=0;
    volatile uint8_t overflow2=0;
    volatile uint8_t overflow3=0;
    volatile uint8_t overflow4=0;
    volatile uint8_t overflow5=0;
    volatile uint8_t overflow6=0;
    
    volatile uint8_t overflow_ADC_max=10;
    volatile uint8_t overflow1_max=6;
    volatile uint8_t overflow2_max=6;
    volatile uint8_t overflow3_max=6;
    volatile uint8_t overflow4_max=6;
    volatile uint8_t overflow5_max=6;
    volatile uint8_t overflow6_max=6;
    
    volatile char sw1a=0;
    volatile char sw1b=0;
    
    volatile char sw2a=0;
    volatile char sw2b=0;
    
    volatile char sw3a=0;
    volatile char sw3b=0;
    
    volatile char sw4a=0;
    volatile char sw4b=0;
    
    volatile uint16_t value;  // zapisywana wartość przetowrnika
    
    
    volatile unsigned char stan1 = 3;
    volatile unsigned char stan2 = 3;
    volatile unsigned char stan3 = 3;
    volatile unsigned char stan4 = 3;
    volatile unsigned char stan5 = 3;
    volatile unsigned char stan6 = 3;
    
    volatile unsigned int value;			// zmienna przechowują stan wyjścia przetwornika ADC
    volatile unsigned int zakres=120; 		// wartść po jakiej ma nastąpić załączenie
    
    volatile unsigned char licznik_ADC = 2;
    
    ISR (TIMER0_OVF_vect)
    {
        TCNT0 = 100;                // Załaduj wartoś początkową do timera 0
    	overflow1++;
    	overflow2++;
    	overflow3++;
    	overflow4++;
    	overflow5++;
    	overflow6++;
    	overflow_ADC++;	
    }
    
    int main (void)
    {
    
    
    DDRB = 255; // Ustawienie rejestru B jako wyjݣie na silnik
    DDRD = 255; // Ustawienie rejestru D jako wyjݣie na silniki
    DDRE = 255; // Ustawienie rejestru E jako wyjݣie na silniki
    DDRF = 0; // Ustawienie rejestru F jako Wejścia z pad'a
    
    PORTF |= _BV(4); //Ustaw PF0 w stan wysoki (podciڧniecie do jedynki)
    PORTF |= _BV(5); //Ustaw PF1 w stan wysoki (podciڧniecie do jedynki)
    PORTF |= _BV(6); //Ustaw PF0 w stan wysoki (podciڧniecie do jedynki)
    PORTF |= _BV(7); //Ustaw PF1 w stan wysoki (podciڧniecie do jedynki)
    
    
    TIMSK = _BV(TOIE0);        // włącz przerwanie od timerem 0
    
    TCCR0  = (_BV(CS00) | _BV(CS01)) ;			//Ustawia timer0 z preskalerem 32
    
    ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADPS0)|_BV(ADPS2)|_BV(ADFR); // ustaw przetwornik ADC
    
    sei();                        // włącz obsługę przerwań
    
    while(1)  // Program główny
    {
    
    
    //////////////////////////////////////////////////// Sprawdzanie przetwornika ADC ///////////////////////
    
    
    if(overflow_ADC>=overflow_ADC_max)
    {	
    
    	licznik_ADC++;
    	if(licznik_ADC>=5)
    	licznik_ADC=1;
    
    	switch(licznik_ADC)
    	{
    	case 1 :
    		ADMUX = 0;    		// wybierz kanł0 przetwornika ADC (przetwarzanie 1)
    		value = ADCW;
    		if(value<=zakres)
    		{
    			sw1a=1;
    			sw1b=0;
    		}
    		else
    		{
    			if(value>=1023-zakres)
    			{
    				sw1a=0;
    				sw1b=1;
    			}
    			else
    			{
    				sw1a=0;
    				sw1b=0;
    			}
    		}
    			
    		while (bit_is_clear(ADCSRA,ADIF))  {}	// czeka na koniec konwersji
    	break;
    
    	case 2:
    		ADMUX = 1;    		// wybierz kanł1 przetwornika ADC (przetwarzanie 2)
    		value = ADCW;
    		if(value<=zakres)
    		{
    			sw2a=1;
    			sw2b=0;
    		}
    		else
    		{
    			if(value>=1023-zakres)
    			{
    				sw2a=0;
    				sw2b=1;
    			}
    			else
    			{
    				sw2a=0;
    				sw2b=0;
    			}
    		}		
    		while (bit_is_clear(ADCSRA,ADIF))  {} // czeka na koniec konwersji 
    	break;
    
    	case 3 :
    		ADMUX = 2;    		// wybierz kanł2 przetwornika ADC (przetwarzanie 3)
    		value = ADCW;
    		if(value<=zakres)
    		{
    			sw3a=1;
    			sw3b=0;
    		}
    		else
    		{
    			if(value>=1023-zakres)
    			{
    				sw3a=0;
    				sw3b=1;
    			}
    			else
    				{
    				sw3a=0;
    				sw3b=0;
    				}
    		}
    		while (bit_is_clear(ADCSRA,ADIF))  {}	// czeka na koniec konwersji	
    	break;	
    	
    	case 4 :
    		ADMUX = 3;    		// wybierz kanł3 przetwornika ADC (przetwarzanie 4)
    		value = ADCW;
    		if(value<=zakres)
    		{
    			sw4a=1;
    			sw4b=0;
    		}
    		else
    		{
    			if(value>=1023-zakres)
    			{
    				sw4a=0;
    				sw4b=1;
    			}
    			else
    			{
    				sw4a=0;
    				sw4b=0;
    			}
    		}
    		while (bit_is_clear(ADCSRA,ADIF))  {}	// czeka na koniec konwersji		
    	break;
    
    	
    	}
    	overflow_ADC=0;
    }
    
    //////////////////////////////////////////////////// SILNIK 1 ///////////////////////
    
    if(overflow1>=overflow1_max) // silnik 1
    {
    
    	if(sw2a != 0)  
    	{
    		stan1++;
    		if(stan1==5)
    		stan1=1;
    	}
    
    	if(sw2b != 0)
    	{
    		stan1--;
    		if(stan1==0)
    		stan1=4;
    	}
    
    switch(stan1)
    	{
    	case 1 :
    	OUT1a_ON;
    	OUT1b_OFF;
    	OUT1c_OFF;
    	OUT1d_OFF;
    
    	break;
    	
    	case 2 :
    	OUT1a_OFF;
    	OUT1b_OFF;
    	OUT1c_ON;
    	OUT1d_OFF;
    	break;
    	
    	case 3 :
    	OUT1a_OFF;
    	OUT1b_ON;
    	OUT1c_OFF;
    	OUT1d_OFF;
    	break;		
    	
    	case 4 :
    	OUT1a_OFF;
    	OUT1b_OFF;
    	OUT1c_OFF;
    	OUT1d_ON;
    	break;	
    	}
    	overflow1=0;
    
    }
    
    //////////////////////////////////////////////////// SILNIK 2 ///////////////////////
    
    if(overflow2>=overflow2_max) // silnik 2
    {
    
    	if(sw1a != 0)  
    	{
    		stan2++;
    		if(stan2==5)
    		stan2=1;
    	}
    
    	if(sw1b != 0)
    	{
    		stan2--;
    		if(stan2==0)
    		stan2=4;
    	}
    
    switch(stan2)
    	{
    	case 1 :
    	OUT2a_ON;
    	OUT2b_OFF;
    	OUT2c_OFF;
    	OUT2d_OFF;
    
    	break;
    	
    	case 2 :
    	OUT2a_OFF;
    	OUT2b_OFF;
    	OUT2c_ON;
    	OUT2d_OFF;
    	break;
    	
    	case 3 :
    	OUT2a_OFF;
    	OUT2b_ON;
    	OUT2c_OFF;
    	OUT2d_OFF;
    	break;		
    	
    	case 4 :
    	OUT2a_OFF;
    	OUT2b_OFF;
    	OUT2c_OFF;
    	OUT2d_ON;
    	break;	
    	}
    	overflow2=0;
    
    }
    
    
    //////////////////////////////////////////////////// SILNIK 3 ///////////////////////
    
    if(overflow3>=overflow3_max) // silnik 3
    {
    
    	if(sw3a != 0)  
    	{
    		stan3++;
    		if(stan3==5)
    		stan3=1;
    	}
    
    	if(sw3b != 0)
    	{
    		stan3--;
    		if(stan3==0)
    		stan3=4;
    	}
    
    switch(stan3)
    	{
    	case 1 :
    	OUT3a_ON;
    	OUT3b_OFF;
    	OUT3c_OFF;
    	OUT3d_OFF;
    
    	break;
    	
    	case 2 :
    	OUT3a_OFF;
    	OUT3b_OFF;
    	OUT3c_ON;
    	OUT3d_OFF;
    	break;
    	
    	case 3 :
    	OUT3a_OFF;
    	OUT3b_ON;
    	OUT3c_OFF;
    	OUT3d_OFF;
    	break;		
    	
    	case 4 :
    	OUT3a_OFF;
    	OUT3b_OFF;
    	OUT3c_OFF;
    	OUT3d_ON;
    	break;	
    	}
    	overflow3=0;
    
    }
    
    
    //////////////////////////////////////////////////// SILNIK 4 ///////////////////////
    
    if(overflow4>=overflow4_max) // silnik 4
    {
    
    	if(sw4a != 0)  
    	{
    		stan4++;
    		if(stan4==5)
    		stan4=1;
    	}
    
    	if(sw4b != 0)
    	{
    		stan4--;
    		if(stan4==0)
    		stan4=4;
    	}
    
    switch(stan4)
    	{
    	case 1 :
    	OUT4a_ON;
    	OUT4b_OFF;
    	OUT4c_OFF;
    	OUT4d_OFF;
    
    	break;
    	
    	case 2 :
    	OUT4a_OFF;
    	OUT4b_OFF;
    	OUT4c_ON;
    	OUT4d_OFF;
    	break;
    	
    	case 3 :
    	OUT4a_OFF;
    	OUT4b_ON;
    	OUT4c_OFF;
    	OUT4d_OFF;
    	break;		
    	
    	case 4 :
    	OUT4a_OFF;
    	OUT4b_OFF;
    	OUT4c_OFF;
    	OUT4d_ON;
    	break;	
    	}
    	overflow4=0;
    
    }
    
    //////////////////////////////////////////////////// SILNIK 5 ///////////////////////
    
    if(overflow5>=overflow5_max) // silnik 5
    {
    
    	if(bit_is_clear(PINF,4)) 
    	{	
    		stan5++;
    		if(stan5==5)
    		stan5=1;
    	}
    
    	if(bit_is_clear(PINF,5))
    	{
    		stan5--;
    		if(stan5==0)
    		stan5=4;
    	}
    
    switch(stan5)
    	{
    	case 1 :
    	OUT5a_ON;
    	OUT5b_OFF;
    	OUT5c_OFF;
    	OUT5d_OFF;
    
    	break;
    	
    	case 2 :
    	OUT1a_OFF;
    	OUT1b_ON;
    	OUT1c_OFF;
    	OUT1d_OFF;
    	break;
    	
    	case 3 :
    	OUT1a_OFF;
    	OUT1b_OFF;
    	OUT1c_ON;
    	OUT1d_OFF;
    	break;		
    	
    	case 4 :
    	OUT1a_OFF;
    	OUT1b_OFF;
    	OUT1c_OFF;
    	OUT1d_ON;
    	break;	
    	}
    	overflow5=0;
    
    }
    
    //////////////////////////////////////////////////// SILNIK 6 ///////////////////////
    
    if(overflow6>=overflow6_max) // silnik 6
    {
    
    	if(bit_is_clear(PINF,6))
    	{
    		stan6++;
    		if(stan6==5)
    		stan6=1;
    	}
    
    	if(bit_is_clear(PINF,7))
    	{
    		stan6--;
    		if(stan6==0)
    		stan6=4;
    	}
    
    switch(stan6)
    	{
    	case 1 :
    	OUT6a_ON;
    	OUT6b_OFF;
    	OUT6c_OFF;
    	OUT6d_OFF;
    
    	break;
    	
    	case 2 :
    	OUT6a_OFF;
    	OUT6b_ON;
    	OUT6c_OFF;
    	OUT6d_OFF;
    	break;
    	
    	case 3 :
    	OUT6a_OFF;
    	OUT6b_OFF;
    	OUT6c_ON;
    	OUT6d_OFF;
    	break;		
    	
    	case 4 :
    	OUT6a_OFF;
    	OUT6b_OFF;
    	OUT6c_OFF;
    	OUT6d_ON;
    	break;	
    	}
    	overflow6=0;
    
    }
    
    	
    
    } 	//zamyka while
    }	//zamyka main
    
    
  • Pomocny post
    #2 7376590
    BoskiDialer
    Poziom 34  
    Prawdopodobnie kod dla "silnik 5", przypadki 2, 3 i 4 sterują nie tym, czym powinny. Kod jest strasznie nieczytelny, a przez proste kopiowanie/wklejanie powstają później takie błędy jak ten.

    -- edit: nie powinieneś pobierać wartości z ADC po zakończeniu konwersji?
  • #3 7377550
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Koleś - ile jeszcze założysz wyróżnionych tematów o JEDNYM PROJEKCIE? Dla mnie zaśmiecasz forum, więc może weź w końcu zacznij pisać w JEDNYM TEMACIE, albo choć przestań je wyróżniać, bo ten śmietnik który tu wyprodukujesz będzie wisiał przez co najmniej miesiąc... Za 3 dni pół strony będzie zapełnione żółtymi tematami od ciebie... Widać, że ten projekt chyba cię przerasta bo jest on dla ciebie jednym wielkim problemem, każdy układ peryferyjny nie działa ci jak trzeba, tak samo jak twój kod - może zlikwiduj przyczynę (swój brak podstawowej wiedzy), a nie skutek (problemy z konkretnym projektem)?

    4\/3!!
  • #4 7384906
    nelik1987
    Poziom 31  
    BoskiDialer napisał:
    Prawdopodobnie kod dla "silnik 5", przypadki 2, 3 i 4 sterują nie tym, czym powinny. Kod jest strasznie nieczytelny, a przez proste kopiowanie/wklejanie powstają później takie błędy jak ten.

    -- edit: nie powinieneś pobierać wartości z ADC po zakończeniu konwersji?


    dokładnie to było problemem i jest dokładnie, tak jak pisałeś. Wygodne kopiuj wklej czasami zawodzi przy takie ilości bardzo podobnych wpisów można czasami dostać oczopląsu i nie zauważyć błędu.

    Co do sprawdzania zakończenia konwersji to też masz rację :) czyli przykładowe sprawdzanie i zapisywanie stanu przetwornika powinno wyglądać tak:

    	switch(licznik_ADC)
    	{
    	case 1 :
    		ADMUX = 0;    		// wybierz kanł0 przetwornika ADC (przetwarzanie 1)
    		
    		while (bit_is_clear(ADCSRA,ADIF))  {}	// czeka na koniec konwersji
    		
    		value = ADCW;
    		if(value<=zakres)
    		{
    			sw1a=1;
    			sw1b=0;
    		}
    		else
    		{
    			if(value>=1023-zakres)
    			{
    				sw1a=0;
    				sw1b=1;
    			}
    			else
    			{
    				sw1a=0;
    				sw1b=0;
    			}
    		}
    	break;
    


    na początku każdej funkcji jaka musi wykonać się nieprzerwanie dodałem na początku cli(); i na końcu sei(); po to by w czasie wykonywania sekwencyjnych przełączeń nie wystąpiło przerwanie, czy tak jest dobrze?

    
    if(overflow1>=overflow1_max) // silnik 1
    {
    	cli();
    	if(sw1a != 0)  
    	{
    		stan1++;
    		if(stan1==5)
    		{
    			stan1=1;
    		}
    	}
    
    	if(sw1b != 0)
    	{
    		stan1--;
    		if(stan1==0)
    		{
    			stan1=4;
    		}
    	}
    
    switch(stan1)
    	{
    	case 1 :
    	OUT1a_ON;
    	OUT1b_OFF;
    	OUT1c_OFF;
    	OUT1d_OFF;
    
    	break;
    	
    	case 2 :
    	OUT1a_OFF;
    	OUT1b_OFF;
    	OUT1c_ON;
    	OUT1d_OFF;
    	break;
    	
    	case 3 :
    	
    	OUT1a_OFF;
    	OUT1b_ON;
    	OUT1c_OFF;
    	OUT1d_OFF;
    	break;		
    	
    	case 4 :
    	
    	OUT1a_OFF;
    	OUT1b_OFF;
    	OUT1c_OFF;
    	OUT1d_ON;
    	break;	
    	}
    	overflow1=0;
    	LED_TOGGLE;
    	sei();
    }
  • #5 7385278
    BoskiDialer
    Poziom 34  
    Do końca poprawne to to nie jest, ale będzie działać w miarę znośnie - przerwania powinieneś zablokować przed pobraniem wartości zmiennej overflow1, inaczej możesz utracić jedno zwiększenie tej zmiennej.

    Jeśli przerwania mają być obsługiwane szybko po zajściu jakiegoś zdarzenia (a jako że do timera wartość jest ładowana w kodzie przy dzielniku /32, to przerwania powinny być realizowane szybko), to od kodu głównego wymaga się, aby części atomowe były maksymalnie krótkie. Tutaj najłatwiej było by wsadzić wszystkie główne warunki do jednej części atomowej, jednak to zwiększy czas reakcji na przerwanie timera. Można każdy warunek wsadzić do osobnego atomu, pamiętając aby pomiędzy sei oraz cli wstawić jednego nop'a (co wynika z architektury avr'ów - w przeciwnym przypadku przerwanie nie zostanie obsłużone pomiędzy nimi). Można wstawić cli() przed warunkiem a sei() w warunku na początku (przesuwając jednocześnie przypisanie do overflow1 na sam początek przed sei) oraz dodatkowe sei w elsie (wraz z dodatkowym nop'em j/w). Jednak najlepszym rozwiązaniem jest przeprojektować kod i umieścić dość sporą część w przerwaniu.

    Dużo czasu przeprojektowanie mi nie zajęło, jak chcesz możesz podejrzeć pomysł - załącznik.
    Załączniki:
  • #6 7385342
    nelik1987
    Poziom 31  
    po napisaniu całego działającego programu miałem zamiar napisać funkcje które będą wywoływały powtarzające się części programu tym by zmniejszyć kod. Na razie sprawdzam czy wszystko działa poprawnie, optymalizację i zmniejszenie kody wykorzystując funkcje zrobię jak wszystko mi ruszy.

    Żeby nie zakładać kolejnego tematu (bo niektórym się to nie podoba) zapytam tutaj o przetwornik ADC. Korzystam z 4 kanałów ADC kolejne kanały chciałem wykorzystać jako porty wejściowe, w tej chwili jak przetwornik działa w trybie FreeRun na wejściach 3,4,5,6 odczytywane są zawsze stany niskie pomimo podania stanu wysokiego przez wewnętrzne podciągnięcie do jedynki.

    Sprawdzałem to na innym porcie i fukcja działa dobrze w programie. Teraz pytanie czy aby pobierać stan wejścia z pinów które należą do przetwornika należy przetworni wyłączyć (to wiem napewno) ale czy można zrobić to tak: ADCSRA = 0; bo jak tak zapiszę to przetwornik przestaje działać (oczywiście na początku programu znów go uruchamiam)
  • #7 7385508
    BoskiDialer
    Poziom 34  
    Jeśli ADC pracuje w trybie FreeRun i próbkuje ciągle, to należało by po wybraniu kanału na multiplekserze wyzerować flagę ADIF (poprzez wpisanie w jej miejsce jedynki) i dopiero wtedy oczekiwać na nowy wynik - jednak jeśli konwersja zaczęła się nie pomiędzy wybraniem kanału oraz wyzerowaniem flagi, to wynik mimo wszystko będzie odnosił się do innego kanału - kod nie będzie działał deterministycznie. Przy inicjalizacji ADC nie ustawiaj bitów ADSC oraz ADFR, a w celu konwersji najpierw wybierz kanał, dopiero potem ustaw bity ADSC aby zacząć konwersję oraz ADIF, aby skasować flagę (kasowanie przez wpisanie jedynki) - wtedy pętla oczekująca na ustawienie bitu ADIF będzie miała szansę wykryć właściwy koniec konwersji (bez zerowania ADIF po pierwszej konwersji warunek zawsze będzie fałszywy i nie będzie oczekiwania).
  • #8 7385943
    nelik1987
    Poziom 31  
    Zrobiłem tak jak poradziłeś, to znaczy podczas inicjalizacji przetwornik NIE ustawiam ADSC oraz ADFR. Po wybraniu kanału ustawiam ADSC i ustawiam ADIF program niestety nie działa w ogóle dlaczego?

    
    // wcześniejsza część programu
    
    ADCSRA = _BV(ADEN)|_BV(ADPS0)|_BV(ADPS2); // ustaw przetwornik ADC	
    
    sei();                        // włącz obsługę przerwań
    
    while(1)  // Program główny
    {
    
    
    //////////////////////////////////////////////////// Sprawdzanie przetwornika ADC ///////////////////////
    
    
    if(overflow_ADC>=overflow_ADC_max)
    {	
    	
    	cli();
    	licznik_ADC++;
    	if(licznik_ADC>=5)
    	licznik_ADC=1;
    
    	switch(licznik_ADC)
    	{
    	case 1 :
    		ADMUX = 0;    							// wybierz kanł0 przetwornika ADC (przetwarzanie 1)
    		ADCSRA = _BV(ADSC)|_BV(ADIF); 			// rozpocznik konwersję wykasuj flagę zakończenia konwersji
    		while (bit_is_clear(ADCSRA,ADIF))  {}	// czeka na koniec konwersji
    		
    		value = ADCW;
    		if(value<=zakres)
    		{
    			sw1a=1;
    			sw1b=0;
    		}
    		else
    		{
    			if(value>=1023-zakres)
    			{
    				sw1a=0;
    				sw1b=1;
    			}
    			else
    			{
    				sw1a=0;
    				sw1b=0;
    			}
    		}
    			
    
    	break;
    
    	case 2:
    		ADMUX = 1;    							// wybierz kanł0 przetwornika ADC (przetwarzanie 1)
    		ADCSRA = _BV(ADSC)|_BV(ADIF); 			// rozpocznik konwersję wykasuj flagę zakończenia konwersji
    		while (bit_is_clear(ADCSRA,ADIF))  {}	// czeka na koniec konwersji
    		value = ADCW;
    		if(value<=zakres)
    		{
    			sw2a=1;
    			sw2b=0;
    		}
    		else
    		{
    			if(value>=1023-zakres)
    			{
    				sw2a=0;
    				sw2b=1;
    			}
    			else
    			{
    				sw2a=0;
    				sw2b=0;
    			}
    		}		
    	break;
    
    	case 3 :
    		ADMUX = 2;    							// wybierz kanł0 przetwornika ADC (przetwarzanie 1)
    		ADCSRA = _BV(ADSC)|_BV(ADIF); 			// rozpocznik konwersję wykasuj flagę zakończenia konwersji
    		while (bit_is_clear(ADCSRA,ADIF))  {}	// czeka na koniec konwersji
    		value = ADCW;
    		if(value<=zakres)
    		{
    			sw3a=1;
    			sw3b=0;
    		}
    		else
    		{
    			if(value>=1023-zakres)
    			{
    				sw3a=0;
    				sw3b=1;
    			}
    			else
    			{
    				sw3a=0;
    				sw3b=0;
    			}
    		}	
    	break;	
    	
    	case 4 :
    		ADMUX = 3;    							// wybierz kanł0 przetwornika ADC (przetwarzanie 1)
    		ADCSRA = _BV(ADSC)|_BV(ADIF); 			// rozpocznik konwersję wykasuj flagę zakończenia konwersji
    		while (bit_is_clear(ADCSRA,ADIF))  {}	// czeka na koniec konwersji
    		value = ADCW;
    		if(value<=zakres)
    		{
    			sw4a=1;
    			sw4b=0;
    		}
    		else
    		{
    			if(value>=1023-zakres)
    			{
    				sw4a=0;
    				sw4b=1;
    			}
    			else
    			{
    				sw4a=0;
    				sw4b=0;
    			}
    		}	
    	break;
    
    	
    	}
    	overflow_ADC=0;
    	sei();
    
    // dlasza część programu
    }
  • #9 7385969
    BoskiDialer
    Poziom 34  
    Aby ustawić konkretne bity(ściślej: wpisać jedynki) z zachowaniem wartości pozostałych:
    ADCSRA = ADCSRA | _BV(ADSC)|_BV(ADIF);
    lub co na jedno wychodzi:
    ADCSRA |= _BV(ADSC)|_BV(ADIF);
    lub korzystając z własności flagi ADIF, można ją pominąć przy ustawianiu bitów (jeśli jest ustawiona, to przypisanie będzie z jedynką a więc skasuje flagę ADIF):
    ADCSRA |= _BV(ADSC); // niejawne skasowanie ADIF
    Ostatnia metoda wychodzi najlepiej, ponieważ kompiluje się do pojedynczego sbi.

    Przy prostym przypisaniu, wszystkie pozostałe bity zostaną skasowane łącznie z ADEN a więc przetwornik się wyłączy, ADIF nie zostanie ustawione i kod się zawiesi w oczekiwaniu.
  • #10 7385988
    nelik1987
    Poziom 31  
    dziękuję ślicznie działa :) nie wiedziałem ze ustawienie konkretnego bitu w słowie kasuje inne bity teraz już będę wiedzieć :)

    Dodano po 31 [minuty]:

    Te ustawienia przetwornika nie dały widocznych rezultatów, tzn działa tak jak działało dla silników 1,2,3,4 dla silników 5,6 nadal nie działa. Te silniki są sterowane zwykłymi przyciskami dlatego badam stan wejść PINF,4 5 6 i 7 (wejścia 4,5 dla silnika 5 a wejścia 6,7 dla silnika 6)

    Sprawdziłem w programie i wychodzi na to że wszytskie we wejścia cały czas mają stan niski dlatego w funkcji sterującej silnikami 5 i 6 najpierw zwiększany jest stan licznika do przełączeń a potem natychmiast kasowany. Sprawdziłem to na innym porcie PORTC i wszystko działa, jak przyłożę stan niski do pinu C4 lub C5 to silnik działa. czyli ogólnie napisane jest dobrze. Problem jest tylko z odczytem na porcie F (port przetwornika).

    Czytałem gdzieś, że aby normalnie posługiwać się potem F czyli portem przetwornika trzeba przetwornik wyłączyć ale to niestety nie pomaga.

    //////////////////////////////////////////////////// SILNIK 5 ///////////////////////
    
    if(overflow5>=overflow5_max) // silnik 5
    {
    	cli();
    	if(bit_is_clear(PINF,4)) 
    	{	LED_TOGGLE;
    		stan5++;
    		if(stan5==5)
    		stan5=1;
    	}
    
    	if(bit_is_clear(PINF,5))
    	{
    		stan5--;
    		if(stan5==0)
    		stan5=4;
    	}
    
    switch(stan5)
    	{
    	case 1 :
    	OUT5a_ON;
    	OUT5b_OFF;
    	OUT5c_OFF;
    	OUT5d_OFF;
    
    	break;
    	
    	case 2 :
    	OUT5a_OFF;
    	OUT5b_ON;
    	OUT5c_OFF;
    	OUT5d_OFF;
    	break;
    	
    	case 3 :
    	OUT5a_OFF;
    	OUT5b_OFF;
    	OUT5c_ON;
    	OUT5d_OFF;
    	break;		
    	
    	case 4 :
    	OUT5a_OFF;
    	OUT5b_OFF;
    	OUT5c_OFF;
    	OUT5d_ON;
    	break;	
    	}
    	overflow5=0;
    	sei();
    }
  • Pomocny post
    #11 7386524
    BoskiDialer
    Poziom 34  
    Zacznij dokładnie czytać dokumentację! PF4..7 to również JTAG, jeśli go nie wyłączyłeś w fusebitach, to dokładnie te 4 wyprowadzenia nie będą do twojej dyspozycji.
  • #12 7386779
    nelik1987
    Poziom 31  
    no i po raz kolejny masz rację :) u mnie z angielskim to trochę słabo i nie wiedziałem, ze jak JTAG jest włączony to zajmowane są piny i nie można z nich korzystać. Jeszcze raz dziękuję. Jak na razie wszystko działa doskonale tak jak chciałem. Teraz zabieram się za dopisanie części programu odpowiedzialnej za czujniki krańcowe. Jeszcze raz dziękuję
REKLAMA