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.

[Bascom] Sterowanie fazowe - procedura nie chce zadziałać

MES Mariusz 11 Lis 2008 21:02 4930 13
  • #1 11 Lis 2008 21:02
    MES Mariusz
    Poziom 36  

    Witam.

    Napisałem sobie prosty program do sterowania fazowego:

    Code:
    $crystal = 8000000
    
    $regfile = "8515def.dat"

    Detfazy Alias Pinb.1
    Config Detfazy = Input

    Q2 Alias Portc.1
    Config Pinc.1 = Output 

    Config Timer1 = Timer , Prescale = 8

    Stop Timer1
    On Timer1 Irq_t1                                            ' jeśli nastąpi przerwanie od timera Timer1 wykonaj procedurę Irq_t1

    Enable Timer1
    Enable Interrupts

    Do
     Bitwait Detfazy , Set
     Q2 = 1
        Load Timer1 , 60536                                     'ustawia wartość do której zlicza Timer1
        Start Timer1                                            ' ponownie włącza odliczanie Timer1
    Loop


    Irq_t1:
       Q2 = 0                                                   ' włącza triak
       Stop Timer1                                              ' zatrzymuje odliczanie
    Return



    Teoretycznie jest bardzo prosty:

    1. Program czeka aż na wyprowadzeniu detfazy ustali się stan wysoki (detekcja przejścia przez zero)

    2. Program uruchamia timer opóźniający. Do jego rejestru wpisano wartość 60536 co spowoduje, że timer odliczy 65536 - 60536 = 5000 taktów. Rezonator ma wartość 8MHz zatem 1 takt trwa 0,125 us. Ponieważ na wejściu zliczającym zegar jest dzielony przez 8 (prescale = 8) zliczenie 5000 taktów spowoduje rzeczywiste opóźnienie 5 ms. Takie opóźnienie sprawi, że do obciążenia zostanie przekazane 50% mocy.

    3. Gdy timer przepełni się nastąpi przerwanie i włączy się triak.

    4. Gdy na wejściu detfazy wykryty zostanie stan przejścia przez zero triak zostanie zgaczony

    5 powrót do punktu 1


    Niestety z jakiegoś powodu proram nie chce zadziałać. Triak cały czas pozostaje w stanie wygaszenia.

    Ktoś podpowie mi coś mądrego?

    Żeby nie było wątpliwości na detfazy mam prawidłowy przebieg prostokątny sprawdzony oscyloskopem, triak Q2 daje się włączać 'z palca' ( q2=0 ).

    0 13
  • #2 11 Lis 2008 21:20
    crazy_phisic
    VIP Zasłużony dla elektroda

    Jak długo trwa stan wysoki na "detfaza"? Możliwe że bitwait się zapętliło.

    "When using bit variables make sure that they are set/reset by software otherwise your program will stay in a loop."

    0
  • #3 12 Lis 2008 00:31
    mirley
    Poziom 17  

    Witam

    Wydaje mi się że linijka:

    Code:

    Load Timer1 , 60536                                   


    Ustawia Timer do zliczania 60536 a nie 5000 ponieważ Load Timer x ładuje do licznika wartość 65536 -x. Prawidłowy wpis to:

    Code:

    Load Timer1 , 5000                                 


    lub

    Code:

    Timer1 = 60536                               


    Ja zawsze używam tej drugiej wersji więc jestem na 99% pewien tego load Timer

    1
  • #4 16 Lis 2008 20:51
    MES Mariusz
    Poziom 36  

    crazy_phisic napisał:
    Jak długo trwa stan wysoki na "detfaza"? Możliwe że bitwait się zapętliło.

    "When using bit variables make sure that they are set/reset by software otherwise your program will stay in a loop."

    Oscyloskop poszedł w ruch...

    Więc tak: przebieg prostokątny: 10% stan wysoki, 90% stan niski. Przejście przez zero następuje dwa razy w jednym okresie sinusoidy, zatem okres od jednego przejścia przez zero do drugiego przejścia przez zero trwa 10 ms, i to się zadza (pomiary oscyloskopowe).

    Wynika z tego, że stan wysoki trwa ok. 1 ms, stan niski 9 ms.

    Czyżby to były zbyt małe czasy dla prawidłowego działania funkcji bitwait?


    --- edit ---

    Rzeczywiście, zastosowanie pisowni Timer1 = 60536 zmieniło sytuację. Do obciążenia prawdopodobnie przekazywane jest teraz ok. 50% mocy, ale... Żarówka paskudnie miga jak na tym filmie (tyle, że bardziej równomiernie).

    Dziwi mnie jednak przebieg wyjściowy (powinno być 5 ms opóźnienia / wyłączenia, i włączenie, które trwa również 5 ms).

    Tymczasem, o ile przebieg na wejściu jest prawidłowy ( film: przebieg na wejściu ) / okres 10 ms, podstawa czasu 5 ms, dwie działki /

    o tyle na pinie włączającym (stanem "0") triak sygnał jest taki: ( film: przebieg na wyjściu ) / sensowny sygnał daje się zaobserwować przy ustawieniu 10 ms / dz, stan wysoki trwa 6,5 działki, stan niski 0,5 działki, a 7 działek x 10 ms daje... 70 ms ???

    Coś tu jest nie tak...

    0
  • #5 16 Lis 2008 22:31
    mirekk36
    Poziom 42  

    Proponuję ci absolutnie zrezygnować z takiej konstrukcji Do Loop i Bitwait w środku, zauważ, że już tu będziesz miał ogromne rozbieżności jeśli chodzi o czas załączania triaka, bo przecież stan wysoki twojej detekcji ZERA ileś tam sobie trwa, w tym czasie twoja pętla Do Loop przekręca się ileś tam (mnóstwo) razy i za każdym razem od nowa ustawia Timer1 czyli generalnie efekt końcowy jest mniej więcej taki, że procek wykonuje dużo niepotrzebnej roboty a dopiero jak funkcja BitWait przestanie wykrywać stan wysoki czyli nastąpiło już zbocze opadające to dopiero wtedy zaczyna się tak na prawdę twoje odliczanie Timera - musiałbyś więc uwzględnić całe to opóźnienie, które może być za każdym razem różne i stąd chyba twoje problemy

    doprowadź sobie twój sygnał detekcji zera do wejścia INT (tak się zwykle robi w takich przypadkach), ustaw go na zbocze narastające, i skoro określiłeś, że stan wysoki trwa ok 10% to podziel go sobie jeszcze przez 2 i to będzie twój prawdziwy mniej więcej ale już milion razy dokładniejszy moment przejścia przez zero, od którego już można startować Timer1 w twoim przypadku. Czyli gdy będziesz chciał uzyskać swoje 50% mocy to będziesz musiał poczekać 5ms plus długość tego 10%twoego czasu podzielonego przez 2. (oczywiście żadnych działań typu dzielenie , mnożenie nie dawaj jak już będziesz chciał regulować płynnie moc tylko zastosuj tablicę - i miej na uwadze, że taka regulacja jest bardzo nieliniowa i trzeba skorzystać z odpowiednich wzorów aby to dobrze wyliczyć tzn wartości tablicy. Ale też są programiki, które to zrobią za ciebie ;) ty tylko wstawisz do programu gotowe wartości w zależności od kilku parametrów jak czestotliwość taktowania, ilość kroków regulacji itp

    Poza tym dzięki zastosowaniu przerwania np INT0 lub INT1 tylko raz ustawisz Timer1 i go wystartujesz a nie tak jak przy tym BitWait ze (może przesadzam ;) - ze 100tys razy

    dodam jeszcze, że już kiedyś w temacie zresztą także założonym przez ciebie sporo na ten temat zostało powiedziane i pokazane. Sam wtedy szukałem informacji na te tematy i dzięki temu wątkowi zrobiłem w Bascomie nawet wielokanałową regulację mocy (czyli kilku żarówek (odbiorników) każdą z osobna)

    https://www.elektroda.pl/rtvforum/viewtopic.ph...iemniacz&sid=81911256c8f2f00f53596b1643ba6287

    0
  • #6 16 Lis 2008 22:49
    MES Mariusz
    Poziom 36  

    mirekk36 napisał:
    Proponuję ci absolutnie zrezygnować z takiej konstrukcji Do Loop i Bitwait w środku ... doprowadź sobie twój sygnał detekcji zera do wejścia INT

    Próbowałem z bitwait tylko dlatego, że mam gotowe płytki. Gdybym je projektował raz jeszcze doprowadziłbym odpowiednie sygnały do wejść przerwań.

    Jakiś czas temu próbowałem na tej samej płytce uruchomić sterowanie fazowe wykorzystując fragmenty kodu gotowca AVT 2749 i o dziwo sterowanie fazowe chodziło płynnie, i bez większego migotania! A więc jednak zastosowanie przerwań nie musi być konieczne.

    Ale ponieważ program (źródło) wydał mi się zbyt zawiły (nie do końca zgadzały mi się obliczenia) postanowiłem program napisać od zera, samodzielnie, wycinając wszystko, co niepotrzebne.

    Ale jak widać efekt nie jest najlepszy.

    Nie upieram się przy bezcelowej rezygnacji z wykorzystania przerwań. Po prostu chciałbym uratować stare płytki.

    0
  • #7 16 Lis 2008 22:59
    mirekk36
    Poziom 42  

    Oczywiście, że można to zrobić na milion sposobów nawet bez użycia choćby jednego przerwania nawet od Timera ;) tego nie neguję - mówię tylko, że w ten sposób chyba najszybciej , najłatwiej , najbardziej przejrzyście a co więcej - lepsze możliwości zastosowania w układzie wprowadzenia innych czynności niż tylko taka super prosta regulacja.

    Jak chcesz więc już koniecznie w ten sposób to wprowadź sobie flagi, które ci pomogą. Np jedną ustawiaj po zadziałaniu BitWait i gdy jest ustawiona to niech się już nie wykonuje ten fragment ustawiający Timer1. Falegę możesz kasować wraz z włączeniem triaka. Wtedy będziesz miał sytuację zbliżoną do działania z przerwaniem i jakby programowego wykrywania zbocza narastającego. Tylko wtedy jeśli w pętli głównej wprowadzisz jeszczesz jakieś działania to będziesz bardzo mocno nusiał przeliczać czas ich wykonania - bo on będzie bardzo wpływał na to wykrywanie i konieczne czasy załączania triaka. Wtedy nawet trochę w łeb weźmie tablica - no ale na pewno da się to jeszcze inaczej napisać - tylko trzeba pogłówkować dalej - flagi to jednak w twoim przypadku dobry trop

    A tak nawiasem mówiąc, co za problem nawet na starych płytkach zrobić JEDEN mały krosik z twojego pinu B.1 jeszcze do INT0. Przecież nawet nie trzeba ścieżek ciąć, tylko dolutować kawałeczek krosu ;) - a dzięki temu program pójdzie szybciej i łatwiej

    0
  • #8 18 Lis 2008 22:13
    MES Mariusz
    Poziom 36  

    Hmm... A może coś takiego:

    Code:
        $asm
    
          sbic pinb, 1
        $end Asm

    :?:

    --- edit ---

    A propos gotowca AVT 2749.

    Rozumie ktoś tą procedurę? Bo ja się gubię...

    Code:
    $include "konfig.bas"
    
    $regfile = "8515def.dat"

    Dim Czas_wlaczenia_triaka As Byte

    Config Timer1 = Timer , Prescale = 1

    Enable Interrupts
    Enable Timer1

    On Timer1 Sterowanie_fazowe

    Do
    Waitms 50
    Loop

    Sterowanie_fazowe:
      Timer1 = 64736
        $asm
          sbic pinb, 1
        $end Asm
        Gosub Zero

      Incr Czas_wlaczenia_triaka
        If Czas_wlaczenia_triaka > 70 Then Reset Q2
    Return

    Zero:
      Czas_wlaczenia_triaka = 1
      Set Q2
    Return


    A najciekawsze jest, że ona działa...

    Co tu mamy...

    1. Program wykonuje pustą pętlę do...loop. W końcu następuje przepełnienie timer1 (na razie nie skonfigurowanego konkretnie).
    2. Program przechodzi do procedury Sterowanie_fazowe. Tutaj następuje skonfigurowanie Timer1 = 64736, a następnie program czeka na stan 1 na pinie b1 (Timer1 cały czas odlicza (?) bo nie był nigdzie zatrzymany)
    3. Kiedy na pinie b1 pojawia się stan 1 resetuje sie czas_włączenia_triaka i triak q2 zostaje wyłączony.
    4. czas_włączenia_triaka się zwiększa o 1 i jeśli przekroczył 70 to włącza się triak.


    Mam wątpliwości co do tego:

    a). dlaczego linijka Timer1 = 64736 znajduje się akurat w tym miejscu i dlaczego ciągle wpisywana jest taka sama wartość (regulacja mocy to w tym wypadku stała 70).
    b). W jakich okolicznościach inkrementuje się czas_włączenia_triaka (procedura zero cały czas zeruje tą wartość).

    Hmm... Żeby czas_włączenia_triaka mogła się inkrementować nie może następować przejście przez zero. Czyli w jednej połówce sinusa sterowanie_fazowe musi zostać wykonane co najmniej 70 razy. Sterowanie_fazowe inicjowane jest przez Timer1. Ale sterowanie_fazowe ciągle resetuje (?) Timer1...

    Się zapętliłem... ;-)

    Ktoś rozjaśni?

    0
  • #9 22 Lis 2008 23:52
    mirekk36
    Poziom 42  

    Witam,

    sorki ale nie znam gotowca AVT 2749 ani nie mam tego programu w całości, żeby tak sobie móc go na szybko przeanalizować a też nie chce mi się zgadywać. To jest tylko jakiś fragment programu, nie widać jaką częstotliwością taktowany jest procek?? (można się tylko domyślać)

    tak więc mogę tylko odnieść się do pewnych - zdaje się, że jasnych fragmentów programu i do twojej analizy

    Cytat:
    1. Program wykonuje pustą pętlę do...loop. W końcu następuje przepełnienie timer1 (na razie nie skonfigurowanego konkretnie).
    - co to znaczy na razie nie skonfigurowanego? a może w tym $include "konfig.bas" coś jest wstępnie ustawiane

    Cytat:
    2. Program przechodzi do procedury Sterowanie_fazowe. Tutaj następuje skonfigurowanie Timer1 = 64736, a następnie program czeka na stan 1 na pinie b1 (Timer1 cały czas odlicza (?) bo nie był nigdzie zatrzymany)

    - tu nie następuje skonfigurowanie Timer1 bo nastąpiło ono przy inicjalizacji, tutaj tylko Timer1 ładowany jest jakąś wartością (jeśli będzie się znało taktowanie procka - to będzie można wiedzieć jaki czas ma odliczać - przypuszczam, że to jest czas 1 kroku spośród iluś tam kroków do płynnej regulacji oświetlenia. No i tu twój największy błąd tejże interpretacji - bo program nie czeka na stan 1 na pinie b1 - tylko w przypadku stanu niskiego na pinie b1 nie wykonuje się skok do procedury Zero: , a jeśli wystąpi już stan 1 - czyli wykryte ZERO sieci to procedura Zero jest wykonana. W związku też z powyższym, zmienna Czas_wlaczenia_triaka inkrementuje się ileś tam razy w czasie pomiędzy szpilkami wykrywającymi zero. Jak mówię - to wydają się być kroki regulacji - tylko ile ich jest można wywnioskować znając częstotliwość taktowania. A ta stała 70??? co to jest - tu powinna być zmienna no chyba, że raz na stałe chcesz ustawić stopień jasności na ileś tam procent - no ale jak mówię ciężko się takie porwane fragmenty analizuje

    Cytat:
    3. Kiedy na pinie b1 pojawia się stan 1 resetuje sie czas_włączenia_triaka i triak q2 zostaje wyłączony.

    - tak, przy czym wg mnie wywołuje się to wiele razy w czasie trwania stanu wysokiego na pinie b1

    Cytat:
    4. czas_włączenia_triaka się zwiększa o 1 i jeśli przekroczył 70 to włącza się triak.

    - tak



    ... no a się zapętliłeś bo nie sprawdziłeś jak działa sbic po prostu. Wydawało ci się, że tu program czeka jak w bascomie przy bitwait ;)

    ... jest to generalnie jakiś pomysł - podobny do tego który opisywałem z flagami, tyle że ładnie wpleciony w przerwanie Timera i też powinien działać

    0
  • #10 23 Lis 2008 09:27
    MES Mariusz
    Poziom 36  

    Jakby co to całość programu znajduje się tutaj

    To co wkleiłem wcześniej to maksymalnie skrócony program (przerobiony na inny uP, zmienna zastąpiona stałą itp,), który działa (próbowałem dojść do tego, jak).

    --- edit ---

    PS.

    W tym programie timer powtarza kilkadziesiąt razy pewien odstęp czasu (97 us?) i w dokonuje inkrementacji pewnej zmiennej. Od wartości tej zmiennej zależy moc przekazywana do obciążenia (np. jasność żarówki). W jakiś sposób autorowi udało się zrealizować płynną regulację jasności świecenia żarówki.

    Ma ktoś pomysł, dlaczego autor zastosował taką a nie inną wartość Timer1 = 64566 (wg komentarza: 'timer1 liczy 970 cylki zegara, czyli przerwanie co ok 97us) ? Dlaczego opóźnienie akurat 97us?

    Dla ułatwienia wklejam kod tutaj:

    Code:
    $regfile = "2313DEF.dat"
    
    $crystal = 10000000

    Dim Eaddress As Eram Byte At 2                              'adres pilota Rc5, zosatał umieszczony pod adresem 2 gdyż z doswiadczenia wiem, że komórki 0 i 1(szczególnie 0) pamięci EEPROM potrafią się skasować przy nagłych skokach napięcia zasilania
    Dim Epamiec(16) As Eram Byte At 3                           'tablica komend przycisków pilota


    Dim Lmram(4) As Byte                                        'cztery zmienne w których jest przechowywana informacja o aktualnym stanie jasnosci lamp
    Dim Address As Byte , Command As Byte                       'zmienne potrzebne do RC5
    Dim Licznik As Byte                                         ' ta zmienna jest potrzebna przy odliczaniu czasu nieświecenie każdej lampy
    Dim Ktora As Byte                                           'ta zmienna określa która lampa jest sterowana
    Dim Digit As Byte                                           'zmienna potrzebna przy zapisie odczycie pamięci eeprom
    Dim Nextlm As Byte                                          'zmienna pomocnicza
    Dim Upbit As Byte                                           '}




    Dim Downbit As Byte                                         ' }te zmienne przyjmuja tylko wartości 0 lub 255 - czyli w programie są traktowane jako bity
                                                                  ' (operacje na bajtach zajmują mniej pamięci FLASH, ale więcej RAMu) ustawiane są po nacisnieciu odp. przycisku na klawiaturze lub pilocie
    Dim Onoffall As Byte                                        'bit mówiący o włączeniu/wyłączeniu czterech lamp
    Dim Kod As Byte                                             'bit(patrz wyzej Upbit, Downbit) pomocniczy przy ustalaniu czy przycisk na pilocie jest trzymany

    Dim Pomocbit As Byte                                        '}
    Dim Pomocbit2 As Byte                                       ' }bity pomocnicze do zapamiętywania upbit i downbit

    Dim X As Byte                                               'zmienna potrzebna do odliczania czasu trzymania przycisku na pilocie potrzebnego do zapisania profilu
    Dim Pomocbit3 As Byte                                       'bit pomocniczy
    Dim Adr As Byte                                             'w tej zmiennej przechowywany jest obliczony adres dostepu do potrzebnego obszaru pamieci eeprom

    Dim Eonofflmgl As Eram Byte At 100                          'tu zapamietywana jest ostatnia wartość zmiennej Onofflmgl
    Dim Onofflmgl As Byte                                       'zmienna mówiaca o włączeniu/wyłączeniu lampy głównej

    Dim K As Integer                                            'zmienna pomocna przy sprawdzaniu czy przycisk został puszczony
    Dim Pomocbit4 As Byte


    Config Portb = &B01111000
    Config Portd = &B0111011                                    'wyjścia/wejscia Portu D zostaną odpowiednio ustawione(podciągnięte) już przy pierwszym skoku do podprogramu Inttim1
    Gosub Incrktora                                             '}
    Gosub Selectktora                                           ' }te dwa polecenia dają w sumie ustawienie (podciągnięcie) we./wy. portu B

    Dim Timefader As Byte                                       ')
    Dim Timefader2 As Byte                                      ' )zmienne do odliczania czasu automatycznego gaszenia lamp

    Config Int0 = Falling
    Config Rc5 = Pind.2

    Config Timer1 = Timer , Prescale = 1

    Enable Interrupts
    Enable Timer1

    On Timer1 Inttim1
    On Int0 Int_0

    Config Watchdog = 2048                                      'jeśli program się zawiessi to watcghdog zresetuje go po ok 2s

    Onofflmgl = Eonofflmgl                                      'wpisanie do onofflmgl takiej wartosci jaka była przed wyłaczeniem zasilania

    $asm
          sbis pinb, 0                                          'jeśli wciśnięty jest przycisk down to
    $end Asm
      Gosub Pilot                                               'skocz do podprogramu zapisujacego komendy pilota


    Do                                                          'tu zaczyna się program główny
      Start Watchdog
      If Address = Eaddress Then                                'jeśli adres pilota dobry
        For Nextlm = 1 To 16                                    'piętnastokrotnie
          If Command = Epamiec(nextlm) Then                     'sprawdzanie komend przycisków pilota
           Select Case Nextlm
             Case 1 : Gosub Incrktora                           'Incr Która
             Case 2 : Gosub Setupbit                            'przycisk Up
             Case 3 : Gosub Setdownbit                          'przycisk Down
             Case 4 : If Kod = 0 Then                           'po to by jednokrotnie zmienic stan onoffall przy jednokrotnym nacisnieciu przycisku pilota
                        Onoffall = Not Onoffall
                        Gosub Setkod
                      End If
             Case 5 : If Kod = 0 Then                           'po to by jednokrotnie zmienic stan onofflmgl przy jednokrotnym nacisnieciu przycisku pilota
                        Onofflmgl = Not Onofflmgl
                        Eonofflmgl = Onofflmgl
                        Gosub Setkod
                      End If
             Case 6 : If Kod = 0 Then                           'po to by jednokrotnie zmienic stan DDRB.7 przy jednokrotnym nacisnieciu przycisku pilota
                        Ddrb.7 = Not Ddrb.7                     'przełączanie PORTD.7 jako we. lub wy. co daje włączanie i wyłączanie Timer Fadera
                        Gosub Setkod
                      End If
             Case Is >= 7 :
                           Incr X                               'zwiekszanie zmiennej X
                           Adr = Nextlm                         '}obliczanie adresu dla pamieci eeprom]
                           Shift Adr , Left , 2
                           If X = 10 Then                       'po ok 1s przyciskania klawisza
                             For Digit = 1 To 4
                               Writeeeprom Lmram(digit) , Adr   'zapis do eeprom wartosci jasnosci lamp danego profilu
                               Gosub Waitms50                   'czas dla EEPROMa na zapis
                               Incr Adr
                             Next Digit
                             Gosub Mrugnij
                             Pomocbit3 = 0
                           Else
                             Pomocbit3 = 255                    'blokowanie odczytu z EEPROM jeśli przycisk jest trzymany
                           End If
           End Select
          End If
        Next Nextlm
        Gosub Address_255
        K = 0
      Else
        Incr K
        If K >= 5000 Then
          Kod = 0
          X = 0
          If Pomocbit3 = 255 Then                               'Zezwolenie Na Odczytanie Z Eeprom
            Pomocbit3 = 0
            For Digit = 1 To 4
              Readeeprom Lmram(digit) , Adr                     'odczyt z eproma wartości jasnosci lamp w danym profilu
              Incr Adr
            Next Digit
          End If
        End If
      End If
      Enable Int0

        $asm
          sbis pinb, 7
        $end Asm
          Gosub Timefadsub

        $asm
          sbis pinb, 1                                          'przycisk up
        $end Asm
           Gosub Wait_setupbit

        $asm
          sbis pinb, 0                                          'przycisk down
        $end Asm
            Gosub Wait_setdownbit

      $asm
        sbis pinb, 2                                            'przycisk next
      $end Asm
        Gosub Incrktora

      If Ktora >= 7 Then Ktora = 1                              'skracanie cyklu licznika która
      Gosub Selectktora
      Gosub Upbitsub
      Reset Watchdog
    Loop
    End



    Inttim1:                                                    'co ok 97us
      Portd.0 = Onofflmgl.0                                     'zapalanie/gaszenie lampy głównej
      Timer1 = 64566                                            'timer1 liczy 970 cylki zegara, czyli przerwanie co ok 97us
      If Licznik >= 50 Then
        $asm
          sbic pind, 6                                          'sprawdzaj stan końcówki PIND6, jeśli jest równa 1 to
        $end Asm
          Gosub Zero                                            'skocz do podprogramu Zero
      End If
      Incr Licznik
      If Onoffall = 255 Then                                    'jeśłi zezwolenie globalne na włączanie lamp = 1 to
        If Licznik > Lmram(1) Then Reset Portd.5                '}
        If Licznik > Lmram(2) Then Reset Portd.4                ' } zapalaj odpowiednio lampy do wartości tablicy Lmram
        If Licznik > Lmram(3) Then Reset Portd.3                '}
        If Licznik > Lmram(4) Then Reset Portd.1                '}
      End If
    Return

    Upbitsub:
      If Upbit = 255 Then
        Gosub Resetupbit
        Decr Lmram(ktora)
      End If
      If Lmram(ktora) = 101 Then Lmram(ktora) = 100             'po to by lmram(która) utrzymywana była w granicach 0 - 161

      If Downbit = 255 Then
        Gosub Resetdownbit
        Incr Lmram(ktora)
      End If
      If Lmram(ktora) = 255 Then Lmram(ktora) = 0               'jeżeli zmniejszymy lmram(która) ponizej 0 to przyjmie ona war. 255 i po tym poleceniu znowu 0
    Return

    Selectktora:
      Select Case Ktora
       Case 1 : Portb = &B00111000                              'świeci LED4
       Case 2 : Portb = &B01011000                              'świeci LED3
       Case 3 : Portb = &B01101000                              'świeci LED2
       Case 4 : Portb = &B01110000                              'świeci LED1
       Case 5 : Portb = &B00000000                              'świecą od LED1 do LED4   ,wszystkie lampy jaśniej/ciemniej

                For Ktora = 1 To 4
                  Pomocbit = Upbit
                  Pomocbit2 = Downbit
                  Gosub Upbitsub
                  Upbit = Pomocbit
                  Downbit = Pomocbit2
                Next Ktora
                Gosub Resetupbit
                Gosub Resetdownbit
                Ktora = 5
       Case 6 : Portb = &B01111000                              'tryb włączania/wyłączania lamp
                Stop Watchdog

                $asm
                  sbis pinb, 1                                  'przycisk up
                $end Asm
                  Gosub Tog_all
                Bitwait Pinb.1 , Set                            'po to by jednoktrotnie zmienic stan onoffall przy jednokrotnym nacisnięciu przycisku up na klawiaturze

                $asm
                  sbis pinb, 0                                  'przycisk down
                $end Asm
                  Gosub Tog_lmgl
                Bitwait Pinb.0 , Set                            'po to by jednoktrotnie zmienic stan onofflmgl przy jednokrotnym nacisnięciu przycisku down na klawiaturze

      End Select
      If Pomocbit4 = 255 Then                                   'opóźnienie dla zmieniania trybu (ktora)
        $asm
          sbis pinb, 2                                          'przycisk next
        $end Asm
          Gosub Waitms200
        $asm
          sbis pinb, 2                                          'przycisk next
        $end Asm
          Gosub Waitms200
        Gosub Address_255
      End If
      Pomocbit4 = 0

    Return

    Tog_all:
      Onoffall = Not Onoffall
    Return

    Tog_lmgl:
      Onofflmgl = Not Onofflmgl
      Eonofflmgl = Onofflmgl
    Return

    Pilot:                                                      'procedurka rejestracji pilota
    Do
        If Address <> 255 Then
          If Downbit = 0 Then
            Gosub Setdownbit                                    'by wykonać tylko raz przy jednym nacisnięciu przycisku
            If Upbit = 0 Then
              Eaddress = Address
              Gosub Setupbit                                    'adres jest zapisywany tylko raz(od jednego(pierwszego) przycisku))
            End If
            Epamiec(ktora) = Command
            Gosub Incrktora                                     'Incr Która
            Gosub Mrugnij
          End If
          K = 0
        Else
          Incr K
          If K >= 19000 Then Gosub Resetdownbit
        End If
        Gosub Address_255
        Enable Int0
    Loop
    Return

    Address_255:
      Address = 255
    Return

    Setkod:
      Kod = 255
    Return

    Setupbit:
      Upbit = 255
    Return

    Setdownbit:
      Downbit = 255
    Return

    Resetupbit:
      Upbit = 0
    Return

    Resetdownbit:
      Downbit = 0
    Return

    Waitms50:
      Waitms 60
    Return

    Zero:
      Licznik = 1                                               'przy kazdym przechodzeniu napiecia sieci przez zero zeuj licznik i
      Portd = Portd Or &B1111110                                'wygas wszystkie 4 lampy
      Incr Timefader
    Return

    Timefadsub:                                                 '
      If Timefader = 100 Then                                   'co 1s
        Timefader = 0
        Incr Timefader2
        If Timefader2 = 12 Then                                 'co 12s ta linijka decyduje co ile czasu ma nastąpić ściemnienie światła o jeden kroczek
          Timefader2 = 0
          Gosub Setdownbit
        End If
      End If
    Return

    Int_0:
      Disable Int0
      Enable Interrupts
      Getrc5(address , Command)                                 'odczytywanie danych z pilota
      Command = Command And &B01111111
    Return

    Mrugnij:
      Set Portb.6
      Gosub Waitms200
      Reset Portb.6
      Gosub Waitms200
    Return

    Waitms200:
      Waitms 200
    Return

    Wait_setupbit:
      Gosub Waitms50
      Gosub Setupbit
    Return

    Wait_setdownbit:
      Gosub Waitms50
      Gosub Setdownbit
    Return

    Incrktora:
      Pomocbit4 = 255
      Incr Ktora
    Return

    0
  • Pomocny post
    #11 26 Lis 2008 21:30
    mirekk36
    Poziom 42  

    Witam,

    już wcześniej na podstawie tego fragmentu kodu, który podałeś mówiłem, że program ten wykorzystuje płynne sterowanie jasnością tylko ty tam wstawiłeś stałą o wartości 70. Mówiłem też, że skoro nie wiadomo jakie jest taktowanie procka to ciężko powiedzieć co z czego wynika.

    Ale teraz widać jak na dłoni potwierdzenie tego co pisałem, jest to typowe rozwiązanie (tak ogólnie) płynnego sterowania mocą żarówek. Sterowanie to odbywa się za pomocą załączania sinusoidy (tzn każdej jej połówki) od momentu przejścia przez ZERO w odpowiednim momencie. Te momenty to nic innego jak właśnie kroki. Skąd ta wartość 97us? - otóż regulacja odbywa się z rozdzielczością czasu 97us w zakresie jednej połówki sinusoidy. Dzięki temu mamy zachowany ładny dla oka płynny efekt (bo i kroków jest dużo)

    reasumując, przychodzi moment wykrycia ZERA sieci, timer cały czas tyka i inkrementuje licznik (wskaźnik tych kroków) i teraz w zmiennych Lram(x) można ustawiać wartości mocy żarówek. Dzięki temu jeśli wartość w Lram(x) = najniższa wartość licznika - to sinusoida jest włączana praktycznie od razu po przejściu przez ZERO i żarówa świeci pełną mocą. Gdy wartość Lram(x) = średnia wartość licznika - co oznacza, że od momentu przejścia od ZERA upłynęło już połowę czasu to dopiero wtedy zapala się żarówa i świeci powiedzmy połową mocy (ta połowa to tak przykładowo - bo jak mówiłem jest to bardzo nieliniowe) i tak dalej

    jakie są minimalne, średnie i tym podobne wartości liczników już nie chce mi się analizować ale zasada jest dokładnie taka sama.

    Ja podobne sterowanie dla kilku urządzeń zrobiłem w programie, który w Bascomie zajmował sporo mniej kodu ale za to korzystałem po drodze z 2 Timerów. Tutaj autor musiał się nieco nagłowić i nakombinować bo ATtiny ma tylko 2 Timery z czego jeden musi być dla obsługi pilota RC5, więc tak ten kod wygląda. Najważniejsze że działa ładnie i aż dziw bierze, że w Bascomie i mieści się w ATtiny ;)

    teraz nieco jaśniej?

    Ja gdy robiłem na szybko sterowanie i dałem np tylko 25 kroków ściemniania to niestety pomimo zaokrągleń i obliczeń odnośnie nieliniowości, widać było w pewnych zakresach małe migotania przy niektórych przejściach. Ale jak dałem już 100 kroków i więcej to było dobrze

    0
  • #12 26 Lis 2008 22:00
    MES Mariusz
    Poziom 36  

    mirekk36 napisał:
    Skąd ta wartość 97us? - otóż regulacja odbywa się z rozdzielczością czasu 97us w zakresie jednej połówki sinusoidy. Dzięki temu mamy zachowany ładny dla oka płynny efekt (bo i kroków jest dużo)

    Rozumiem więc, że nie jest to jakaś wartość krytyczna, której należy ściśle przestrzegać (wyliczać), a jedynie taka, która ma kilkadziesiąt - kilkaset razy zmieścić się w okresie pomiędzy przejściami przez zero, im mniejsza ona będzie tym większa będzie musiała być liczba kroków (u mnie chwilowo stała o wartości 70).

    Jeśli połówka sinusoidy trwa 10 ms to rozdzielczość 97 us czyli 0,097 ms da około 104 kroki rozdzielczości, więc mniej więcej się zgadza.

    0
  • #13 26 Lis 2008 22:46
    mirekk36
    Poziom 42  

    oczywiście, że nie są to wartości krytyczne jeśli chodzi o czasy trwania kroków. Więc jak najbardziej można tu trenować ze swoimi wartościami - na pewno wyjdzie. Ważne tylko aby załapać jeden ze sposobów jak to robić - co się chyba udało ;)

    0
  • #14 26 Lis 2008 23:09
    MES Mariusz
    Poziom 36  

    Warto zauważyć, że sposób, jaki zastosowano w układzie AVT 2749 ma duże plusy:

    a). pozwala oszczędzić przerwania
    b). pozwala na sterowanie więcej niż jednym urządzeniem

    0