-
        

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 12

Thema: Problem mit Alarm bei Selbstbau-Uhr

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    03.10.2013
    Beiträge
    11

    Problem mit Alarm bei Selbstbau-Uhr

    Anzeige

    Hallo!
    Im Rahmen eines größeren Bastelprojekts (Langzeitbetrieb einer Kamera mit PC über Jahre) habe ich ständig Probleme mit der (eingebauten) Wochenzeitschaltuhr.
    Diese ist ja leider nicht mit DCF77 ausgerüstet (hab ich noch nie gesehen) und darum muß ich ständig auf der Lauer sein.
    Jeden Monat einmal die Zeit korrigieren und jedes Halbjahr die Umstellung Sommer/Winterzeit. Und bei Stromausfall korrigieren.
    Das wurde mir jetzt zuviel und deshalb muß jetzt eine "richtige" Uhr her.
    Das Programm für die Uhr selbst ist schon fertig und läuft tadellos. Ich habe sie - als Anfänger - aus verschiedenen Codeschnipseln
    und etwas eigenem dazu zusammengesetzt. Ein I2C-RTC-Modul steuert die BASCOM-Softclock und wird von einem ELV-DFC77-Modul
    genau gehalten.
    Ohne Schaltausgang nützt sie mir allerdings garnichts, denn die Uhr soll ja täglich einmal den PC aufwecken, nach 5 Minuten ein
    Programm starten und den PC wieder schlafen legen.
    Also hab ich versucht, das mal selbst zu entwickeln. Der jetzige Stand ist:
    Die Umschaltung Stellen - Alarm EIN funktioniert.
    Beim Stellen kann ich auch Stunde und Minute erhöhen.
    Beim Zurückschalten auf Alarm Ein geht aber die Anzeige wieder auf Null.
    Das sagt mir: die Zahlen im LCD bleiben nicht erhalten. Warum? Keine Ahnung...
    Hier noch der Code:
    Code:
    Locate 4 , 1 : Lcd "Alarm"
    
    '--------------- Taster - Schleife --------------------------------
    Do
          If Ta_stellen = 0 Then
             Waitms 10
             While Ta_stellen = 0
                NOP                                             ' Debouncing
                Nop
             Wend
       Goto Set_alarm
          End If
    Locate 4 , 13 : Lcd " Ein     "
    Loop
    
    '-------------- Stellen - Schleife ------------------------------------------
    Set_alarm:
    Do
             If Ta_min = 0 Then
              Al_min = Al_min + 1                               'Minute stellen
                If Al_min = 60 Then Al_min = 0
                   Waitms 200
             End If
             If Ta_std = 0 Then
              Al_std = Al_std + 1                               'Stunde stellen
                If Al_std = 24 Then Al_std = 0
                   Waitms 200
             End If
    '-----------------------------------------------------------------------------------------
    If Ta_stellen = 0 Then Exit Do
    '-----------------------------------------------------------------------------------------
    Locate 4 , 13 : Lcd "Stellen"
    Locate 4 , 7 : Lcd Al_std ; ":" ; Al_min
    Loop
    
    Return
    
    End
    Wie schon ober geschrieben, ist das nur ein Teil einer ganzen Uhrsteuerung.
    Es sollte möglichst keinen Timer oder Interrupt brauchen.
    Das muß doch gehen!
    Den Rest, also den Uhrzeit-Vergleich und den Ausgang zum Pc kann ich wieder selbst.

    Vielleicht ist es nur eine Kleinigkeit, die ich mangels Erfahrung übersehe.
    Joachim

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.112
    Hallo Joachim,
    nur mit diesem Codeschnipsel kann man dir schlecht raten, was du ändern solltest.
    Du hast dort ein Goto Set_alarm drin, also ein Sprung zu einer anderen Stelle im Programm.
    Bei dem Label wird die Alarmzeit gestellt, soweit sollte es funktionieren.
    Nach der Schleife dort kommt ein Return. Wenn sich der ganze Codeteil innerhalb einer Subroutine befindet, dann würde er jetzt hinter dem entsprechenden Aufruf weitermachen. Wenn nicht, wird der Controller wahrscheinlich resetten und wieder von vorne beginnen.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    03.10.2013
    Beiträge
    11
    Danke für die schnelle Rückmeldung!
    Dieser "Codeschnipsel" ist eigentlich schon das ganze Programm bzw. Teilprogramm für den Alarm.
    Vom Uhrenprogramm wird nur die aktuelle Zeitinformation übernommen (_hour, _min) und mit der eingestellten Zeit verglichen.
    Das ist das Ganze:

    Code:
    $regfile = "m8def.dat"
    $crystal = 9830400
    $hwstack = 60
    $swstack = 32
    $framesize = 64
    $include "INIT_LCD20x4.bas"                                 'LCD an Port D
    Pinb = &B11000000                                           'B 0,1 = Enc; 2,3,4,5 = Taster
    Portb = &B00111111
    Dim Al_min As Byte , Al_std As Byte
    Enc_a Alias Pinb.0
    Enc_b Alias Pinb.1
    Ta_std Alias Pinb.2
    Ta_min Alias Pinb.3
    Ta_stellen Alias Pinb.4
    Ta_enc Alias Pinb.5
    
    Locate 4 , 1 : Lcd "Alarm"
    
    '--------------- Taster - Schleife --------------------------------
    Do
          If Ta_stellen = 0 Then
             Waitms 10
             While Ta_stellen = 0
                NOP                                             ' Debouncing
                Nop
             Wend
       Goto Set_alarm
          End If
    Locate 4 , 13 : Lcd " Ein     "
    Loop
    
    '-------------- Stellen - Schleife ------------------------------------------
    Set_alarm:
    Do
             If Ta_min = 0 Then
              Al_min = Al_min + 1                               'Minute stellen
                If Al_min = 60 Then Al_min = 0
                   Waitms 200
             End If
             If Ta_std = 0 Then
              Al_std = Al_std + 1                               'Stunde stellen
                If Al_std = 24 Then Al_std = 0
                   Waitms 200
             End If
    '-----------------------------------------------------------------------------------------
    If Ta_stellen = 0 Then Exit Do
    '-----------------------------------------------------------------------------------------
    Locate 4 , 13 : Lcd "Stellen"
    Locate 4 , 7 : Lcd Al_std ; ":" ; Al_min
    Loop
    
    'Return
    
    End
    
    '(
    '-------------- LCD rechtsbündige Anzeige ------------------------------------
    Locate 4 , 7                                                ' Anzeige Al_Std
             If Al_Std < 10 Then Lcd " " ; Al_Std Else Lcd Al_Std ; "  "
          Locate 4 , 9                                          ' Anzeige Al_Min
             If Al_Min < 10 Then Lcd ":0" ; Al_Min Else Lcd ":" ; Al_Min
       Waitms 50
    ')
    Ich hab den RETURN mal rausgenommen, dann bleibt er wie vorhersehbar bei "Stellen" stehen.
    Die Frage ist für mich also: Wie komme ich aus der Stellroutine, ohne den Inhalt von Al_std und Al_min
    zu verlieren?
    Angehängte Dateien Angehängte Dateien

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    03.10.2013
    Beiträge
    11
    Ich hab jetzt mal versucht, die eingestellten Werte als Temp1 und 2 zu speichern, kein Erfolg, steht nur Null drin....
    Es muß doch möglich sein, die engestellten Daten vor dem Verlassen der Schleife woanders zu speichern?
    Ich hab auch schon die Stellen-Schleife als SUB deklariert. Dann kann er sie nicht mehr verlassen bzw. springt gleich
    nach Mode-Taste wieder rein. So sieht das jetzt aus:
    Code:
    $regfile = "m8def.dat"
    $crystal = 9830400
    $hwstack = 40
    $swstack = 16
    $framesize = 32
    $include "INIT_LCD20x4.bas"                                 'LCD an Port D
    Pinb = &B11000000                                           'B  2,3,4 = Taster
    Portb = &B00111100
    Dim Al_min As Byte , Al_std As Byte , Temp1 As Byte , Temp2 As Byte
    Ta_std Alias Pinb.2
    Ta_min Alias Pinb.3
    Ta_mode Alias Pinb.4
          Locate 1 , 1 : Lcd "Alarm "
          Locate 2 , 2 : Lcd Temp1
          Locate 3 , 2 : Lcd Temp2
    '---------------Mode - Taster - Schleife --------------------------------
    Do
          Locate 1 , 13 : Lcd "Ein    "
          Locate 1 , 7 : Lcd Al_std ; ":" ; Al_min
             If Ta_mode = 0 Then
                Waitms 10
                While Ta_mode = 0
                   NOP                                          ' Debouncing
                   Nop
                Wend
       Goto Set_alarm
             End If
    Loop
    '-------------- Stellen - Schleife ------------------------------------------
    Set_alarm:
    Do
                If Ta_min = 0 Then
                   Al_min = Al_min + 1                          'Minute stellen
                      If Al_min = 60 Then Al_min = 0
                         Waitms 200
                End If
                If Ta_std = 0 Then
                   Al_std = Al_std + 1                          'Stunde stellen
                      If Al_std = 24 Then Al_std = 0
                         Waitms 200
                End If
     '-----------------------------------------------------------------------------------------
          If Ta_mode = 0 Then Exit Do
     '-----------------------------------------------------------------------------------------
          Locate 1 , 13 : Lcd "Stellen"
          Locate 1 , 7 : Lcd Al_std ; ":" ; Al_min
    Temp1 = Al_std                                              'geht auch nicht
    Temp2 = Al_min                                              ' nur Nullen drin
    Loop
    
    Return
    
    End
    
    ')
    Ich weiß nicht mehr weiter, mit meinem Anfängerwissen bin ich am Ende...

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.112
    Hallo Joachim,
    dein Programm läuft jetzt nach dem Stellen wieder auf das Return. Das funktioniert so nicht.
    Du könntest aus dem Goto Set_alarm mal ein Gosub Set_alarm machen.
    Nach dem Ende des Stellens würde er aufgrund des Return zurück hinter den Gosub Befehl springen.
    Habe ich mir jetzt aber noch nicht angesehen, was dann passieren würde.

    Edit: Willst du eigentlich die Taste TA_mode drücken um in den Stellmodus zu gelangen und auch wieder, um den zu verlassen (If Ta_mode = 0 Then Exit Do)? Dann wäre die Taste immer noch gedrückt, wenn das Programm nach dem Return zum Befehl hinter Gosub ... zurückkehrt. Nach der Ausgabe aufs LCD springt er dann sofort wieder in die Set_alarm Routine. Dass müsstest du dir dann noch einmal ansehen.

  6. #6
    Erfahrener Benutzer Roboter Genie Avatar von HeXPloreR
    Registriert seit
    08.07.2008
    Ort
    24558
    Alter
    39
    Beiträge
    1.356
    Hallo,

    ich meine das mit dem "return" was for_ro anspricht ist schon mal ein ganz heißer Tipp. Du solltest vielleicht Gosub's aus Deinen Einstellungsteilen machen und da muss dann mit einem "return" beendet werden - hier ist das "return" falsch, da vorher kein Aufruf erfolgt ist.

    Das Goto Set_Alarm benötigst Du nicht wenn Du den Teil auf den sich das bezieht in den ersten mit integrierst. Weil Du gehst ja sowieso dahin, wenn Du drin bist.

    Das "debouncing" ist nutzlos wenn nach dem zweiten testen nicht die Reaktion des Tasters ausgeführt wird.
    Geändert von HeXPloreR (03.11.2013 um 13:21 Uhr)
    "Es ist schwierig, jemanden dazu zu bringen, etwas zu verstehen, wenn er sein Gehalt dafür bekommt, dass er es nicht versteht" [Upton Sinclair] gez-boykott

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    03.10.2013
    Beiträge
    11
    @ for_ro:
    Genau wie Du schreibst, ist es!
    Nochmal kurz erklärt, was ich eigentlich will:
    Der "Mode"-Taster soll zwischen "Anzeigen-und Alarm-Ein" Mode" und " Stellen" Mode" umschalten.
    Es könnte auch so gehen, das ich gleichzeitig Mode- und Stelltaster zum stellen drücken muß.
    Ich glaube, das geht wohl am Einfachsten.
    Das Debouncing stammt noch vom alten Codeschnipsel, das wird nicht nötig sein.

    - - - Aktualisiert - - -

    Ich hab das jetzt mal so gemacht:
    Code:
    $regfile = "m8def.dat"
    $crystal = 9830400
    $hwstack = 40
    $swstack = 16
    $framesize = 32
    $include "INIT_LCD20x4.bas"                                 'LCD an Port D
    Pinb = &B11000000                                           'B  2,3,4 = Taster
    Portb = &B00111100
    Dim Al_min As Byte , Al_std As Byte
    Ta_std Alias Pinb.2
    Ta_min Alias Pinb.3
    Ta_mode Alias Pinb.4
    Locate 1 , 1 : Lcd "Alarm "
    Do
          If Ta_mode = 0 Then
             Locate 1 , 13 : Lcd "Stellen"
                Else
             Locate 1 , 13 : Lcd "Ein     "
          End If
          If Ta_min = 0 And Ta_mode = 0 Then
                   Al_min = Al_min + 1                          'Minute stellen
                      If Al_min = 60 Then Al_min = 0
                         Waitms 200
          End If
          If Ta_std = 0 And Ta_mode = 0 Then
                   Al_std = Al_std + 1                          'Stunde stellen
                      If Al_std = 24 Then Al_std = 0
                         Waitms 200
          End If
    '-------------- LCD rechtsbündige Anzeige ------------------------------------
    Locate 1 , 7
                   If Al_Std < 10 Then Lcd " " ; Al_Std Else Lcd Al_Std ; "  "
    Locate 1 , 9
                   If Al_Min < 10 Then Lcd ":0" ; Al_Min Else Lcd ":" ; Al_Min
       Waitms 50
    Loop
    End
    und das geht so wie gewollt! Die zwei-Taster-Bedienung ist garnicht mal schlecht.

    Jetzt brauch ich nur noch den Uhrzeit-Vergleich und die Ausgabe austüfteln.

    Ich danke Euch für die hilfreichen Tipps, hab ich doch wieder was gelernt!

    Joachim

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    03.10.2013
    Beiträge
    11
    Hallo!
    Ich hänge mich jetzt mal an meinen Thread selbst dran, weil ich noch eine Frage zur selben Sache habe.

    Erstmal kann ich mitteilen, daß dank eurer Hilfe die Uhr nun soweit läuft.

    Zum Einstellen der Alarmzeit bin ich aber von den Tastern abgegangen, weil mid das doch zu aufwendig war, die werden
    ja nur ein-zweimal im Jahr gebraucht.
    Dazu kommt noch der Nachteil, das ich damit nur vorwärts stellen könnte.

    Also hab ich mir bei ebay diese Drehencoder besorgt:

    Klicke auf die Grafik für eine größere Ansicht

Name:	Encoder.JPG
Hits:	11
Größe:	43,5 KB
ID:	26726

    Die gabs 15 Stück für 8 €, haben einen versenkbaren Drehknopf und einen Kontakt beim rausdrücken. Nach vielen Versuchen fand
    ich auch einen Programmschnipsel, der für diese Type sehr gut läuft:

    Code:
    $regfile = "m8def.dat"
    $crystal = 9830400
    $hwstack = 40
    $swstack = 16
    $framesize = 32
    $include "D:\PROG\INIT_LCD20x4.bas"
    Deflcdchar 1 , 2 , 6 , 14 , 31 , 14 , 6 , 2 , 32            'Pfeil nach links
    Portc = &B111                                               'Pullup
    Enc_a Alias Pinc.1
    Enc_b Alias Pinc.0
    Ta_alarm Alias Pinc.2
    Dim Al_min As Integer                                       'INT wegen Wert kleiner Null !
    Dim Al_std As Integer
    Dim Zw As Byte                                              'Zustandswechsel z.B.: &b0011_0010
    Config Timer0 = Timer , Prescale = 1024                     '= ~10MHz= ~0,1µs * 1024= 0,1ms
    On Timer0 Enc_int                                           'Interrupt
    Timer0 = 246                                                'Timerstartwert:10; ~0,1ms * 10= 1ms
    Enable Timer0
    Enable Interrupts
             Locate 1 , 2 : Lcd "Encoder mit Timer0"
             Locate 4 , 1 : Lcd "Alarmzeit: "                   '11 Zeichen
    If Ta_alarm = 0 Then
       Do
                Locate 4 , 12
             If Al_std < 10 Then Lcd " " ; Al_std Else Lcd Al_std       ' ; "  "
                Locate 4 , 14
             If Al_min < 10 Then Lcd ":0" ; Al_min Else Lcd ":" ; Al_min ; " "
                Locate 4 , 17 : Lcd " " ; Chr(1) ; "  "
             If Al_min < 0 Then
                   Al_min = 59
                   Al_std = Al_std - 1
                End If
             If Al_std < 0 Then Al_std = 23
             If Al_min > 59 Then
                   Al_min = 0
                   Al_std = Al_std + 1
                End If
             If Al_std > 23 Then Al_std = 0
    '-------Ab hier die Alarmzeit mit GOSUB in RTC speichern !-------------
                   If Ta_alarm = 1 Then Exit Do
       Loop
    End If
    
    Enc_int:
    Timer0 = 246                                                'Timerstartwert
    Zw.0 = Enc_a                                                'Zustandswechsel
    Zw.1 = Enc_b
    Select Case Zw
      Case &H0_2 : Incr Al_min
      Case &H0_1 : Decr Al_min
    End Select
    Zw.4 = Zw.0
    Zw.5 = Zw.1
    Return
    Damit stelle ich die Minuten, die Stunden folgen selbst. Vorwärts und rückwärts. Das kenne ich so von meinem Herd, ist ganz praktisch.

    Aber jetzt kommt die Frage!
    Bei Übereinstimmung von Uhrzeit und Alarmzeit will ich ja ein Signal bekommen, und zwar in der Zeit einstellbar im Bereich eine
    bis ca. 5 Sekunden. Das kann ich ja nicht in die Main-Schleife einbauen, weil die würde ja dann stehenbleiben!
    Bei einer SUB passiert dasselbe, bis zum RETURN bleibt alles stehen.
    Wie kann ich zu diesem "Unterprogramm" springen, ohne den normalen Ablauf zu unterbrechen?
    Also zur gegebenen Zeit die 5 Sekunden nebenher ablaufen lassen, ohne weitere Aktionen.
    Das kann ich nicht rausfinden, trotz intensiver Hilfesuche.
    Vielleicht kann mir da jemand auf die Sprünge helfen! Ich hänge hier noch das ganze Uhrenprogramm dran, das könnte
    Ja hilfreich sein:
    Code:
    $regfile = "m8def.dat"
    $crystal = 9830400
    $hwstack = 64
    $swstack = 32
    $framesize = 64
    $include "D:\PROG\INIT_LCD20x4.bas"                         'LCD an Port D
    '------------------------------------------ 'für RTC ------------------------------------------------------------
    $lib "I2C_TWI.lbx"
    Config Sda = Portc.4
    Config Scl = Portc.5
    Config Twi = 100000
    I2cinit
    Dim Ds_weekday As Byte , Ds_day As Byte , Ds_month As Byte , Ds_year As Byte
    Dim Ds_sec As Byte , Ds_min As Byte , Ds_hour As Byte
    '-------------------------------------------------- 'für DCF ---------------------------------------------------
    Config Dcf77 = Pinc.3 , Timer = 1
    Config Date = Dmy , Separator = .
    Config Pinb.3 = Output                                      'DCF - Status - LED
    Config Pinb.4 = Output                                      ' DCF - Blink - LED
    '---------------------------------------für ENC ---------------------------------------------------------------
    Portc = &B111                                               ' Pullups
    Enc_a Alias Pinc.1
    Enc_b Alias Pinc.0
    Ta_alarm Alias Pinc.2                                       'Taste Alarmzeit stellen EIN - AUS
    Deflcdchar 1 , 2 , 6 , 14 , 31 , 14 , 6 , 2 , 32            'Pfeil nach links
    Dim Al_min As Integer , Al_std As Integer                   'nötig wegen <Null !
    Dim V_al_min As Byte , V_al_std As Byte                     'für Anzeige
    Dim Zw As Byte                                              'Zustandswechsel z.B.: &b0011_0010
    Config Timer0 = Timer , Prescale = 1024                     '= ~10MHz= ~0,1µs * 1024= 0,1ms
    On Timer0 Enc_int                                           'Interrupt
    Timer0 = 246                                                'Timerstartwert:10; ~0,1ms * 10= 1ms
    Enable Timer0
    Stop Timer0
    Enable Interrupts
    '---------------------------------------- für Ausgang --------------------------------------------------------
    Config Pinb.0 = Input                                       'Schalter Alarm EIN - AUS
    Portb.0 = 1                                                 'Pullup
    Config Pinb.1 = Output                                      'grüne LED für Ausgang EIN
    
    '--------------------------MAIN - SCHLEIFE----------------------------------------------------------------
    Do
       If Pinc.3 = 1 Then Portb.4 = 1 Else Portb.4 = 0          ' LED für DCF-Impuls
       If Dcf_status.7 = 1 Then Portb.3 = 1 Else Portb.3 = 0    'LED für DCF-Status
       Gosub Show_clock                                         ' Anzeige vom RCT - Speicher holen
       Gosub Show_alarm                                         ' Anzeige vom RCT - Speicher holen
       If Ta_alarm = 0 Then Gosub Al_stellen
    Loop
    '------------------------------------------------------------------------------------------------------------------
    Al_stellen:
    Do
       Start Timer0
                Locate 3 , 12
             If Al_std < 10 Then Lcd "0" ; Al_std Else Lcd Al_std       ' ; "  "
                Locate 3 , 14
             If Al_min < 10 Then Lcd ":0" ; Al_min Else Lcd ":" ; Al_min ; " "
                Locate 3 , 17 : Lcd " " ; Chr(1) ; "  "
             If Al_min < 0 Then
                   Al_min = 59
                   Al_std = Al_std - 1
                End If
             If Al_std < 0 Then Al_std = 23
             If Al_min > 59 Then
                   Al_min = 0
                   Al_std = Al_std + 1
                End If
             If Al_std > 23 Then Al_std = 0
    Gosub Alarm_speichern
       If Ta_alarm = 1 Then
             Stop Timer0
             Exit Do
       End If
    Loop
    '----------TIMER 0 Interrupt für ENC -------------------------------------------------
    Enc_int:
    Timer0 = 246                                                'Timerstartwert für 1ms
    Zw.0 = Enc_a                                                'Zustandswechsel
    Zw.1 = Enc_b
    Select Case Zw
      Case &H0_2 : Incr Al_min                                  'bei jedem zweiten Tick
      Case &H0_1 : Decr Al_min                                  'dito
    End Select
    Zw.4 = Zw.0
    Zw.5 = Zw.1
    Return
    
    '----------RTC Uhrzeit und Datum auslesen und anzeigen----------------------
    Show_clock:
       I2cstart
          I2cwbyte 208
          I2cwbyte 0
             I2cstop
       I2cstart
          I2cwbyte 209
          I2crbyte Ds_sec , Ack
          I2crbyte Ds_min , Ack
          I2crbyte Ds_hour , Ack
          I2crbyte Ds_weekday , Ack
          I2crbyte Ds_day , Ack
          I2crbyte Ds_month , Ack
          I2crbyte Ds_year , Nack
       I2cstop
    Gosub Rtc_stellen
    '------------------ANZEIGE-----------------------------------------------------
                Locate 1 , 1 : Lcd "Uhrzeit:   " ; Bcd(ds_hour) ; ":" ; Bcd(ds_min) ; ":" ; Bcd(ds_sec)
                Locate 2 , 1 : Lcd "Datum: " ; Lookupstr(ds_weekday , Wochentag) ; ", "
                Locate 2 , 12 : Lcd Bcd(ds_day) ; "." ; Bcd(ds_month) ; "." ; Bcd(ds_year)
    '------------------ANZEIGE-----------------------------------------------------
    Return
    '-------------RTC Alarmzeit auslesen und anzeigen--------------------------
    Show_alarm:
       I2cstart
          I2cwbyte 208
          I2cwbyte 10
       I2cstart
          I2cwbyte 209
          I2crbyte V_al_std , Ack
          I2crbyte V_al_min , Nack
       I2cstop
    Locate 3 , 1 : Lcd "Alarmzeit: " ; Bcd(v_al_std) ; ":" ; Bcd(v_al_min) ; " "
       If Pinb.0 = 0 Then
    Locate 3 , 18 : Lcd "Aus"
       Else
    Locate 3 , 18 : Lcd "Ein"
       End If
    Return
    '----------------- Uhrzeit in RTC speichern
    Rtc_speichern:
             Ds_sec = Makebcd(ds_sec)
             Ds_min = Makebcd(ds_min)
             Ds_hour = Makebcd(ds_hour)
             Ds_day = Makebcd(ds_day)
             Ds_month = Makebcd(ds_month)
             Ds_year = Makebcd(ds_year)
             Ds_weekday = Makebcd(ds_weekday)
       I2cstart
          I2cwbyte 208
          I2cwbyte 0
          I2cwbyte Ds_sec
          I2cwbyte Ds_min
          I2cwbyte Ds_hour
          I2cwbyte Ds_weekday
          I2cwbyte Ds_day
          I2cwbyte Ds_month
          I2cwbyte Ds_year
       I2cstop
    Return
    '-------------------Alarmzeit in RTC speichern
    Alarm_speichern:
    V_al_min = Makebcd(al_min)
    V_al_std = Makebcd(al_std)
       I2cstart
          I2cwbyte 208
          I2cwbyte 10
          I2cwbyte V_al_std
          I2cwbyte V_al_min
       I2cstop
    Return
    '----------------- RTC nach DCF77 stellen
    Rtc_stellen:
       If Dcf_status.7 = 1 And Ds_sec <> _sec Then
             Ds_hour = _hour
             Ds_min = _min
             Ds_sec = _sec
             Ds_weekday = _weekday
             Ds_day = _day
             Ds_month = _month
             Ds_year = _year
                Gosub Rtc_speichern
          End If
    Return
    '-----------------AUSGANG - BAUSTELLE ! ---------------------------------------------
    
        If Ta_alarm = 1 And Pinb.0 = 1 Then Gosub Ausgang
    
        Ausgang:
    
     If V_al_std = Ds_hour And V_al_min = Ds_min Then Portb.1 = 1
    Wait 5
    Portb = 1
    
    
    Wochentag:
    Data "  " , "Mo" , "Di" , "Mi" , "Do" , "Fr" , "Sa" , "So"
    Joachim

  9. #9
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    46
    Beiträge
    765
    Meine Methode ist da wesentlich anders. Ich stelle die RTC, wenn die Zeit per NTP gestellt wurde (In Deinem Fall per DCF-Signal empfangen und für gültig erklärt wurde) und laufe die restliche Zeit mit der internen Uhr von Bascom. Einmal die Stunde wird wieder aktualisiert. Für DCF: Wenn tagsüber schlechter Empfang herrscht (z.B. Schaltnetzteil in der Nähe), dann die RTC nachts nachstellen. Ist der DCF-Empfang tagsüber schlecht, dann die Zeit mal von der RTC holen.

    Die RTC würde ich nie kontinuierlich auslesen. Die DS1307 würde dann sogar evtl. arg nachgehen. Zeitfunktionen kommen bei mir ins Sectic. Werden also maximal einmal pro Sekunde ausgeführt. In dem Sub Sectic werden auch Timer abgearbeitet.
    Vereinfachtes Prinzip mal eben schnell aus dem Kopf:
    Code:
    Wenn Minutealt <> Minute dann ' So umgeht man, dass man die Sekunde 0 wegen evtl. Zeiteinstellung verpasst...
    Minutealt=Minute
    Wenn Weckeraktiv>0 dann Weckeraktiv = Weckeraktiv -1
    Wenn Weckzeit=Uhrzeit, dann Variable für Weckeraktiv auf 60 Minuten stellen (habe ein Internetradio gebaut).
    Ist Weckeraktiv>0 dann Radio einschalten, wenn es noch nicht an ist.
    Ist Weckeraktiv=0 dann Radio ausschalten
    Das geht auch mit Sekunden.
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    03.10.2013
    Beiträge
    11
    Bezüglich der Nachstellung hab ich eigentlich keine Probleme. Du hast ja NTP, da ist das etwas einfacher, aber es geht auch so.
    Die RTC wird ja maximal jede Minute aktualisiert (wenn das DCF77-Statusbit einen kompletten Satz Daten empfangen hat).
    Und da der Speicher der RTC SRAM ist, gibt es eigentlich kein Problem.

    Aber das Problem des Alarmausgangs habe ich inzwischen gelöst. Mit Deiner Methode kam ich nicht zurecht, es wollte nicht laufen.
    Nun ist der Ausgang in einer Sub, die von der Hauptschleife abgerufen wird:

    Code:
    Do                                                          ' MAIN - SCHLEIFE
       Locate 1 , 16
          If Dcf_pin = 1 Then Lcd "+" Else Lcd " "              'DCF-Impuls
       Locate 1 , 6
          If Dcf_status.7 = 1 Then Lcd "*" Else Lcd " "         'DCF-Status
       Gosub Show_clock                                         ' Anzeige vom RCT - Speicher holen
       Gosub Show_alarm                                         ' Anzeige vom RCT - Speicher holen
       Gosub Hbl_pwm                                            'Hintergrundbeleuchtung
          If Ta_alarm = 1 And Sw_alarm = 1 Then A = 1 Else A = 0
          If V_al_std = Ds_hour And V_al_min = Ds_min Then B = 1 Else B = 0
          If A = 1 And B = 1 Then C = 1 Else C = 0
          If C = 1 And Ds_sec = 5 Then Gosub Ausgang
          If Ta_alarm = 0 Then Gosub Al_stellen
    Loop
    Ausgang:                                                    ' AUSGANG
    Al_out = 1
    Sound Buzz , 200 , 150                                      'Buzzer Länge, Tonhöhe
    Wait 1                                                      'Alarm - EIN - Zeit
    Al_out = 0
    Return
    Die Anzeige bleibt zwar für die Alarmzeit (1 bis 2 Sekunden) stehen, aber die Uhr läuft weiter.

    Da nun alles zur Zufriedenheit lief und der Mega8 nichtmal halb ausgelastet ist, habe ich als kleines Schmankerl noch eine
    Steuerung der Hintergrundbeleuchtung über das Umgebungslicht draufgesetzt.
    Zunächst wollte ich das kontinuierlich regeln, habe aber davon Abstand genommen, weil ich ein flackern der Helligkeit einfach nicht
    wegbekam. So habe ich den ADC- Ausgang auf 5 Bit runtergesetzt und schalte damit nur noch Hell oder Dunkel. Das reicht mir völlig
    aus. Die Steuerung macht der Timer 2 mit PWM, dahinter ist noch ein Transistor, weil die HBL ca. 40mA braucht. Der Code dafür ist
    recht einfach:

    Code:
    Hbl_pwm:                                                    'Hintergrundbeleuchtung
    Ldr = Getadc(2)
    Shift Ldr , Right , 5                                       'Auflösung 5 Bit
    If Ldr < 8 Then Pwm_ = 50
    If Ldr > 15 Then Pwm_ = 255
    Compare2 = Pwm_
    Return
    und ist auch als Sub in der Hauptschleife. Das ganze sieht nun so aus:

    Code:
    'Ausgänge = B.1 = Alarm , B.2 = Buzzer , B.3 = HBL(PWM)
    'C.4 und C.5 = TWI/I2C ,  Port D 2 bis D.7 für LCD
    'Eingänge = , D.0 = Schalter Alarm Ein , D.1 = Taster Alarm stellen
    'C.0 und C1 = ENC , C.2 = LDR für HBL , B.0 = DCF77
    $regfile = "m8def.dat"
    $crystal = 2000000
    $hwstack = 64
    $swstack = 32
    $framesize = 64
    $include "D:\PROG\INIT_LCD16x2.bas"                         'LCD an Port D
    $lib "I2C_TWI.lbx"
    Config Sda = Portc.4
    Config Scl = Portc.5
    Config Twi = 100000
    Ddrb = &B11001110
    Portc = &B11                                                ' Pullups
    Portd = &B11                                                'Pullups
    Enc_a Alias Pinc.1
    Enc_b Alias Pinc.0
    Dcf_pin Alias Pinb.0
    Al_out Alias Portb.1
    Buzz Alias Portb.2
    Hbl_out Alias Portb.3                                       'Beleuchtung Ausgang (PWM)
    Sw_alarm Alias Pind.0                                       'Schalter Alarm EIN - AUS
    Ta_alarm Alias Pind.1                                       'Taste Alarmzeit stellen EIN - AUS
    Dim Al_zeit As Byte , A As Byte , B As Byte , C As Byte , Zw As Byte
    Dim Ds_day As Byte , Ds_month As Byte , Ds_year As Byte
    Dim Ds_sec As Byte , Ds_min As Byte , Ds_hour As Byte
    Dim Al_min As Integer , Al_std As Integer , V_al_min As Byte , V_al_std As Byte
    Dim Ldr As Word , Pwm_ As Byte                              'LDR = Fotowiderstand
    Al_min = 30 : Al_std = 20                                   'Startwert
    Deflcdchar 1 , 2 , 6 , 14 , 31 , 14 , 6 , 2 , 32            'Pfeil nach links
    '*********** TIMER 1 für DCF77****************
    Config Dcf77 = Pinb.0 , Timer = 1
    Config Date = Dmy , Separator = .
    '*********** TIMER 0 für Drehencoder*********
    Config Timer0 = Timer , Prescale = 64                       '= ~2Mhz = ~0,5µs * 64 = ~ 32µs
    Timer0 = 225                                                'Startwert = 31 x ~ 32µs = ~1ms
    On Timer0 Enc_int
    Enable Timer0
    '*********** TIMER 2 und ADC 2 für Hintergrundbeleuchtung*********
    Config Timer2 = Pwm , Prescale = 64 , Compare Pwm = Clear Up
    Enable Timer2
    Config Adc = Single , Prescaler = Auto , Reference = Avcc
    
    Enable Interrupts
    Do                                                          ' MAIN - SCHLEIFE
       Locate 1 , 16
          If Dcf_pin = 1 Then Lcd "+" Else Lcd " "              'DCF-Impuls
       Locate 1 , 6
          If Dcf_status.7 = 1 Then Lcd "*" Else Lcd " "         'DCF-Status
       Gosub Show_clock                                         ' Anzeige vom RCT - Speicher holen
       Gosub Show_alarm                                         ' Anzeige vom RCT - Speicher holen
       Gosub Hbl_pwm                                            'Hintergrundbeleuchtung
          If Ta_alarm = 1 And Sw_alarm = 1 Then A = 1 Else A = 0
          If V_al_std = Ds_hour And V_al_min = Ds_min Then B = 1 Else B = 0
          If A = 1 And B = 1 Then C = 1 Else C = 0
          If C = 1 And Ds_sec = 5 Then Gosub Ausgang
          If Ta_alarm = 0 Then Gosub Al_stellen
    Loop
    Ausgang:                                                    ' AUSGANG
    Al_out = 1
    Sound Buzz , 200 , 150                                      'Buzzer Länge, Tonhöhe
    Wait 1                                                      'Alarm - EIN - Zeit
    Al_out = 0
    Return
    Al_stellen:                                                 ' STELLEN
    Do
                Locate 2 , 8
             If Al_std < 10 Then Lcd "0" ; Al_std Else Lcd Al_std
                Locate 2 , 10
             If Al_min < 10 Then Lcd ":0" ; Al_min Else Lcd ":" ; Al_min ; " "
                Locate 2 , 14 : Lcd " " ; Chr(1) ; "  "
             If Al_min < 0 Then
                   Al_min = 59
                   Al_std = Al_std - 1
             End If
             If Al_std < 0 Then Al_std = 23
             If Al_min > 59 Then
                   Al_min = 0
                   Al_std = Al_std + 1
             End If
             If Al_std > 23 Then Al_std = 0
    Gosub Alarm_speichern
       If Ta_alarm = 1 Then Exit Do
    Loop
    Enc_int:                                                    'TIMER 0 Interrupt für Drehencoder
    Timer0 = 225                                                'Timer Startwert
    Zw.0 = Enc_a                                                'Zustandswechsel
    Zw.1 = Enc_b
    Select Case Zw
      Case &H0_2 : Incr Al_min                                  'bei jedem zweiten Tick
      Case &H0_1 : Decr Al_min
    End Select
    Zw.4 = Zw.0
    Zw.5 = Zw.1
    Return
    Show_clock:                                                 ' RTC Uhrzeit und Datum auslesen und anzeigen
       I2cstart
          I2cwbyte 208
          I2cwbyte 0
       I2cstart
          I2cwbyte 209
          I2crbyte Ds_sec , Ack
          I2crbyte Ds_min , Ack
          I2crbyte Ds_hour , Ack
          I2crbyte Ds_day , Ack
          I2crbyte Ds_month , Ack
          I2crbyte Ds_year , Nack
       I2cstop
    Gosub Rtc_stellen
             Locate 1 , 1 : Lcd "Zeit:"
             Locate 1 , 8 : Lcd Bcd(ds_hour) ; ":" ; Bcd(ds_min) ; ":" ; Bcd(ds_sec)
    Return
    Show_alarm:                                                 ' RTC Alarmzeit auslesen und anzeigen
       I2cstart
          I2cwbyte 208
          I2cwbyte 10
       I2cstart
          I2cwbyte 209
          I2crbyte V_al_std , Ack
          I2crbyte V_al_min , Nack
       I2cstop
    Locate 2 , 1 : Lcd "Alarm: " ; Bcd(v_al_std) ; ":" ; Bcd(v_al_min)
    Locate 2 , 14
       If Sw_alarm = 0 Then Lcd "Aus" Else Lcd "Ein"
    Return
    Rtc_speichern:                                              ' Uhrzeit in RTC speichern
             Ds_sec = Makebcd(ds_sec)
             Ds_min = Makebcd(ds_min)
             Ds_hour = Makebcd(ds_hour)
             Ds_day = Makebcd(ds_day)
             Ds_month = Makebcd(ds_month)
             Ds_year = Makebcd(ds_year)
       I2cstart
          I2cwbyte 208
          I2cwbyte 0
          I2cwbyte Ds_sec
          I2cwbyte Ds_min
          I2cwbyte Ds_hour
          I2cwbyte Ds_day
          I2cwbyte Ds_month
          I2cwbyte Ds_year
       I2cstop
    Return
    Alarm_speichern:                                            ' Alarmzeit in RTC speichern
    V_al_min = Makebcd(al_min)
    V_al_std = Makebcd(al_std)
       I2cstart
          I2cwbyte 208
          I2cwbyte 10
          I2cwbyte V_al_std
          I2cwbyte V_al_min
       I2cstop
    Return
    Rtc_stellen:                                                ' RTC nach DCF77 stellen
       If Dcf_status.7 = 1 And Ds_sec <> _sec Then
             Ds_sec = _sec
             Ds_hour = _hour
             Ds_min = _min
             Ds_day = _day
             Ds_month = _month
             Ds_year = _year
                Gosub Rtc_speichern
          End If
       Reset Dcf_status.7
    Return
    Hbl_pwm:                                                    'Hintergrundbeleuchtung
    Ldr = Getadc(2)
    Shift Ldr , Right , 5                                       'Auflösung 5 Bit
    If Ldr < 8 Then Pwm_ = 50
    If Ldr > 15 Then Pwm_ = 255
    Compare2 = Pwm_
    Return
    Hier noch ein Foto der gesamten Technik, aufgebaut mit myAVR-Light Board:

    Klicke auf die Grafik für eine größere Ansicht

Name:	Uhr v2 1 16x2.JPG
Hits:	16
Größe:	81,4 KB
ID:	26782

    Links der Fotowiderstand mit Vorwiderständen, unten die ELV-DCF77 und rechts der Drehencoder und der Schalter für die
    Alarmzeiteinstellung.
    Einen Schaltplan hab ich auch gemacht, er zeigt mir gleich die mechanische Anordnung der Teile. Das LCD kommt über die Platine
    zu liegen:

    Klicke auf die Grafik für eine größere Ansicht

Name:	Schema2.jpg
Hits:	21
Größe:	61,3 KB
ID:	26783

    Dieses ganze Projekt hätte ich mir sparen können, wenn es eine einfachere Lösung für das eigentliche Problem gäbe, nämlich:

    Eine Möglichkeit festzustellen, ob am PC ein USB- Gerät aktiv ist oder nicht. Denn meine Robot- Kamera schaltet ja bei Dunkelheit
    aus bzw. um auf USB- Ausgang. Ich habe aber nicht herausgefunden, wie man das am PC auswerten könnte.
    Der bräuchte dann nur noch die gemachten Fotos runterzuladen, mit Datum zu versehen, abzuspeichern und die SD-Karte
    der Kamera zu löschen. Das macht er jetzt auch schon, seit über sechs Jahren, es fehlen nur drei Tage wegen Stromausfall
    bzw. Computerversagen. Nur die Schaltuhr mußte ich ständig beobachten.
    Aber das hat jetzt ein Ende.

    Allerdings war die Entwicklung auch sehr interessant und lehrreich, das ist für die nächsten Projekte bestimmt von Nutzen!
    Eine Uhr kann man immer gebrauchen
    Joachim

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Genauer Temperaturmonitor mit einstellbarem Alarm
    Von Roboternetz-News im Forum Neuigkeiten / Technik-News / Nachrichten / Aktuelles
    Antworten: 0
    Letzter Beitrag: 29.08.2012, 22:40
  2. Antworten: 3
    Letzter Beitrag: 03.07.2012, 16:55
  3. Bascom Uhr Problem
    Von xbgamer im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 33
    Letzter Beitrag: 03.07.2010, 13:11
  4. Problem mit Selbstbau-Ätzmaschinen-Heizung
    Von Majuz im Forum Konstruktion/CAD/Sketchup und Platinenlayout Eagle & Fritzing u.a.
    Antworten: 19
    Letzter Beitrag: 24.04.2009, 11:43
  5. Tipp!!! Probleme bei Selbstbau ISP Dongel
    Von colognerabb im Forum AVR Hardwarethemen
    Antworten: 4
    Letzter Beitrag: 06.10.2006, 20:58

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •