Attiny mit Timer und Taster

#3441951
Lesenswert?

Verstehe ich richtig, dass du auf Tastendruck einen Timer aktivierst?

Ohne etwas mehr Erklärung wird das wohl nichts werden. Wo fragst du den 
Taster ab? Der Timer läuft, wenn der Taster gedrückt ist, oder immer? 
Wird die Timer ISR dann periodisch aufgerufen, oder soll diese nur 
einmal ausgeführt werden?

Wenn die Tasterabfrage in der main Methode passiert, kannst du doch 
einfach den Timer wieder deaktivieren.

Du kannst auch alternativ den Taster als Interrupt Auslöser verwenden 
und in der main Methode die Arbeit erledigen und mittels Flag von der 
ISR in die main Methode signalisieren, was zu tun ist.

Eigentlich tappe ich aber im Dunklen, weil deine Angaben mehr als 
dürftig sind.
#3442228
Lesenswert?

Ups!!Da hab ich doch glatt vergessen den Code anzuhängen.War schon a 
bisi müde! :)
1
$regfile = "attiny13.dat"                                   'verwendeter Prozessor
2
$crystal = 1200000                                          'Definition des Takt
3
$hwstack = 15
4
$swstack = 15
5
$framesize = 15
6

7
Config Timer0 = Timer , Prescale = 1024                     'hier wird der timer configuriert
8
Timer0 = 57722
9

10
On Timer0 Ontimer1                                          'bei einem timerüberlauf springt der controller zu ontimer0
11

12

13

14
Config Pinb.2 = Input
15
Config Portb.1 = Output
16

17
Dim Zeit As Byte
18

19
Taster1 Alias Pinb.2
20

21

22
Hauptprogramm:
23
Do
24
If Taster1 = 0 Then Gosub Relais1
25

26
Loop
27

28

29
Relais1:
30
   Enable Timer0                                            'der timer wird eingeschaltet
31
   Enable Interrupts                                        'die interrupts werden eingeschaltet (hier nur der timer interrupt ist nötig dass der avr interrupts zulässt)
32
   Portb.1 = 1
33

34
      Do
35
         If Zeit < 1 Then
36
                                            ' wen die zeit Über 1 sekunde ist werden der timer und die interrupts wieder deaktiviert
37
            Disable Timer0
38
            Disable Interrupts
39
            Portb.1 = 0                                     'das relai fällt ab
40
            Goto Hauptprogramm                              'der controller verlässt die do loop schleife und kommt weider zum hauptprogramm zurück
41
         End If
42
      Loop
43
Return
44

45

46

47

48

49
Ontimer1:                                                   ' hier der timer interrupt
50
   Zeit = Zeit + 1                                          ' zeit wird um eins erhöht
51
   Timer0 = 57722
52
Return                                                      ' der timer bekommt einen wert dass er nicht die vollen 65535 takte zählen muss das würde länger als eine sekunde dauern
53
                                           ' der controller kehrt zum programm zurück
Angehängte Dateien:
#3442327
Lesenswert?

Tommy Tomatronic schrieb:
> Ups!!Da hab ich doch glatt vergessen den Code anzuhängen.

Ist das der Code, der zu deiner Ausgangsfrage im Eröffnungsposting 
gehört.

Denn dann
> Was fehlt da noch?

Antwort:
Ziemlich viel. Der ganze Prgorammaufbau ist mies.
Schmeiss ihn weg, überleg dir was anderes und probier das aus.


Hinweis: Der Ansatz mit dem Timer ist grundsätzlich ok. Das geht schon 
mal in die richtige Richtung.

Hinweis 2:
Grundsätzlich gibt es 2 verschiedene Möglichkeiten für eine derartige 
'Uhrenverwendung'. Man kann die Zeit positiv abzählen. Im Sinne von: ich 
zähle einen Zähler raus und wenn der eine bestimmte Zahl erreicht hat, 
ist die zu wartende Zeit um.
Man kanns aber auch anders rum machen: Der Zähler zählt nicht hoch und 
es wird auf das Erreichen eines bestimmten Zählerstandes geprüft, 
sondern man dreht das Pferd um. Ein Countdown. Der Zähler startet bei 
einem bestimmten Zählerstand und wenn 0 erreicht wird, dann ist die Zeit 
um.

