Termometr LED - problem z menu


Ponieważ nie jestem za mocny w Bascomie, to wykorzystałem kod źródłowy Mirleya PODST.BAS, by na procku AT89C2051 i czujniku DS1820 zrobić termometr na 2 wyswietlaczach LED i po kilku poprawkach (m.in. dzięki Mirleyowi) udało mi się go uruchomić. Problem nie do pokonania przeze mnie pojawił się, gdy chciałem rozszerzyć go o funkcje termostatu. Dodałem 3 przyciski (+,-,menu) i wykorzystując z kolei fragment kodu TERMOSTAT.BAS dopisałem ich obsługę w maksymalnie uproszczony sposób - bez migania, autopowrotu i sterowania przekaźnikiem (alarm będzie sygnalizować dioda po przekroczeniu Tmin lub Tmax ale to zostawiłem na później). Oto kod:

'****************************
           'Konfiguracja
'****************************
$crystal = 12000000                                           '12MHz
$regfile = "89C2051.DAT"
 
Config 1wire = P3.2
 
A1 Alias P3.1
A2 Alias P3.4
 
Znak Alias P3.3
 
Config Timer0 = Timer , Gate = Internal , Mode = 2
 
On Timer0 Przerwanie
Load Timer0 , 250                                             'okres Timera0 250*12*Tosc = 250us
Enable Timer0
Start Timer0
Enable Interrupts
 
'****************************
      'Zmienne
'****************************
Dim Lsb As Byte
Dim Msb As Byte
Dim Co4ms As Byte , Co100ms As Byte , Co1s As Byte
Dim Wysw As Byte , Wysw1 As Byte , Wysw10 As Byte
Dim Temp As Byte
Dim Tmin As Byte
Dim Tmax As Byte
Dim Poz_menu As Byte
Dim Sw_licz(3) As Byte
Dim Zezw_wysw As Bit
Dim Zezw_przyciski As Bit
Dim Zezw_alarm As Bit
Dim Mux As Bit
'Dim Miganie As Bit
Dim Pomiar As Bit
Dim Ur As Bit
 
'****************************
      'Wartosci Poczatkowe
'****************************
Reset Pomiar
Reset Ur
Poz_menu = 0
Zezw_alarm = 1
Tmin = 22
Tmax = 28
P1 = 255
P3 = 255
Wysw10 = 225                                                  'o
Wysw1 = 229                                                   'n
 
'****************************
      'Petla glowna
'****************************
Do
If Zezw_wysw = 1 Then
  Reset Zezw_wysw                                             'co 4ms
  Select Case Poz_menu
    Case 0:
      Wysw = Temp
    Case 1:
      Wysw = Tmin
    Case 2:
      Wysw = Tmax
  End Select
  If Ur = 1 Then Gosub Przelicz
  Gosub Wyswietl
End If
 
If Zezw_przyciski = 1 Then                                    'co 100ms
  Reset Zezw_przyciski
 
  If P3.5 = 0 Then                                            'PLUS
    Incr Sw_licz(1)
      If Sw_licz(1) = 10 Then
        Sw_licz(1) = 5
 
        Select Case Poz_menu
          Case 0:
           Zezw_alarm = 1
          Case 1:
           If Tmin < 24 Then Incr Tmin
          Case 2:
           If Tmax < 30 Then Incr Tmax
        End Select
 
'Autopowrot = 0
      End If
   Else
    Sw_licz(1) = 8
   End If
 
 
  If P3.7 = 0 Then                                            'MINUS
    Incr Sw_licz(2)
      If Sw_licz(2) = 10 Then
        Sw_licz(2) = 5
 
        Select Case Poz_menu
          Case 0:
           Zezw_alarm = 0
          Case 1:
           If Tmin > 20 Then Decr Tmin
          Case 2:
           If Tmax > 26 Then Decr Tmax
        End Select
 
'Autopowrot = 0
      End If
  Else
    Sw_licz(2) = 8
  End If
 
 
  If P3.0 = 0 Then                                            'MENU
    Incr Sw_licz(3)
      If Sw_licz(3) = 10 Then
        Sw_licz(3) = 5
 
        Incr Poz_menu
        If Poz_menu = 3 Then Poz_menu = 0
 
'Autopowrot = 0
      End If
  Else
    Sw_licz(3) = 8
  End If
 
End If
Loop
End
 
 
'****************************
      'Przerwanie Timer0
'****************************
 
