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] Atmega16 + TSOP1736 + LD271

Tomu$L 15 Lut 2011 10:52 4131 27
REKLAMA
  • #1 9154231
    Tomu$L
    Poziom 11  
    Witam

    Podpinam odbiornik TSOP1736 do atmegi16 zgodnie ze schematem:
    [C] Atmega16 + TSOP1736 + LD271

    Jako nadajnik używam diody LD271. Dioda świeci widać to w aparacie.

    Do procesora wrzucam kod który generuje mi 36kHz dla diody i odczytuje sygnał z odbiornika.

    
    // IR LED is connected to PORTC3,  
    // output of TSOP is connected to PORTC4.  
    
    volatile static unsigned char flag=0b00000000 ; 
    volatile  unsigned char  pulses=0;                       
     
    ISR(TIMER2_COMP_vect) 
     {PORTC=PORTC^(flag);                                                                  
     pulses++;  
      }; 
     
     
    // main program  
     
    int main (void) 
    {  
    
    DDRC=0b00001000; 
    DDRD=0b00000001;  
     
    TCCR2=0b00001010; 
    OCR2=139; 
     
    TIMSK|= (1<<(OCIE2));  
    sei();                                  
     
     while(1)
    {  
      
        if ((pulses>=25)&&(bit_is_set(flag,3))) 
       { 
           pulses=0;  
           flag=flag&0b11110111;
        } 
    
       if ((pulses>=60)&&(bit_is_clear(flag,3))) 
       {  
           pulses=0; 
           flag=flag|0b00001000;
       } 
      
        if (bit_is_clear(PINC,4))  
        {
            PORTD=(PORTD|0b00000001);
        }  
             
        else 
        {
           PORTD=(PORTD&0b11111110);
        }
     }
    }
    


    Wydaje mi się że powinno działać ale niestety tak nie jest. Ma ktoś jakiś pomysł jak to rozwiązać??

    Pozdrawiam
    Tomek
  • REKLAMA
  • #2 9154312
    piotrva
    VIP Zasłużony dla elektroda
    nie wiem czy dobrze myślę, ale to nie ma szans działać, bo procesor jednocześnie nie nadaje i odbiera...
  • #3 9154575
    Tomu$L
    Poziom 11  
    no właśnie teraz tak myślę nad tym i chyba masz racje, tylko jak to rozwiązać. Mam zrobiony generator na ne555 ale nie wiem czy na pewno działa tak jak należy dlatego chciałem generować z uC i sprawdzić czy odbiornik działa prawidłowo.
  • #4 9154632
    LordBlick
    VIP Zasłużony dla elektroda
    Sprawdzaj czy wejście z wyjściem się zgadza w przerwaniu. Możesz sobie nawet liczyć ile zgodności i niezgodności jest.
  • #5 9157094
    Tomu$L
    Poziom 11  
    Stworzyłem coś takiego, ale niestety już dzisiaj nie przetestuje. Czy Waszym zdaniem będzie to działało??

    
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    
    SIGNAL(SIG_INTERRUPT0) 
    { // przerwania dla TSOPa  
        PORTA=0xFF; 
    } 
    
    ISR(TIMER1_COMPA_vect) 
    { 
            PORTD ^= (1 << PD7); // zmiana stanu diody Led 
    } 
    
    int main(void) 
    { 
        
        PORTD |= (1<<PD2); // TSOP Out 
        
    	DDRA = 0xFF;
        
        DDRD |= (1<<PD7); // Dioda IR 
    
        
        TCCR1B |= (1 << WGM12);// Ustawia timer w tryb CTC 
        OCR1A = 111;             // Ustawia wartość pożądaną na 36Hz dla preskalera 1: 
                                // (1/36000)/(1/8000000) = 222,222.. / 2 = 111 
        TCCR1B |= (1 << CS10); // Ustawia timer z preskalerem Fcpu/1 
        TIMSK |= (1 << OCIE1A);// Obsluga przerwan dla timera 
        
        
        // ustawienie przerwania na zbocze opadajace, uruchomienie przerwan 
        MCUCR &= ~ISC00; 
        MCUCR |= ISC01; 
        GICR = (1<<INT0); 
        
        
        _delay_ms(1000); 
        sei(); 
        
    
        while (1) 
    	{ 
                
            TIMSK |= (1 << OCIE1A);     // wlacz przerwanie IR 
            _delay_us(800);                // DEL1 - pusc sygnal IR 36kHz 
            TIMSK &= ~(1 << OCIE1A);    // wylacz przerwanie IR 
            _delay_us(10000);             // DEL2 - odczekaj do nastepnego sygnalu 
        
        } 
        
    } 
    
    
  • #6 9157337
    mirekk36
    Poziom 42  
    piotrva napisał:
    nie wiem czy dobrze myślę, ale to nie ma szans działać, bo procesor jednocześnie nie nadaje i odbiera...


    Ma szanse działać ;) zapewniam cię. Tylko trzeba to dobrze oprogramować. Wprawdzie sam kiedyś tak myślałem ale ostatnio aż się zdziwiłem że kody wygenerowane w podczerwieni z diody IR (za pomocą zresztą programu z PC'ta, który przez USART wysyłał polecenia nadawania kodów) .... zostały jednocześnie odebrane przez odbiornik podczerwieni i ładnie wyświetlone na LCD ;)

    Tyle że obsługa odbioru podczerwieni była zrobiona na przerwaniu ICP od Timer1 ;) a do nadawania wykorzystywany był Timer0 w celu odliczania opóźnień impulsów a jeszcze Timer2 generował mi sprzętowo nośną 36kHz ;)

    Więc na pewno da się zrobić. Nawet jest to opisane w pewnej książce ;)
  • REKLAMA
  • #7 9158761
    Tomu$L
    Poziom 11  
    Patrzył ktoś może na ten program??
  • REKLAMA
  • #8 9159211
    LordBlick
    VIP Zasłużony dla elektroda
    Ktoś na pewno patrzał... Kod po kompilacji i zaprogramowaniu µC będzie działać, a czy zgodnie z założeniami, to nie wiem, bo ich dokładnie to nie podałeś...
  • REKLAMA
  • #9 9159804
    Tomu$L
    Poziom 11  
    Sprawdziłem to wczoraj i coś świruje. Dzisiaj kupuje nowy odbiornik może ten jest zepsuty.
  • #10 9162893
    LordBlick
    VIP Zasłużony dla elektroda
    Się nie zrozumieliśmy...
    Nie podałeś, co chcesz tym kodem osiągnąć, a pytasz czy zadziała...
    "coś świruje" - to nie jest opis problemu w sposób jasny i logiczny...
  • #11 9163096
    Tomu$L
    Poziom 11  
    Generalnie to ma być bariera podczerwieni. Na diodę generuje timerem częstotliwość 36 kHz a odbiornik ma odbierać wiązkę. Jeśli odbierze to nic nie robi a jak nie dotrze wiązka to przerywa program i wystawia sygnał na porcie. Problem jest taki że odbiornik na wyjściu ma cały czas ten sam stan czy go naświetlam czy nie.
  • #12 9163433
    LordBlick
    VIP Zasłużony dla elektroda
    Po tym wyjaśnieniu mogę stwierdzić, co następuje :
    1. Daj sobie siana z "SIGNAL(SIG_INTERRUPT0)". Poza tym, dlaczego używasz starej konwencji przerwań, skoro w przerwaniu od timera jest już nowa ?
    2. Bezpośrednio w przerwaniu ISR(TIMER1_COMPA_vect) przy gaszeniu bitu sprawdzaj, czy stan na PORTC4 jest niski (odbiornik oświetlony IR) - jeśli tak, to oznacza, że nie ma przeszkody po drodze, a jeśli wysoki, to znaczy, że jest. Zapisujesz to do jakiejś zmiennej z atrybutem volatie i masz status na bieżąco w pętli głównej.
    3. Bez oscyloskopu nie podchodź do zabawy...
    P.S. Mam podobny problem już rozwiązany, tyle że układ odbiornika (dwa tory bariery) kosztował mnie dużo taniej (fototranzystor 0,30 zł, kilka elementów biernych i komparator lm393 0,50 zł).
  • #13 9163464
    Tomu$L
    Poziom 11  
    A na jaką odległość działa Ci ten fototranzystor??
  • #14 9163468
    LordBlick
    VIP Zasłużony dla elektroda
    W docelowym urządzeniu na pewno 70 cm. Więcej nie testowałem, bo nie było takiej potrzeby. Zawsze można zwiększyć moc w nadajniku. Skoro jednak temat jest o TSOP1763, to proponuję dokończyć doświadczenie, bo i tak rdzeń rozwiązania jest w oprogramowaniu...
  • #15 9163505
    y0yster
    Poziom 19  
    Trzeba najpierw zacząć od wykorzystania funkcji opóźniających.
    Dla _delay_us() masz coś takiego:

    Cytat:
    The maximal possible delay is 768 us / F_CPU in MHz.

    If the user requests a delay greater than the maximal possible one,
    _delay_us() will automatically call _delay_ms() instead. The user
    will not be informed about this case.


    Używanie za dużych liczb w argumencie funkcji nie ma sensu jeśli zależy Ci na większej precyzji.

    Co do generowania 36kHz. Sprawdź oscyloskopem, czy generuje Ci się sygnał na zadanym wyjściu.
  • #16 9163530
    Tomu$L
    Poziom 11  
    Właśnie w tym jest problem że nie mam dostępu do oscyloskopu tak to od razu wyjście było by sprawdzone.
  • #17 9163546
    y0yster
    Poziom 19  
    To w takim razie możesz jeszcze sprawdzić sobie odbiornik.
    Zmontuj sobie prosty układ. Wyjście odbiornika daj na tranzystor, a następnie świeć na niego pilotem. Jak będzie ci mrugać to znaczy, że odbiornik jest w porządku.
  • #18 9163578
    Tomu$L
    Poziom 11  
    Wiem wiem ale na mieszkaniu niestety nie mam żadnego pilota dopiero w weekend to sprawdzę. Dziękuje za zainteresowanie.
  • #19 9163668
    y0yster
    Poziom 19  
    Skoro nie masz pilota, to możesz przetestować to jeszcze w inny sposób.
    W programie daj sobie zwykłe załączanie diody na opóźnieniach.

    
    for(;;)
    {
    _delay_us(12);
    sbi( PORTX, PXY);
    _delay_us(12);
    cbi( PORTX, PXY);
    }
    


    Po takim zabiegu będziesz miał na wyjściu "jakiś" sygnał o f=40kHz. To jest pi razy drzwi, ale odbiornik powinien, Ci to odbierać.

    W sumie w taki sposób nie sprawdzisz w pełni odbiornika, bo może Ci się zapchać zgodnie z tym, co jest napisane w datasheet'cie.
  • #20 9182727
    Tomu$L
    Poziom 11  
    Witam ponownie. Podłączyłem nowy odbiornik zgodnie ze schematem w dokumentacji. Na wyjściu dałem diodę. Oświetlałem odbiornik pilotem i widać było zmianę na diodzie, mrugała. Jednak po podpięciu do uC i zastosowaniu funkcji if(bit_is_set......) miało zapalić diodę, nic się nie zmieniało.
  • #22 9187385
    Tomu$L
    Poziom 11  
    Kodu jako takiego to za wiele nie było. Poza sprawdzaniem stanu na jednym pinie i wyświetleniu na drugim porcie.

    
    
    int main (void)
    { 
    
    DDRD=0x00;
    DDRA = 0xFF;                           
     
     while(1)
    { 
     
        if (bit_is_clear(PIND, 0))
       {
           PORTA=0xFF;
        }
       else
       PORTA=0x00;
       
    } 
    


    Coś takiego to było.

    Dorzucam jeszcze schemat do tsop, oczywiście out do uP podłączone.
    [C] Atmega16 + TSOP1736 + LD271
  • #24 9189352
    Tomu$L
    Poziom 11  
    No właśnie powinno być wszystko ok i to jest w tym najdziwniejsze. Nie żadnej optymalizacji nigdy nie używam.
  • #25 9189972
    janbernat
    Poziom 38  
    
    #include <avr/io.h>
    
    int main (void)
    {
    
    DDRD=0x00;
    DDRA = 0xFF;                           
     
    while(1)
    {
    	if (bit_is_clear(PIND, 0))
    	{
           PORTA=0xFF;
        }
    	else
    	PORTA=0x00;
    } 
    }
     
    

    Działa.
    Ale w wersji przycisk/dioda LED.
    A nie TSOP i dioda- bo nie mam zmontowanego układu.
    Zastanawiam się czy nie kręcisz się za własnym ogonem.
    Sprawdzasz stan odbiornika- nie jest taki jak ma być- przechodzisz do else- które znowu wystawia stan wysoki itd.
  • #26 9190720
    y0yster
    Poziom 19  
    Według mnie nie jest to powód niepoprawnego działania. Diodę powinno dać się zauważyć. uC pełni tylko rolę przekaźnika, a że robi to relatywnie szybko nie powinno to stanowić problemu.
    Można się upewnić, czy tutaj rzeczywiście coś się dzieje nie tak. Po prostu, wystarczy wstawić część odpowiedzialną za włączenie diody jeśli będzie jakiś sygnał.

    #include <avr/io.h>
    
    int main (void)
    {
    
    DDRD=0x00;
    DDRA = 0xFF;                           
     
    while(1)
    {
       if (bit_is_clear(PIND, 0))
       {
           PORTA=0xFF;
        }
    }
    } 


    Natomiast jeśli jest dużo zakłóceń nic Ci nie da takie postępowanie.
    Wystarczy:

    #include <avr/io.h>
    
    int main (void)
    {
    
    DDRD=0x00;
    DDRA = 0xFF;                           
     
    while(1)
    {
       if (bit_is_clear(PIND, 0))
       {
           PORTA=0xFF;
           
           _delay_ms(200);
        }
       else
       PORTA=0x00;
    }
    } 


    Teraz na pewno coś zauważysz.
  • #27 9195523
    Tomu$L
    Poziom 11  
    janbernat napisał:

    Działa.
    Ale w wersji przycisk/dioda LED.
    A nie TSOP i dioda- bo nie mam zmontowanego układu.
    Zastanawiam się czy nie kręcisz się za własnym ogonem.
    Sprawdzasz stan odbiornika- nie jest taki jak ma być- przechodzisz do else- które znowu wystawia stan wysoki itd.


    Dla przycisku działa, wiem bo też to sprawdzałem. Ale to ma działać na TSOP nie na przycisk ;p Dobrze by było jakby to ktoś przetestował na swoim TSOP jak ma układzik.
  • #28 9196496
    Tomu$L
    Poziom 11  
    Zrobiłem takiego myka i wydaje się że wszystko działa tak jak należy.

    
    #include<avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    #include <inttypes.h>
    #include <util/delay.h>
    
    
    int main(void)
    {
     DDRD=0x00; 
     DDRB = 0xFF;
     DDRA |= _BV(PA0);
     PORTA |= _BV(PA0);
    
     TCNT0 = 34; //wartość początkowa dla timer0
     TCCR0 = (1 << CS00);   //| (1 << CS00); // 0b00000111; prescaler na 1
     TIMSK |= (1 << TOIE0);  // aktywne przerwanie overflow
    
     while(1) 
    { 
       if (bit_is_clear(PIND, 0)) 
       { 
           PORTB=0xFF; 
            
           _delay_ms(200); 
        } 
       else 
       PORTB=0x00; 
    } 
    
     return(0);
    }
    
     SIGNAL (SIG_OVERFLOW0)
     {
      TCNT0 = 34;
      PORTA ^= (1 << PA0);
     }
    
    
    


    Tylko jest jeden problem. Jak świece na odbiornik to diody na porcie B świecą ale co delay(200) gasną i potem znów świecą. A ja potrzebuje że jak świece na odbiornik to diody świecą bez żadnego mrugnięcia a jak nie świece do i diody milczą.
REKLAMA