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

[C] Atmega nie usatwia prawidlowo portów

-nobile- 02 Mar 2010 07:54 1957 13
REKLAMA
  • #1 7771971
    -nobile-
    Poziom 16  
    Mam problem z atmega w prostym robocie, po odpowiedniej konfiguracji pinow jesli ustawiam pin 2 to nie podaje na niego calych 5V a pozatym podaje np na pin obok 2V albo cos podobnego. atmega sprawna (sprawdzanie na kilku). Atmega steruje przez mostek H silnikami.czujnik odczytuje prawa lewa (mostek i czujniki sprawne).
    czy wiecie co moze powodowac takie objawy??

    
    #include <avr/io.h>
    #include <util/delay.h>
    
    
    int main()
    {
    	DDRA = 0xFF;		//port D na wyjście
    	PORTA = 0x00;		//stan niski na porcie D
    	DDRC = 0x00;		//port C na wejście
    	PORTC = 0x00;		//stan niski na porcie C
    	DDRB = 0x10;		//port B na wejscie
    	PORTB = 0xEF;		
    	int wl = 0;
    	
    	while(1)
    	{
    		if(!(PINB & 0x01))	//jesli wciśniety przycisk 1
    		{
    			wl++;
    		}
    	
    	
    		for(;wl>0;)
    		{
    			
    		PORTB = 0x10;	//zapal LED
    		
    		if(PINC & 0x01)		//czujnik LEWY	on
    		{
    			PORTA = 0x04;	//PRAWY silnik
    			
    		}
    		
    		if(PINC & 0x02)		//czujnik PRAWY on
    		{
    			PORTA = 0x02;	//LEWY silnik
    			
    		}
    		
    		if(PINC & 0x03)		//czujnik PRAWY i LEWY on
    		{
    			PORTA = 0x06;	//PRAWY i LEWY silnik
    			
    		}
    		
    		if(!(PINC & 0x03))	//czujnik PRAWY i LEWY off
    		{
    		
    			PORTA = 0x00;	//silniki off
    			
    		}
    		}
    		
    		PORTB = 0xFF;
    		_delay_ms(15);
    		PORTB = 0xEF;
    		_delay_ms(15);
    	}
    
    
    
    
    
    
    }
  • REKLAMA
  • #2 7771987
    prokopcio
    Poziom 29  
    Błędy w programie pewnie.... Nie znam C ale wydaje mi się że zmieniasz bardzo szybko stany na wyjściach dlatego nie działa jakbyś tego oczekiwał. Skróć program tylko i wyłącznie do konfiguracji portów najpierw jako wyjścia jako jedynki, później jako zera (drugi program) i pomierz napięcia. Będzie na pewno dobrze. dodawaj sukcesywnie po obsłudze jednej linii portu i patrz co się dzieje.
  • #3 7772126
    pol1111
    Poziom 12  
    Musisz opisać dokładnie o które piny chodzi. Podejrzewam, że pin2 to ten na porcie A. A ten pin obok to nie wiem.

    Pierwsza sprawa. to raczej nie przypisuje się wartości to całego portu w celu nastawienia jednego bitu. Niby z punktu widzenia C to jest ok, ale rodzi same problemy.

    Popatrz co się dzieje jak masz sygnał z obu czujników. Zanim ustali się ten sygnał wysoki na obu pinach A0 i A1, to przechodzi przez wszystkie konfiguracje 00, 01, 10, 11.
    i tak w pętli. a delay jest poza for'em.
    W rezultacie po wciśnięciu przycisku zaczyna się wykonywać w nieskończoność ten for, a stany przeskakują Ci tak jak pisałem wyżej.
    Czyli dają na wyjściu napięcie średnie rzeczywiście ok 2,5V
    Przeorganizuj program tak, żeby przypisanie do portu A było tylko raz w pętli na jej końcu.
  • REKLAMA
  • #4 7772149
    mirekk36
    Poziom 42  
    -nobile- -->

    To nie ATmega nie ustawia prawidłowo portów, to TY je nieprawidłowo ustawiasz i hmmm program piszesz trochę nie teges ;)

       DDRA = 0xFF;      //port D na wyjście 
       PORTA = 0x00;      //stan niski na porcie D 


    to w końcu port A czy port D ??? zastanów się czy przez tą literówkę już coś ci się nie miesza, to po pierwsze.

    Po drugie, raz sprawdzasz wejście - czyli co jest na pinie tak:

    if(!(PINB & 0x01))


    a zaraz potem tak:

    if(PINC & 0x01)


    dostrzegasz różnicę ???? (no chyba że u ciebie czujnik są takie że badasz stan JEDEN a nie ZERO jak w mikrosłiczach - ale tego trzeba się tu domyślać. Jeśli jest odwrotnie to masz źle badanie stanów czujników)

    Ta twoja obsługa klawiszy, podejrzewam tak bez schematu, jest bez sensu niestety.

    No i na koniec masz takiego dziwoląga:

          PORTB = 0xFF; 
          _delay_ms(15); 
          PORTB = 0xEF; 
          _delay_ms(15); 


    co chcesz uzyskać? zmieniać co 15ms stan na jednym pnie portu B ? dokładniej na pinie PB7 ???? Jeśli tak to czy nie jaśniej byłoby to napisane tak:

          PORTB |= (1<<PB7); 
          _delay_ms(15); 
          PORTB &= ~(1<<PB7); 
          _delay_ms(15); 


    No ale to też tłumaczy dlaczego np ty na tym pinie "widzisz" za pomocą multimeru napiecie 2V - masz na nim można powiedzieć jakby programowy przebieg PWM i pomiar napięcia na takim pinie jest też bez sensu - można na niego co najwyżej "patrzeć" oscyloskopem jeśli się ma pod ręką - a nie wszystkiego się dowiedzieć za pomocą pomiaru napięcia.

    Poza tym wszystkim, na koniec, jak się już robi jakąkolwiek obsługę klawiszy to wypadałoby pomyśleć o czymś takim jak drgania styków .... poczytaj o tym bo będziesz miał jeszcze dużo problemów przez to, że nie myślisz o tym w programie.
  • #5 7772830
    -nobile-
    Poziom 16  
    Czujnik podaje stan 1/0,

    PORTB = 0xFF;
          _delay_ms(15);
          PORTB = 0xEF;
          _delay_ms(15);


    to mruga dioda sygnalizując iz nie jest odczytywany stan z czujników;

    DDRA = 0xFF;      //port D na wyjście
       PORTA = 0x00;      //stan niski na porcie D


    zmieniałem porty i zapomniałem zmienić komentarza.


    Co do przycisków to zdaje sobie sprawę z drgań i wiem jak im zapobiegać (przez odczekanie)
    ale nie o klawisze chodzi, tylko o sterowanie mostkiem H.

    dzięki za rady, jak wrócę do domu (szkola) to poprawie program i zobaczę czy pomoże. jak nie to postaram sie wrzucić schemat (bo każdą cześć jest na oddzielnym schemacie - budowa modułowa)

    Śpieszyłem sie z tym programem (na dzis miało to działać) ale jeszcze nie umiem tego za bardzo robić dlatego pewnie tyle błędów.
  • REKLAMA
  • #6 7772903
    H0miczek
    Poziom 20  
    Nawiasem mówiac, zdajesz sobie sprawę w jakich warunkach Mega wejdzie w tego if'a?:
          if(PINC & 0x03)      //czujnik PRAWY i LEWY on 
          { 
             PORTA = 0x06;   //PRAWY i LEWY silnik 
              
          } 

    I czy wiesz co w zwiazku z tym bedzie sie dzialo z jednym silnikow jesli na portC bedziesz mial np 1?

    Poza tym po wcisnieciu chocby na krotko przycisku uC grzęźnie Ci na wieki w forze. tak ma byc?
  • REKLAMA
  • #7 7773671
    -nobile-
    Poziom 16  
    To ze grzęźnie w tym forze to zdaje sobie sprawę tak miało być (chwilowo).

    A co drugiego, ja to rozumiem tak ze jeśli na 2 pinach (czujnikach) stan wysoki, ustaw 2 piny na porcie A na stan wysoki (oba silniki do przodu).
    Czy wejdzie jeśli na którym kol wiek z tych 2 bitów będzie stan wysoki?!
    Jeśli jest tu błąd to proszę o poprawienie mnie.
  • #8 7773720
    H0miczek
    Poziom 20  
    tak. dobrze myslisz.
    zauwaz roznice miedzy tym zapisem:
    if(PINC & 0x03)
    a takim:
    if((PINC & 0x03)==0x3)
    hmm? :)
    podstaw sobie w miejsce PINC np 0x1 i przeanalizuj
  • #9 7773874
    -nobile-
    Poziom 16  
    	if(PINC & 0x01)		//czujnik LEWY	on
    		{
    			PORTA = 0x04;	//PRAWY silnik
    			
    		}
    		
    		if(PINC & 0x02)		//czujnik PRAWY on
    		{
    			PORTA = 0x02;	//LEWY silnik
    			
    		}
    		
    		if((PINC & 0x03)==0x03)		//czujnik PRAWY i LEWY on
    		{
    			PORTA = 0x06;	//PRAWY i LEWY silnik
    			
    		}
    		
    		if(!((PINC & 0x03)==0x03))	//czujnik PRAWY i LEWY off
    		{
    		
    			PORTA = 0x00;	//silniki off
    			
    		}


    wtedy bylo cos w stylu:

    PORT 01
    &
    PROG 11 (0x3)
    wynik 01

    Czyli wykonywało jako prawde (tak?)

    to teraz poprawiłem tak jak poleciłaś ze musi być tylko i wyłącznie stan 11
    i dalej się coś gryzie (najbardziej jak jest tylko stan wysoki z jednego czujnika)
  • Pomocny post
    #10 7774021
    H0miczek
    Poziom 20  
    Jasne ze sie gryzie.
    Zastanow sie tym razem nad tym:
    if(!((PINC & 0x03)==0x03))   //czujnik PRAWY i LEWY off 
          { 
           
             PORTA = 0x00;   //silniki off 
              
          }

    Dla jakich stanów tu wejdzie?

    Edit:
    dobra, najlepiej zrob tak:
      if(PINC & 0x01)      //czujnik LEWY   on 
          { 
             PORTA|= 0x04;   //PRAWY silnik          
          }else{
              PORTA&=~0x04;   
          }
    
       if(PINC & 0x02)      //czujnik  PRAWY   on 
          { 
             PORTA|= 0x02;   //LEWY silnik         
          }else{
              PORTA&=~0x02;   
          }

    I bedzie śmigac.
    tylko zrozum ten fragment i dlaczego akurat tak, prosze..
  • #11 7774243
    -nobile-
    Poziom 16  
    if((PINC & 0x03)==0x00)

    Tak jest poprawnie?

    edit.

    z tym moim tez działa, ale z tym twoim lepiej (przy moim silniki przy jezdzie prosto jakieś 90%mocy, przy twoim 100%)

    rozumiem oba programy (zasadę działania) tylko nie wiem dlaczego przy moim nie dostawałem max napięcia... :/
  • #12 7774947
    H0miczek
    Poziom 20  
    No to pomyśl jeszcze raz nad zasadą dzialania, bo nie rozumiesz.
    Masz na PORTC 0x3. najpierw uC wejdzie w pierwszego if'a i włączy pierwszy silnik a drugi wylaczy. potem wejdzie w drugiego if'a i wyłączy pierwszy a wlaczy drugi. a potem trzeci if i wlaczy oba.

    PS.
    if((PINC & 0x03)==0x00)
    jest poprawnie ale pierwsza wersja akurat tez dzialala :)

    troche bardziej myśl co piszesz, analizuj i symuluj. wtedy nie popelnisz takich bledow...
  • #13 7943738
    jblew
    Poziom 10  
    Miałem ten sam problem, chociaż programowałem w bascom avr. Pomogło ustawienie na starcie wszystkich pinów w porcie na domyślny stan wysoki.
  • #14 7943870
    -nobile-
    Poziom 16  
    Robot oczywiście już działa poprawnie, dziękuje wszystkim za pomoc.
REKLAMA