Przerwanie:
Incr Co4ms
 If Co4ms = 16 Then
   Co4ms = 0
   '***************************************  co 4ms
   Set Zezw_wysw
   Incr Co100ms
   If Co100ms = 25 Then
     Co100ms = 0
     '*************************************** co 100 ms
     Set Zezw_przyciski
'Miganie = Not Miganie
     Incr Co1s
     If Co1s = 10 Then
       Co1s = 0
       '*************************************** co 1s
       Pomiar = Not Pomiar
 
       Disable Interrupts
       1wreset
 
       If Pomiar = 1 Then
        1wwrite &HCC
        1wwrite &H44
       Else
        If Err = 0 Then
 
          1wwrite &HCC
          1wwrite &HBE
          Lsb = 1wread():
          Msb = 1wread():
 
          If Msb = 0 Then
            Set Znak
          Else                                                'jesli temperatura ujemna
            Reset Znak
            Lsb = 256 - Lsb
          End If
 
          Temp = Lsb / 2
          If Ur = 0 Then Ur = 1
 
        Else
          Temp = 200                                          'Er wyswietli sie pozniej
        End If
       End If
 
       Enable Interrupts
       '***************************************
     End If
     '***************************************
   End If
   '***************************************
 End If
Return
 
 
'****************************
      'Inne Etykiety
'****************************
 
Przelicz:
 If Wysw < 100 Then
   Wysw1 = Wysw Mod 10
   Wysw1 = Lookup(wysw1 , Tabela)
   If Wysw > 9 Then
     Wysw10 = Wysw / 10
     Wysw10 = Lookup(wysw10 , Tabela)
   Else
     Wysw10 = 255                                             'wygaszenie wyswietlacza dziesiatek
   End If
 Else
   If Wysw = 200 Then
     Wysw10 = 131                                             'E
     Wysw1 = 231                                              'r
   Else
     Wysw10 = 239                                             '- temperatura ponad 99 stopni
     Wysw1 = 239                                              '- (przekroczony zakres pomiaru)
   End If
 End If
Return
 
 
Wyswietl:
  Mux = Not Mux
  If Mux = 1 Then
    Reset A2
    P1 = Wysw1
    Set A1
  Else
    Reset A1
    P1 = Wysw10
    Set A2
  End If
Return
 
 
'***********************************************************************
           'Tabela znakow do wyswietlania na wyswietlaczach:
'***********************************************************************
Tabela:
 Data 17 , 125 , 35 , 41 , 77 , 137 , 129 , 61 , 1 , 9
'znak: 0    1     2    3    4    5     6     7   8   9
'***********************************************************************

Niestety, tak zmodyfikowany program nie chce działać - wyświetlacze są ciągle wygaszone. Programowałem procka kilka razy, przeanalizowałem cały kod ale już nic mi nie przychodzi do głowy, co jest nie tak. Pomóżcie, proszę !!!




Portret użytkownika mirley

Re: Termostat 2 LED

Dodaj jeszcze do powyższego opisu kod który używałeś i który napewno Ci działał

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika j23nadaje

Re: Re: Termostat 2 LED

Dzięki Mirley za zainteresowanie. Oto kod termometra 2 LED, który mi działa bez problemów (nie wyświetla się wprawdzie "Er" po odłączeniu czujnika tylko 0 na prawym wyświetlaczu, ale to drobiazg):

'****************************
           'Konfiguracja
'****************************
 
$crystal = 12000000                                           '12MHz
$regfile = "89C2051.DAT"
Config 1wire = P3.2
 
A1 Alias P3.1
A2 Alias P3.4
Alarm Alias P3.3
Minus Alias P1.0
 
Config Timer0 = Timer , Gate = Internal , Mode = 2
 
On Timer0 Przerwanie
Load Timer0 , 250                                             'okres Timera0 250*12*Tosc = 250us
Enable Timer0
Start Timer0
Enable Interrupts
 
 
'****************************
      'Zmienne
'****************************
 
Dim Lsb As Byte
Dim Msb As Byte
Dim Co4ms As Byte , Co100ms As Byte , Co1s As Byte
Dim Wysw As Byte , Wysw1 As Byte , Wysw10 As Byte
Dim Temp As Byte
Dim Mux As Bit
Dim Zezw_wysw As Bit
Dim Pomiar As Bit
Dim Ur As Bit
 
 
'****************************
      'Wartosci Poczatkowe
'****************************
 
