Verzweifelung bei simpler Zeitschaltung

gerd51

Mitglied
18. Jan. 2013
43
0
6
Sprachen
  1. BascomAVR
Hallo Freunde der hohen Programmierkunst,

nach krankheitsbedingter längerer Enthaltsamkeit vonPc und Lötkolben greife ich jetzt wieder an. Natürlich mit einem Problem!!:mad::mad:

Da mein UV Belichter durch jahrelangen Nichtgebrauch irgendwohin diffundiert ist, eine neuer einiges kostet, habe ich mich zum Selbstbau mittels 300 UV-LEDs (bei ebay für sehr kleines Geld zu bekommen) entschieden.
Hardware ist fertig und funktioniert. (Wenn Intersse besteht kann ich Schaltung un Layout zur Verfügung stellen). Die Software läuft auch und macht fast alles was sie soll, nur nicht auf Knopfdruck starten.

Die Idee: Über zwei Taster wird die Belichtungszeit eingestellt und durch einen weiteren Tastendruck der Countdown und über Relais die Beleuchtung gestartet. Den Zeitverlauf kann man über eine 7-Seg Anzeige verfolgen.
Nach Ablauf der Zeit stoppt der Timer und die Relais schalten erneut. (Mehrere Relais, da ich ein dreiteiliges Netzteil gebaut habe mit drei äquivalenten Ausgängen)

Zeit kann ich stellen, den Countdown starten nicht :confused::mad::banghead:

Code:
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
Ddrd = &B01111111
Ddrb = &B11111111
Ddrc = &B00000111
Config Portb = Output

Config Portc.0 = Output
Relais1 Alias Portc.0
Relais1 = 0

Config Portc.1 = Output
Relais2 Alias Portc.1
Relais2 = 0

Config Portc.2 = Output
Relais3 Alias Portc.2
Relais3 = 0

Config Pinc.3 = Input
Portc.3 = 1
Taster_sekundenstellen Alias Pinc.3

Config Pinc.4 = Input
Portc.4 = 1
Taster_minutenstellen Alias Pinc.4

Config Pinc.5 = Input
Portc.5 = 1
Taster_start Alias Pinc.5

Config Pind.7 = Output
Led Alias Portd.7




'Sekundentakt erzeugen
On Timer1 Ontimer1
Config Timer1 = Timer , Prescale = 256                      '1Hz
Tcnt1 = 34286
Enable Timer1
Stop Timer1


'Multiplexfrequenz erzeugen
On Timer0 Ontimer0
Config Timer0 = Timer , Prescale = 64
Enable Timer0
Tcnt0 = 224

Enable Interrupts


Dim Wert As Byte
Dim Multiplex As Word
Dim Sek_einer As Byte
Sek_einer = 5                                               'Testeinstellung
Dim Sek_zehner As Byte
Sek_zehner = 2                                              'Testeinstellung
Dim Min_einer As Byte
Min_einer = 2                                                'Testeinstellung
Dim Min_zehner As Byte
Min_zehner = 1                                               'Testeinstellung

multiplex =1
'Main

Do

Debounce Taster_sekundenstellen , 0 , Sekunden_stellen , Sub
Debounce Taster_minutenstellen , 0 , Minuten_stellen , Sub
Debounce Taster_start , 0 , Los , Sub

Loop





Ontimer1:
 Tcnt1 = 34286
 Toggle Led

 If Sek_einer > 0 Then
     Decr Sek_einer
        Else
          If Sek_zehner > 0 Then
               Decr Sek_zehner
               Sek_einer = 9
                  Else
                    If Min_einer > 0 Then
                       Decr Min_einer
                       Sek_zehner = 5
                       Sek_einer = 9
                            Else
                              If Min_zehner > 0 Then
                                  Decr Min_zehner
                                  Min_einer = 9
                              End If
                    End If
           End If
  End If

' -------------------Uhr ist auf Null gelaufen-----------------
                       '
   If Sek_einer = 0 And Sek_zehner = 0 And Min_einer = 0 And Min_zehner = 0 Then
   Stop Timer1
   Relais1 = 1 : Relais2 = 1 : Relais3 = 1
   End If
   Return




