Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Analogowe wejście w atmedze8

mEatrikZ 06 Maj 2011 00:07 1634 25
  • #1 06 Maj 2011 00:07
    mEatrikZ
    Poziom 8  

    Próbuję nauczyć się używania ADC w atmedze8. Jako że z elektroniki jestem wybitnie amatorem, rozwiązanie może być idiotycznie proste.


    a więc: podłaczam potencjometr tak, jak tu:
    Analogowe wejście w atmedze8
    Wszystko jest podłączone do jednej i tej samej bateryjki, IMO błąd siedzi w programie. Program wygląda tak:

    Code:
    #include <avr/io.h>
    
    #define   F_CPU   8000000 
    #define   CYCLES_PER_US   ((F_CPU + 500000)/8000000)

    void delay(unsigned int us)
    {
       unsigned int delay_loops;
       register unsigned int i;
            delay_loops = (us+3)/5*CYCLES_PER_US;
       for(i=0;i<delay_loops;i++) {};
    }   
    void delay_ms(unsigned int ms)
    {
       unsigned int i;
       for(i=0;i<ms;i++)
       {
          delay(999);
       }
    }




    void inic(void)
    {
       DDRC = 0x00;      // Port jako wejścia
       PORTC = 0x00;      // Port C wejścia bez podciągania
       //DDR_F=0xF0;         // Młodsza połowa portu jako wejścia starsze cztery bity jako wyjścia
    //   PORT_F=0xFF;      // Wejścia z podciąganiem wyjścia w stanie wysokim
         
    // Wybranie wewnętrznego żródła napięcia odniesienia   
       ADMUX |= _BV(REFS0);     
       ADMUX |= _BV(REFS1);
    //   Wybranie sposobu zapisu wyniku z wyrównaniem do lewej (osiem starszych bitów wyniku w rejestrze ADCH)
       ADMUX |= _BV(ADLAR);     
    // Zezwolenie na konwersję   
       ADCSRA |= _BV(ADEN);     
    // Wybranie częstotliwości dla taktowania przetwornika  (1/8 częstotliwosci zegara kontrolera)
       ADCSRA |= _BV(ADPS0);   
       ADCSRA |= _BV(ADPS1);   //
       
    }


    int pomiar;

    int main(void)
    {
       DDRD = 0x00;

       

       
     inic();
       while (1)
       {
       
       
        ADCSRA |= _BV(ADSC);         // Rozpoczęcie przetwarzania
        while(bit_is_set(ADCSRA,ADSC))   // Oczekiwanie na zakończenie przetwarzania
        {};   
       pomiar=ADCH;

       if (pomiar < 250)
       {
       DDRD ^= _BV(PD5);
       }
       else
       {
       DDRD ^= _BV(PD6);   
       }
       delay_ms(10);
    //wejście


    //wyjście






    }
       return(0);
    }


    program świeci wszystkimi (trzema, na PD5, PD6 i PD7) diodami jaśniej lub ciemniej, zależy od tego jak wyreguluję to potencjometrem, czyli nie to do czego dążyłem. Co jest nie tak?

    0 25
  • #2 06 Maj 2011 00:42
    dondu
    Moderator Mikrokontrolery Projektowanie

    mEatrikZ napisał:
    ... czyli nie to do czego dążyłem. Co jest nie tak?

    A do czego dążyłeś?

    0
  • #3 06 Maj 2011 00:58
    mEatrikZ
    Poziom 8  

    Do odczytania wartości z potencjonometru i wyświetlenia jej na trzech diodkach LED.

    0
  • #4 06 Maj 2011 01:01
    dondu
    Moderator Mikrokontrolery Projektowanie

    I za rozróżnienie tych stanów jest odpowiedzialny ten fragment?

    Kod: c
    Zaloguj się, aby zobaczyć kod


    A czy wiesz do czego służy DDRD?
    Gdzie na schemacie są LEDy?

    0
  • #5 06 Maj 2011 01:04
    mEatrikZ
    Poziom 8  

    ten schemat, który dałem pokazuje tylko to, w jaki sposób podłączyłem potencjometr. Diody są podłączone ujemnym biegunem do nóżek PD5, PD6 i PD7.


    DDRD? Zapewne nie wiem, na moje to "włącza i wyłącza prąd" w danej nóżce.

    0
  • #6 06 Maj 2011 01:14
    dondu
    Moderator Mikrokontrolery Projektowanie

    Nie. DDRx określa kierunek pinu, czyli czy jest wejśceim czy wyjściem
    Jeżeli pin jest wyjściem to jego stan ustawiasz za pomocą PORTx czyli w Twoim przypadku PORTD bo korzystasz z pinów w porcie D.

    0
  • #7 06 Maj 2011 01:18
    mEatrikZ
    Poziom 8  

    Czyli zamiast "włączać diodki" z użyciem DDRD powinienem używać do tego celu PORTD. Ale co mam zrobić żeby mi zaczęło czytać wartość tegp potencjometru?

    0
  • #8 06 Maj 2011 01:23
    dondu
    Moderator Mikrokontrolery Projektowanie

    mEatrikZ napisał:
    Czyli zamiast "włączać diodki" z użyciem DDRD powinienem używać do tego celu PORTD.

    Tak.


    mEatrikZ napisał:
    Ale co mam zrobić żeby mi zaczęło czytać wartość tegp potencjometru?

    Powoli.
    Najpierw zrób porządnie ten fragment - jest z nim jeszcze inny problem, ale o Tym później.
    Skoro jesteś "wibitnie amatorem" to naprowadzę Cię na poprawne rozwiązanie - jeśli chcesz.


    Najpierw musisz prawidłowo ustawić kierunek pinów (jako wyjścia) za pomocą DDRD, tych pinów które są podłączone do diod LED.

    Powinieneś to zrobić zaraz na początku main() - jest tam rozkaz, ale zły.

    Dla ułatwienia podam, że 0 będzie oznaczać iż pin jest wejściem, a 1 że wyjściem.

    0
  • #9 06 Maj 2011 01:31
    mEatrikZ
    Poziom 8  

    To, że pod AREF i AVCC mam podłączone napięcie może coś zmieniać w kwestii tych diodek? Próbuję w różne sposoby, a efekt wciąż ten sam. Wcześniej robiłem wszystko bez napięcia pod tymi nóżkami i nawet moimi metodami działało tak jak powinno.

    0
  • #10 06 Maj 2011 01:37
    dondu
    Moderator Mikrokontrolery Projektowanie

    mEatrikZ napisał:
    Próbuję w różne sposoby, a efekt wciąż ten sam.

    Nie próbuj, tylko czytaj co piszę wprowadź zmianę i wklej kod, bym mógł go sprawdzić.
    AREF zostaw na potem. Na razie podstawa czyli LEDy.


    mEatrikZ napisał:
    ... i nawet moimi metodami działało tak jak powinno.

    Chcesz zrobić poprawnie czy byle coś działało?
    Jeżeli to drugie to efekt już masz.

    0
  • #11 06 Maj 2011 01:43
    mEatrikZ
    Poziom 8  

    Code:

    #include <avr/io.h>
    #define   F_CPU   8000000
    #define   CYCLES_PER_US   ((F_CPU + 500000)/8000000)

    void delay(unsigned int us)
    {
       unsigned int delay_loops;
       register unsigned int i;
            delay_loops = (us+3)/5*CYCLES_PER_US;
       for(i=0;i<delay_loops;i++) {};
    }   
    void delay_ms(unsigned int ms)
    {
       unsigned int i;
       for(i=0;i<ms;i++)
       {
          delay(999);
       }
    }




    void inic(void)
    {
       DDRC = 0x00;      // Port jako wejścia
       PORTC = 0x00;      // Port C wejścia bez podciągania
       //DDR_F=0xF0;         // Młodsza połowa portu jako wejścia starsze cztery bity jako wyjścia
    //   PORT_F=0xFF;      // Wejścia z podciąganiem wyjścia w stanie wysokim
         
    // Wybranie wewnętrznego żródła napięcia odniesienia   
       ADMUX |= _BV(REFS0);     
       ADMUX |= _BV(REFS1);
    //   Wybranie sposobu zapisu wyniku z wyrównaniem do lewej (osiem starszych bitów wyniku w rejestrze ADCH)
       ADMUX |= _BV(ADLAR);     
    // Zezwolenie na konwersję   
       ADCSRA |= _BV(ADEN);     
    // Wybranie częstotliwości dla taktowania przetwornika  (1/8 częstotliwosci zegara kontrolera)
       ADCSRA |= _BV(ADPS0);   
       ADCSRA |= _BV(ADPS1);   //
       
    }


    int pomiar;

    int main(void)
    {
       DDRD = 0x00;

       

       
     inic();
       while (1)
       {
       
       
        ADCSRA |= _BV(ADSC);         // Rozpoczęcie przetwarzania
        while(bit_is_set(ADCSRA,ADSC))   // Oczekiwanie na zakończenie przetwarzania
        {};   
       pomiar=ADCH;

       if (pomiar < 250)
       {
    PORTD |= (1<<5);   
       }
       else
       {
    PORTD |= (1<<6);   
       }

    //tu się zaczynają śmieci testujące czy coś w ogóle migocze
       delay_ms(100);
       
      PORTD |= (1<<6);   
    delay_ms(100);
      PORTD |= (0<<6);
      //a tu się kończą


    //wyjście






    }
       return(0);
    }


    google mi tak podpowiedziały.

    Cytat:
    Chcesz zrobić poprawnie czy byle coś działało?
    Jeżeli to drugie to efekt już masz.

    Nie chodziło mi o to, że chcę w ten sposób zrobić tylko dziwił mnie fakt, że na poprzedniej płytce wszystko było dobrze, a na tej już się w ten sposób nie da.

    0
  • #12 06 Maj 2011 01:45
    dondu
    Moderator Mikrokontrolery Projektowanie

    mEatrikZ napisał:
    google mi tak podpowiedziały.

    To niech Ci dalej Google podpowiada... powodzenia.

    0
  • #13 06 Maj 2011 01:46
    mEatrikZ
    Poziom 8  

    Nie mam pojęcia, mam po prostu zamienić:
    DDRD ^= _BV(PD6);
    na
    PORTD ^= _BV(PD6);

    ?

    0
  • Pomocny post
    #15 06 Maj 2011 12:29
    skalsky5000
    Poziom 20  

    Code:

    int pomiar;

    int main(void)
    {
       DDRD = 0x00;

       

       
     inic();
       while (1)
       {
       

    W tym momencie masz piny jako wejścia zmień na DDRD = 0xFF;

    0
  • #16 06 Maj 2011 15:05
    mEatrikZ
    Poziom 8  

    Dzięki! Teraz już nie wygaszają się, świecą tak jak program przykazał...


    ...acz działa to w ten sposób, że kiedy powinny nie świecić świecą ciemniej, kiedy powinny świecić świecą jaśniej. <- tak było, jak robiłem moje amatorskie świecenie na DDRD.


    W tej chwili kod wygląda tak:

    Code:
    #include <avr/io.h>
    
    #define   F_CPU   8000000
    #define   CYCLES_PER_US   ((F_CPU + 500000)/8000000)

    void delay(unsigned int us)
    {
       unsigned int delay_loops;
       register unsigned int i;
            delay_loops = (us+3)/5*CYCLES_PER_US;
       for(i=0;i<delay_loops;i++) {};
    }   
    void delay_ms(unsigned int ms)
    {
       unsigned int i;
       for(i=0;i<ms;i++)
       {
          delay(999);
       }
    }

    void inic(void)
    {
       DDRC = 0x00;      // Port jako wejścia
       PORTC = 0x00;      // Port C wejścia bez podciągania
       //DDR_F=0xF0;         // Młodsza połowa portu jako wejścia starsze cztery bity jako wyjścia
    //   PORT_F=0xFF;      // Wejścia z podciąganiem wyjścia w stanie wysokim
         
    // Wybranie wewnętrznego żródła napięcia odniesienia   
       ADMUX |= _BV(REFS0);     
       ADMUX |= _BV(REFS1);
    //   Wybranie sposobu zapisu wyniku z wyrównaniem do lewej (osiem starszych bitów wyniku w rejestrze ADCH)
       ADMUX |= _BV(ADLAR);     
    // Zezwolenie na konwersję   
       ADCSRA |= _BV(ADEN);     
    // Wybranie częstotliwości dla taktowania przetwornika  (1/8 częstotliwosci zegara kontrolera)
       ADCSRA |= _BV(ADPS0);   
       ADCSRA |= _BV(ADPS1);   //
       
    }


    int pomiar;

    int main(void)
    {
       DDRD = 0xFF;
       DDRD ^= _BV(PD7);
       

       
     inic();
       while (1)
       {
       
       
        ADCSRA |= _BV(ADSC);         // Rozpoczęcie przetwarzania
        while(bit_is_set(ADCSRA,ADSC))   // Oczekiwanie na zakończenie przetwarzania
        {};   
       pomiar=ADCH;

       if (pomiar < 250)
       {
       PORTD |= (0<<PD5);
       delay_ms(10);
       PORTD |= (1<<PD5);
       }
       else
       {
       PORTD |= (0<<PD6);
       delay_ms(10);
       PORTD |= (1<<PD6);
       }
       delay_ms(10);
    //wejście


    //wyjście






    }
       return(0);
    }

    i po włączeniu układu świeci tą diodką którą powinno, zależnie od ustawienia potencjometru, ale jeżeli przestawię potencjometr nie wyłączając układu przestanie świecić którąkolwiek diodką. Co jest?

    0
  • Pomocny post
    #17 06 Maj 2011 15:34
    piotrva
    Moderator na urlopie...

    bo nie masz wygaszania diodek:

    Code:

     if (pomiar < 250)
       {
       PORTD |= (0<<PD5);//zapalamy pd5
       PORTD &= ~(1<<PD6);//gasimy pd6
       }
       else
       {
       PORTD |= (0<<PD6);//zapalamy pd6
       PORTD &= ~(1<<PD5);//gasimy pd5
       }
       delay_ms(10);

    PS. czemu nie używasz biblioteki util/delay.h do opóźnień?

    0
  • #18 06 Maj 2011 15:45
    mEatrikZ
    Poziom 8  

    Teraz niezależnie od ustawienia potencjometru świecą wszystkie trzy. Może powinienem odwrócić diody? Plus do nóżki procka, minus do minusa baterii (i przestawić trochę w programie)?

    Nie używam tej biblioteki bo mi w kompilatorze wywala jakieś warningi. Poza tym, co w niej jest tam lepszego od tej "mojej"?


    EDIT:
    Zadziałało:

    Code:
    #include <avr/io.h>
    
    // #define   F_CPU   8000000
    // #define   CYCLES_PER_US   ((F_CPU + 500000)/8000000)

    // void delay(unsigned int us)
    // {
       // unsigned int delay_loops;
       // register unsigned int i;
            // delay_loops = (us+3)/5*CYCLES_PER_US;
       // for(i=0;i<delay_loops;i++) {};
    // }   
    // void delay_ms(unsigned int ms)
    // {
       // unsigned int i;
       // for(i=0;i<ms;i++)
       // {
          // delay(999);
       // }
    // }

    // void inic(void)
    // {
       // DDRC = 0x00;      // Port jako wejścia
       // PORTC = 0x00;      // Port C wejścia bez podciągania
       DDR_F=0xF0;         // Młodsza połowa portu jako wejścia starsze cztery bity jako wyjścia
      PORT_F=0xFF;      // Wejścia z podciąganiem wyjścia w stanie wysokim
         
    Wybranie wewnętrznego żródła napięcia odniesienia   
       // ADMUX |= _BV(REFS0);     
       // ADMUX |= _BV(REFS1);
      Wybranie sposobu zapisu wyniku z wyrównaniem do lewej (osiem starszych bitów wyniku w rejestrze ADCH)
       // ADMUX |= _BV(ADLAR);     
    Zezwolenie na konwersję   
       // ADCSRA |= _BV(ADEN);     
    Wybranie częstotliwości dla taktowania przetwornika  (1/8 częstotliwosci zegara kontrolera)
       // ADCSRA |= _BV(ADPS0);   
       // ADCSRA |= _BV(ADPS1);   //
       
    // }


    // int pomiar;

    // int main(void)
    // {
       // DDRD = 0xFF;
       

       

     // inic();
       // while (1)
       // {
       
       

       
        // ADCSRA |= _BV(ADSC);         // Rozpoczęcie przetwarzania
        // while(bit_is_set(ADCSRA,ADSC))   // Oczekiwanie na zakończenie przetwarzania
        // {};   
       // pomiar=ADCH;




       // PORTD |= (1<<PD5);
       // PORTD |= (1<<PD6);
       // PORTD |= (1<<PD7);

       // delay_ms(10);

       
        // if (pomiar < 250)
       // {
       // PORTD |= (0<<PD5);//zapalamy pd5
       // PORTD &= ~(1<<PD6);//gasimy pd6
       // }
       // else
       // {
       // PORTD |= (0<<PD6);//zapalamy pd6
       // PORTD &= ~(1<<PD5);//gasimy pd5
       // }
       // delay_ms(10);
    wejście


    wyjście






    // }
       // return(0);
    // }

    Dzięki wszystkim za pomoc : )

    0
  • #19 06 Maj 2011 16:09
    skalsky5000
    Poziom 20  

    Masz jeszcze 1 błąd.Czytasz najpierw ADCH , a w nocie jak byk pisze ze najpierw czyta sie ADCL a potem ADCH.Wczytaj ADCL do jakieś zmiennej przed ADCH

    0
  • #20 06 Maj 2011 16:17
    asembler
    Poziom 32  

    Jak chodzi o błędy to trzeba zacząć od schematu. Do Vref mozna podłączyć kondensator ale nigdy nie łączyć z Vcc bo robisz zwarcie w pewnych przypadkach np takich jak tutaj

    0
  • #21 06 Maj 2011 16:25
    kult
    Poziom 16  

    asembler napisał:
    Jak chodzi o błędy to trzeba zacząć od schematu. Do Vref mozna podłączyć kondensator ale nigdy nie łączyć z Vcc bo robisz zwarcie w pewnych przypadkach np takich jak tutaj

    WTF?

    0
  • #22 06 Maj 2011 16:33
    skalsky5000
    Poziom 20  

    asembler a jak to ma się do fusów skoro można wewnętrznie połączyć AVCC z AVREF ?? i napięcia zasilania używać jako referencyjnego.

    0
  • #23 06 Maj 2011 16:35
    mEatrikZ
    Poziom 8  

    w sumie to w tej chwili nie mam już nic podłączonego do VREF i jakoś działa : |

    0
  • #24 06 Maj 2011 16:47
    skalsky5000
    Poziom 20  

    Masz ustawione na wewnętrzne napięcie,daj kondensator 100nF do masy na pinie VREF.

    0
  • #25 06 Maj 2011 16:53
    asembler
    Poziom 32  

    skalsky5000 napisał:
    asembler a jak to ma się do fusów skoro można wewnętrznie połączyć AVCC z AVREF ?? i napięcia zasilania używać jako referencyjnego.

    Nie wiem o co ci chodzi.

    0
  • #26 06 Maj 2011 16:58
    skalsky5000
    Poziom 20  

    Ok sorki teraz czaje o co ci chodziło moja pomyłka.

    0