Reset Pomiar
Reset Ur
P1 = 255
P3 = 255
Wysw10 = 225                                                  'o
Wysw1 = 229                                                   'n
 
 
'****************************
      'Petla glowna
'****************************
 
Do
If Zezw_wysw = 1 Then
  Reset Zezw_wysw                                             'co 4ms
  Wysw = Temp
  If Ur = 1 Then Gosub Przelicz
  Gosub Wyswietl
End If
Loop
End
 
 
'****************************
      'Przerwanie Timer0
'****************************
 
Przerwanie:
Incr Co4ms
 If Co4ms = 16 Then
   Co4ms = 0
   '***************************************  co 4ms
   Set Zezw_wysw
   Incr Co100ms
   If Co100ms = 25 Then
     Co100ms = 0
     '*************************************** co 100 ms
     'ew. flaga obslugi przyciskow
     Incr Co1s
     If Co1s = 10 Then
       Co1s = 0
       '*************************************** co 1s
       Pomiar = Not Pomiar
 
       Disable Interrupts
       1wreset
 
       If Pomiar = 1 Then
        1wwrite &HCC
        1wwrite &H44
       Else
        If Err = 0 Then
 
          1wwrite &HCC
          1wwrite &HBE
          Lsb = 1wread():
          Msb = 1wread():
 
          If Msb = 0 Then
            Set Minus
          Else                                                'jesli temperatura ujemna
            Reset Minus
            Lsb = 256 - Lsb
          End If
 
          Temp = Lsb / 2
          If Ur = 0 Then Ur = 1
          If Temp < 25 Then                                   'alarm
            Reset Alarm
          Else
            Set Alarm
          End If
        Else
          Temp = 200                                          'Er wyswietli sie pozniej
        End If
       End If
 
       Enable Interrupts
       '***************************************
     End If
     '***************************************
   End If
   '***************************************
 End If
Return
 
 
'****************************
      'Inne Etykiety
'****************************
 
Przelicz:
 If Wysw < 100 Then
   Wysw1 = Wysw Mod 10
   Wysw1 = Lookup(wysw1 , Tabela)
   If Wysw > 9 Then
     Wysw10 = Wysw / 10
     Wysw10 = Lookup(wysw10 , Tabela)
   Else
     Wysw10 = 255                                             'wygaszenie wyswietlacza dziesiatek
   End If
 Else
   If Wysw = 200 Then
     Wysw10 = 131                                             'E
     Wysw1 = 231                                              'r
   Else
     Wysw10 = 239                                             '- temperatura ponad 99 stopni
     Wysw1 = 239                                              '- (przekroczony zakres pomiaru)
   End If
 End If
Return
 
 
Wyswietl:
  Mux = Not Mux
  If Mux = 1 Then
    Reset A2
    P1 = Wysw1
    Set A1
  Else
    Reset A1
    P1 = Wysw10
    Set A2
  End If
Return
 
 
'***********************************************************************
           'Tabela znakow do wyswietlania na wyswietlaczach:
'***********************************************************************
 
Tabela:
 Data 17 , 125 , 35 , 41 , 77 , 137 , 129 , 61 , 1 , 9
'znak: 0    1     2    3    4    5     6     7   8   9
 
'***********************************************************************

Czyżby źródłem problemów było dołożeniu grup SELECT CASE? Ale to chyba niemożliwe ...

Portret użytkownika mirley

Re:termostat

Teraz trzeba po kolei wszystko wpisywać. najpierw ten fragment:

If Zezw_wysw = 1 Then
  Reset Zezw_wysw                                             'co 4ms
  Wysw = Temp
  If Ur = 1 Then Gosub Przelicz
  Gosub Wyswietl
End If

podmień na:

If Zezw_wysw = 1 Then
  Reset Zezw_wysw                                             'co 4ms
  Select Case Poz_menu
    Case 0:
      Wysw = Temp
    Case 1:
      Wysw = Tmin
    Case 2:
      Wysw = Tmax
  End Select
  If Ur = 1 Then Gosub Przelicz
  Gosub Wyswietl
End If

i na początku programu ustaw Poz_menu = 0, nie powinno się nic zmienić. Potem ustaw na początku jakieś wartości dla Tmin i Tmax i kolejno zmieniaj w kodzie Poz_menu=1 i poz_menu=2 żeby zobaczyć czy wisywanie wartości do wyświetlania działa.

potem dodaj flagę do obsługi przycisków tylko w głównej pętli nie dawaj sprawdzania pinów a tylko jeśli flaga ustawiona to skasuj flagę i zmień stan diody na przeciwny. jeśli będzie migała około 5x na sekundę to jest ok.

