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

[ATmega8][C] Kłopoty z detekcją zera, fazowa regulacja mocy.

boohoo 16 Wrz 2010 15:13 7245 12
REKLAMA
  • #1 8517055
    boohoo
    Poziom 12  
    Witam,

    Zbudowałem układ wykorzystujący mikroprocesor ATmega8 do sterowania mocą żarówki poprzez układ triak - optotriak. Wszystko działa w porządku, poza detekcją zera. W tym celu wykorzystuję podwójny transoptor PC814, jak na schemacie poniżej:
    [ATmega8][C] Kłopoty z detekcją zera, fazowa regulacja mocy.
    Pin nr 4 transoptora podłączam do INT1 mikrokontrolera. Napisałem gotowy program, jednak żarówka migała bądź świeciła się cały czas. Stworzyłem więc program testowy, który wskazuje, co jaki czas następuje przerwanie. Kod:
    ISR(INT1_vect) //dolutowane wyjście z transoptorów, zero-crossing
    {
    
     TCCR1B =0;
    
          zmienna1=TCNT1;
          itoa(zmienna1,nmb_to_str,10);
          write_text_RAM(nmb_to_str);
          write_text_RAM("\n\r");
     
     TCCR1B |= (1 << CS10);
    }
    

    Okazało się, że przerwania występują dokładnie co 83 cykle procesora, czyli co 8.3 [us]. To tłumaczy, czemu nie działał poprzedni program, jednak nie rozumiem, dlaczego te przerwania są tak częste.

    Czy ktoś ma jakiś pomysł i mógłby poratować? Z góry dzięki za pomoc.
    Pozdrawiam.
  • REKLAMA
  • #2 8517246
    Karol966
    Poziom 31  
    Zbudowałem taki układ:
    Transoptor PC814 przez rezystor 1,1 kOhm do uzwojenia wtórnego transformatora 18V AC, wyjście tzn emiter do masy a kolektor tak jak u Ciebie do uP ale z dodatkowym rezystorem podciągającym 510 Ohm do +5V. Układ działa w 100%. Wcześniej jak się okazało po obejrzeniu przebiegów na oscyloskopie był za duży rezystor przed transoptorem.
  • REKLAMA
  • #3 8517635
    landy13
    Poziom 31  
    Ustawiłeś odpowiednio rejestr MCUCR?
  • #4 8517716
    boohoo
    Poziom 12  
    Dzięki za odpowiedzi.
    landy13 napisał:
    Ustawiłeś odpowiednio rejestr MCUCR?
    Tak, wygląda to następująco:
    /////////////////////////////
    //Inicjalizacja INT0 i INT1//
    /////////////////////////////
    MCUCR |= (1 << ISC01) | (1 << ISC11);
    GICR |= (1 << INT0) | (1 << INT1);
    Nie mam już pomysłów, co może być nie tak. Podejrzewałem jakieś zakłócenia, ale przerwania wywoływane są zawsze dokładnie po 83 cyklach...
    Na pewno dużo ułatwiłoby przebadanie układu oscyloskopem, jednak nie mam aktualnie dostępu.
  • #5 8517765
    landy13
    Poziom 31  
    boohoo napisał:
    Podejrzewałem jakieś zakłócenia, ale przerwania wywoływane są zawsze dokładnie po 83 cyklach...


    Czyli sam podejrzewasz błąd programowy. A programu nie pokazujesz. Jakiej pomocy się spodziewasz?
  • REKLAMA
  • #6 8517841
    Konto nie istnieje
    Konto nie istnieje  
  • #7 8519414
    boohoo
    Poziom 12  
    Więc tak, napisałem program od nowa, zliczając tym razem przerwania INT1 i wywołując funkcję write_text_RAM() (wysyłającą dane po rs232) w przerwaniu TIMER1_OVF z odpowiednią wartością wpisaną do TCNT1. Okazało się, że jednak przerwania INT1 występują prawidłowo, co 0.01 [s].

    Wróciłem więc do programu sterującego mocą żarówki, który po znacznym uproszczeniu prezentuje się następująco:
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    #include <stdlib.h>
    
    
    #define SW1 2 //przyciski, port D
    #define SW2 3
    #define SW3 0 //przycisk, port B
    
    #define D1 2 //diody podłączone do pinów portu C
    #define D2 3
    
    #define LAMPA 5 //żarówka, port B
    #define RELAY 3 //przekaźnik, port B
    
    
    //unsigned int ttt=63036;
    unsigned int licznik=65500;
    
    ////////
    //MAIN//
    //////// 
    
    int main(void)
    {
    //////////////////////////////
    //Ustawienie kierunku portów//
    //////////////////////////////
    DDRC = (1 << D1) | (1 << D2);
    DDRB = (1 << LAMPA) | (1 << RELAY);
    
    PORTD = (1 << SW1) | (1 << SW2);
    PORTB = (1 << SW3) | (1 << LAMPA);
    
    /////////////////////////////
    //Inicjalizacja INT0 i INT1//
    /////////////////////////////
    MCUCR |= (1 << ISC01) | (1 << ISC11);
    GICR |= (1 << INT0) | (1 << INT1);
    
    ////////////////////
    //Inicjacja Timer1//
    ////////////////////
    TCNT1 = licznik;
    TIMSK |= 1 << TOIE1;
     
    
    sei();
    
    
    while(1);
     
    return 0;
    }
    /////////////////////////////////////////////////
    
    
    ISR(INT0_vect)
    {
     licznik=61488;
    }
    
    
    
    ISR(TIMER1_OVF_vect)
    {
     PORTB |= (1 << LAMPA);
     PORTC &= ~(1 << D1);
    }
    
    
    ISR(INT1_vect) //zero-crossing
    {
    
     PORTB &= ~(1 << LAMPA);
     PORTC |= (1 << D1);
     
     TCNT1 = licznik;
     TCCR1B |= (1 << CS10);
    }


    Niestety program nie działa prawidłowo. Co prawda dioda D1 reaguje jak należy - mogę wpływać na jasność, ale żarówka pozostaje cały czas włączona na 100% niezależnie od wartości TCNT1.

    Nie umiem znaleźć błędu, jeśli ktoś ma jakiś pomysł, będę wdzięczny.
    Pozdrawiam.
  • REKLAMA
  • #8 8519548
    Konto nie istnieje
    Konto nie istnieje  
  • #9 8521126
    boohoo
    Poziom 12  
    Dzięki za odpowiedź. Posiedziałem dziś trochę nad teorią i przeszukałem elektrodę, ale ciągle nie umiem poradzić sobie z problemem.

    Z tego co zrozumiałem, impuls na bramkę triaka powoduje, że przechodzi on w stan przewodzenia i przewodzi aż do momentu zaniku prądu (przejście przez zero). Wtedy triak przechodzi z powrotem w stan zaporowy.

    Podsumowując, żeby regulować moc żarówki, powinienem załączać triaka z odpowiednim, większym lub mniejszym opóźnieniem. Wyłączy się on automatycznie przy przejściu przez zero.

    Zmieniłem program, konkretnie dwie linijki w przerwaniach, ale żarówka dalej świeci na 100%. Prosiłbym o kolejne wskazówki.
    ISR(TIMER1_OVF_vect)
    {
     PORTB &= ~(1 << LAMPA);
     PORTC &= ~(1 << D1);
    }
    
    
    ISR(INT1_vect) //zero-crossing
    {
    
     PORTB |= (1 << LAMPA);
     PORTC |= (1 << D1);
     
     TCNT1 = licznik;
     TCCR1B |= (1 << CS10);
    }


    Pozdrawiam.
  • #10 8521249
    szelus
    Poziom 34  
    Dobrze zrozumiałeś. Tylko jeszcze wyłączać sygnał na bramce triaka musisz przed sygnałem z detektora zera. Ten ostatni pojawia się z zasady z pewnym opóźnieniem w stosunku do faktycznego przejścia przez zero. W rezultacie wyłączanie na ten sygnał powoduje "przeciągnięcie" sygnału na bramce na następny okres i może to być wystarczająco długo do ponownego otworzenia triaka.
  • #11 8523058
    ginar
    Poziom 21  
    tak, było to juz wiele razy, ale może coś jeszcze da się dopowiedzieć...

    sterujesz wg
    [ATmega8][C] Kłopoty z detekcją zera, fazowa regulacja mocy.

    w punkcie 2 podaj impuls (generowany w przerwaniu od timera) triak się wyłączy- jak pisałeś -zgodnie z rys. przy przejściu przez zero sieci; a nawet wcześniej => ze względu na parametr prąd podtrzymania. Z tego samego względu nie da się załączyć triaka z opóźnieniem t_offset = 0 czyli nie da się uzyskać jasności np. żarówki 100% - uwzględnij to w programie bo może się okazać że zamiast 100% jasności, będzie 0%.
    Sprawa się komplikuję jeżeli sterowanie urządzenie nie jest odbiornikiem czysto rezystancyjnym.
  • #12 8523752
    boohoo
    Poziom 12  
    Układ pięknie już działa :) Po wskazówce szelus wystarczyło przenieść jedną linijkę kodu w inne miejsce i zadziałało. Idealnie, bez żadnego migotania. Wielkie dzięki wszystkim za pomoc.

    Mam jeszcze ostatnie pytanie, dla świętego spokoju. Docelowo chcę zastąpić tradycyjny łącznik jednobiegunowy takim właśnie sterownikiem oświetlenia. Przewód fazowy z puszki włącznika podłączę do X2-2 (schemat z pierwszego postu), drugi przewód prowadzący do żyrandola do X2-1. Czy nie będzie niespodzianek i układ zadziała jak podczas testów z jedną żarówką?
  • #13 8527447
    niemy
    Poziom 14  
    Nie będzie. Pod warunkiem, że prąd pobierany przez żyrandol nie przekroczy max. prądu triaka, ale to chyba nie grozi w domowych warunkach ;-) i wszystkie żarówki bedą połączone równolegle.
REKLAMA