Die zweite Lösung hat den Vorteil, dass das Prüfen der Endbedingung 
immer auf 0 erfolgt, was den Code öfter etwas vereinfacht, weil man 
keine variable Endbedingung braucht (wenn die Zeit variabel sein soll). 
Soll meine Uhr unterschiedliche Zeiträume abmessen können, dann geht das 
ganz einfach, in dem ich ihr eben jene unterschiedlichen Zeitan als 
Startwert vorgebe.

Funktionieren tut beides und man muss dann im Einzelfall entscheiden, 
was einfacher ist.

Hinweis 3:
Auch wenn immer wieder gesagt wird, dass Interrupt Routinen kurz sein 
sollen (was ja grundsätzlich auch stimmt), so bedeutet das nicht, dass 
man in ihnen gar nichts tun darf.
Wenn du dort einen Zähler erhöhst, dann darf man da durchaus auch in der 
ISR Prüfen, ob dieser Zählwert eine bestimmte Bedingung erfüllt und dann 
zb davon abhängig einen Ausgang schalten. In Summe ist das immer noch 
einfacher und schneller abgearbeitet, als irgendwelche anderen 
Konstrukte. Denn in dem Fall bedeutet das dann ganz einfach, dass die 
Hauptschleife eben nicht auf das Ablaufen der Zeitdauer warten muss und 
in der Zwischenzeit was anderes tun kann. Zum Beispiel einen weiteren 
Tastendruck auswerten. Die Hauptschleife startet einfach nur den Timer 
(eventuell unter Vorgabe einer zu wartenden Zeit, wenn es sich um einen 
Countdown-Zähler handelt), setzt einen Ausgang und die Interrupt Routine 
schaltet dann den Ausgang nach Ablauf der Zeit selbsttätig wieder ab.

Als Skizze
1
countdown = 0
2
timer starten
3
interrupt enable
4

5

6
do
7

8
  if( Taste gedrückt ) then
9
    Ausgang ein schalten
10
    countdown = 5
11
  end if
12

13
loop
14

15
OnTimer
16
  if countdown > 0 then
17
    countdown = countdown - 1
18
    if countdown = 0 then
19
      Ausgang aus schalten
20
    endif
21
  endif
22
  return


da solltest du jetzt auch eine Möglichkeit finden, wie du ein 
vorzeitiges Ende mittels Tastendruck einbauen kannst. Hinweis: Du weißt 
das die Wartezeit noch nicht abgelaufen ist, wenn die Variable countdown 
einen Wert ungleich 0 besitzt.

D.h. du kannst hier
1
do
2

3
  if( Taste gedrückt ) then
4

5
    ****************
6

7
    Ausgang ein schalten
8
    countdown = 5
9
  end if
anhand des aktuellen Wertes in countdown unterscheiden, ob ein 
Tastendruck den Zähler ein oder ausschalten soll.
Beachte auch, dass ich durch die Systematik jetzt auch nicht mehr 
laufend den Timer starten/stoppen bzw. Interrupts ein ausschalten muss. 
Denn wenn Countdown bereits auf 0 steht, dann macht die Interrupt 
Routine einfach nichts mehr. Damit ist es aber egal, ob der Timer läuft 
oder nicht. Und im Zweifelsfall entscheide ich mich dann für die 
einfachere Variante, in der ich mich um den Timer selbst im weiteren 
Programmverlauf nicht mehr kümmern muss.


Hinweis 3:
Das hier
1
If Taster1 = 0 Then
ist auch in BASCONM keine vernünftige Methode um einen Tastendruck zu 
erkennen. BASCOM macht es dir insofern leicht, als es dafür den Befehl 
"DEBOUNCE" gibt. Man mag dazu stehen wie man will, aber das ist nun mal 
die BASCOM Methode um einen Tastendruck zu erkennen.
#3442704
Lesenswert?

Himmel,Arsch und Zwirn!! :)