potem dopiero reszta obsługi klawiatury a na samym końcu sterowanie przekaźnikiem czy czymś tam

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika j23nadaje

Termostat 2LED

Dziwna sprawa, Mirley - zrobiłem tylko tą podmianę i zadeklarowałem Poz_menu oraz nadałem jej wartość 0 na początku jak radziłeś ale efekt jest taki sam jak poprzednio - zgaszone wyświetlacze. Teraz wiem już na pewno, że program się jakoś zawiesza z powodu dodanej instrukcji SELECT CASE, natomiast kompletnie nie wiem, dlaczego. Bascom (używam wersji 8051 IDE 2.0.14.0 ściągniętej ze strony MCS) nie sygnalizuje błędów syntaktycznych i kompiluje kod bez problemu. Poza tym porównałem dla kodu PODST.BAS Twój plik BIN i skompilowany u mnie - zawartość obu jest identyczna. Może coś z programatorem? Dodam, że używam wprawdzie programatora na COM (układ 041 z Nowego Elektronika) - innego, niż zalecany przez Ciebie, ale dotąd (a mam go już jakiś czas) nie było z nim problemów. Ale nie przypominam też sobie, czy programowałem nim jakiś kod zawierający SELECT CASE ...

Portret użytkownika mirley

Re: Case

to daj zamiast tego 3 instrukcje if i po problemie :)

if Poz_menu = 0 then Wysw = Temp
if Poz_menu = 1 then Wysw = Tmin
if Poz_menu = 2 then Wysw = Tmax

Nie mam możliwości sprawdzenia nic na 2051 i podobnych bo już dawno przesiadłem się w całości na mikrokontrolery AVR

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika j23nadaje

Za dużo IF-ów ?

Zamieniłem SELECT CASE na kilka IF-ów:

Do
 
If Zezw_wysw = 1 Then
  Reset Zezw_wysw                                             'co 4ms
 
  If Poz_menu = 0 Then
    Wysw = Temp
  Else
    If Poz_menu = 1 Then
      If Miganie = 1 Then Wysw = Tmin Else Wysw = 255
    Else
      If Poz_menu = 2 Then
        If Miganie = 1 Then Wysw = Tmax Else Wysw = 255
      End If
    End If
  End If
 
  If Ur = 1 Then Gosub Przelicz
  Gosub Wyswietl
 
End If
 
If Zezw_przyciski = 1 Then                                    'co 100ms
  Reset Zezw_przyciski
 
  If Menu = 0 Then                                            'MENU
    Incr Sw_licz(1)
      If Sw_licz(1) = 10 Then
        Sw_licz(1) = 5
 
        Incr Poz_menu
        If Poz_menu = 3 Then Poz_menu = 0
 
      End If
  Else
    Sw_licz(1) = 8
  End If
 
End If
 
Loop
End

i jest to, co trzeba - przyciskiem MENU mogę zmieniać tryb wyswietlania: Temp oraz migająco Tmin i Tmax. Poszedłem za ciosem i dołożyłem w pętli flagi przycisków obsługę dwóch pozostałych Up i Down:

  If Up = 0 Then                                              'PLUS
    Incr Sw_licz(2)
      If Sw_licz(2) = 10 Then
        Sw_licz(2) = 5
 
        If Poz_menu = 1 And Tmin < 24 Then Incr Tmin
        If Poz_menu = 2 And Tmax < 30 Then Incr Tmax
 
      End If
  Else
    Sw_licz(2) = 8
  End If
 
  If Down = 0 Then                                            'MINUS
    Incr Sw_licz(3)
      If Sw_licz(3) = 10 Then
        Sw_licz(3) = 5
 
        If Poz_menu = 1 And Tmin > 20 Then Decr Tmin
        If Poz_menu = 2 And Tmax > 26 Then Decr Tmax
 
      End If
  Else
    Sw_licz(3) = 8
  End If

i niestety - wyświetlacze mam znowu zgaszone. Co ciekawe, jeśli zrezygnuję po jednym z najbardziej zagnieżdżonych IF-ów, to program działa (ale mam wtedy tylko możliwość zmiany albo Tmin albo Tmax). Próbowałem jeszcze zamienić warunki: If Up = 0 oraz If Down = 0 na 4 prostsze:

If Up = 0 And Poz_menu = 1
If Up = 0 And Poz_menu = 2
If Down = 0 And Poz_menu = 1
If Down = 0 And Poz_menu = 2

ale też nie chce to działać (działa tylko albo dla Poz_menu = 1 albo Poz_menu = 2). Czyżby tych IF-ów było za dużo? No ale jak to rozwiązać? W końcu 3 przyciski to chyba nie jakiś zbytek...

Zaiste, dziwny ten cały Bascom...

Portret użytkownika mirley

Re: Termostat

Myślę że powinieneś sciągnąć najnowszą wersję bascoma ze strony producenta i spróbować to przekompilować ponownie, a jak masz już najnowszą to coś starszego, może to wina kompilatora, mogli coś zepsuć w najnowszej wersji albo poprawić błąd jeśli był w starszej wersji. Już dawno nie używałem BASCOMA8051, teraz działam tylko na AVR

Możesz jeszcze spróbować napisać:

        If Poz_menu = 1 then
          if Tmin < 24 Then Incr Tmin
        end if
        If Poz_menu = 2 then
          if Tmax < 30 Then Incr Tmax
        end if

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika j23nadaje

Termostat - przyciski

Aktualnie korzystam z najnowszej wersji Bascom-8051 Demo 2.0.14.0 (2007), ściągniętej ze strony www.mcselec.com. Za radą Mirleya zainstalowałem poprzednią wersję, jaką miałem - 2.0.11.0 (2002), ale niestety nie rozwiązało to problemu.

Postanowiłem zatem, że zrezygnuję z przycisku Down, żeby może było prościej. Zatem ustawianie Tmin/Tmax będzie się odbywało tylko w górę (przyciskiem Up), po czym zmniejszane. Myślałem, że to coś pomoże:

  If Up = 0 Then
    Incr Sw_licz(2)
      If Sw_licz(2) = 10 Then
        Sw_licz(2) = 5
 
        If Poz_menu = 1 Then                      'Tmin
          Incr Tmin
          If Tmin = 25 Then Tmin = 20
        End If
 
        If Poz_menu = 2 Then                      'Tmax
          Incr Tmax
          If Tmax = 31 Then Tmax = 26
        End If
 
      End If
  Else
    Sw_licz(2) = 8
  End If

a tu znowu kicha... Rozdzielenie jednego warunku na dwa:

If Up = 0 And Poz_menu = 1 Then                    'Tmin
.
.
 Incr Tmin
 If Tmin = 25 Then Tmin = 20
.
.
End If
 
If Up = 0 And Poz_menu = 2 Then                    'Tmax
.
.
  Incr Tmax
  If Tmax = 31 Then Tmax = 26
.
.
End If

też nic nie daje. Program chodzi tylko wtedy, gdy zrezygnuję z ustawiania Tmin albo Tmax, ale to mnie nie satysfakcjonuje. Ręce mi już opadają... Czyżby wersja demo miała aż takie ograniczenia? Wolałbym nie przesiadać się na AVR, bo nie mam z tym żadnego doświadczenia i też nie mam pewności czy Bascom AVR sobie z tym poradzi.

Portret użytkownika mirley

Re: Wersja Demo

Wersja demo nie ma żadnych ograniczeń jesli chodzi o złożoność kodu tylko plik wynikowy nie może być większy niż 4kB. popatrz na moje programy, nigdy takie coś mi się nie działo a niekiedy mam case w casie. Wrzuć cały swój kod (plik bas wyslij na stronę za pomocą menadżera plików w swoim profilu i link podaj do niego) w wersji gdzie miałeś 3 przyciski (otworze go w bascomie to może mi się coś jeszcze nasunie) i zastosowane moje wcześniejsze wskazówki... rozdzielanie przycisków w taki sposób jak napisałeś wyżej to bez sensu.

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika j23nadaje

Termostat - 3 przyciski

Też dotychczas byłem przekonany, że wersje demo nie powinny mieć takich ograniczeń ale fakty (przynajmniej u mnie) niestety są takie jak opisane powyżej. Wiem, że znacznie bardziej złożone kody chodzą i to tym bardziej jest dołujące ale liczę też na Twoje znacznie większe doświadczenie i skuteczną pomoc.

Kod wersji 3-przyciskowej z Twoimi wskazówkami wrzuciłem na http://mirley.firlej.org/files/user_img/u353/TERM3K.BAS

P.S. Dziś jest prima aprilis ale kod jest na poważnie! Przy okazji życzę Wesołych Świąt i pozdrawiam :)