regulator PWM 2 kanały


Witam. Ostatnio z potrzeby chwili zrobiłem regulator PWM dla dwóch kanałów.
PWM liczy do 255 ,jednak ograniczyłem do 250 (łatwiej przeliczyć ,aby pokazywało 100%), a skok jest co 5 (2%). Regulator służy do zasilania taśm LED w 2 sekcjach (góra ,dół). Układ zmontowany działa poprawnie zgodnie z założeniami.
Regulacja odbywa się za pomocą 3 przycisków :
MENU-wchodzimy do regulacji 1 i 2 kanału
2 przyciski-zwiększanie i zmniejszanie
Wyjście z MENU powoduje zapis ustawionych wartości i włączenie diody LED.
Kod zajmuje 99% ,także już nic nie wejdzie, zrezygnowałem z przycisków OFF na rzecz zwykłego wyłącznika zasilania (i tak musiałem wyłączać zasilacz do taśm).
Jak dostrzeżecie jakieś błędy, to poproszę o napisanie co można poprawić.


'marekszy@op.pl  Regulator 2xPWM działa,11.2015r  (99% zajete)
'regulacja na PWM1a/PWM1b (OC1a/OC1b)(PB.3/pb.4)
'zapis + przyciski + wyswietlanie (wyswietlacz 2x8)+watchdog
'CKDIW 8 - wylaczone
 
$regfile "attiny2313.dat"                                   'deklaracja procesora
$crystal = 4000000                                          'deklaracja częstotliwości
 
Config Watchdog = 1024
 
Config Porta = &B11111100 : Porta = &B11111111
Config Portb = &B11111111 : Portb = &B11100111
Config Portd = &B11000111 : Portd = &B00111000
 
 
Config Lcdpin = Pin , Db4 = Portb.6 , Db5 = Portb.5 , Db6 = Portb.7 , Db7 = Portb.2 , E = Portb.0 , Rs = Portb.1
Config Lcd = 16 * 2
Cls
Cursor Off Noblink
 
Locate 1 , 1
Lcd "Marekszy"
Locate 2 , 1
Lcd "Reg.PWM "
Wait 3
 
Deflcdchar 1 , 31 , 31 , 24 , 24 , 32 , 32 , 32 , 32        ' gora lewa strona
Deflcdchar 2 , 31 , 31 , 3 , 3 , 32 , 32 , 32 , 32          ' gora prawa strona
Deflcdchar 3 , 31 , 31 , 32 , 32 , 32 , 32 , 32 , 32        ' kreska gora
Deflcdchar 4 , 32 , 32 , 32 , 32 , 24 , 24 , 31 , 31        ' dol lewa strona
Deflcdchar 5 , 32 , 32 , 32 , 32 , 3 , 3 , 31 , 31          ' dol prawa strona
Deflcdchar 6 , 32 , 32 , 32 , 32 , 32 , 32 , 31 , 31        ' kreska dol
 
 
Config Timer1 = Pwm , Pwm = 8 , Prescale = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up       'Konfiguracja Timera1 dla PWM
 'pwm "up" poniewz tranzystor jest jak inwerter,bez tranzystora "down"
 
Config Timer0 = Timer , Prescale = 64
Enable Timer0 : On Timer0 Prztimer0
 
Enable Interrupts
 
Dim Dzielnik As Byte
Dim Flaga_4ms As Bit , Flaga_100ms As Bit
Dim Sw As Byte , Stan_sw As Byte , Licznik_sw As Byte
Dim Poz_menu As Byte
Dim Procent_a3 As Byte , Procent_a4 As Byte
Dim Procent_b3 As Byte , Procent_b4 As Byte
Dim Procent_a As Byte , Procent_a1 As Byte , Procent_b As Byte , Procent_b1 As Byte
 
Readeeprom Pwm1a , 4
Readeeprom Pwm1b , 8
 
Start Watchdog
'*****************************petla glowna**************************************
Do
  If Flaga_4ms = 1 Then
    Flaga_4ms = 0
     Gosub Przyciski
  End If
   If Flaga_100ms = 1 Then
    Flaga_100ms = 0
     Reset Watchdog
     Gosub Wyswietlanie
  End If
 Loop
End
'****************************petla glowna koniec********************************
 
'***************************przerwanie timer0***********************************
 
Prztimer0:
 Timer0 = 7
 Flaga_4ms = 1
  Incr Dzielnik
   If Dzielnik = 25 Then
      Dzielnik = 0                                          '25*4ms = 100ms
      Flaga_100ms = 1
   End If
Return
'***************************przerwanie timer0 koniec****************************
 
'*******************************wyswietlanie ***********************************
Wyswietlanie:
 
 Select Case Poz_menu
Case 0:
 Procent_a = Pwm1a / 5
 Procent_a1 = Procent_a * 2
 Locate 1 , 1 : Lcd Chr(1) + Chr(3) + Chr(2) + " " ; Procent_a1 ; "%   "
 Procent_b = Pwm1b / 5
 Procent_b1 = Procent_b * 2
 Locate 2 , 1 : Lcd Chr(4) + Chr(6) + Chr(5) + " " ; Procent_b1 ; "%   "
 Set Portd.2
 
Case 1:
 Locate 1 , 1 : Lcd "LED  " + Chr(1) + Chr(3) + Chr(2)
 Procent_a3 = Pwm1a / 5
 Procent_a4 = Procent_a3 * 2
 Locate 2 , 1 : Lcd "Moc-" ; Procent_a4 ; "%  "
 Reset Portd.2
 
Case 2:
 Locate 1 , 1 : Lcd "LED  " + Chr(4) + Chr(6) + Chr(5)
 Procent_b3 = Pwm1b / 5
 Procent_b4 = Procent_b3 * 2
 Locate 2 , 1 : Lcd "Moc-" ; Procent_b4 ; "%  "
 Reset Portd.2
 
