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

Atmega 32, ADC. Dlaczego zamieszczony kod nie działa?

mati1988k 19 Gru 2010 01:30 2390 7
REKLAMA
  • #1 8886303
    mati1988k
    Poziom 13  
    Witam. Mam taki oto kod:
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include <stdlib.h>
    
    #define SetBit(x,y)	x |= (1<<y)
    #define ClrBit(x,y) x &= ~(1<<y)
    #define NegBit(x,y) x ^= (1<<y)
    
    int main(void)
    {
    	DDRD=0xFF;
    	PORTD=0x00;
    	DDRA=0x00;
    	PORTA=0x00;
    
    	
    	TCCR1A=0b10001000;
    	TCCR1B=0b00010010;
    	ICR1=20000;
    	OCR1A=1500;
    
    
        ADMUX = 0b01000000;
        ADCSRA = 0b11000000; // Zacznij pierwsza konwersję
    
    	while(bit_is_set(ADCSRA,ADSC)) {}
    
    	int a=1000;
    
    while(1)
    	{
    
    	SetBit(ADCSRA,6);	// Konwersja
    	while(bit_is_set(ADCSRA,ADSC)) {}	// Czekaj na zakończenie konwersji
    
    	a=2000 - ADC;
    	
    	OCR1A=a;
    	}
    }
    


    Wydaje mi się, że wszystko powinno być ok ale w ogóle mi to nie działa :). Pod Vref mam podłączone 5V, pod PA0 podłączony jest potencjometr i chodzi o to aby podczas kręcenia potencjometrem kręciło się też serwo. PWM'ka jest ustawiona poprawnie.
  • REKLAMA
  • #2 8886779
    mirekk36
    Poziom 42  
    Ciekaw jestem po co podłączyłeś 5V pod AREF? skoro można a nawet trzeba to zrobić programowo poprzez odpowiednie ustawienie rejestru ADC a do AREF podłączyć tylko kondensator 100nF do GND. W przeciwnym przypadku jeśli nie przestawisz domyślnie włączonego wewnętrznego źródła odniesienia 2,56V to niejako "smażysz" procka.
  • REKLAMA
  • #3 8887307
    mati1988k
    Poziom 13  
    O a ja myślałem, że tam się podłącza właśnie napięcie odniesienia :), Ale nawet po zmianie mi to nie działa. Z tego co rozumiem w datashicie jest napisane, że po wpisaniu jedynki na ADSC czyli 6 bit ADCSRA zaczyna się pojedyncza konwersja.
    Potem czekam aż na tym bicie pojawi się zero które oznacza, że konwersja się zakończyła i mogę sczytywać wartość z ADC.
    Na ADCSRA ustawiłem jeszcze jedynie 1 na 7 bicie czyli "ADC enable" no i ADC prescaler ustawiłem na 2. Więc wydaje mi się, że tutaj wszystko powinno być dobrze.
    Na ADMUX Ustawiłem jedynie napięcie odniesienie z AVCC i pomiar na pinie ADC0.

    ADC u mnie cały czas wynosi 1023
  • #4 8889947
    mati1988k
    Poziom 13  
    Proszę was jeszcze raz bardzo o pomoc :) zależy mi na tym aby to działało a próbowałem już chyba wszystkiego.
  • REKLAMA
  • #5 8890019
    mirekk36
    Poziom 42  
    mati1988k napisał:
    .... zależy mi na tym aby to działało a próbowałem już chyba wszystkiego.


    Wszystkiego na pewno NIE ;)

    To ja ci poradzę jedną rzecz.

    Takie układy, programy (zresztą każde) uruchamia się krokami. A ty rzucasz się od razu na całość bez przejścia mniejszych kroków stąd twoje poważne problemy no i będą się tylko piętrzyć.

    Siadasz widzę do kompa - piszesz cały program (jakbyś grał na fortepianie jakąś etiudę G-Mol) - nie testując jego fragmentów a potem SKUCHA. "kurczę" NIC nie działa - hmmm "o co chodzi?", "pomóżcie"

    No to pomagamy ;)

    zrób pierwszy krok - i uruchom sterowanie samym serwomechanizmem tak żeby kręciło się cyklicznie od jednej skrajnej pozycji do drugiej powoli. Ot jakaś prosta pętelka ;) - i to wszystko - żadnych ADC na tym etapie.

    Jak wyjdzie to utwórz nowy projekt i tym razem "pomacaj" ADC - podłącz sobie np 8diod LED do wolnego portu albo jakiś wyświetlacz LCD , do tego potencjometr - no i napisz programik najprostszy możliwy żeby obserwować na tych diodach LED albo na LCD jak zmienia się wynik pomiaru przy kręceniu potencjometrem. Najlepiej jakbyś zrobił i na diodach LED i na LCD - da ci to większy trening ;)

    gdy to już wyjdzie

    ...... uuuuf - to teraz utwórz nowy projekt i napisz to co zamierzasz - GWARANTUJĘ że wtedy wyjdzie. Daję wręcz obciąć sobie głowę. (ale tylko wtedy gdy uprzednio w 100% zadziałają ci poprzednie kroki testowe). Powiem więcej wtedy nawet nie będziesz musiał zadawać dodatkowych pytań na elektrodzie. Ale oczywiście jeśli jakieś konkretne przyjdą do głowy to jak najbardziej proszę bardzo

    .... byle nie takie, że:

    "Panowie wklejam kod programu, powiedzcie mi proszę co tu jest źle?"
  • REKLAMA
  • #6 8890092
    mati1988k
    Poziom 13  
    Serwo działa bo robiłem właśnie tak jak napisałeś :).
    Teraz napisałem kod wysyłając po UARCIE wartość ADC i widzę że ma on cały czas wartość 1023.
    Teraz kod tak wygląda:
       
    	DDRD=0xFF;
    	PORTD=0x00;
    	DDRA=0x00;
    	PORTA=0x00;
    
    (...)
    
     ADCSRA = 0b00000000;
        ADMUX = 0b01000001;
        ADCSRA = 0b10000000;					 // Zacznij pierwsza konwersję
    	SFIOR = 0b00000000;
    
    	//while(bit_is_set(ADCSRA,ADSC)) {}
    
    	char buf[10];
    
    	int a=1000, ADCH_temp=0;
    
    while(1)
    	{
    
    		SetBit(ADCSRA,6);					// Konwersja
    		while(!(ADCSRA & 0x10)); 			// wait for conversion done, ADIF flag active
    		ADCSRA|=(1<<ADIF);
    
    
    		a = ADCL; 
    		ADCH_temp = ADCH;		
    		a +=(ADCH_temp << 8);
    
    		_delay_ms(1000);
    		sprintf(buf,"%d\n ", a);
    
    		send_string(buf);
    
    	}
  • #7 8890150
    mirekk36
    Poziom 42  
    Jak ja widzę tak pisany kod programu:
     ADCSRA = 0b00000000; 
        ADMUX = 0b01000001; 
        ADCSRA = 0b10000000;                // Zacznij pierwsza konwersję 
       SFIOR = 0b00000000; 
    
    
       TCCR1A=0b10001000; 
       TCCR1B=0b00010010; 


    to mnie odrzuca, zresztą wielu ludzi odrzuca - bo to masakra ;) i ciężko nawet skusić się żeby coś analizować i podpowiadać.

    czy nie czytelniej jest tak, jak to napisałeś w JEDNEJ tylko linijce?

    ADCSRA|=(1<<ADIF); 


    najwyraźniej sam wpadłeś we własną pułapkę tak niechlijnego pisania kodu, i któreś zero lub jedynka ci przeskoczyła a teraz klops ;)
  • Pomocny post
    #8 8890262
    zerpo
    Poziom 22  
    Może spróbuj tak:

        
    
    (...) 
    
    ADMUX = 1<<REFS0;	// AVCC, channel 0
    ADCSRA = 1<<ADEN | 1<<ADIF | 1<<ADPS2 | 1<<ADPS1 | 1<<ADPS0;
    
    char buf[10]; 
    int a=1000;
    
    while(1) 
       { 
    
          ADCSRA |=  1<<ADSC | 1<<ADIF;
          while(! (ADCSRA&(1<<ADIF)));   // czekaj na koniec konwersji
    
          a = ADC; 
          _delay_ms(1000); 
          sprintf(buf,"%d\n ", a); 
    
          send_string(buf); 
    
       }


    Ustawiłeś bity ADPSx na 0, czyli ADC jest taktowany zegarem/2, wartość powinno się ustawić zgodnie z datasheetem, sprawdź to. Wartość zależy częstotliwości jaką taktujesz procka. Chociaż nie wiem, czy akutat to powinno stwarzać problemy.
REKLAMA