Nietypowy przerywacz na Tiny13


Witam wszystkich.

Piszę tu bo już mi ręce opadają. Nie chciałbym zawracać głowy tak błahym problemem, ale już nie wiem co zrobić. Dodam że jestem początkującym "bascomowcem" :-)

Brat wmontował zwykłą domową klimatyzacje do kombajnu sąsiada i potrzebuje prostego sterownika który by co 2 minuty na 20 sekund wyłączał cały system (długo by tu pisać), ale mniejsza z tym. Z początku było to zrobione na ne555 i odpowiednich kondensatorach ale to się nie sprawdziło więc trzeba było coś innego wymyślić.

Powiedziałem że takie coś jest proste i wykonam mu to na małym tiny13. Zaprojektowałem układ który jest widoczny na schemacie poniżej, wykonałem płytkę, polutowałem i przystąpiłem do programowania.

I tu zaczynają się schody. Początkowo zrobiłem programik na 10 linijek kodu z komendami set, reset wait w pętli do loop. Niestety komenda wait 20 czasami trwała minutę a wait 120 5 minut itp. Dlatego chciałem to zrobić na timerze który jest rzekomo dokładny lecz też mam problem.

Proszę o jakiekolwiek wskazówki jak zrobić program poprawnie, bo niby udało mi się obliczyć jedną sekundę na timerze ale jak już ich chcę zliczyć 20 to na stoperze wychodzi 13 itp.

Dla sprawdzenia zrobiłem w samym przerwaniu tak by co 20s zmieniał się stan diody na przeciwny, a docelowo ma się zmieniać to jak pisałem wyżej w pętli głównej.

Co do mikrokontrolera - częstotliwość wewnętrzna 9,6MHz, włączony dzielnik na 8. W tym momencie obliczenia timera wyglądają tak:

9600000/8=1200000

1200000/64=18750 (prescaler timera)

18750/250=75 (wartość do zliczenia w timere to 250)

W IFie jest liczona 75 razy co daje sekundę.

Poniżej schemat od kod jaki teraz mam:

$crystal = 9600000
$regfile = "attiny13a.dat"
$hwstack = 10
$swstack = 10
$framesize = 20
 
 
 
 
 
Config Pinb.4 = Output
Config Timer0 = Timer , Prescale = 64
 
 
 
 
On Timer0 Odmierz_1s
 
'Declare Sub Czas
 
Dim Licz_ms As Byte
Dim Sek As Byte
Dim Odlicz As Byte
 
Sek = 0
 
 
Enable Interrupts
 
Enable Timer0
 
Load Timer0 = 250
 
 
 
 
 
 
Do
 
   'Set Pinb.4
 
'    Do
 
'    Loop Until Sek = 1
'    Sek = 0
 
 
 
'   'Odlicz = 2 : Call Czas
'   Reset Pinb.4
'    Do
 
'    Loop Until Sek = 12
'    Sek = 0
 
 
 
 
   'Odlicz = 12 : Call Czas
 
 
Loop
End
 
 
 
 
'Sub Czas:
'Load Timer0 = 250
'Sek = 0
'Start Timer0
'Do
 
'Loop Until Sek = Odlicz
'Stop Timer0
'End Sub
 
 
 
 
 
Odmierz_1s:
 
   Load Timer0 = 250
   Incr Licz_ms
 
   If Licz_ms = 75 Then
 
 
      Licz_ms = 0
      'Toggle Portb.4
      Incr Sek
 
         If Sek = 20 Then
            Toggle Portb.4
            Sek = 0
         End If
 
 
 
 
 
   End If
 
 
 
Return




Portret użytkownika mirley

Re: Timer tiny13

Jeśli dobrze ustawiłeś fusebity i masz dzielenie przez 8 włączone to w pierwszej linii ma być:

$crystal = 9600000

Poza tym zamiast load timer0= 250 które kiedyś mi nie działało załaduj po prostu do timera wartość 6 (256-250) wpisując Timer0 = 6 zamiast Load timer0 = 250

Ponadto powinieneś skonfigurować cały port i ustawić stan początkowy wszystkich pinów za pomocą:

Config portb=$B11111111 : Portb=$B11101111

Odpowiednio przestaw końcówki na wejścia wstawiając 0 w odpowiednie bity $BXXXXXXXX po poleceniu Config i stan początkowy do drugiej wartości binarnej

-

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 mareks6

no więc tak, co do fusów - z

no więc tak, co do fusów - z fabrycznego ustawienia nic nie zmieniałem bo tiny13 na dzień dobry ma on ustawione 9,6MHz oraz dzielenie przez 8.
Jak widać w pierwszej lini mam wpisaną częstotliwość o której pisałeś.

Co do load timer0=250 lub timer0=6 - to już też próbowałem i jedno i drugie działa tak samo, tzn pojedynczą sekunde liczy mi poprawnie co obserwuje w przerwaniu dzięki komendzie toggle, lecz jak już chcę gdzieś zliczyć kilka sekund (zarówno w pętli głównej jak i w samym przerwaniu timera) to przy zliczonych 20 stoper pokazuje mi 13...

Co do portu - muszę konfigurować cały nawet jak korzystam tylko z jednego pinu?

Zmodyfikowałem program oraz usunąłem wszystko co zbędne - wpierw skupiłem się na poprawnym odmierzeniu 20 sekund i udało się. w przerwaniu liczy mi 20s i zmienia stan diody, porównałem ze stoperem. Teraz postaram się pozmieniać program tak by przerwanie liczyło sekundę a reszta była w pętli głównej programu.

Obecny listing jest poniżej,

$crystal = 9600000
$regfile = "attiny13a.dat"
$hwstack = 10
$swstack = 10
$framesize = 20
 
 
 
 
Config Portb = $b11111111 : Portb = $b11101111
Config Timer0 = Timer , Prescale = 64
 
On Timer0 Odmierz_1s
 
Dim Licz_ms As Byte
Dim Sek As Byte
 
 
Sek = 0
 
 
Enable Interrupts
 
Enable Timer0
 
Timer0 = 6
 
 
 
Do                                                          'pętla głowna
 
 
Loop
End
 
 
 
 
Odmierz_1s:                                                 'odmierzanie 1 sekundy
 
   Timer0 = 6
   Incr Licz_ms
 
   If Licz_ms = 75 Then
 
 
      Licz_ms = 0
      'Toggle Portb.4
      Incr Sek
 
         If Sek = 20 Then
            Toggle Portb.4
            Sek = 0
         End If
 
 
 
 
 
   End If
 
 
 
Return

Portret użytkownika mirley

Tiny 13

W pierwszej linii masz mieć:

$crystal = 1200000

Jeśli nie tykałeś fusów mikrokontrolera

-

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 mareks6

aaa, teraz rozumiem - czyli

aaa, teraz rozumiem - czyli crystal sie wpisuje taki jaki faktycznie jest podlaczony tylko gdy podzial przez 8 jest wylączony, a w moim przypadku wpisuje tam to co podlaczone i podzielone przez 8.

zmienie to i sprawdze

Portret użytkownika mirley

Re: taktowanie

dokładnie tak, wpisujesz częstotliwość jaką jest taktowany procek.... według mnie ktoś bardzo głupio nazwał ten parametr i temu się teraz myli

-

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 mareks6

obecny kod

pozmieniałem i uzupełniłem kod tak by działał jak potrzebuję ale mam znów problem. Zauważyłem że poszczególne czasy jakie mają być dla włączonego i wyłączonego przekaźnika są sumowane i przekaźnik zmienia swój stan na przeciwny w równych odstępach. Na przykład ustawiłem SET na 5 sekund a RESET na 22 i po uruchomieniu przekaźnik się włącza i wyłącza na przemiennie w odstępach czasowych 27 sekund. Jakieś wskazówki? Oto kod:

$crystal = 1200000
$regfile = "attiny13a.dat"
$hwstack = 10
$swstack = 10
$framesize = 20
 
 
 
 
Config Portb = $b11111111 : Portb = $b11101111
Config Timer0 = Timer , Prescale = 64
 
 
 
 
On Timer0 Odmierz_1s
 
 
Dim Licz_ms As Byte
Dim Sek As Byte
 
Sek = 0
 
 
Enable Interrupts
 
Enable Timer0
 
 Timer0 = 6
 
 
 
 
Do
 
 
 Set Pinb.4
 
    Do
 
    Loop Until Sek = 5
    Sek = 0
 
 
 
 
 Reset Pinb.4
    Do
 
    Loop Until Sek = 22
    Sek = 0
 
 
 
Loop
End
 
 
 
Odmierz_1s:
 
 
   Incr Licz_ms
 
   If Licz_ms = 75 Then
 
 
      Licz_ms = 0
      'Toggle Portb.4
 
      Incr Sek
 
         'If Sek = 20 Then
        '    Toggle Portb.4
        '    Sek = 0
        ' End If
 
 
   End If
 
    Timer0 = 6
 
Return

UDAŁO MI SIĘ W KOŃCU TO ZROBIĆ, a oto kod

$crystal = 1200000
$regfile = "attiny13a.dat"
$hwstack = 10
$swstack = 10
$framesize = 20
 
 
 
 
Config Portb = $b11111111 : Portb = $b11101111
Config Timer0 = Timer , Prescale = 64
 
 
 
 
On Timer0 Odmierz_1s
 
 
Dim Licz_ms As Byte
Dim Sek As Byte
 
Sek = 0
 
 
Enable Interrupts
 
Enable Timer0
 
 Timer0 = 6
 
 
 
 
Do
 
 
 Portb.4 = 1
 
    Do
 
    Loop Until Sek = 120
    Sek = 0
 
 
 
 
 Portb.4 = 0
    Do
 
    Loop Until Sek = 10
    Sek = 0
 
 
 
Loop
End
 
 
 
Odmierz_1s:
 
 
   Incr Licz_ms
 
   If Licz_ms = 75 Then
 
 
      Licz_ms = 0
 
      Incr Sek
 
   End If
 
    Timer0 = 6
 
Return

Portret użytkownika mirley

Re: Timer

To trochę bez sensu.... pętla do loop główna stoi w miejscu a po to masz timer żeby nie stała w miejscu..... jak będziesz chciał coś teraz zrobić żeby co 100ms np dioda migała to jak to wykonasz.... użyj flagi tak jak ja to robię w programach... W przerwaniu tam gdzie masz incr Sek daj set F_1s, gdzie F_1s jest zmienną typu bit. Potem w pętli głównej:

Do
if F_1s=1 Then
  F_1s=0
 
  'ten kod będzie wykonywany raz na sekundę
  incr Sek
  If Portb.4 = 1 Then
   if Sek = 5 Then      'czas działania
     Sek=0
     portb.4=0
   End if
  Else
   if Sek = 22 Then      'czas przerwy
     Sek=0
     portb.4=1
   End if
  End if 
End if
 
 
'tutaj inne polecenia albo obsługa innej flagi np co 100ms itd
 
Loop

-

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.