End Select
Return
 
 
'************************koniec wyswietlania************************************
'******************************przyciski****************************************
Przyciski:
Sw = Pind And &B00111000                                    'maskowanie nieużywanych pinów
 
If Sw <> &B00111100 And Stan_sw = Sw Then
    Incr Licznik_sw
    If Licznik_sw = 90 Then                                 'bylo 100(za wolno)
      Licznik_sw = 0
      Select Case Stan_sw
 
        Case &B00110000:                                    'poz.menu pd2
         Incr Poz_menu
          If Poz_menu = 3 Then
           Poz_menu = 0
            Writeeeprom Pwm1a , 4
            Writeeeprom Pwm1b , 8
          End If
 
        Case &B00101000:                                    'UP   pd3
          Select Case Poz_menu
 
            Case 1:
              If Pwm1a < 250 Then Pwm1a = Pwm1a + 5
 
            Case 2:
              If Pwm1b < 250 Then Pwm1b = Pwm1b + 5
 
          End Select
 
        Case &B00011000:                                    'DOWN  pd4
          Select Case Poz_menu
 
            Case 1:
              If Pwm1a > 0 Then Pwm1a = Pwm1a - 5
 
            Case 2:
             If Pwm1b > 0 Then Pwm1b = Pwm1b - 5
 
          End Select
 
      End Select
    End If
  Else
    Stan_sw = Sw
    Licznik_sw = 80
  End If
 
Return
 
'*****************************koniec przyciski**********************************

Praca

ustawianie kanału nr.1

ustawianie kanału nr.2

Pozdrawiam




Portret użytkownika EDC

Dwukanałowy regulator

Miło widzieć taki "gotowiec" :D

Jak będzie potrzebny to jak znalazł.
Tak na szybko to mam dwie uwagi.

Użycie komendy Config Portb = &b11111111 to tak na prawdę jest równoznaczne z Ddrb = &b11111111

DDRx to rejestr portu X gdzie x to litera portu. Ustala się w nim czy pin jest wyjściem czy wejsciem.
W zależności więc od tego jakie dany mikrokontroler ma porty możemy spotkać DDRB i DDRD dla portów B i D
Znajdziemy też czasem DDRC i DDRA
Mamy więc PIND dla czytania z portu D, PORTD dla wpisywania do portu D i DDRD dla ustalania czy port jest wejściem czy wyjściem.

Podsumowując, chodziło mi o to że jeśli u góry napisano Config Portb to późniejsze Ddrb = &B11111111 jest masłem maślanym i na pewno niczego nie odblokowuje :D

Musiało się tam przyplątać z innego kodu.

Poważniejszą pomyłkę widzę w procedurze obsługi przerwania.
Kiedy piszemy warunek IF i napiszemy cokolwiek po wyrażeniu Then to cała instrukcja jest zakończona i wykonywana w tej jednej linii.
Tak wiec napisane pod tym Flaga_100ms = 1 wcale nie dzieje się co 100ms :D

Uważam że ta Flaga jest ustawiana z tą samą częstotliwością co Flaga 4ms bo nie obejmuje jej ten If
Zamierzenie było chyba takie:

If Dzielnik = 25 Then
    Dzielnik = 0                       '25*4ms = 100ms
     Flaga_100ms = 1
End if

Co ciekawe moje Bascomy (sprawdzałem na 2078 i 2079) piszą że kod zajmuje tylko 7%
Kazały mi tylko zamienić "+" plusy pomiędzy Chr(x) na średniki.

Kiedy u góry w kodzie napiszesz $lib "mcsbyte.lbx" to robi się z tego 6%

Miłego wieczoru

-

BARTek
Moja strona

Portret użytkownika marekszy

Dwukanałowy regulator

Dzięki za uwagi, odnośnie

Ddrb = &b11111111 
to już wywaliłem z kodu, a timer0 poprawiony (dzięki za wytłumaczenie o co biega z Ddrb).
Mam bascom 2071 i niestety nie chce być inaczej ,ale postaram się o nowszą wersję i zobaczymy.
Dodanie
$lib"mcsbyte.lbx"
faktycznie zmniejsza do 91%. Możesz napisać za co jest odpowiedzialne?
Dzięki

Portret użytkownika EDC

Odp. Dwukanałowy regulator

No mam jeszcze Bascom 2075 na wirtualnym XP i tam pokazało 91% więc zacząłem węszyć :D

W Bascom jak nie wiadomo o co chodzi to warto znaleźć plik XML - taki konfiguracyjny. Kiedy się w Bascom naciśnie u góry Help i About to pokazuje ścieżkę dostępu do tego pliku.

Zmieniłem wiec nazwę tego pliku i wtedy Bascom zachowuje się jak nowy.
No i pokazał, że kod zajmuje 90% tak więc coś tam było u mnie :D

Co do $lib"mcsbyte.lbx" -- funkcje Bascoma sa napisane uniwersalnie i pasują do Byte, Word ale też musza być przygotowane na większe zmienne i to kosztuje trochę kodu - ta uniwersalność.
W Twoim kodzie zauważyłem że używane sa prawie tylko bajty.
Kiedy w kodzie napisze się żeby używał "mcsbyte.lbx" to kod jest mniejszy bo funkcje są nastawione tylko na Bajty.
Nie byłoby chyba wesoło jak byś użył tej biblioteki a potem gdzies użył Single albo Long.

Jest jeszcze mcsbyteint.lib - wtedy chyba kod tez nie puchnie ale można już używać zmiennych dwubajtowych Word - Integer.

-

BARTek
Moja strona