'-----------------Interrupt-Routinen -----------------------------

Ontimer0:


 Tcnt0 = 224                                               

   'Hier wird die Umschaltsequenz (Multiplexen)  erzeugt!
   Multiplex = Multiplex * 2                                '1,2,4,8,
   If Multiplex = 16 Then Multiplex = 1



   Portd = &B00000000                                       'Alle Segmente vor dem Umschalten ausschalten
   Portb = Multiplex



   If Multiplex = 1 Then Wert = Sek_einer                   'Ab hier erfolgt die Zuordnung von Anzeige und Wert
   If Multiplex = 2 Then Wert = Sek_zehner
   If Multiplex = 4 Then Wert = Min_einer
   If Multiplex = 8 Then Wert = Min_zehner



   'Hier erfolgt die die Auswahl (Dekodierung) welche Segmente leuchten sollen
   Select Case Wert
      Case 0
         Portd = &B00111111                                 '0
      Case 1
         Portd = &B00000110                                 '1
      Case 2
         Portd = &B01011011                                 '2
      Case 3
         Portd = &B01001111                                 '3
      Case 4
         Portd = &B01100110                                 '4
      Case 5
         Portd = &B01101101                                 '5
      Case 6
         Portd = &B01111101                                 '6
      Case 7
         Portd = &B00000111                                 '7
      Case 8
         Portd = &B01111111                                 '8
      Case 9
         Portd = &B01101111                                 '9
      Case Else
         Portd = &B00000000                                 'Anzeige dunkel schalten
   End Select

Return

'------------------Stell-Routine für Sekunden------------
Sekunden_stellen:

 Incr Sek_einer

      If Sek_einer = 10 Then
               Sek_einer = 0
                Sek_zehner = Sek_zehner + 1

                  If Sek_zehner = 6 Then
                     Sek_zehner = 0
                  End If
            End If

Return

'------------------Stell-Routine für Minuten------------

Minuten_stellen:

Incr Min_einer

  If Min_einer = 10 Then
              Min_einer = 0
               Min_zehner = Min_zehner + 1

                  If Min_zehner = 6 Then
                     Min_zehner = 0
                  End If
  End If

Return


'-----------------Start Countdown---------------

Los:

 Relais1 = 0 : Relais2 = 0 : Relais3 = 0
    Start Timer1
    Return

Return

Vielleicht kann mal jemand von euch drüberschauen. Ist mit Sicherheit ein saublöder Fehler (sind Fehler nicht immer saublöd??), aber ich steh völlig auf dem Schlauch.
Vorerst schon mal vielen Dank

Gerd
 
hm,
ich finde deine verschachtelte IF Anweisung bei ontimer1 etwas unglücklich.
Code:
Ontimer1:
 Tcnt1 = 34286
 Toggle Led

 If Sek_einer > 0 Then
     Decr Sek_einer
        Else
          If Sek_zehner > 0 Then
               Decr Sek_zehner
               Sek_einer = 9
                  Else
                    If Min_einer > 0 Then
                       Decr Min_einer
                       Sek_zehner = 5
                       Sek_einer = 9
                            Else
                              If Min_zehner > 0 Then
                                  Decr Min_zehner
                                  Min_einer = 9
                              End If
                    End If
           End If
  End If

weiß jetzt nicht wie das mit der Uhr abläuft. Aber wenn die Sekunden auf null sind, macht der bei den Minuten nicht weiter.
Ich würde das alles in Sekunden umwandeln.
Macht die Sache einfacher.
Funktioniert der Sekundentakt?
Zum testen mal ne Diode im Takt schalten lassen.

Gruß
Tenor
 
Hallo Tenor,

es funktioniert alles. Wenn ich die Stop-TimerAnweisung im Dekjlarationsteil entferne läuft alles wie geschmiert. Ich kann auch bei laufendem Countdown die Zeiteinstellung verändern, was natürlich keinen Sinn macht, aber es klappt.
Nur wenn der Timer anfangs gestoppt ist, läßt er sich nicht wieder anwerfen.

Deine übrigen Bedenken sind also grundlos.

Gruß
Gerd
 
Timer 1 soll dir doch den Sekundentakt liefern, dieser kann doch nicht kommen wenn du den timer vorher stoppst (wie in der Deklaration).

Dachte erst das du die Config neu laden müsstest nachdem du den Timer gestoppt hast:
If CONFIG TIMERx = option , CONFIGURATION=mysetting

was used, you would specify START TIMERx, mysetting.
siehe Bascom Hilfe.

Wird aber daran liegen das der Event Ontimer 1 niemals kommt, da der Timer gestoppt ist.

Gruß
Tenor
 
Timer 1 soll dir doch den Sekundentakt liefern, dieser kann doch nicht kommen wenn du den timer vorher stoppst (wie in der Deklaration).

Hallo,

habe eben nur mal schnell über Dein Listing gesehen.
Was mir da auch aufgefallen ist, ist das der Timer1 erst gar nicht loslaufen kann. Dieser soll doch den Sekundentakt liefern.
Du gibst zwar kurz den Timer1 frei, um ihn aber gleich danach wieder zu stoppen. Hast Du das zu Testzwecken so umgesetzt?
Mit der globalen Freigabe der Interrupts (SREG.7 = 1) erlaubst Du nur, dass Interrupts zugelassen werden.

Der Sekundentakt sollte doch eigentlich "lösgelöst" vom restlichen Programm funktionieren.
Vorschlag - falls noch nicht geschehen: Lass doch im Sekundentakt einen Port toggeln.

Wegen den IF-THEN-ELSE- Anweisungen:
Hier könntest Du gff. mit dem Select-Case arbeiten...
Würde die Sache evtl. einfacher machen.

MfG
FreeVee
 
Hallo FreeVee,

der Timer1 und damit der Sekundentakt soll erst mit Drückem der Starttaste "losgelassen" werden. Zum Stellen genügt einfach das Stelltasterdrücken.

Aber genau da liegt das Problem: wie gesagt alles funktioniiert, wie es soll: Die Voreingestellte Zeit erscheint auf dem Display. mit Hilfe der Stelltasten kann ich diese verändern. Habe ich jetzt die richtige Zeit eingestellt. drücke ich die "Los"-Taste und ...nichts.
Gebe ich den Timer im Deklarationsteil frei, verzichte also auf das statement "Stop Timer1" läüft die Zeit unmittelbar nach Inbetriebnahme ab.Am Ende hält der Timer ordnungsgemäß an, das Display steht auf "00:00" und die Relais schalten das Licht ab.

Gruß
Gerd
 
Hallo FreeVee,

der Timer1 und damit der Sekundentakt soll erst mit Drückem der Starttaste "losgelassen" werden. Zum Stellen genügt einfach das Stelltasterdrücken.

Aber genau da liegt das Problem: wie gesagt alles funktioniiert, wie es soll: Die Voreingestellte Zeit erscheint auf dem Display. mit Hilfe der Stelltasten kann ich diese verändern. Habe ich jetzt die richtige Zeit eingestellt. drücke ich die "Los"-Taste und ...nichts.
Gebe ich den Timer im Deklarationsteil frei, verzichte also auf das statement "Stop Timer1" läüft die Zeit unmittelbar nach Inbetriebnahme ab.Am Ende hält der Timer ordnungsgemäß an, das Display steht auf "00:00" und die Relais schalten das Licht ab.

Gruß
Gerd


Hallo,
ah, jetzt habe ich verstanden, was Du vorhast.

Trotzdem wäre es besser, wenn Du den Timer zu Beginn starten würdest.

Das einzigste, was Du nur noch einfügen musst, ist ein Flag, welches eben nach Betätigung des entsprechenden Tasters gesetzt wird.
Dieses Flag fragst Du dann VOR Beginn Deiner eigentlichen Zählroutine ab und startest damit Deine eigentliche Zählroutine.

MfG

FreeVee
 
Hallo FreeVee,

die Idee ist gut, habe ich gemacht und rate was passiert, richtig: nichts

Hier die Änderung, hoffentlich stimmt die. Kann nach einer Nacht und einem Tag den Mist schon nicht mehr sehen. Nennt man wohl: Betriebsblindheit.
Gruß
Gerd

Code:
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
Ddrd = &B01111111
Ddrb = &B11111111
Ddrc = &B00000111
Config Portb = Output

Config Portc.0 = Output
Relais1 Alias Portc.0
Relais1 = 0

Config Portc.1 = Output
Relais2 Alias Portc.1
Relais2 = 0

Config Portc.2 = Output
Relais3 Alias Portc.2
Relais3 = 0

Config Pinc.3 = Input
Portc.3 = 1
Taster_sekundenstellen Alias Pinc.3

Config Pinc.4 = Input
Portc.4 = 1
Taster_minutenstellen Alias Pinc.4

Config Pinc.5 = Input
Portc.5 = 1
Taster_start Alias Pinc.5

Config Pind.7 = Output
Led Alias Portd.7




'Sekundentakt erzeugen
On Timer1 Ontimer1
Config Timer1 = Timer , Prescale = 256                      '1Hz
Enable Timer1
Tcnt1 = 34286


'Multiplexfrequenz erzeugen
On Timer0 Ontimer0
Config Timer0 = Timer , Prescale = 64
Enable Timer0
Tcnt0 = 224

Enable Interrupts


Dim Wert As Byte
Dim Multiplex As Word
Dim Sek_einer As Byte
Sek_einer = 5                                               'Testeinstellung
Dim Sek_zehner As Byte
Sek_zehner = 2                                              'Testeinstellung
Dim Min_einer As Byte
Min_einer = 2                                                'Testeinstellung
Dim Min_zehner As Byte
Min_zehner = 1                                               'Testeinstellung
Dim Tasterflag As Bit
Tasterflag = 0

multiplex =1
'Main

Do

Debounce Taster_sekundenstellen , 0 , Sekunden_stellen , Sub
Debounce Taster_minutenstellen , 0 , Minuten_stellen , Sub
Debounce Taster_start , 0 , Los , Sub

Loop





Ontimer1:

 Tcnt1 = 34286

 If Tasterflag = 1  then


 If Sek_einer > 0 Then
     Decr Sek_einer
        Else
          If Sek_zehner > 0 Then
               Decr Sek_zehner
               Sek_einer = 9
                  Else
                    If Min_einer > 0 Then
                       Decr Min_einer
                       Sek_zehner = 5
                       Sek_einer = 9
                            Else
                              If Min_zehner > 0 Then
                                  Decr Min_zehner
                                  Min_einer = 9
                              End If
                    End If
           End If
  End If

  End If

' -------------------Uhr ist auf Null gelaufen-----------------
                       '
   If Sek_einer = 0 And Sek_zehner = 0 And Min_einer = 0 And Min_zehner = 0 Then
   Stop Timer1
   Relais1 = 1 : Relais2 = 1 : Relais3 = 1
   
   Tasterflag = 0
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
Ddrd = &B01111111
Ddrb = &B11111111
Ddrc = &B00000111
Config Portb = Output

Config Portc.0 = Output
Relais1 Alias Portc.0
Relais1 = 0

Config Portc.1 = Output
Relais2 Alias Portc.1
Relais2 = 0

Config Portc.2 = Output
Relais3 Alias Portc.2
Relais3 = 0

Config Pinc.3 = Input
Portc.3 = 1
Taster_sekundenstellen Alias Pinc.3

Config Pinc.4 = Input
Portc.4 = 1
Taster_minutenstellen Alias Pinc.4

Config Pinc.5 = Input
Portc.5 = 1
Taster_start Alias Pinc.5

Config Pind.7 = Output
Led Alias Portd.7




'Sekundentakt erzeugen
On Timer1 Ontimer1
Config Timer1 = Timer , Prescale = 256                      '1Hz
Enable Timer1
Tcnt1 = 34286


'Multiplexfrequenz erzeugen
On Timer0 Ontimer0
Config Timer0 = Timer , Prescale = 64
Enable Timer0
Tcnt0 = 224

Enable Interrupts


Dim Wert As Byte
Dim Multiplex As Word
Dim Sek_einer As Byte
Sek_einer = 5                                               'Testeinstellung
Dim Sek_zehner As Byte
Sek_zehner = 2                                              'Testeinstellung
Dim Min_einer As Byte
Min_einer = 2                                                'Testeinstellung
Dim Min_zehner As Byte
Min_zehner = 1                                               'Testeinstellung
Dim Tasterflag As Bit
Tasterflag = 0

multiplex =1
'Main

Do

Debounce Taster_sekundenstellen , 0 , Sekunden_stellen , Sub
Debounce Taster_minutenstellen , 0 , Minuten_stellen , Sub
Debounce Taster_start , 0 , Los , Sub

Loop





Ontimer1:

 Tcnt1 = 34286

 If Tasterflag = 1  then


 If Sek_einer > 0 Then
     Decr Sek_einer
        Else
          If Sek_zehner > 0 Then
               Decr Sek_zehner
               Sek_einer = 9
                  Else
                    If Min_einer > 0 Then
                       Decr Min_einer
                       Sek_zehner = 5
                       Sek_einer = 9
                            Else
                              If Min_zehner > 0 Then
                                  Decr Min_zehner
                                  Min_einer = 9
                              End If
                    End If
           End If
  End If

  End If

' -------------------Uhr ist auf Null gelaufen-----------------
                       '
   If Sek_einer = 0 And Sek_zehner = 0 And Min_einer = 0 And Min_zehner = 0 Then
   
   Relais1 = 1 : Relais2 = 1 : Relais3 = 1
   
   Tasterflag = 0
End if

   Return




'-----------------Interrupt-Routinen -----------------------------

Ontimer0:


 Tcnt0 = 224                                                '16Mhz/256/(256-100)= 400Hz

   'Hier wird die Umschaltsequenz (Multiplexen)  erzeugt!
   Multiplex = Multiplex * 2                                '1,2,4,8,
   If Multiplex = 16 Then Multiplex = 1



   Portd = &B00000000                                       'Alle Segmente vor dem Umschalten ausschalten
   Portb = Multiplex



   If Multiplex = 1 Then Wert = Sek_einer                   'Ab hier erfolgt die Zuordnung von Anzeige und Wert
   If Multiplex = 2 Then Wert = Sek_zehner
   If Multiplex = 4 Then Wert = Min_einer
   If Multiplex = 8 Then Wert = Min_zehner



   'Hier erfolgt die die Auswahl (Dekodierung) welche Segmente leuchten sollen
   Select Case Wert
      Case 0
         Portd = &B00111111                                 '0
      Case 1
         Portd = &B00000110                                 '1
      Case 2
         Portd = &B01011011                                 '2
      Case 3
         Portd = &B01001111                                 '3
      Case 4
         Portd = &B01100110                                 '4
      Case 5
         Portd = &B01101101                                 '5
      Case 6
         Portd = &B01111101                                 '6
      Case 7
         Portd = &B00000111                                 '7
      Case 8
         Portd = &B01111111                                 '8
      Case 9
         Portd = &B01101111                                 '9
      Case Else
         Portd = &B00000000                                 'Anzeige dunkel schalten
   End Select

Return

'------------------Stell-Routine für Sekunden------------
Sekunden_stellen:

 Incr Sek_einer

      If Sek_einer = 10 Then
               Sek_einer = 0
                Sek_zehner = Sek_zehner + 1

                  If Sek_zehner = 6 Then
                     Sek_zehner = 0
                  End If
            End If

Return

'------------------Stell-Routine für Minuten------------

Minuten_stellen:

Incr Min_einer

  If Min_einer = 10 Then
              Min_einer = 0
               Min_zehner = Min_zehner + 1

                  If Min_zehner = 6 Then
                     Min_zehner = 0
                  End If
  End If

Return


'-----------------Start Countdown---------------

Los:
 Relais1 = 0 : Relais2 = 0 : Relais3 = 0
 Tasterflag = 1
    Return

Return

   Return




'-----------------Interrupt-Routinen -----------------------------

Ontimer0:


 Tcnt0 = 224                                                '16Mhz/256/(256-100)= 400Hz

   'Hier wird die Umschaltsequenz (Multiplexen)  erzeugt!
   Multiplex = Multiplex * 2                                '1,2,4,8,
   If Multiplex = 16 Then Multiplex = 1



   Portd = &B00000000                                       'Alle Segmente vor dem Umschalten ausschalten
   Portb = Multiplex



   If Multiplex = 1 Then Wert = Sek_einer                   'Ab hier erfolgt die Zuordnung von Anzeige und Wert
   If Multiplex = 2 Then Wert = Sek_zehner
   If Multiplex = 4 Then Wert = Min_einer
   If Multiplex = 8 Then Wert = Min_zehner



   'Hier erfolgt die die Auswahl (Dekodierung) welche Segmente leuchten sollen
   Select Case Wert
      Case 0
         Portd = &B00111111                                 '0
      Case 1
         Portd = &B00000110                                 '1
      Case 2
         Portd = &B01011011                                 '2
      Case 3
         Portd = &B01001111                                 '3
      Case 4
         Portd = &B01100110                                 '4
      Case 5
         Portd = &B01101101                                 '5
      Case 6
         Portd = &B01111101                                 '6
      Case 7
         Portd = &B00000111                                 '7
      Case 8
         Portd = &B01111111                                 '8
      Case 9
         Portd = &B01101111                                 '9
      Case Else
         Portd = &B00000000                                 'Anzeige dunkel schalten
   End Select

Return

'------------------Stell-Routine für Sekunden------------
Sekunden_stellen:

 Incr Sek_einer

      If Sek_einer = 10 Then
               Sek_einer = 0
                Sek_zehner = Sek_zehner + 1

                  If Sek_zehner = 6 Then
                     Sek_zehner = 0
                  End If
            End If

Return

'------------------Stell-Routine für Minuten------------

Minuten_stellen:

Incr Min_einer

  If Min_einer = 10 Then
              Min_einer = 0
               Min_zehner = Min_zehner + 1

                  If Min_zehner = 6 Then
                     Min_zehner = 0
                  End If
  End If

Return


'-----------------Start Countdown---------------

Los:
 Relais1 = 0 : Relais2 = 0 : Relais3 = 0
 Tasterflag = 1
    Return

Return
 
Hallo FreeVee,

die Idee ist gut, habe ich gemacht und rate was passiert, richtig: nichts

Hallo Gerd,

... aber leider ist Deine Umsetzung nicht so gut.

Du musst die ISR des Timer1 so kurz wie möglich halten.
D.h., die ganze IF-THEN-ELSE-Abfrage bleibt in der Main.

Eigentlich solltest Du nur mit Hilfe des Flags den Zähler starten.


Ich glaube, da must Du wohl noch mal ran.

Nur Mut, es ist noch kein Meister vom Himmel gefallen!


MfG

FreeVee
 
Hallo Freunde der Nacht,

es funktioniert.
Fehler: Der Atmega8 stammt aus der Bauteilkiste und steckte in einer Fassung. Da der Teufel bekanntlich ein Eichhörnchen ist, war beim Chip ausgerechnet an Pin28 das Bein abgebrochen, was man allerdings wegen der Fassung nicht sehen konnte. Habe ihn ausgetauscht und alles läuft.
Sagt jetzt nichts dazu, alles was ihr sagen könnt habe ich mir bereits selbst gesagt. Trotzdem Dank für eure moralische Unterstützung. Und ja, wenn ich mal Zeit habe werde ich die If-Schachtel überarbeiten.

Gruß
Gerd
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)