Das wird nix! Hat niemand eine fertige Lösung für mich?Ich bin schon am 
verzweifeln.Da kann doch nichts dabei sein,habe ich mir gedacht.Da ist 
doch nix dran.Aber es will einfach nicht sein.
Also ganz einfach!
Ich möchte:Wenn ich Portb.2 mit einem Taster 0,3sek lang auf Gnd 
ziehe,soll Portb.1 60 min auf High schalten.Wenn ich innerhalb der 60 
min wieder Portb.2 für 0,3 auf low ziehe,soll Portb.1 auch schon auf low 
schalten.
Das ganze mit einem ATtiny13 oder 45.
Danke für eure mühen!!
#3442801
Lesenswert?

Nochmal:
wo ist DEIN Code?

Den Code von pfff hab ich nicht näher studiert, der ist mir zu 
umfangreich für die Aufgabenstellung.
ABer ich weiß 100%-ig, dass das weiter oben skizzierte Framework die 
Aufgabe mit Leichtigkeit lösen kann. Also: wie hast du die Skizze 
umgesetzt?
#3442814
Lesenswert?

Tommy Tomatronic schrieb:
> Karl Heinz schrieb:
>> Also: wie hast du die Skizze
>> umgesetzt?
>
> Ich hab da ungefähr 20 - 30 mal rumgestrickt

Zeigen

> Ich bin einfach zu doof für so was vermutlich leichtes. :)
Die Umstellung in der Denkweise ist das schwierige.
Der Rest ist reines Anwenden der BASCOM Syntax an den Stellen, die ich 
lapidar einfach in Deutsch formuliert habe bzw. Ergänzen von 
Standardsachen, wie Variablendefinition oder Konfiguration von I/O Pins.
Gast #3442849
Lesenswert?

bei mir ist da ein externer widerstand als pullup dran.
also sieht er die taste garnicht.
also hinter
config pinb.1 = input    ' schalte port auf in
portb.1 = 1              ' schalte pullup für pin ein

aber du solltest mal bei halvar rein schauen!
#3443247
Lesenswert?

So jetzt hats gereicht!! :)
Jetzt hab ich da ein Uhrenprogramm hergenommen und das umgstrickt,dass 
es mit dem ATtiny45 läuft es funktioniert sogar. :)
Etwas schöner muss ich das noch schreiben aber es funzt! :) :) :)


$regfile = "attiny45.dat"                                   'verwendeter 
Prozessor
$crystal = 8000000                                          'Definition 
des Takt
$hwstack = 15 
'Reservierung im SRAM
$swstack = 15
$framesize = 15

'*** Ports 
konfigurieren********************************************************

Ddrb = &B00001100
Portb = &B00000011

On Timer1 Ontimer1
Config Timer1 = Timer , Prescale = 1024
Enable Timer1

Enable Interrupts

Dim Wert As Byte
Dim Multiplex As Byte
Dim Hsek_einer As Byte
Dim Hsek_zehner As Byte
Dim Sek_einer As Byte
Dim Sek_zehner As Byte
Dim Min_einer As Byte
Dim Min_zehner As Byte
Dim Std_einer As Byte
Dim Std_zehner As Byte

Declare Sub Minute
Declare Sub Stunde

Multiplex = 1
Timer1 = 51803

Stop Timer1

Do
   Debounce Pinb.0 , 0 , Minute , Sub
   Debounce Pinb.1 , 0 , Stunde , Sub
Loop

'*** Sub-Routinen 
**************************************************************
Sub Minute

    Start Timer1
    Portb.3 = 1
End Sub

Sub Stunde

    Stop Timer1
Hsek_einer = 0
Hsek_zehner = 0
Sek_einer = 0
Sek_zehner = 0
Portb.3 = 0
Portb.2 = 0

End Sub

'*** Interrupt-Routinen 
********************************************************
Ontimer1:                                                   'Aufruf im 
Sekundentakt
   Timer1 = 51803 
'65536-15625=49911 =1Hz

   Incr Hsek_einer

     If Hsek_einer >= 7 Then
      Hsek_einer = 0

      Incr Hsek_zehner
   End If

     If Hsek_zehner >= 7 Then
      Hsek_zehner = 0

      Incr Sek_einer
      Toggle Portb.2
   End If

   If Sek_einer = 40 Then

      Portb.3 = 0
      Return


   End If

   Return
   End

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren