Forum: Mikrocontroller und Digitale Elektronik Sommerzeitberechnung mit Bascom


von Manfred S. (Firma: Manfred) (xfred343)


Lesenswert?

Arbeite mit den internen Datumsvariablen von Bascom,
in der DS1307 wird die Uhrzeit fortlaufend erstellt,
die Sommerzeit wird dann später mit der Funktion durch Addieren
einer Stunde berechnet.

1
Config Clock = User
2
Config Date = Mdy , Separator = .                           'German
3
Dim byt as byte  'Globale Hilfsvariable
4
Declare Function Fxsommerzeit() As Byte
5
'...
6
'Einlesen von DS1307
7
'...
8
Function Fxsommerzeit() As Byte
9
If _month < 3 Or _month > 10 Then
10
   Fxsommerzeit = 0
11
   Exit Function
12
End If
13
If _day >= 25 Then
14
    Byt = Dayofweek()                                       '0=Mo, 1=Di,.. 6=So lt. Bascom
15
    If Byt = 6 And _hour >= 2 Then
16
       Byt = 1
17
    Else
18
       Byt = _day - Byt
19
       If Byt <= 25 Then
20
          Byt = 0
21
       Else
22
          Byt = 1
23
       End If
24
    End If
25
Else
26
   Byt = 0
27
End If
28
If _month = 10 Then
29
    Fxsommerzeit = 1 - Byt
30
Else
31
    Fxsommerzeit = Byt
32
End If
33
End Function

Im wesentlichen bestimme ich, ob der letzte Sonntag im Monat erreicht 
ist oder nicht (Byt=0 bzw. Byt=1), ich bin gerade am Überlegen, ob die 
Funktion ein Bit zurückgeben sollte oder ein Byte - was ist bei Bascom 
besser zum Weiterrechnen? (z.B. 1 Stunde addieren) - geht das mit Bit 
genauso?

Weiters hoffe ich, dass die Funktion so richtig rechnet (hab ich gerade 
in Anlehnung an Peter Danneggers C-Code)umgeschrieben und sogar insofern 
optimiert, dass die Wochentagsberechnung nur ab 25. erfolgen muss

Vielleicht kann ja jemand das brauchen

von Karl H. (kbuchegg)


Lesenswert?

Manfred S. schrieb:

> ist oder nicht (Byt=0 bzw. Byt=1), ich bin gerade am Überlegen, ob die
> Funktion ein Bit zurückgeben sollte oder ein Byte - was ist bei Bascom
> besser zum Weiterrechnen? (z.B. 1 Stunde addieren) - geht das mit Bit
> genauso?

Keine Ahnung. Wird aber ziemlich egal sein. Denn die kleinste 
handhabbare Einheit in einem Computer ist ein Byte. Es gibt zwar 
Bitbefehle, aber die sind so universell nun auch wieder nicht, dass man 
damit im Allgemeinen Fall sinnvoll arbeiten kann.

> Weiters hoffe ich, dass die Funktion so richtig rechnet

Prüfe die Funktion lieber noch mal ausführlich. Die kommt mir nicht ganz 
koscher vor.
Am Anfang schliesst du erst mal die Monate 1, 2, 11 und 12 aus. Können 
keine Sommerzeit sein und ist soweit ok.

Aber dann machst du da was mit den Tagen und Taggrenzen. Und dort kommt 
dann das Monat überhaupt nicht mehr vor. Das kann aber nicht sein, denn 
zb im Juli ist das ganze Monat Sommerzeit, unabhängig davon auf welhen 
Tag der letzte Sonntag im Juli fällt.

Ich hab aber die Funktion nicht durchprobiert, mag sein dass ich mich 
irre. Daher - teste das lieber durch. Nimm dir ein bestimmtes Jahr raus, 
und lass alle Daten (vom 1.1. bis zum 31.12) durch die Funktion durch 
und sieh nach, ob das Ergebnis stimmt. Ist schnell gemacht und danach 
weißt du es genau.

von Manfred S. (Firma: Manfred) (xfred343)


Lesenswert?

Herzlichen Dank, Herr Buchegger,

In der Hitze des Gefechts, habe ich wirklich übersehen, dass es ja auch 
April-September gibt ;-)
Ich muss aber auch zugeben, dass der von Herrn Dannegger veröffentlichte 
C-Code wesentlich kniffliger ist. Bei der Portierung nach Bascom muss 
ich allerdings darauf achten, einfache Wenn-Vergleiche und meist nicht 
mehr als 2 Rechenoperationen je Zeile vorzusehen. Dafür ist dieser Code 
jetzt irgendwie effizienter und schneller, da er den Wochentag nur mehr 
für März un Oktober berechnen muss ;-) - hab ihn gerade mit der 
"baugleichen" Excel-VBA Routine von 2011-2099 durchgetestet, klappt - 
tja wer am Anfang zum Testen zu faul ist, muss auf gute Ratschläge 
hören...


Hier der Code
1
Config Clock = User
2
Config Date = Mdy , Separator = .                           'German
3
Dim byt as byte  'Globale Hilfsvariable
4
Declare Function Fxsommerzeit() As Byte
5
'...
6
'Einlesen von DS1307
7
'...
8
'**************************** Sommerzeit - Shift 1 _hour
9
Function Fxsommerzeit() As Byte
10
If _month < 3 Or _month > 10 Then                           'keine Sommerzeit
11
   Fxsommerzeit = 0
12
   Exit Function
13
End If
14
If _month >= 4 And _month <= 9 Then                         'jedenfalls Sommerzeit
15
   Fxsommerzeit = 1
16
   Exit Function
17
End If                                                      'betrachte nur mehr 3 und 10
18
If _day >= 25 Then                                          'Grenze: letzter Sonntag im Monat
19
    Byt = Dayofweek()                                       '0=Mo, 1=Di,.. 6=So lt. Bascom
20
    If Byt = 6 And _hour >= 2 Then                          'sonntags ab 2.00
21
       Byt = 1
22
    Else
23
       Byt = _day - Byt                                     'ermittle Grenze vor oder nach letztem Sonntag
24
       If Byt <= 25 Then
25
          Byt = 0
26
       Else
27
          Byt = 1
28
       End If
29
    End If
30
Else
31
   Byt = 0
32
End If
33
If _month = 10 Then                                         'in Oktober nach Grenze: keine Sommerzeit
34
    Fxsommerzeit = 1 - Byt
35
Else
36
    Fxsommerzeit = Byt                                      'in März: nach Grenze: Sommerzeit
37
End If
38
End Function

Und zum Testen in Excel-VBA
1
Function Fxsommerzeit(dat As Date)
2
Dim tag As Long
3
Dim monat As Long
4
Dim jahr As Long
5
Dim byt As Byte
6
tag = Day(dat)
7
monat = Month(dat)
8
jahr = Year(dat)
9
If monat < 3 Or monat > 10 Then
10
   Fxsommerzeit = 0
11
   Exit Function
12
End If
13
If monat > 3 And monat < 10 Then
14
    Fxsommerzeit = 1
15
    Exit Function
16
End If
17
If tag >= 25 Then
18
    byt = Weekday(dat, vbMonday) - 1 'wie Bascom
19
    If byt = 6 And Hour(dat) >= 2 Then
20
       byt = 1
21
    Else
22
       byt = tag - byt
23
       If byt <= 25 Then
24
          byt = 0
25
       Else
26
          byt = 1
27
       End If
28
    End If
29
Else
30
   byt = 0
31
End If
32
If monat = 10 Then
33
    Fxsommerzeit = 1 - byt
34
Else
35
    Fxsommerzeit = byt
36
End If
37
End Function

Es ist schon erstaunlich, wie "kompatibel" Bascom zu VBA ist...

von Paul B. (paul_baumann)


Lesenswert?

@Manfred

Prima! Danke. Das werde ich mal in mein Uhrprogramm hineinbauen, damit 
ich
das Biest nicht immer von Hand umstellen muß.

MfG Paul

von Manfred S. (Firma: Manfred) (xfred343)


Lesenswert?

Hallo,

jetzt der komplette Beispielcode, ich finde, die Bascom-Routinen sind 
hier mit Clock=User sehr gut einbindbar
1
$regfile = "m644def.dat"
2
$crystal = 8000000
3
$lib "i2c_twi.lbx"
4
Config Twi = 100000                                         'DS1307 mag nicht mehr!!!
5
Config Clock = User
6
Config Date = Dmy , Separator = .                           'German
7
'**************************** Hardware-Definitionen
8
Config Lcdpin = Pin , Db4 = Porta.4 , Db5 = Porta.5 , Db6 = Porta.6 , Db7 = Porta.7 , E = Porta.3 , Rs = Porta.2
9
Config Lcd = 16 * 2
10
Config Sda = Portc.1                                        'I2C-Pins definieren, bei Atmega 8: PortC.4
11
Config Scl = Portc.0                                        'PortC.5 bei Atmega 8
12
Const Ds1307_write = 208                                    '&HD0 I2C Adresse der Uhr DS1307
13
Const Ds1307_read = 209                                     '&HD1 I2C Adresse der Uhr DS1307
14
'**************************** Declare-Routinen
15
Declare Function Fxsommerzeit() As Byte
16
'**************************** Globale Hilfsvariablen
17
Dim Byt As Byte
18
Date$ = "27.03.11"                                          'Bascom steuert Setdate bzw. Settime automatisch an
19
Time$ = "01:59:55"                                          'kurz vor Beginn der Sommerzeit, Uhr springt auf 3.00
20
Do
21
   Cls
22
   Lcd Date$
23
   Lowerline
24
   Lcd Time$                                                'Uhr springt gleich auf 3:00 statt auf 2:00
25
   Waitms 1000
26
   If _sec >= 3 And _min = 0 Then Exit Do
27
Loop
28
_year = 11                                                  'direktes Setzen der Variablen
29
_month = 10
30
_day = 30
31
Gosub Setdate                                               'wirksam erst bei manuellem Aufrufen der Schreibroutine
32
_hour = 1
33
_min = 59
34
_sec = 55
35
Gosub Settime
36
Do
37
   Cls
38
   Lcd Date$                                                'getddatetime wird automatisch ausgeführt
39
   Lowerline
40
   Lcd Time$                                                'nach 1 Stunde wird wieder bei 2:00 begonnen
41
   Waitms 1000
42
Loop
43
End
44
'**************************** Uhrzeit
45
Getdatetime:
46
I2cstart                                                    ' Start
47
I2cwbyte Ds1307_write                                       ' DS1307 schreiben
48
I2cwbyte 0                                                  ' DS1307 Adresszeiger auf 0 stellen
49
I2cstart                                                    ' Start
50
I2cwbyte Ds1307_read                                        ' DS1307 lesen (ab vorher eingestellter Adresse 0)
51
I2crbyte Byt , Ack                                          ' Sekunden
52
_sec = Makedec(byt)
53
I2crbyte Byt , Ack                                          ' Minuten
54
_min = Makedec(byt)
55
I2crbyte Byt , Ack                                          ' Stunden
56
_hour = Makedec(byt)
57
I2crbyte Byt , Ack                                          ' Wochentag (in Dummy gelesen da von date$/time$ nicht genutzt)
58
I2crbyte Byt , Ack                                          ' Tag
59
_day = Makedec(byt)
60
I2crbyte Byt , Ack                                          ' Monat
61
_month = Makedec(byt)
62
I2crbyte Byt , Nack                                         ' Jahr
63
_year = Makedec(byt)
64
I2cstop
65
Byt = Fxsommerzeit()
66
If Byt = 1 Then                                             'nicht erlaubt bis Bascom 2.0.6: fxsommerzeit()=1
67
  If _hour = 23 Then
68
      _hour = 0
69
      If _month = 4 Or _month = 6 Or _month = 9 Then        'Monate 4,6,9 je 30 Tage
70
         Byt = 30
71
      Else
72
         Byt = 31                                           'Monate 3,5,7,8 je 31 Tage
73
      End If
74
      If _day = Byt Then
75
         _day = 1
76
         Incr _month
77
      Else
78
         Incr _day
79
      End If
80
   Else
81
      Incr _hour
82
   End If
83
End If
84
Return
85
Setdate:
86
  I2cstart                                                  ' Start
87
  I2cwbyte Ds1307_write                                     ' DS1307 schreiben
88
  I2cwbyte 3                                                ' DS1307 Adresszeiger auf 4 (Byte 5) stellen
89
  Byt = Dayofweek()
90
  I2cwbyte Byt
91
  Byt = Makebcd(_day)
92
  I2cwbyte Byt                                              ' Tag schreiben
93
  Byt = Makebcd(_month)
94
  I2cwbyte Byt                                              ' Monat schreiben
95
  Byt = Makebcd(_year)
96
  I2cwbyte Byt                                              ' Jahr schreiben
97
  I2cstop
98
Return
99
Settime:
100
  Byt = Fxsommerzeit()
101
  If Byt = 1 Then                                           'nicht erlaubt bis Bascom 2.0.6: fxsommerzeit()=1
102
     If _hour = 0 Then
103
         _hour = 23
104
         If _day = 1 Then
105
            If _month = 5 Or _month = 7 Or _month = 10 Then
106
               _day = 30
107
            Else
108
               _day = 31
109
            End If
110
         Else
111
            Decr _day
112
         End If
113
         Gosub Setdate                                      'Sonderfall: Sommerzeit wirkt sich auf Datum aus!!
114
     Else
115
        Decr _hour
116
     End If
117
  End If
118
  I2cstart                                                  ' Start
119
  I2cwbyte Ds1307_write                                     ' DS1307 schreiben
120
  I2cwbyte 0
121
  Byt = Makebcd(_sec)                                       ' DS1307 Adresszeiger auf 0 stellen
122
  I2cwbyte Byt                                              ' Sekunden schreiben
123
  Byt = Makebcd(_min)
124
  I2cwbyte Byt                                              ' Minuten schreiben
125
  Byt = Makebcd(_hour)
126
  I2cwbyte Byt                                              ' Stunden schreiben
127
  I2cstop
128
Return
129
'**************************** Sommerzeit - Shift 1 _hour
130
Function Fxsommerzeit() As Byte
131
If _month < 3 Or _month > 10 Then                           'keine Sommerzeit
132
   Fxsommerzeit = 0
133
   Exit Function
134
End If
135
If _month >= 4 And _month <= 9 Then                         'jedenfalls Sommerzeit
136
   Fxsommerzeit = 1
137
   Exit Function
138
End If                                                      'betrachte nur mehr 3 und 10
139
If _day >= 25 Then                                          'Grenze: letzter Sonntag im Monat
140
    Byt = Dayofweek()                                       '0=Mo, 1=Di,.. 6=So lt. Bascom
141
    If Byt = 6 And _hour >= 2 Then                          'sonntags ab 2.00
142
       Byt = 1
143
    Else
144
       Byt = _day - Byt                                     'ermittle Grenze vor oder nach letztem Sonntag
145
       If Byt <= 25 Then
146
          Byt = 0
147
       Else
148
          Byt = 1
149
       End If
150
    End If
151
Else
152
   Byt = 0
153
End If
154
If _month = 10 Then                                         'in Oktober nach Grenze: keine Sommerzeit
155
    Byt = 1 - Byt
156
End If
157
Fxsommerzeit = Byt                                          'in März: nach Grenze: Sommerzeit
158
End Function
159
Return

von Thomas R. (gastrodus)


Lesenswert?

Hallo zusammen

Schön gelöst, die Sommerzeitumstellung. Nur liegt da leider eine falsche 
Annahme vor. Die Zeitumstellung geschieht nicht um Mitternacht sondern 
um 2 Uhr im März und um 3 Uhr im Oktober. Somit kann das Thema mit der 
Datum-Umstellung auch vergessen werden.

Gruss
Thomas

von Karl H. (kbuchegg)


Lesenswert?

Thomas Riesen schrieb:
> Hallo zusammen
>
> Schön gelöst, die Sommerzeitumstellung. Nur liegt da leider eine falsche
> Annahme vor. Die Zeitumstellung geschieht nicht um Mitternacht sondern
> um 2 Uhr im März und um 3 Uhr im Oktober.

Kommt drauf an, wofür man es braucht.

Für eine Aquariumsbeleuchtung ist es egal, ob die Uhr in der Nacht jetzt 
fälschlicherweise um Mitternacht  um 1 Stunde hüpft oder erst um 3:00.

Hauptsache um 7 in der Früh stimmt wieder alles und das Licht schaltet 
sich mit dem Piepston der 7-Uhr Nachrichten im Radio ein.

von Manfred S. (Firma: Manfred) (xfred343)


Lesenswert?

Zudem wird ja eh auf 2.00  im Programmcode abgeprüft. Ich hab das 
Programm in meinen Türsteuerungen erfolgreich im Einsatz

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Für eine Aquariumsbeleuchtung ist es egal, ob die Uhr in der Nacht jetzt
> fälschlicherweise um Mitternacht  um 1 Stunde hüpft oder erst um 3:00.
                       ***********

Um 2 natürlich. Ist ja extra eine Prüfung darauf drinnen.
Mitternacht wäre ein bischen dämlich, weil man darauf aufpassen müsste, 
beim zurückstellen der Uhr den Datumswechsel nicht 2 mal zu zählen.

Edith: zu langsam. Manfred hats schon gesehen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.