Upload
others
View
12
Download
0
Embed Size (px)
Citation preview
Die Geburtstagskalenderuhr
Video: http://www.youtube.com/watch?v=czhl8_Aprc8
Beschreibung des ProjektsDa ich leider manchmal die Geburtstage lieber Mitmenschen vergesse, habe ich mir gedacht, ein
Geburtstagskalender könnte vielleicht ganz nützlich sein. Wie bei einem Geburtstagskalender in
Papierform, sollten die Termine unabhängig vom jeweiligen Jahr und Wochentag am Geburtsda-
tum angezeigt werden. Nebenbei sollten auch andere Feiertage mit angezeigt werden.
Dazu sollte die Kalenderuhr Datum, Uhrzeit und Wochentag anzeigen und optisch und akustisch
daran erinnern, dass Heute ein besonderer Tag ist. Da ich gern fotografiere und bei Sonnenaufgang
oder Sonnenuntergang das beste Licht ist, wollte ich, dass mir die Uhr die entsprechenden Zeiten
angibt.
Datum, Uhrzeit und andere Informationen sollten auf einem 16x4 LCD-Modul angezeigt werden,
Uhrzeit und Datum der besseren Ablesbarkeit wegen auf einer zusätzlichen 7-Segmentanzeige.
- 1 -
Als Grundlage sollte das myAVR Board light dienen, von dem möglichst alle verfügbaren Kompo-
nenten eine Funktion bekommen sollten. Zeit und Datum sollte eine RTC-Komponente (DS1307)
liefern und sämtliche Daten sollten in einem seriellen EEPROM gespeichert werden. Die Daten-
übertragung sollte PC-gesteuert über das myUSBtoUART-Modul erfolgen.
HardwareDas myAVR Board light ist die Grundlage der Kalenderuhr, auf die eine zweite (Lochraster)Platine
mit den Anzeigekomponenten gesetzt wird (Abbildung 1). Die Anzeigen sind ein 16x4 LCD-Modul
(Displaytech 164A) und eine serielle 7-Segment LED Anzeige (blau, Sparkfun Electronics). Die 7-
Segemtanzeige sieht nicht nur super aus (wie ich finde), sie hat auch den Vorteil nur eine einzige
Datenleitung zu benötigen. Der ATmega8 des myAVR Board light wird durch einen ATmega168
ersetzt, um etwas mehr Platz für das Programm zu haben.
Sämtliche Daten für Geburtstage, Feiertage, Sonnenaufgänge und Sonnenuntergänge werden in
einem EEPROM (24AA128-I/P, Microchip) gespeichert. Eine Echtzeituhr (DS1307, Dallas) liefert
Datum und Uhrzeit. Das batteriegepufferte NV-RAM der Uhr dient als Speicher für Einstellungen.
Beide Komponenten werden über den seriellen I2C-Bus angesteuert. Strom liefert ein Netzteil (5V)
basierend auf dem externPowerKit von Laser & Co. Solutions GmbH. Alle diese Komponenten
werden auf dem Rasterfeld des myAVR Board light untergebracht.
- 2 -
Abbildung 1: Seitenansicht der Kalenderuhr
Stückliste
Bauteil Anzahl Anbieter
myAVR Board light, Bausatz 1 Laser & Co. Solutions GmbH
16x4 LCD-Modul 164A (Displaytech) 1 Reichelt, Art.-Nr.: LCD 164A LED
7-Segment LED Anzeige blau (seriell) 1 Watterott electronic, Art.-Nr.: COM-09765
IC1: ATmega168PA-PU 1
IC2: EEPROM 24AA128-I/P 1
IC3: RTC DS1307 1
VR1: Spannungsregler µA 1705 1
BR1: Gleichrichter DIL B80C800DIP 1
T1: Transistor BC547C 1
D1: Diode BAT46 1
D2: Diode 1A - 1N4001 1
C6,8: Kondensator 47µF 2
C7,9: Kondensator 100nF 2
P1: Einstellpotentiometer, liegend, 5 K-Ohm 1
R2,3,6: Widerstand 10 K-Ohm 3
R5: Widerstand 480 Ohm 1
Q2: Uhrenquarz 32,768kHz (12.5 pF) 1
BAT1: Lithium-Knopfzelle: CR 2032 1
Batteriehalter 20 mm 1
IC-Sockel 28-polig (optional) 1
IC-Sockel 8-polig (optional) 2
Lochrasterplatine 100 x 100 mm 1
20 pol. Buchsenleiste gerade (RM 2,54, H: 8,5 mm) 1
10 pol. Buchsenleiste gerade (RM 2,54, H: 8,5 mm) 1
50-pol Stiftleiste gerade, RM 2,54 1
Hohlstecker-Einbaubuchse, gewinkelt 1
Wannenstecker 6-polig gerade 1
Buchsen-/Stiftleisten für Anzeigen (optional)
- 3 -
Schaltplan
- 4 -
Abbildung 2: Schaltplan
Zusammebau des myAVR BoardsDas myAVR Board light wird fast wie in der Anleitung angegeben aufgebaut. Zusätzlich wird der
6-polige Wannenstecker aufgelötet, um den ATmega168 über die ISP-Schnittstelle programmieren
zu können.
Die gewinkelte Buchsenleiste wird durch eine gerade Buchsenleiste ersetzt, die auf der Rückseite
des myAVR Boards angebracht wird. Eine Diode (D1) wird zwischen das myAVR Board light und
myUSBtoUART-Modul gelötet.
Zusätzlich wird bzw. werden:
• PD2 und PD3 auf der Rückseite des Boards mit Taster 1 und 2 über Drähte verbunden
• PB1 mit dem Summer verbunden.
• PC2 mit der Photodiode verbunden.
Bestückung des Rasterfeldes auf dem myAVR Board lightZuerst werden die Komponenten der Spannungsversorgung aufgebracht, dann die 8-poligen IC-So-
ckel, die Widerstände R2 und R3, der Uhrenquarz Q2 und der Batteriehalter (Abbildung 3) Nach-
dem die Komponenten gemäß Abb. 2 – 4 eingesetzt und verdrahtet sind, wird noch eine 10-polige
Buchsenleiste auf die Rückseite des myAVR Boards gelötet und entsprechend angeschlossen
(Abbildung 4). SDA und SCL werden mit PC4 und PC5 verbunden. LED-out wird mit der grünen
LED verbunden. Zuletzt wird der Hohlstecker über zwei Drähte mit dem Brückengleichrichter BR1
verbunden. An diesen Hohlstecker wird später das Netzteil angeschlossen.
- 5 -
Abbildung 3: Rasterfeld Oberseite
Dieser Aufbau stellt für sich genommen schon eine vollständig funktionierende Einheit dar und
kann unabhängig von der Anzeigekomponente betrieben werden.
Aufbau der AnzeigekomponenteDie Anzeigekomponente wird auf einer herkömmlichen 100 x 100 mm Punktrasterplatine aufge-
baut. Zuerst werden die Stiftleisten (20- und 10-polig) auf der Cu-Seite der Platine aufgelötet. Das
gestaltet sich schwierig, da Lötzinn nicht auf der unbeschichteten Seite haftet. Man muss die Stift-
leisten leicht herausziehen und diese mit der Spitze des Lötkolben auf der Cu-Seite löten
(Abbildung 5).
Die Stiftleisten werden später mit dem myAVR Board verbunden. Man sollte sicherstellen, dass
das Board mittig auf der Punktrasterplatine sitzt. Dann werden optional die Buchsenleisten für die
- 6 -
Abbildung 5: Anbringen der Stiftleiste
Abbildung 4: Rasterfeld Unterseite (Durchsicht)
Anzeigeelemente angebracht. Auch hier sollte man darauf achten, dass hinterher alles so ange-
bracht werden kann, wie man es sich gewünscht hat. Dann werden Trimmer P1, die Widerstände
R5, R6 und der Transistor T1 aufgelötet und gemäß Abbildung 6 und Abbildung 7 verdrahtet. Es ist
hilfreich, etwas Lötzinn von der Stiftleiste bis zum nächsten Punkt auf der Rasterplatine zu ziehen,
um von hier aus die Verdrahtung durchzuführen. Die Drähte direkt an der Stiftleiste anzulöten, ist
recht schwierig.
- 7 -
Abbildung 6: Anzeigekomponente Oberseite (R4 und T1 liegen im realen Aufbau unterhalb des LCD-Moduls)
Die Anzeigekomponente kann jetzt mit dem myAVR Board verbunden werden. Mit P1 lässt sich
der Kontrast des LCD-Moduls regeln, die Hintergrundbeleuchtung kann über die Software (PB2)
an und ausgestellt werden. Die Kommunikation mit der seriellen 7-Segmentanzeige erfolgt über
PB0. PD4-PD7 und PC0/PC1 dienen zur Ansteuerung des LCD-Moduls.
Jetzt fehlt nur noch die Stromversorgung. Die erledigt ein Steckernetzteil mit 9V Spannung.
Anmerkung: Auf den Fotos sind noch 3 Jumper zu erkennen. Diese hatte ich zum testen des Auf-
baus genutzt (Hintergrundbeleuchtung, Direktverbindung PC > 7-Segementanzeige und RW-Mo-
dus des LCD-Moduls). Für die Funktion der Uhr sind sie nicht notwendig.
- 8 -
Abbildung 7: Anzeigekomponente Unterseite (Durchsicht)
- 9 -
Abbildung 8: Bestücktes Rasterfeld mit dem myUSBtoUART-Modul und der BAT46-Diode (links)
Abbildung 9: Rückseite des myAVR Boards und der Anzeigekomponente (siehe dazu auch die An-merkung auf der vorhergehenden Seite)
Programmierung Als Programmiersprache wurde BASCOM v2 gewählt. Das fertige Programm gelangt über die ISP-
Schnittstelle auf den Mikrocontroller. Das Programm, dass die Daten vom PC überträgt, wurde mit
AutoIt v3 realisiert.
Programmstruktur (Atmega168)Das Programm kann in 3 Teilbereiche gegliedert werden:
1. Anzeige von Uhrzeit, Datum, Geburtstagen, Feiertagen, Sonnenaufgängen/-untergängen
2. Empfang und Speichern von Daten und Einstellungen über das myUSBtoUART-Modul
3. Einstellungen; dazu gehören:
Uhrzeit und Datum
Hintergrundbeleuchtung des LCD-Moduls
Sommer-/Winterzeit
Zeitkorrektur
Anzeige von Uhrzeit, Datum, Geburtstagen, Feiertagen etc. (Übersicht)Auf dem 16x4 LCD-Modul werden jeweils nach Tastendruck nacheinander folgende Bildschirme
angezeigt:
- 10 -
Abbildung 10: Verschiedene Anzeigen auf dem 16x4-LCD-Modul (für besser Lesbarkeit bitte vergrößern). Video: http://www.youtube.com/watch?v=czhl8_Aprc8
Startbildschirm
Termine
Sonnenaufgänge / Sonnenuntergänge
Datum & Uhrzeit einstellen
Taster1
Taster1
Taster1
Taster1
Anzeige für einen:normalen Tag Geburtstag Feiertag
Geburtstagskind „Klaus“
geboren „1951“, wird heute „60“
um „7:43“ wird eine Melodie abgespielt
Wie in Abbildung 10 gezeigt, ändert sich die Anzeige des Startbildschirms, wenn ein besonderes
Datum erreicht ist. Die in der zweiten Zeile angegebene Uhrzeit ist dann die Zeit, an der eine Melo-
die abgespielt werden kann; es kann sich dabei natürlich auch um die genaue Geburtszeit handeln.
Bei einem Geburtstag sieht man noch das Geburtsjahr und das erreichte Alter.
Die nachfolgenden Bildschirme zeigen die nächsten 3 Termine bzw. Sonnenaufgänge / Sonnenun-
tergänge der nächsten 3 Tage.
Der letzte Bildschirm verzweigt in den Bereich zur manuellen Zeit- bzw. Datumseinstellung. Viel
komfortabler lassen sich diese Einstellungen allerdings mit dem PC-Programm machen.
Die 7-Segmentanzeige zeigt unabhängig von den ersten 3 Bildschirmen in wechselnden Zeitabstän-
den Uhrzeit & Datum wie folgt an:
Wenn Bildschirm 4 (Datum & Uhrzeit einstellen) erreicht wird, gibt die Anzeige „Set“ aus. Der
Doppelpunkt bei der Zeitanzeige und der Punkt bei der Datumsangabe blinken im 2s-Takt. Wenn
das Jahr angezeigt wird, wird kein (Doppel-)Punkt angezeigt
Ausgabe auf dem LCD-Modul
Die Realisierung einer Ausgabe auf einem LCD-Modul ist mit BASCOM sehr komfortabel. Dazu
muss am Anfang des Programms folgende Befehlssequenz eingefügt werden:
Config Lcdpin = Pin , Rs = Portc.0 , E = Portc.1 , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7Config Lcd = 16 * 4Cursor = Off
In der Hauptprogrammschleife wird dann beispielsweise folgende Befehlssequenz verwendet:
Locate 1 , 1 : Lcd "Datum & Uhrzeit "Locate 2 , 1 : Lcd Weekdaystr ; Spc(spaces)Locate 3 , 1 : Lcd Date$ ; Spc(8)Locate 4 , 1 : Lcd Time$ ; Spc(8)
Der Befehl „Cls“ wird kaum verwendet; stattdessen wird jede Zeile des LCD-Moduls vollständig
überschrieben, ggf. werden Leerzeichen (Anweisung Spc) eingefügt.
Die Umschaltung zwischen den einzelnen Bildschirmen (Abbildung 10) erledigt eine Select Case-
- 11 -
Abbildung 11: Wechselnde Darstellung der 7-Segmentanzeige
UhrzeitHH:MM
Anzeigedauer: 52s
DatumTT.MM
Anzeigedauer: 4s
DatumJJJJ
Anzeigedauer 4s
Anweisung in der Hauptprogrammschleife, welche die Zahl der Tastendrücke auswertet (Variable
Cntb1). Jeder Tastendruck des Tasters 1 wird über einen Debounce-Befehl ausgewertet. Debounce
(eine Art Software-Entprellung) ist optimal, allzu „nervöse“ Taster zu bändigen. Um wirklich sicher
zu gehen, wartet in der Button1-Subroutine noch ein Bitwait-Befehl auf den Taster.
Debounce Pind.2 , 0 , Button1 , Sub...Button1: Bitwait Pind.2 , Reset If Cntb1 = 3 Then Cntb1 = 0 Else Incr Cntb1 ClsReturn
Select Case Cntb1
Case 0: 'Startbildschirm...Case 1: 'Termine...Case 2: 'Sonnenauf/-untergänge...Case 3: 'Datum & Uhrzeit einstellen...End Select
Ausgabe auf der seriellen 7-Segmentanzeige
Für die Ausgabe auf der seriellen 7-Segmentanzeige muss zuerst ein Software-UART in BASCOM
realisiert werden, da das Hardware-UART für den Datenempfang zuständig sein soll:
Open "comb.0:9600,8,n,1" For Output As #1
Die serielle 7-Segementanzeige wird in der Hauptprogrammschleife dann über eine Print #1-
Anweisung folgendermaßen angesteuert:
Timestr = Time$...A = Mid(timestr , 1 , 2)B = Mid(timestr , 4 , 2)...Print #1 , A ; B;
Die serielle 7-Segementanzeige kennt einige Steuerbefehle (siehe Datenblatt beim Anbieter), so
etwa zum setzen des Doppelpunkts oder des Dezimalpunkts:
Print #1 , "w";Printbin #1 , 16 ;...Print #1 , "w";Printbin #1 , 2;
Wichtig ist ein “;“ am Ende eines Print-Befehls, sonst zeigt das Modul nur „Müll“ an.
Die im 2s-Takt blinkende Anzeige des (Doppel)Punktes wird über den 16 Bit-Timer des
ATmega168 realisiert, dabei wird die Variable Colon_onoff auf 0 oder 1 gesetzt (Toggle-
Anweisung):
- 12 -
Config Timer1 = Timer , Prescale = 64On Timer1 Toggle_colonEnable Timer1Start Timer1
Enable Interrupts...Toggle_colon: Timer1 = 7936 Toggle Colon_onoff If All_off = 1 Then Colon_onoff = 0Return
Der automatische Wechsel von Datum, Uhrzeit und (Doppel-)Punkt (siehe Abbildung 11) wird
dann über einige If-Then-Else Anweisungen in der Hauptprogrammschleife realisiert
(Colon_onoff/Dp_onoff/All_off schaltet :/./ / AN bzw. AUS):
Timestr = Time$ Datestr = Date$
A = Mid(timestr , 1 , 2) B = Mid(timestr , 4 , 2) C = Mid(timestr , 7 , 2)
If Colon_onoff = 0 And Dp_onoff = 0 Then Print #1 , "w"; Printbin #1 , 0 ; Elseif Colon_onoff = 1 And Dp_onoff = 0 And All_off = 0 Then Print #1 , "w"; Printbin #1 , 16 ; Elseif Colon_onoff = 1 And Dp_onoff = 1 And All_off = 0 Then Print #1 , "w"; Printbin #1 , 2 ; Else Print #1 , "w"; Printbin #1 , 0; End If
If C > "30" And C < "35" Then All_off = 0 A = Mid(datestr , 1 , 2) B = Mid(datestr , 4 , 2) Dp_onoff = 1 Elseif C > "34" And C < "39" Then All_off = 1 A = "20" B = Mid(datestr , 7 , 2) Else Dp_onoff = 0 All_off = 0 End If
If A < "10" Then A = Mid(a , 2 , 1) Print #1 , "x" ; A ; B; Else Print #1 , A ; B; End If
In der letzten If-Then-Else-Anweisung wird bei einer führenden Null das erste Segment der 7-
Segemtanzeige ausgeschaltet ("x"). Aus z.B. „07:34“ wird „7:34“ bzw. wird aus dem „07.04“ der
„7.04“.
Steuerung der Hintergrundbeleuchtung des LCD-Moduls
Die Hintergrundbeleuchtung des LCD-Moduls kann über das PC-Programm AN/AUS gestellt wer-
- 13 -
den. Daneben gibt es noch den Auto-Modus. Dieser Modus wertet die Helligkeit im Raum über den
Fotowiderstand des myAVR Boards und nutzt den A/D-Wandler des ATmega. Wenn es zu dunkel
ist, wird die Beleuchtung ein- und wenn es hell genug ist wieder ausgeschaltet. Unabhängig davon
wird die Hintergrundbeleuchtung um 0.00 Uhr vollständig ausgestellt und ab 7.00 wieder in den
Auto-Modus versetzt. Immer AN ist die Hintergrundbeleuchtung bei der manuellen Zeiteinstellung
und beim Abspielen einer Melodie:
Config Portc.2 -1 = OutputConfig Adc = Single , Prescaler = Auto , Reference = Avcc
Dim Licht As Word
Lcd_bl Alias Portb.2Config Lcd_bl = Output...Lcd_blonoff:
Licht = Getadc(2) If Lcd_blst = "1" Then Lcd_bl = 1 Elseif Lcd_blst = "3" And Licht < 120 And _hour > 6 Then Lcd_bl = 1 Else Lcd_bl = 0 End If
Return
Die Lcd_blonoff-Subroutine wird dann in der Hauptprogrammschleife aufgerufen. Lcd_bl (ein
„Alias“ für Portb.2) schaltet die Hintergrundbeleuchtung AN oder AUS. Lcd_blst bestimmt, wel-
cher Modus vorliegt. Die Variable Licht steuert, ab wann die Beleuchtung angeschaltet wird; 120
war hier ein guter Wert. Die Variable Lcd_blst wird im NV SRAM der DS1307-RTC gespeichert.
Wie das funktioniert, wird im Abschnitt Schreiben & Lesen von Daten & Zeiteinstellung beschrie-
ben.
Uhrzeit & DatumAktuelle Uhrzeit und Datum sind in den Variablen Time$ und Date$ enthalten, die BASCOM gene-
riert. Über den I2C-Bus wird die DS1307-RTC wie folgt angesprochen:
$lib "i2c_twi.lbx" 'TWIConfig Sda = Portc.4Config Scl = Portc.5Const Ds1307w = &HD0 'DS1307 schreibenConst Ds1307r = &HD1 'DS1307 lesen...Config Clock = UserConfig Date = Dmy , Separator = ....Getdatetime: I2cstart I2cwbyte Ds1307w I2cwbyte 0 I2cstart I2cwbyte Ds1307r I2crbyte _sec , Ack I2crbyte _min , Ack I2crbyte _hour , Ack I2crbyte Weekday , Ack I2crbyte _day , Ack
- 14 -
I2crbyte _month , Ack I2crbyte _year , Nack I2cstop _sec = Makedec(_sec) : _min = Makedec(_min) : _hour = Makedec(_hour) _day = Makedec(_day) : _month = Makedec(_month) : _year = Makedec(_year)Return
Eine Ausgabe auf dem LCD-Modul wird wie oben angegeben realisiert:
Locate 1 , 1 : Lcd "Datum & Uhrzeit "Locate 2 , 1 : Lcd Weekdaystr ; Spc(spaces)Locate 3 , 1 : Lcd Date$ ; Spc(8)Locate 4 , 1 : Lcd Time$ ; Spc(8)
Der Wochentag „Weekday“ ist eine Zahl, die über eine Data-Tabelle in den entsprechenden Wo-
chentag „Weekdaystr“ umgesetzt wird:
Weekdaystr = Lookupstr(weekday , Weekdays)...Weekdays:
Data "dummy" , "Montag" , "Dienstag" , "Mittwoch" , "Donnerstag" , "Freitag" , "Samstag" , "Sonn-tag"
Empfang von Daten über das UARTDer Empfang der Zeichen erfolgt Interrupt-gesteuert. Im Gegensatz zum Input-Befehl wird das
Programm weiter ausgeführt und wartet nicht auf eine Eingabe:
Dim L As String * 4Dim S As String * 30Dim Z(31) As Byte At S OverlayDim N As Byte...On Urxc OnrxdEnable Urxc'ggf. „Enable Interrupts“ falls noch nicht anderweitig aktiviert...Onrxd: Incr N Z(n) = UDRReturn
Eine weitere schöne Sache an BASCOM sind „Overlays“ (siehe BASCOM-Hilfe). Die über UART
empfangenen Zeichen „Z(n)“ werden zum String „S“ zusammengesetzt.
Bei jeder Übertragung werden 31 Zeichen „N“ gesendet, die ersten vier Zeichen „L“ geben an, um
welche Art von Daten es sich handelt und was der ATmega damit machen soll (Select Case,
Case...):
If N > 30 Then
L = Left(s , 4)
Select Case L
Case "TEST": ... Case "TIME":
- 15 -
... Case "SETT": ... Case "SUNS": ... Case "DATE": ... Case "CDAT": ... End Select
End If
Der „Case“ TEST ist der einfachste Fall, hier wird der empfangene String an den PC zurück gesen-
det. Das dient zur Kontrolle, ob die Kommunikation zwischen Kalenderuhr und PC funktioniert:
...Case "TEST":
N = 0 Print S;...
N muss nach jeder CASE-Anweisung wieder auf 0 gesetzt werden.
Schreiben & Lesen von Daten & Zeiteinstellung
Zeiteinstellungen
Datum, Wochentag und Uhrzeit können über folgende Unterprozeduren gesetzt werden (man be-
achte jeweils das I2Cwbyte nach Ds1307w):
Const Ds1307w = &HD0 'DS1307 schreiben...Setdate: _day = Makebcd(_day) : _month = Makebcd(_month) : _year = Makebcd(_year) I2cstart I2cwbyte Ds1307w I2cwbyte 4 I2cwbyte _day I2cwbyte _month I2cwbyte _year I2cstop Waitms 10Return
Setweekday: I2cstart I2cwbyte Ds1307w I2cwbyte 3 I2cwbyte Weekday I2cstop Waitms 10Return
Settime: _sec = Makebcd(_sec) : _min = Makebcd(_min) : _hour = Makebcd(_hour) I2cstart I2cwbyte Ds1307w I2cwbyte 0 I2cwbyte _sec I2cwbyte _min I2cwbyte _hour I2cstop Waitms 10Return
- 16 -
Zeit und Datum lassen sich in BASCOM aber auch komfortabel über die Variablen Time$ und
Date$ setzen.
Die Echtzeituhr verfügt außerdem über 56 Byte batteriegepuffertes NV SRAM. In diesem werden
diverse Einstellungen der Kalenderuhr gespeichert. Nachfolgend die Angabe, ob momentan Som-
merzeit (Stset=1, Wtset=0) oder Winterzeit (Stset=0, Wtset=1) ist (man beachte wieder das
I2Cwbyte nach Ds1307w):
Const Ds1307w = &HD0 'DS1307 schreiben...Writenvram: I2cstart I2cwbyte Ds1307w I2cwbyte 8 I2cwbyte Stset I2cwbyte Wtset I2cstop Waitms 10Return
Die Zeitdaten, die das Programm über den PC empfängt (siehe Empfang von Daten über das
UART), sehen folgendermaßen aus:
TIME :07.04.1140121:56:57xxxxxx
TIME kennzeichnet, dass es sich um eine Zeitübertragung handelt
07.04.11 ist das Datum
4 ist der Wochentag (Donnerstag)
01 zeigt an, dass wir Sommerzeit haben (10 wäre Winterzeit)
21:56:57 ist die Uhrzeit
xxxxxx ist einfach ein Platzhalter, da immer 31 Zeichen übertragen werden.
Die Echtzeituhr wird dann wie folgt eingestellt:
...Case "TIME":
N = 0 Time$ = Mid(s , 18 , 8) Date$ = Mid(s , 7 , 8) Weekdayst = Mid(s , 15 , 1) Weekday = Weekdayst Call Setweekday
Wtsetst = Mid(s , 16 , 1) Stsetst = Mid(s , 17 , 1)
Wtset = Val(wtsetst) Stset = Val(stsetst)
Call Writenvram...
Aus dem empfangenen String „s“ werden Zeit und Datum über die Mid-Anweisung extrahiert und
gesetzt. Der Wochentag „Weekday“ wird über Call Setweekday gesetzt. Ob momentan Sommer-
bzw. Winterzeit vorliegt, wird in das NV SRAM über Call Writenvram geschrieben.
- 17 -
Einstellen von Sommerzeit und Winterzeit
Sommer- und Winterzeit werden von der Kalenderuhr automatisch eingestellt (Letzter Sonntag im
März oder Oktober). Wichtig ist, dass bei einer Zeitübertragung vom PC aus immer angegeben wer-
den muss, ob momentan Sommerzeit oder Winterzeit vorliegt. Bei einer Übertragung werden die
Variablen Stset und Wtset im NV SRAM gespeichert und von der nachfolgenden Routine ausge-
wertet:
Dst_onoff: If _month = 3 And _day > 24 And Weekday = 7 And _hour = 2 Then _hour = _hour + 1 Waitms 10 Call Settime Stset = 1 Wtset = 0 Waitms 10 Call Writenvram End If
If Wtset = 0 And _month = 10 And _day > 24 And Weekday = 7 And _hour = 3 Then _hour = _hour - 1 Waitms 10 Call Settime Wtset = 1 Stset = 0 Waitms 10 Call Writenvram End IfReturn
Die Anweisung _hour = _hour + 1 bzw. _hour = _hour – 1 stellt die Uhr eine Stunde vor bzw.
zurück. Über Call Settime wird die Uhrzeit gespeichert und die aktuellen Variablen Wtset und
Stset werden im NV SRAM gespeichert (Call Writenvram). Die Subroutine Dst_onoff wird in
der Hauptprogrammschleife aufgerufen.
Weitere Einstellungen
Weitere Einstellungen, die NV SRAM gespeichert werden, ist der Modus der
Hintergrundbeleuchtung und die Zeitkorrektur. Die Variablen werden über das PC-Programm
gesendet (siehe Empfang von Daten über das UART) und im NV SRAM abgelegt. Der gesendete
String ist folgendermaßen aufgebaut:
SETT: 310300000000000000000000x
SETT kennzeichnet, dass es sich um eine Einstellung handelt
3 bedeutet, dass die Hintergrundbeleuchtung auf Auto gestellt werden soll (1 = AN; 2=AUS)
1 bedeutet, dass die nachfolgende Sekundenzahl immer nach 24h abgezogen wird
(Zeitkorrektur) ; 0 würde bedeuten, dass die nachfolgende Sekundenzahl immer nach 24h
addiert wird
03 ist die Zahl der Sekunden, um die nach 24h korrigiert wird
die restlichen Nullen und das x sind Platzhalter, da immer 31 Zeichen übertragen werden.
Um die Zeitkorrektur nach 24h durchzuführen, muss die Kalenderuhr wissen, wann die Korrektur-
- 18 -
daten übertragen wurden. Dazu werden die BASCOM-Routinen Sysday() und Secofday() aufge-
rufen und die Ergebnisse zusammen mit den übertragenen Daten im NV SRAM abgelegt (Call
Writenvram_sett). Die Definition der Variablen als „Overlay“ ermöglicht eine direkte Transfor-
mation der Variablen (Systemtag, Sekdestages) als abspeicherbare Bytes (Systemtagby,
Sekdestagesby):
Dim Systemtag As LongDim Systemtagby(4) As Byte At Systemtag Overlay
Dim Sekdestages As LongDim Sekdestagesby(4) As Byte At Sekdestages Overlay
...Case "SETT":
N = 0
Systemtag = Sysday() Sekdestages = Secofday()
Call Writenvram_sett Call Readnvram...
Die Zeichen aus der Datenübertragung vom PC können direkt im NV SRAM abgelegt werden; Z(7)
ist z.B. das 7. übertragene Zeichen. Das I2Cwbyte nach Ds1307w ist diesmal 10, da 8 und 9 bereits
belegt sind (siehe Writenvram):
Writenvram_sett: I2cstart I2cwbyte Ds1307w I2cwbyte 10 I2cwbyte Z(7) I2cwbyte 0 I2cwbyte Z(8) I2cwbyte 0 I2cwbyte Z(9) I2cwbyte Z(10) I2cwbyte 0 I2cwbyte Systemtagby(1) I2cwbyte Systemtagby(2) I2cwbyte Systemtagby(3) I2cwbyte Systemtagby(4) I2cwbyte Sekdestagesby(1) I2cwbyte Sekdestagesby(2) I2cwbyte Sekdestagesby(3) I2cwbyte Sekdestagesby(4) I2cstop Waitms 10Return
Da wichtige Einstellungsvariablen nicht im RAM des ATmega gelandet sind, muss der gerade ins
NV SRAM geschriebene Inhalt sofort wieder über Call Readnvram gelesen werden (hier erfolgt
dann die Zuordnung der Daten aus dem NV SRAM zu Variablen):
Dim Lcd_blst As String * 1Dim Lcd_blby(2) As Byte At Lcd_blst Overlay
Dim Plusminst As String * 1Dim Plusminby(2) As Byte At Plusminst Overlay
Dim Sekundest As String * 2Dim Sekundeby(3) As Byte At Sekundest Overlay
- 19 -
Dim Systemtag As LongDim Systemtagby(4) As Byte At Systemtag Overlay
Dim Sekdestages As LongDim Sekdestagesby(4) As Byte At Sekdestages Overlay...Readnvram: I2cstart I2cwbyte Ds1307w I2cwbyte 8 I2cstart I2cwbyte Ds1307r I2crbyte Stset , Ack I2crbyte Wtset , Ack I2crbyte Lcd_blby(1) , Ack I2crbyte Lcd_blby(2) , Ack I2crbyte Plusminby(1) , Ack I2crbyte Plusminby(2) , Ack I2crbyte Sekundeby(1) , Ack I2crbyte Sekundeby(2) , Ack I2crbyte Sekundeby(3) , Ack I2crbyte Systemtagby(1) , Ack I2crbyte Systemtagby(2) , Ack I2crbyte Systemtagby(3) , Ack I2crbyte Systemtagby(4) , Ack I2crbyte Sekdestagesby(1) , Ack I2crbyte Sekdestagesby(2) , Ack I2crbyte Sekdestagesby(3) , Ack I2crbyte Sekdestagesby(4) , Nack I2cstopReturn
Bei jedem Reset oder direkt nach dem Einschalten der Kalenderuhr wir vor der Hauptprogramm-
schleife Call Readnvram ausgeführt.
Zeitkorrektur
Die DS1307-RTC + Quarz ist nicht unbedingt ein hochpräzises Zeitmessinstrument, was am Quarz
liegen kann oder allgemein am Aufbau. Die nachfolgende Subroutine korrigiert die Uhrzeit alle 24h
zu einer bestimmten Uhrzeit um +/– x Sekunden. Die nachfolgende Routine ist recht komplex, was
daran liegt, dass die Zeitkorrektur erst am darauffolgenden Tag passieren darf und dass bei einer
negativen Zeitkorrektur die Kalenderuhr nicht in einer Korrekturschleife hängen bleibt. Sekundest
(Sekunde, um die korrigiert wird) und Plusminst (Zeitkorrektur + oder – ) werden aus dem NV
SRAM gelesen (Readnvram) (über „Overlay“ umgewandelt), ebenso Systemtag (Datum der Zeit-
korrekturübertragung) und Sekdestages (Sekunde des Tages, an dem die Zeitkorrekturübertra-
gung stattfand) (siehe vorheriger Abschnitt):
Dim Korrektur As LongDim Sekundelong As LongDim Sysd As LongDim Secd As LongDim Zeitkorrekturbit As Bit...Zeitkorrektur:
Call Readnvram
Sysd = Sysday() Secd = Secofday() Sekundelong = Val(sekundest)
If Secd = 86399 Then Zeitkorrekturbit = 0
- 20 -
If Plusminst = "0" Then Korrektur = Sekdestages + Sekundelong If Plusminst = "1" Then Korrektur = Sekdestages - Sekundelong
If Sysd <> Systemtag And Secd = Sekdestages And Sekundelong <> 0 And Zeitkorrekturbit = 0 Then ' Time$ = Time(korrektur) Zeitkorrekturbit = 1 End IfReturn
Sysd und Secd entsprechen der aktuellen Systemsekunde und dem aktuellen Systemdatum. Nur
wenn diese nicht den gespeicherten Daten entsprechen, wird die Zeitkorrektur angewendet (letzte
If-Then-Else-Anweisung). Die Zeit wird über die BASCOM-Funktion Time aus der korrigierten
Sekunde des Tages eingestellt (Time$ = Time(korrektur)). Danach muss das Zeitkorrektur-
bit auf 1 gesetzt werden, um zu verhindern, dass bei einer negativen Korrektur die Zeit immer
wieder neu eingestellt wird. Am Ende des Tages wird das Zeitkorrekturbit wieder auf 0 gesetzt
(If Secd = 86399 Then Zeitkorrekturbit = 0).
Sonnenaufgänge und Sonnenuntergänge speichern und abrufen
Sonnenaufgänge und Sonnenuntergänge für einen bestimmten Standort zu berechnen, ist recht
aufwendig, so dass diese Daten nur übertragen (siehe Empfang von Daten über das UART) und im
EEPROM abgespeichert werden. Der gesendete String ist folgendermaßen aufgebaut:
SUNS: 421704:2420:280000000000x
SUNS kennzeichnet, dass es sich um einen Sonnenauf/untergang handelt
4217 ist der Tag des Sonnenauf/untergangs (gerechnet ab dem 01.01.2000)
04:24 ist der Zeitpunkt des Sonnenaufgangs
20:28 ist der Zeitpunkt des Sonnenuntergangs
die restlichen Nullen und das x sind Platzhalter, da immer 31 Zeichen übertragen werden.
Die nachfolgende CASE-Anweisung ruft die Subroutine Eepromwsonne auf:
... Case "SUNS":
N = 0
Call Eepromwsonne...
Const Eeprw = &HA0Const Eeprr = &HA1
Dim Adresse_sonne As WordDim Adresse_sonne_high As ByteDim Adresse_sonne_low As ByteDim X As Byte...Eepromwsonne:
N = 0
For X = 7 To 20
Adresse_sonne_high = High(adresse_sonne)
- 21 -
Adresse_sonne_low = Low(adresse_sonne)
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_sonne_high I2cwbyte Adresse_sonne_low I2cwbyte Z(x) I2cstop
Waitms 10
Incr Adresse_sonne
Next
If Adresse_sonne > 1399 Then Adresse_sonne = 0 '14 bytes pro sonnenauf/-untergang /
Return
Da es sich um ein größeres EEPROM handelt, muss man den Adressbereich in High- und Low
trennen, was BASCOM praktischerweise über die Funktionen High und Low erledigt. Ansonsten
muss man noch beachten, dass von jedem übertragenen String nur die Zeichen 7 bis 20 gespeichert
(For X = 7 To 20....I2cwbyte Z(x)...). Nach 100 übertragenen Tagen wird die Adresse wie-
der auf 0 gesetzt.
Gelesen werden diese Daten über die nachfolgende Funktion. Übergeben wird der Funktion als Ar-
gument die Adresse (adresse_sonne) und man erhält als Ergebnis einen String, der den Tag und
die Uhrzeiten für Sonnenaufgang bzw. Sonnenuntergang beinhaltet:
Const Eeprw = &HA0Const Eeprr = &HA1
Dim Sonnetagst As String * 14Dim Sonnetagby(14) As Byte At Sonnetagst Overlay
Dim Adresse_sonne As WordDim Adresse_sonne_high As ByteDim Adresse_sonne_low As ByteDim X As Byte
Dim Stageeprom As String * 14Dim Stageepromday As String * 4Dim Sahst As String * 2Dim Sarest As String * 3Dim Suhst As String * 2Dim Surest As String * 3Dim Sahstn As IntegerDim Suhstn As Integer
...Function Eepromrsonne(adresse_sonne As Word) As String * 14
For X = 1 To 14
Adresse_sonne_high = High(adresse_sonne) Adresse_sonne_low = Low(adresse_sonne)
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_sonne_high I2cwbyte Adresse_sonne_low
I2cstart I2cwbyte Eeprr I2crbyte Sonnetagby(x) , Nack I2cstop
- 22 -
Incr Adresse_sonne
Next
Stageeprom = Sonnetagst Stageepromday = Left(stageeprom , 4)
If Stset = 1 And Wtset = 0 Then
Sahst = Mid(stageeprom , 5 , 2) Sarest = Mid(stageeprom , 7 , 3) Suhst = Mid(stageeprom , 10 , 2) Surest = Mid(stageeprom , 12 , 3)
Sahstn = Val(sahst) Incr Sahstn Sahst = Str(sahstn) Sahst = Format(sahst , "00")
Suhstn = Val(suhst) Incr Suhstn Suhst = Str(suhstn) Suhst = Format(suhst , "00")
Stageeprom = Stageepromday + Sahst + Sarest + Suhst + Surest
End If
Eepromrsonne = Stageeprom
End Function
Auf den ersten Blick wirkt diese Funktion recht umfangreich, da ggf. die Sommerzeit berücksichtigt
werden muss. Eigentlich werden sonst nur 14 Bytes zu einem String zusammengesetzt, der den Tag
und die Uhrzeiten für Sonnenaufgang bzw. Sonnenuntergang beinhaltet.
Geburtstagstermine und Feiertage (kurz Termine) speichern und abrufen
Im Vergleich zur Sonnenaufgangs- oder Sonnenuntergangsdaten sind die Funktionen, um Geburts-
tage und Feiertage im EEPROM abzuspeichern oder von dort zu lesen etwas komplexer. Das liegt
hauptsächlich darin begründet, dass die Anzahl der abzuspeichernden Daten nicht konstant ist (im
Fall Sonnenaufgänge und Sonnenuntergänge waren es genau 100) und das zu bestimmten Termi-
nen bestimmte Aktionen ausgeführt werden sollen.
Als erstes muss bei jeder Datenübertragung vom PC die Startadresse der Datenspeicherung auf Ih-
ren Ursprungswert zurück gesetzt werden, da der ATmega nicht weiß, ob jetzt der erste oder ir-
gendeinen nachfolgender Termin gesendet wird. Dazu wird vom PC vor der eigentlichen Daten-
übertragung folgender String gesendet (siehe Empfang von Daten über das UART):
CDATxxxxxxxxxxxxxxxxxxxxxxxxxxx
CDAT kennzeichnet, dass die Startadresse zur Terminspeicherung im EEPROM angesteuert
werden soll
die restlichen x sind Platzhalter, da immer 31 Zeichen übertragen werden.
Die nachfolgende CASE-Anweisung setzt dann das EEPROM auf die Startadresse:
- 23 -
Dim Adresse_terminw As Word... Case "CDAT":
N = 0
Adresse_terminw = 0...
Danach sendet der PC folgenden String (bzw. mehrere Strings, je nach der Anzahl der Termine):
DATE0304195127780G1Klaus 1
DATE kennzeichnet, dass es sich um einen Termin handelt
03041951 ist das Geburtsdatum (03.04.1951)
27780 ist die Uhrzeit und gleichzeitig die Zeit, an der eine Melodie abgespielt wird;
angegeben als Sekunde des Tages (07:43)
G kennzeichnet, dass es sich um einen Geburtstag handelt (F = Feiertag)
1 ist die abzuspielende Melodie (0= Keine Melodie)
Klaus ist das Geburtstagskind; bis zu 10 Zeichen sind hier möglich
1 kennzeichnet, dass 1 Termin übertragen wird (2 für 2 Termine, 3 für 3 usw.; max. 99).
Am Ende der Übertragung werden zwei DATE-Strings gesendet, die nur Nullen enthalten,
DATE000000000000000000000000000. Das hat den Zweck, das Ende der aktuell übertragenen Ter-
minliste zu kennzeichnen. Da die Daten im EEPROM nicht gelöscht, sondern nur immer wieder
überschrieben werden, könnte der Fall eintreten, dass eine evtl. vorher im EEPROM abgelegte Lis-
te länger war als die gerade übertragene. Durch die beiden letzten DATE-Strings wird verhindert,
dass die Termine der alten Liste auf der Kalenderuhr angezeigt werden.
Die nachfolgende CASE-Anweisung ruft die Subroutine Eepromwtermine auf:
...Case "DATE":
N = 0
Call Eepromwtermine
...
Const Eeprw = &HA0Const Eeprr = &HA1
Dim Adresse_terminw As WordDim Adresse_termine14k As WordDim Adresse_termine_high14k As ByteDim Adresse_termine_low14k As Byte...Eepromwtermine:
N = 0
For X = 5 To 31
Adresse_termine14k = 1400 + Adresse_terminw Adresse_termine_high14k = High(adresse_termine14k) Adresse_termine_low14k = Low(adresse_termine14k)
- 24 -
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_termine_high14k I2cwbyte Adresse_termine_low14k I2cwbyte Z(x) I2cstop
Waitms 10 Incr Adresse_terminw
Next
Return
Diese Subroutine ist analog zur Subroutine Eepromwsonne, mit dem Unterschied, dass die Start-
adresse mit 1400 addiert wird (sonst würden die Daten für den Sonnenaufgang bzw. Sonnenunter-
gang überschrieben werden) und dass die Startadresse am Ende nicht zurückgesetzt wird (das erle-
digt „CDAT“). Von jedem übertragenen String werden nur die Zeichen 5 bis 31 gespeichert (For X =
5 To 31....I2cwbyte Z(x)...).
Gelesen werden diese Daten über die nachfolgende Funktion. Übergeben wird der Funktion als Ar-
gument die Speicheradresse eines Termins (adresse_termine) und man erhält als Ergebnis über
die BASCOM-Funktion Dayofyear den Tag im Jahr, an dem das Ereignis stattfindet (Termin-
date):
Const Eeprw = &HA0Const Eeprr = &HA1
Dim Adresse_termine As WordDim Adresse_termine14k As WordDim Adresse_termine_high14k As ByteDim Adresse_termine_low14k As Byte
Dim Terminest As String * 28Dim Termineby(28) As Byte At Terminest Overlay
Dim Termine_t As String * 2Dim Termine_m As String * 2Dim Termine_j As String * 2Dim Termine_jv As String * 4Dim Termine_jvi As IntegerDim Terminedatest As String * 8Dim Terminedate As Integer
Dim Schaltjahr As IntegerDim Termine_ij As Integer
...Function Gettermintag(adresse_termine As Word) As Integer
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine Adresse_termine_high14k = High(adresse_termine14k) Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_termine_high14k I2cwbyte Adresse_termine_low14k
I2cstart I2cwbyte Eeprr I2crbyte Termineby(x) , Nack I2cstop
- 25 -
Incr Adresse_termine
Next
Termine_t = Left(terminest , 2) Termine_m = Mid(terminest , 3 , 2) Termine_j = Mid(terminest , 7 , 2) Termine_jv = Mid(terminest , 5 , 4) Terminedatest = Termine_t + "." + Termine_m + "." + Termine_j Terminedate = Dayofyear(terminedatest)
Termine_ij = Val(termine_j) Schaltjahr = Termine_ij Mod 4
If Schaltjahr = 0 And Terminedate > 59 Then 'Schaltjahr Decr Terminedate End If
Gettermintag = Terminedate
End Function
Zuerst muss das im EEPROM abgelegte Datum (z.B. 03041951) in ein für die Funktion Dayofyear
verwertbares Datumsformat umgeformt werden (aus 030411951 wird 03.04.1951). Das Jahr wird
noch einmal extra als Zahl in die Variable Termine_ij geschrieben. Wenn man mit Dayofyear ar-
beitet, muss man wissen, ob das Jahr ein Schaltjahr ist. Das lässt sich bequem über die Anweisung
Schaltjahr = Termine_ij Mod 4 ermitteln (jedes Schaltjahr zwischen 1901 und 2099 ist ohne
Rest durch 4 teilbar). Das betrifft natürlich nur Termine nach dem 28. Februar (...Terminedate
> 59).
Für die Nutzung der Terminfunktion der Kalenderuhr sind aber noch ein paar weitere Funktionen
nötig. Die folgende Funktion, Getterminadresse, ermittelt die Speicheradresse eines bestimmten
Termins im EEPROM. Übergeben wird der Funktion als Argument der Tag heute, der über die
BASCOM-Funktion Dayofyear(Date$) in der Hauptprogrammschleife erzeugt wird und man er-
hält als Ergebnis die Speicheradresse des Termins des heutigen Tages:
Dim Maxadressew As WordDim Heute As IntegerDim Alarm_heute As Bit...Function Getterminadresse(heute As Integer) As Word
Maxadressew = Getmaxadressetermine(0)
For Adresse_termine = 0 To Maxadressew Step 27
Terminedate = Gettermintag(adresse_termine)
If Terminedate = Heute Then Alarm_heute = 1 Else Alarm_heute = 0
If Terminedate >= Heute Then Exit For
Next
Getterminadresse = Adresse_termine
End Function
Hauptsächlich bedient sich diese Funktion der Ergebnisse der Funktionen
Getmaxadressetermine und Gettermintag. Falls der heutige Tag ein besonderer Tag ist
- 26 -
(Geburtstag oder Feiertag), setzt die Funktion die Variable Alarm_heute auf 1.
Die Funktion Getmaxadressetermine ermittelt die Speicheradresse des letzten Termins einer Rei-
he von Terminen. Übergeben wird der Funktion als Argument adresse_termine (Speicheradres-
se eines bestimmten Termins), das aber im Programm immer 0 ist. Es wäre also nicht wirklich not-
wendig gewesen, die nachfolgenden Anweisungen in eine Funktion zu packen, der Übersichtlich-
keit halber habe ich es aber so gelassen. Als Ergebnis erhält man die oben erwähnte Speicher-
adresse des letzten Termins:
Const Eeprw = &HA0Const Eeprr = &HA1
Dim Maxadressew As WordDim Maxadressest As String * 2
...Function Getmaxadressetermine(adresse_termine As Word) As Word
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine Adresse_termine_high14k = High(adresse_termine14k) Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_termine_high14k I2cwbyte Adresse_termine_low14k
I2cstart I2cwbyte Eeprr I2crbyte Termineby(x) , Nack I2cstop
Incr Adresse_termine
Next
Maxadressest = Mid(terminest , 26 , 2) Maxadressew = Val(maxadressest) Maxadressew = Maxadressew * 27
Getmaxadressetermine = Maxadressew
End Function
Die Funktion setzt den ersten im EEPROM gespeicherten Termin-String wieder zusammen. Die
letzten zwei Zeichen des Strings (Maxadressest = Mid(terminest , 26 , 2)) enthalten die
maximale Anzahl an übertragenen Datensätzen (siehe DATE-String). Daraus lässt sich dann die
Speicheradresse des letzten Termins ermitteln.
Die Funktionen Eepromrtermine gibt einen im EEPROM abgelegten String aus. Übergeben wird
der Funktion als Argument adresse_termine, also die Speicheradresse eines bestimmten Ter-
mins:
Const Eeprw = &HA0Const Eeprr = &HA1
Dim Termine_t As String * 2Dim Termine_m As String * 2Dim Termine_p As String * 10Dim Terminelcdst As String * 16
- 27 -
...Function Eepromrtermine(adresse_termine As Word) As String * 16
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine Adresse_termine_high14k = High(adresse_termine14k) Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_termine_high14k I2cwbyte Adresse_termine_low14k
I2cstart I2cwbyte Eeprr I2crbyte Termineby(x) , Nack I2cstop
Incr Adresse_termine
Next
Termine_t = Left(terminest , 2) Termine_m = Mid(terminest , 3 , 2) Termine_p = Mid(terminest , 16 , 10)
Terminelcdst = Termine_t + "." + Termine_m + " " + Termine_p
If Termine_t = "00" Then Terminelcdst = Space(16)
Eepromrtermine = Terminelcdst
End Function
Die Funktion setzt im ersten Schritt einen im EEPROM gespeicherten Termin-String wieder zu-
sammen. Dabei wird aus „0304195127780G1Klaus 1“ „03.04 Klaus „. Das sind
dann genau 16 Zeichen, entsprechend der Anzeigegröße des LCD-Moduls. Das Ergebnis wird in der
Variable Terminelcdst gespeichert. Falls der Termin-String nur Nullen enthält (bzw. die ersten
beiden Zeichen 00 sind), werden 16 Leerzeichen ausgegeben (If Termine_t = "00" Then
Terminelcdst = Space(16)).
Eine letzte Funktion in diesem Zusammenhang ist Eepromrtermine_alarm. Übergeben wird der
Funktion als Argument adresse_termine, also die Speicheradresse eines bestimmten Termins.
Als Ergebnis ermittelt die Funktion die Sekunde des Tages, an dem ggf. eine Melodie abgespielt
werden soll:
Const Eeprw = &HA0Const Eeprr = &HA1
Dim Termine_sek As String * 5Dim Termine_mu As String * 1Dim Termine_geburtstag As String * 1Dim Termine_alarml As Long...Function Eepromrtermine_alarm(adresse_termine As Word) As Long
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine Adresse_termine_high14k = High(adresse_termine14k) Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_termine_high14k
- 28 -
I2cwbyte Adresse_termine_low14k
I2cstart I2cwbyte Eeprr I2crbyte Termineby(x) , Nack I2cstop
Incr Adresse_termine
Next
Termine_sek = Mid(terminest , 9 , 5) Termine_mu = Mid(terminest , 15 , 1) 'Musik abspielen? Termine_geburtstag = Mid(terminest , 14 , 1) 'Geburtstag oder Feiertag
Termine_alarml = Val(termine_sek)
Eepromrtermine_alarm = Termine_alarml
End Function
Die Funktion ermittelt wie beschrieben aus einem im EEPROM gespeicherten Termin-String die
Sekunde des Tages (Termine_sek), die Information, ob Musik abgespielt werden soll und welche
(Termine_mu) und die Information, ob es sich um einen Geburtstag oder Feiertag handelt
(Termine_geburtstag) (siehe dazu auch DATE-String). Die Variablen Termine_mu und
Termine_geburtstag werden zwar nicht direkt als Ergebnis der Funktion übermittelt, werden
aber innerhalb der Funktion mit Werten gefüllt, die in der Hauptprogrammschleife abgerufen wer-
den.
Ausgabe von gespeicherten Daten auf dem 16x4-LCD-ModulSämtliche gespeicherten Daten, sowie Datum & Uhrzeit werden innerhalb der Hauptprogramm-
schleife ausgegeben. Durch drücken des Tasters kann zwischen verschiedenen Ausgabebildschir-
men umgeschaltet werden. Die Zahl der Tastendrücke wird über eine CASE-Anweisung ausgewertet
(siehe Anzeige von Uhrzeit, Datum, Geburtstagen, Feiertagen etc. (Übersicht)). Der erste Ausgabe-
bildschirm zeigt normalerweise Wochentag, Datum und Uhrzeit an. Liegt ein besonderer Termin
vor, wir dieser angezeigt:
Dim Adresse_termine As WordDim Termine_geburtstag As String * 1Dim Termine_alarmst As String * 6Dim Termine_alarml As LongDim Alarm_heute As BitDim Termin_heute As String * 16Dim Termine_jv As String * 4Dim Termine_jvi As IntegerDim Bdate As String * 2Dim Bdatei As IntegerDim Alter As IntegerDim Spaces As Integer...Select Case Cntb1
Case 0:
If Alarm_heute = 1 Then
Adresse_termine = Getterminadresse(heute) Termin_heute = Eepromrtermine(adresse_termine) Termin_heute = Mid(termin_heute , 7 , 10)
- 29 -
Termine_alarml = Eepromrtermine_alarm(adresse_termine) Termine_alarmst = Time(termine_alarml) Termine_alarmst = Left(termine_alarmst , 5)
Bdate = Mid(datestr , 7 , 2) Bdate = "20" + Bdate Termine_jvi = Val(termine_jv) Bdatei = Val(bdate) Alter = Bdatei - Termine_jvi
Locate 1 , 1 : Lcd "Heute " ; Termin_heute
If Termine_geburtstag = "G" Then Locate 2 , 1 : Lcd Termine_alarmst ; " " ; Termine_jv ; " " ; Alter ; " J" Else Locate 2 , 1 : Lcd Termine_alarmst ; Spc(11) End If
Locate 3 , 1 : Lcd Date$ ; Spc(8) Locate 4 , 1 : Lcd Time$ ; Spc(8)
Else
Spaces = Len(weekdaystr) Spaces = 16 - Spaces
Locate 1 , 1 : Lcd "Datum & Uhrzeit " Locate 2 , 1 : Lcd Weekdaystr ; Spc(spaces) Locate 3 , 1 : Lcd Date$ ; Spc(8) Locate 4 , 1 : Lcd Time$ ; Spc(8)
End If...
Ob ein besonderer Termin vorliegt, gibt die Variable Alarm_heute an. Die auszugebenden Daten
werden aus dem EEPROM geladen. Die entsprechenden Funktionen dazu (Getterminadresse,
Eepromrtermine, Eepromrtermine_alarm) wurden im vorangegangenen Kapitel vorgestellt. Das
Alter (Variable Alter) des Geburtstagskindes wird ebenfalls berechnet. Die Ausgabe eines Feierta-
ges oder Geburtstages ist unterschiedlich. Die Variable Termine_geburtstag zeigt an, ob es sich
bei dem Termin um einen Feiertag (F) oder Geburtstag (G) handelt. Der Variablen wird durch das
Aufrufen der Funktion Eepromrtermine_alarm der entsprechende Wert zugewiesen. Die verschie-
denen Ausgabebildschirme sind in Abbildung 10 dargestellt.
Der nächste Ausgabebildschirm zeigt die nächsten 3 anstehenden Termine:
Dim Adresse_termine As WordDim Heute As IntegerDim Maxadressew As WordDim Eepromrtermine_heute As String * 17...Case 1:
Heute = Dayofyear(date$) Maxadressew = Getmaxadressetermine(0) Adresse_termine = Getterminadresse(heute) Eepromrtermine_heute = Eepromrtermine(adresse_termine)
If Adresse_termine > Maxadressew Then Adresse_termine = 0
Locate 1 , 1 : Lcd "Termine" ; Spc(9)
If Eepromrtermine_heute <> " " Then Locate 2 , 1 : Lcd Eepromrtermine(adresse_termine) Else Adresse_termine = 0 Locate 2 , 1 : Lcd Eepromrtermine(adresse_termine)
- 30 -
End If
Adresse_termine = Adresse_termine + 27 Locate 3 , 1 : Lcd Eepromrtermine(adresse_termine) Adresse_termine = Adresse_termine + 27 Locate 4 , 1 : Lcd Eepromrtermine(adresse_termine)...
Zuerst wird der Variablen Heute der Tag des Jahres zugewiesen. Die Variable Maxadressew ent-
hält die Gesamtzahl der Termine. Sollte der letzte Termin erreicht sein, wird Adresse_termine
auf null gesetzt. Das bedeutet, nachdem der letzte im EEPROM abgelegte Termin angezeigt wurde,
wird wieder der erste im EEPROM abgelegte Termin angezeigt. Nachdem die Adresse des ersten
anzuzeigenden Termins bekannt ist, werden einfach die beiden nächsten abgespeicherten Termine
angezeigt (Adresse_termine = Adresse_termine + 27). Damit nicht irgendwann Termine aus
einer alten Terminliste oder Datenmüll angezeigt wird, enthalten die letzten beiden im EEPROM
abgelegten Einträge nur Nullen (siehe DATE-String). Die Funktionen Getmaxadressetermine,
Getterminadresse und Eepromrtermine wurden im vorangegangenen Kapitel vorgestellt. Der
Ausgabebildschirm ist in Abbildung 10 dargestellt.
Im nächsten Ausgabebildschirm werden die Uhrzeiten für die Sonnenaufgänge bzw. Sonnenunter-
gänge der heutigen Tages und der folgenden 2 Tage angegeben. Der Übersichtlichkeit halber, wer-
den im folgenden Abschnitt Funktionsaufrufe und Berechnungen teilweise ausführlicher darge-
stellt, als eigentlich für die Funktion der Kalenderuhr notwendig.
Dim Stageeprom As String * 14Dim Stageepromday As String * 4Dim Sahst As String * 2Dim Sarest As String * 3Dim Suhst As String * 2Dim Surest As String * 3Dim Sahstn As IntegerDim Suhstn As Integer
Dim Sa As String * 5Dim Su As String * 5
Dim Sysdx As LongDim Sysdw As Word
Dim Systemtageepr As String * 5Dim Systemtageeprl As Long...Case 2:
Sa = Eepromrsonne(0) Systemtageepr = Mid(sa , 1 , 4) Systemtageeprl = Val(systemtageepr)
Sysdx = Sysday() Sysdw = Sysdx - Systemtageeprl Sysdw = Sysdw * 14 Sa = Eepromrsonne(sysdw) Sa = Mid(sa , 5 , 5) Su = Eepromrsonne(sysdw) Su = Mid(su , 10 , 5)
Locate 1 , 1 : Lcd "SonnenA/U 3 Tage" Locate 2 , 1 : Lcd "A " ; Sa ; Spc(2) ; "U " ; Su
Sysdx = Sysday() Sysdx = Sysdx + 1
- 31 -
Sysdw = Sysdx - Systemtageeprl Sysdw = Sysdw * 14 Sa = Eepromrsonne(sysdw) Sa = Mid(sa , 5 , 5) Su = Eepromrsonne(sysdw) Su = Mid(su , 10 , 5)
Locate 3 , 1 : Lcd "A " ; Sa ; Spc(2) ; "U " ; Su
Sysdx = Sysday() Sysdx = Sysdx + 2 Sysdw = Sysdx - Systemtageeprl Sysdw = Sysdw * 14 Sa = Eepromrsonne(sysdw) Sa = Mid(sa , 5 , 5) Su = Eepromrsonne(sysdw) Su = Mid(su , 10 , 5)
Locate 4 , 1 : Lcd "A " ; Sa ; Spc(2) ; "U " ; Su
...
Zuerst wird der erste im EEPROM gespeicherte String über die Funktion Eepromrsonne abgefragt
(siehe dazu auch Sonnenaufgänge und Sonnenuntergänge speichern und abrufen). Aus diesem
String wird der (System)Tag (gerechnet ab dem 01.01.2000) ermittelt (Systemtageeprl). Danach
wird der aktuelle Systemtag über die BASCOM-Funktion Sysday ermittelt. Über die Subtraktion
des aktuellen Systemtages mit dem ersten gespeicherten Systemtag (Sysdw = Sysdx - System-
tageeprl) erhält man nach der Multiplikation mit 14 (Sysdw = Sysdw * 14) die Speicheradresse
des heutigen Tages im EEPROM. Der gespeicherte String, der die Daten des heutigen Tages ent-
hält, wird über die Funktion Eepromrsonne ermittelt. Aus diesem String werden die Zeitangaben
für den Sonnenaufgang (Sa) und Sonnenuntergang (Su) ermittelt. Für die Anzeige der Daten des
nächsten Tages wird der aktuelle Systemtag mit 1 addiert (Sysdx = Sysdx + 1) , für den über-
nächsten Tag mit 2 (Sysdx = Sysdx + 2). Der Ausgabebildschirm ist in Abbildung 10 dargestellt.
Der nächste Ausgabebildschirm (Case 3)widmet sich der manuellen Einstellung von Wochentag,
Datum und Zeit (Abbildung 10). Auf eine ausführliche Erläuterung dieses Programmteils wird an
dieser Stelle verzichtet, da sich Datum und Zeit bequemer über das PC-Programm einstellen lassen
(siehe Zeiteinstellungen).
Abspielen einer MelodieOb eine und wann eine Melodie abgespielt wird, wird in der Hauptprogrammschleife ermittelt:
Dim Adresse_termine As WordDim Termine_alarml As LongDim Alarm_heute As BitDim Termin_heute As String * 16Dim Termine_mu As String * 1... Heute = Dayofyear(date$)... Adresse_termine = Getterminadresse(heute) Termine_alarml = Eepromrtermine_alarm(adresse_termine)
If Termine_alarml = Secofday() And Alarm_heute = 1 And Termine_mu <> "0" Then Call Play_music(termine_mu) End If...
- 32 -
Zuerst wird die Speicheradresse des heutigen Tages über die Funktion Getterminadresse ermit-
telt. Die Funktion Eepromrtermine_alarm ermittelt die Sekunde des Tages, an dem die Melodie
abgespielt werden soll. Mit der If-Anweisung wird ermittelt, ob alle Bedingungen für das Abspie-
len einer Melodie erfüllt sind. Den Variablen Alarm_heute und Termine_mu werden Werte durch
das Aufrufen der Funktionen Getterminadresse und Eepromrtermine_alarm zugewiesen. Die
aktuelle Sekunde des Tages wird über die BASCOM-Funktion Secofday ermittelt. Ist diese Se-
kundenzahl gleich der Sekunde, die im EEPROM gespeichert wurde und ist der heutige Tag ein be-
sonderer Tag und ist die Variable Termine_mu ungleich “0“, wird schließlich Call Play_mu-
sic(termine_mu) ausgeführt. Der Subroutine Play_music wird die Nummer der abzuspielenden
Melodie übergeben. Durch den Aufruf der Subroutine und der nachfolgenden Select Case...Case-
Anweisungen wir die Melodie abgespielt:
Lcd_bl Alias Portb.2Config Lcd_bl = Output
Config Portb.1 = OutputSpeaker Alias Portb.1...Dim Note As IntegerDim Laenge As IntegerDim Pause As Integer...Sub Play_music(song_nr As String * 1)
If Lcd_bl = 0 Then Lcd_bl = 1
Select Case Song_nr
Case "1"
For I = 0 To 55 Note = Lookup(i , Happyb) Incr I If Note = 0 Then Pause = Lookup(i , Happyb) Waitms Pause Else Laenge = Lookup(i , Happyb) Sound Speaker , Note , Laenge End If Next I
Case "2"
For I = 0 To 57 Note = Lookup(i , Merryx) Incr I If Note = 0 Then Pause = Lookup(i , Merryx) Waitms Pause Else Laenge = Lookup(i , Merryx) Sound Speaker , Note , Laenge End If Next I
End Select...Happyb:Data 65% , 587% , 65% , 587% , 147% , 523% , 131% , 587% , 175%Data 440% , 165% , 466% , 0% , 250% , 65% , 587% , 65% , 587% , 147%Data 523% , 131% , 587% , 196% , 392% , 175% , 440% , 0% , 250% , 65%Data 587% , 65% , 587% , 262% , 294% , 220% , 349% , 175% , 440% , 165%Data 466% , 147% , 523% , 0% , 125% , 117% , 330% , 117% , 330% , 220%Data 349% , 175% , 440% , 196% , 392% , 175% , 440%
- 33 -
Merryx:Data 147% , 523% , 196% , 392% , 98% , 392% , 110% , 349% , 98% , 392%Data 92% , 415% , 165% , 466% , 131% , 587% , 165% , 466% , 220% , 349%Data 110% , 349% , 124% , 311% , 110% , 349% , 98% , 392% , 185% , 415%Data 294% , 523% , 247% , 311% , 124% , 311% , 131% , 294% , 124% , 311%Data 110% , 349% , 196% , 392% , 165% , 466% , 73% , 523% , 73% , 523%Data 165% , 466% , 220% , 349% , 185% , 415% , 196% , 392%
Die Tonausgabe erledigt in BASCOM die Anweisung Sound mit den Variablen Speaker, Note,
Laenge. Speaker ist dabei ein Alias auf Portb.1 (siehe auch Schaltplan), die Werte für Note und
Laenge werden über Lookup aus einer Data-Tabelle gelesen. Die Variable I in der For-Next-An-
weisung gibt die Nummer des Wertes in der Tabelle an. Pausen (ohne Ton) werden über den Wert
Note = 0 ermöglicht. Im oberen Code-Abschnitt sind zwei Melodien angegeben. Insgesamt wären
9 möglich. Beim Abspielen einer Melodie wird die Hintergrundbeleuchtung des LCD-Moduls ein-
geschaltet. Die Berechnung der Werte für die Variablen Note und Laenge wird im nächsten Kapitel
erläutert.
Programmstruktur des PC-Programms (tool.au3)Die Programmierung des PC-Programms erfolgte mit AutoIt v3. Die Datenübertragung nutzt die
Bibliothek CommMG.au3 v2.8 von Martin Gibson. Die Programmoberfläche wurde mit Koda er-
stellt. Auf die Programmierung werde ich nachfolgend nicht so ausführlich eingehen, wie im voran-
gegangenen Kapitel. Der Programmcode ist (so denke ich) recht übersichtlich. Innerhalb der
Hauptprogrammschleife werden über Switch und Case jeweils nach bestimmten Aktionen (Maus-
klick) bestimmte Programmteile ausgeführt. Der Befehl _CommSendString sendet die im Kapitel
Empfang von Daten über das UART erwähnten Strings an die Kalenderuhr. Die Übertragung ist
relativ langsam (dafür sicher), kann aber je nach System und Anbindung auch schneller erfolgen.
Das muss man individuell austesten. Wenn die Kalenderuhr nur Datenmüll anzeigen sollte, erfolgt
die Übertragung jedenfalls zu schnell für das System. Daneben enthält das Programm Funktionen,
um Sonnenaufgänge bzw. Sonnenuntergänge und variable Feiertage, wie etwa die Osterfeiertage zu
berechnen.
Das Programm besteht aus 3 Tabs, die verschiedene Funktionen des Programms zusammenfassen.
Diese Funktionen werden nachfolgend kurz vorgestellt.
- 34 -
Datum, Uhrzeit, Einstellungen, Sonnenaufgänge und SonnenuntergängeNach dem Öffnen des Programms wird folgender Tab gezeigt:
Die Funktionen sind relativ selbsterklärend. Zuerst muss der passende COM-Port ausgewählt wer-
den. Die Einstellung kann getestet werden, in dem man einen Test-String sendet. Datum und Uhr-
zeit können zu Testzwecken auf jeden beliebigen Wert eingestellt und übertragen werden. Sind die
Häkchen bei Systemdatum und/oder Systemzeit gesetzt, wird das aktuelle Datum bzw. die aktuelle
Uhrzeit des PCs übertragen (siehe Zeiteinstellungen). Einstellungen zur Hintergrundbeleuchtung
und zur Zeitkorrektur können ebenfalls gesetzt und gesendet werden (siehe Weitere Einstellungen
und Steuerung der Hintergrundbeleuchtung des LCD-Moduls). Als letzte Funktion auf diesem Tab
können Sonnenaufgänge und Sonnenuntergänge an die Kalenderuhr gesendet werden (siehe
Sonnenaufgänge und Sonnenuntergänge speichern und abrufen). Im Programmcode des AutoIt-
Skripts müssen ggf. noch Breitengrad und Längengrad des Ortes angepasst werden.
- 35 -
Abbildung 12: Erstes Tab (Registerkarte) des PC-Programms. Die dem Screenshot hinzugefügten Erläuterungen zu den Steuerfunktionen sind Blau gedruckt.
Auswahl des COM-Ports Test-String sendenTEST: Gesendet & Empfangen 1234
Test-String senden
Datum und Zeit individuell einstellen Sommerzeit?Datum und Zeit individuell einstellen
Datum und Zeit des PCs
Einstellungen senden
TIME :18.04.1110122:27:40xxxxxx
Datum / Zeit senden Gesendeter String
ZeitkorrekturHintergrundbeleuchtung
Gesendeter String
Fortschrittsbalken
SETT: 100000000000000000000000x
Sonnena./u. senden
Geburtstage und FeiertageEine Liste von Geburtstagen und Feiertage kann im folgenden Tab angelegt, gespeichert und an die
Kalenderuhr übertragen werden:
Die Termine werden automatisch nach Datum (Tag und Monat) sortiert und können auf dem PC
gespeichert und wieder geladen werden. Feiertage hinzufügen fügt automatisch eine Reihe von
Feiertagen zur Terminliste hinzu. Das Datum der variablen Feiertage (Ostern, Pfingsten und Him-
melfahrt) wird vom PC-Programm jeweils vorher berechnet. Momentan kann nur zwischen 2 Me-
lodien bzw. keiner Melodie gewählt werden. Ohne größere Anpassung des Codes wären bis zu 9
Melodien möglich. Mit Senden wird die Terminliste schließlich übertragen (siehe
Geburtstagstermine und Feiertage (kurz Termine) speichern und abrufen).
- 36 -
Abbildung 13: Zweites Tab (Registerkarte) des PC-Programms. Die dem Screenshot hinzugefügten Erläuterungen zu den Steuerfunktionen sind Blau gedruckt.
(Geburts-)Datum(Geburts-)Zeit Geburtstag oder Feiertag?
Welche Melodie?
Ausgabetext (10 Zeichen)
Hinzufügen
Termine: Speichern / Laden / an die Kalenderuhr senden
Gesendeter String FortschrittsbalkenDATE3112201143200F0Silvester 15
Der MelodiegeneratorDas ist eine Funktion des Programms, die mit Hilfe des myAVR Boards Klingeltöne, wie sie etwa
um das Jahr 2000 herum üblich waren, wieder abspielbar macht. Auf der folgenden Internetseite
ist recht ausführlich erklärt, wie Noten für die BASCOM-Sound Anweisung umgesetzt werden
können:
http://www.mcselec.com/index.php?option=com_content&task=view&id=221&Itemid=57
Anhand der dort angegebenen Berechnungen, die hauptsächlich von der Frequenz des eingesetzten
Quarzes abhängen, können z.B. über eine Tabellenkalkulation für jede mögliche Note die entspre-
chenden Werte ausgerechnet werden.
Auf der nachfolgenden Internetseite finden sich z.B. noch jede Menge Klingeltöne, die einfach nur
in das Programmfenster des PC-Programms kopiert werden müssen:
http://www.xs4all.nl/~vbergen/ringtones/siemens/index_2000.html
- 37 -
Abbildung 14: Drittes Tab (Registerkarte) des PC-Programms. Die dem Screenshot hinzugefügten Erläuterungen zu den Steuerfunktionen sind Blau gedruckt.
Name der Melodie
Klingelton im Siemens (C25/S25/C35/S35/M35)-Format
BASCOM-Code
Im unteren Bereich steht der BASCOM-Code für den entsprechenden Klingelton bzw. die Melodie,
der nur noch in das Programm eingefügt werden muss. Die entsprechenden Variablen wurden zu
Programmbeginn deklariert.
FazitSoviel zum Projekt der Kalenderuhr. Fast alle Funktionen des myAVR Boards konnten genutzt
werden. Nur die beiden Potis sind noch frei, sowie ein Pin des ATmega.
Softwareseitig ist noch etwas Speicherplatz vorhanden, der mit weiteren Melodien oder mit
Programmcode gefüllt werden kann, auch das EEPROM hat noch Platz für Daten.
Der Programmcode bietet bestimmt dem einen oder anderen erfahrenen BASCOM-Programmierer
noch Ansätze zum optimieren. Funktionsfähig ist er jedenfalls und läuft so wie er ist, seit einiger
Zeit stabil.
Ohne Hilfe hätte ich die Kalenderuhr niemals zum laufen bekommen. An erster Stelle soll hier die
BASCOM-Hilfe stehen, die wirklich sehr umfangreich ist und schon viele Lösungsansätze bietet:
http://avrhelp.mcselec.com/index.html
Sehr hilfreich bei der Programmierung waren auch die folgenden Internetseiten:
http://halvar.at/elektronik/kleiner_bascom_avr_kurs/
http://www.rn-wissen.de/index.php/Kategorie:Quellcode_Bascom
http://www.rowalt.de/mc/index.htm
Die im PC-Programm verwendeten Funktionen sind, soweit übernommen, dort gekennzeichnet.
Hardwareseitig waren mir die von der Laser & Co. Solutions GmbH bereitgestellten Schaltpläne
eine große Hilfe, so wurde der Aufbau fast zum Kinderspiel.
Bei der Zusammenstellung von Texten und Abbildungen bin ich mit großer Sorgfalt vorgegangen.
Trotzdem kann ich Fehler nicht vollständig ausschließen. Für fehlerhafte Angaben und deren
Folgen kann ich weder irgendeine Haftung noch juristische Verantwortung übernehmen.
Sebastian Dechert
- 38 -
BASCOM-QuellcodeDie wichtigsten Programmteile werden im Kapitel Programmierung ausführlich erklärt.
$regfile = "m168def.dat"$crystal = 3686400$baud = 9600
$lib "i2c_twi.lbx" 'Config Sda = Portc.4Config Scl = Portc.5Const Ds1307w = &HD0Const Ds1307r = &HD1Const Eeprw = &HA0Const Eeprr = &HA1
Config Timer1 = Timer , Prescale = 64On Timer1 Toggle_colonEnable Timer1Start Timer1
Enable Interrupts
Config Lcdpin = Pin , Rs = Portc.0 , E = Portc.1 , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7Config Lcd = 16 * 4Cursor = Off
Config Clock = UserConfig Date = Dmy , Separator = .
On Urxc OnrxdEnable Urxc
Config Pind.2 = 0Config Pind.3 = 0Portd.2 = 1Portd.3 = 1
Lcd_bl Alias Portb.2Config Lcd_bl = Output
Config Portb.1 = OutputSpeaker Alias Portb.1
Config Portc.2 -1 = OutputConfig Adc = Single , Prescaler = Auto , Reference = Avcc
Dim Licht As Word
Dim A As String * 10Dim B As String * 10Dim C As String * 10Dim D As IntegerDim E As IntegerDim F As IntegerDim G As IntegerDim H As IntegerDim I As IntegerDim J As IntegerDim K As IntegerDim Timestr As String * 10Dim Datestr As String * 10Dim Weekdaystr As String * 10Dim Colon_onoff As BitDim Dp_onoff As BitDim All_off As BitDim Weekday As ByteDim Weekdayst As String * 1Dim Cntb1 As IntegerDim Cntb2 As IntegerDim Exitbyte As Byte
- 39 -
Dim Stset As ByteDim Wtset As ByteDim Stsetst As String * 1Dim Wtsetst As String * 1
Dim L As String * 4Dim S As String * 30Dim Z(31) As Byte At S OverlayDim N As Byte
Dim Lcd_blst As String * 1Dim Lcd_blby(2) As Byte At Lcd_blst Overlay
Dim Plusminst As String * 1Dim Plusminby(2) As Byte At Plusminst Overlay
Dim Sekundest As String * 2Dim Sekundeby(3) As Byte At Sekundest Overlay
Dim Systemtag As LongDim Systemtagby(4) As Byte At Systemtag Overlay
Dim Sekdestages As LongDim Sekdestagesby(4) As Byte At Sekdestages Overlay
Dim Korrektur As LongDim Sekundelong As LongDim Sysd As LongDim Secd As LongDim Zeitkorrekturbit As Bit
Dim Sonnetagst As String * 14Dim Sonnetagby(14) As Byte At Sonnetagst Overlay
Dim Adresse_sonne As WordDim Adresse_sonne_high As ByteDim Adresse_sonne_low As ByteDim X As Byte
Dim Xx As WordDim Stageeprom As String * 14Dim Stageepromday As String * 4Dim Sahst As String * 2Dim Sarest As String * 3Dim Suhst As String * 2Dim Surest As String * 3Dim Sahstn As IntegerDim Suhstn As Integer
Dim Sa As String * 5Dim Su As String * 5
Dim Sysdx As LongDim Sysdw As Word
Dim Systemtageepr As String * 5Dim Systemtageeprl As Long
Dim Terminest As String * 28Dim Termineby(28) As Byte At Terminest Overlay
Dim Adresse_terminw As WordDim Adresse_termine As WordDim Adresse_termine14k As WordDim Adresse_termine_high14k As ByteDim Adresse_termine_low14k As Byte
Dim Termine_t As String * 2Dim Termine_m As String * 2Dim Termine_j As String * 2Dim Termine_x As String * 1Dim Termine_p As String * 10Dim Terminedatest As String * 8Dim Terminedate As IntegerDim Heute As IntegerDim Terminelcdst As String * 16Dim Maxadressest As String * 2
- 40 -
Dim Maxadressew As Word
Dim Schaltjahr As IntegerDim Termine_ij As Integer
Dim Termine_sek As String * 5Dim Termine_mu As String * 1Dim Termine_geburtstag As String * 1Dim Termine_alarmst As String * 6Dim Termine_alarml As LongDim Alarm_heute As BitDim Termin_heute As String * 16Dim Termine_jv As String * 4Dim Termine_jvi As IntegerDim Bdate As String * 2Dim Bdatei As IntegerDim Alter As IntegerDim Spaces As Integer
Dim Eepromrtermine_heute As String * 17Dim Dummy As Byte
Dim Note As IntegerDim Laenge As IntegerDim Pause As Integer
Declare Sub Happy_melDeclare Sub Merry_melDeclare Sub SetupDeclare Sub SetupweekdayDeclare Sub SetweekdayDeclare Sub SetdateDeclare Sub SettimeDeclare Sub SetuptimeDeclare Sub GotomainDeclare Sub Dst_onoffDeclare Sub Sun_risesetDeclare Sub DelnvramDeclare Sub WritenvramDeclare Sub Writenvram_settDeclare Sub ReadnvramDeclare Sub Setup1Declare Sub Lcd_blonoffDeclare Sub ZeitkorrekturDeclare Sub EepromwsonneDeclare Sub EepromwtermineDeclare Sub Play_music(song_nr As String)
Declare Function Eepromrsonne(byval Adresse_sonne As Word) As StringDeclare Function Eepromrtermine(byval Adresse_termine As Word) As StringDeclare Function Getterminadresse(byval Heute As Integer) As WordDeclare Function Getmaxadressetermine(byval Adresse_termine As Word) As WordDeclare Function Gettermintag(byval Adresse_termine As Word) As IntegerDeclare Function Eepromrtermine_alarm(byval Adresse_termine As Word) As Long
'Wochentag, Uhrzeit und Datum ohne Setup einstellen'Time$ = "00:04:00"'Date$ = "08:02:11"'Weekday = 1'Call Setweekday
Open "comb.0:9600,8,n,1" For Output As #1
Waitms 500
Print #1 , "v"; 'Reset der 7Seg.-AnzeigeClose #1
'Print #1 , "z"; 'Helligkeit der 7Seg.-Anzeige einstellen'Printbin #1 , 128 ;'Close #1
Waitms 500
- 41 -
Call Readnvram
Waitms 500'Call Delnvram 'NV-Ram der RTC loeschen
Cls
'#####################################################'# main loop #'#####################################################
Do
Call Dst_onoff Call Lcd_blonoff Call Zeitkorrektur
Heute = Dayofyear(date$)
Termine_j = Mid(date$ , 7 , 2) Termine_ij = Val(termine_j) Schaltjahr = Termine_ij Mod 4
If Schaltjahr = 0 And Heute >= 60 Then 'Schaltjahr Decr Heute End If
Adresse_termine = Getterminadresse(heute) Termine_alarml = Eepromrtermine_alarm(adresse_termine)
If Termine_alarml = Secofday() And Alarm_heute = 1 And Termine_mu <> "0" Then Call Play_music(termine_mu) Else End If
Timestr = Time$ Datestr = Date$ Weekdaystr = Lookupstr(weekday , Weekdays)
A = Mid(timestr , 1 , 2) B = Mid(timestr , 4 , 2) C = Mid(timestr , 7 , 2)
If Colon_onoff = 0 And Dp_onoff = 0 Then Print #1 , "w"; Printbin #1 , 0 ; 'Close #1 Elseif Colon_onoff = 1 And Dp_onoff = 0 And All_off = 0 Then Print #1 , "w"; Printbin #1 , 16 ; 'Close #1 Elseif Colon_onoff = 1 And Dp_onoff = 1 And All_off = 0 Then Print #1 , "w"; Printbin #1 , 2 ; Else Print #1 , "w"; Printbin #1 , 0; End If
If C > "30" And C < "35" Then All_off = 0 A = Mid(datestr , 1 , 2) B = Mid(datestr , 4 , 2) Dp_onoff = 1 Elseif C > "34" And C < "39" Then All_off = 1 A = "20" B = Mid(datestr , 7 , 2) Else Dp_onoff = 0 All_off = 0 End If
If A < "10" Then A = Mid(a , 2 , 1) Print #1 , "x" ; A ; B;
- 42 -
Else Print #1 , A ; B; End If
Select Case Cntb1
Case 0:
If Alarm_heute = 1 Then
Adresse_termine = Getterminadresse(heute) Termin_heute = Eepromrtermine(adresse_termine) Termin_heute = Mid(termin_heute , 7 , 10)
Termine_alarml = Eepromrtermine_alarm(adresse_termine) Termine_alarmst = Time(termine_alarml) Termine_alarmst = Left(termine_alarmst , 5)
Bdate = Mid(datestr , 7 , 2) Bdate = "20" + Bdate Termine_jvi = Val(termine_jv) Bdatei = Val(bdate) Alter = Bdatei - Termine_jvi
Locate 1 , 1 : Lcd "Heute " ; Termin_heute
If Termine_geburtstag = "G" Then Locate 2 , 1 : Lcd Termine_alarmst ; " " ; Termine_jv ; " " ; Alter ; " J" Else Locate 2 , 1 : Lcd Termine_alarmst ; Spc(11) End If
Locate 3 , 1 : Lcd Date$ ; Spc(8) Locate 4 , 1 : Lcd Time$ ; Spc(8)
Else
Spaces = Len(weekdaystr) Spaces = 16 - Spaces
Locate 1 , 1 : Lcd "Datum & Uhrzeit " Locate 2 , 1 : Lcd Weekdaystr ; Spc(spaces) Locate 3 , 1 : Lcd Date$ ; Spc(8) Locate 4 , 1 : Lcd Time$ ; Spc(8)
End If
Case 1:
Heute = Dayofyear(date$) Maxadressew = Getmaxadressetermine(0) Adresse_termine = Getterminadresse(heute) Eepromrtermine_heute = Eepromrtermine(adresse_termine)
If Adresse_termine > Maxadressew Then Adresse_termine = 0
Locate 1 , 1 : Lcd "Termine" ; Spc(9)
If Eepromrtermine_heute <> " " Then Locate 2 , 1 : Lcd Eepromrtermine(adresse_termine) Else Adresse_termine = 0 Locate 2 , 1 : Lcd Eepromrtermine(adresse_termine) End If
Adresse_termine = Adresse_termine + 27 Locate 3 , 1 : Lcd Eepromrtermine(adresse_termine) Adresse_termine = Adresse_termine + 27 Locate 4 , 1 : Lcd Eepromrtermine(adresse_termine)
Case 2:
Sa = Eepromrsonne(0) Systemtageepr = Mid(sa , 1 , 4) Systemtageeprl = Val(systemtageepr)
- 43 -
Sysdx = Sysday() Sysdw = Sysdx - Systemtageeprl Sysdw = Sysdw * 14 Sa = Eepromrsonne(sysdw) Sa = Mid(sa , 5 , 5) Su = Eepromrsonne(sysdw) Su = Mid(su , 10 , 5)
Locate 1 , 1 : Lcd "SonnenA/U 3 Tage" Locate 2 , 1 : Lcd "A " ; Sa ; Spc(2) ; "U " ; Su
Sysdx = Sysday() Sysdx = Sysdx + 1 Sysdw = Sysdx - Systemtageeprl Sysdw = Sysdw * 14 Sa = Eepromrsonne(sysdw) Sa = Mid(sa , 5 , 5) Su = Eepromrsonne(sysdw) Su = Mid(su , 10 , 5)
Locate 3 , 1 : Lcd "A " ; Sa ; Spc(2) ; "U " ; Su
Sysdx = Sysday() Sysdx = Sysdx + 2 Sysdw = Sysdx - Systemtageeprl Sysdw = Sysdw * 14 Sa = Eepromrsonne(sysdw) Sa = Mid(sa , 5 , 5) Su = Eepromrsonne(sysdw) Su = Mid(su , 10 , 5)
Locate 4 , 1 : Lcd "A " ; Sa ; Spc(2) ; "U " ; Su
Case 3:
Exitbyte = 0 Call Setup
End Select
Debounce Pind.2 , 0 , Button1 , Sub
If N > 30 Then
L = Left(s , 4)
Select Case L
Case "TEST":
N = 0 Print S;
Case "TIME":
N = 0 Time$ = Mid(s , 18 , 8) Date$ = Mid(s , 7 , 8) Weekdayst = Mid(s , 15 , 1) Weekday = Weekdayst Call Setweekday
Wtsetst = Mid(s , 16 , 1) Stsetst = Mid(s , 17 , 1)
Wtset = Val(wtsetst) Stset = Val(stsetst)
Call Writenvram
Case "SETT":
N = 0
Systemtag = Sysday() Sekdestages = Secofday()
- 44 -
Call Writenvram_sett Call Readnvram
Case "SUNS":
N = 0
Call Eepromwsonne
Case "DATE":
N = 0
Call Eepromwtermine
Case "CDAT":
N = 0
Adresse_terminw = 0
End Select
End If
Loop
'#####################################################'# UART Interuppt / Zeichen über UART empfangen #'#####################################################
Onrxd: Incr N Z(n) = UdrReturn
'#####################################################'# Datum & Uhrzeit einstellen / CASE 2 #'#####################################################
Setup:
Bitwait Pind.2 , Reset Lcd_bl = 1 Cls
Print #1 , "SEtx" ; Print #1 , "w"; Printbin #1 , 0 ;
While Cntb1 = 3 Locate 1 , 1 : Lcd "Datum & Uhrzeit" Locate 2 , 1 : Lcd " einstellen" Locate 3 , 1 : Lcd ">T1=Uebernehmen<" Locate 4 , 1 : Lcd ">T2=Einstellen<" Debounce Pind.2 , 0 , Gotomain , Sub Debounce Pind.3 , 0 , Setupweekday , Sub Wend
Return
'-------
Setupweekday:
Cls While Exitbyte = 0 Weekdaystr = Lookupstr(weekday , Weekdays) Locate 1 , 1 : Lcd "Wochentag einst." Locate 2 , 1 : Lcd Weekdaystr ; " " Debounce Pind.2 , 0 , Setupdate , Sub Debounce Pind.3 , 0 , Incrweekday , Sub Waitms 20
- 45 -
Wend
Return
'-------
Incrweekday:
Bitwait Pind.3 , Reset If Weekday < 7 Then Incr Weekday Else Weekday = 1
Return
'--------
Setupdate:
Call Setweekday
Locate 2 , 1 : Lcd "Tag" ; Spc(13)
A = Mid(datestr , 1 , 2) B = Mid(datestr , 4 , 2) C = Mid(datestr , 7 , 2)
D = Val(a) : E = Val(b) : F = Val(c)
While Exitbyte = 0 A = Str(d) A = Format(a , "00") B = Str(e) B = Format(b , "00") C = Str(f) C = Format(c , "00") Locate 1 , 1 : Lcd "Datum einst. " Locate 3 , 1 : Lcd A ; "." ; B ; "." ; C Debounce Pind.2 , 0 , Setupdmy , Sub Debounce Pind.3 , 0 , Incrdmy , Sub Waitms 20 Wend
Call Setuptime
Return
'-------
Incrdmy:
Bitwait Pind.3 , Reset
Select Case I
Case 0: Locate 2 , 1 : Lcd "Tag" ; Spc(13) If D < 31 Then Incr D Else D = 1 Case 1: Locate 2 , 1 : Lcd "Monat" ; Spc(11) If E < 12 Then Incr E Else E = 1 Case 2: Locate 2 , 1 : Lcd "Jahr" ; Spc(12) If F < 30 Then Incr F Else F = 11 End Select
Return
'--------
Setupdmy:
Bitwait Pind.2 , Reset
If I > 1 Then I = 0 _day = D : _month = E : _year = F Call Setdate Exitbyte = 1
- 46 -
Else Incr I End If
Return
'--------
Setuptime:
Locate 2 , 1 : Lcd "Stunde" ; Spc(10)
A = Mid(timestr , 1 , 2) B = Mid(timestr , 4 , 2) C = Mid(timestr , 7 , 2)
G = Val(a) : H = Val(b) : J = Val(c)
While Exitbyte = 1 A = Str(g) A = Format(a , "00") B = Str(h) B = Format(b , "00") C = Str(j) C = Format(c , "00") Locate 1 , 1 : Lcd "Uhrzeit einst. " Locate 4 , 1 : Lcd A ; ":" ; B ; ":" ; C Debounce Pind.2 , 0 , Setuphms , Sub Debounce Pind.3 , 0 , Incrhms , Sub Waitms 20 Wend
Return
'-------
Incrhms: Bitwait Pind.3 , Reset
Select Case I
Case 0: Locate 2 , 1 : Lcd "Stunde" ; Spc(10) If G < 23 Then Incr G Else G = 0 Case 1: Locate 2 , 1 : Lcd "Minute" ; Spc(10) If H < 59 Then Incr H Else H = 0 Case 2: Locate 2 , 1 : Lcd "Sekunde" ; Spc(9) If J < 59 Then Incr J Else J = 0 End Select
Return
'--------
Setuphms:
Bitwait Pind.2 , Reset
If I > 1 Then I = 0 _hour = G : _min = H : _sec = J Call Settime Call Gotomain Exitbyte = 2 Else Incr I End If
Return
'#####################################################'# ENDE Datum & Uhrzeit einstellen #'#####################################################
- 47 -
'#####################################################################'# DS1307 Datum, Uhrzeit & Einstellungen auslesen und schreiben #'#####################################################################
Getdatetime: I2cstart I2cwbyte Ds1307w I2cwbyte 0 I2cstart I2cwbyte Ds1307r I2crbyte _sec , Ack I2crbyte _min , Ack I2crbyte _hour , Ack I2crbyte Weekday , Ack I2crbyte _day , Ack I2crbyte _month , Ack I2crbyte _year , Nack I2cstop _sec = Makedec(_sec) : _min = Makedec(_min) : _hour = Makedec(_hour) _day = Makedec(_day) : _month = Makedec(_month) : _year = Makedec(_year)Return
Setdate: _day = Makebcd(_day) : _month = Makebcd(_month) : _year = Makebcd(_year) I2cstart I2cwbyte Ds1307w I2cwbyte 4 I2cwbyte _day I2cwbyte _month I2cwbyte _year I2cstop Waitms 10Return
Setweekday: I2cstart I2cwbyte Ds1307w I2cwbyte 3 I2cwbyte Weekday I2cstop Waitms 10Return
Settime: _sec = Makebcd(_sec) : _min = Makebcd(_min) : _hour = Makebcd(_hour) I2cstart I2cwbyte Ds1307w I2cwbyte 0 I2cwbyte _sec I2cwbyte _min I2cwbyte _hour I2cstop Waitms 10Return
Delnvram:For K = 8 To 63 I2cstart I2cwbyte Ds1307w I2cwbyte K I2cwbyte 00 I2cwbyte 00 I2cstop Waitms 10 NextReturn
Writenvram: I2cstart I2cwbyte Ds1307w I2cwbyte 8 I2cwbyte Stset I2cwbyte Wtset I2cstop Waitms 10Return
- 48 -
Writenvram_sett: I2cstart I2cwbyte Ds1307w I2cwbyte 10 I2cwbyte Z(7) I2cwbyte 0 I2cwbyte Z(8) I2cwbyte 0 I2cwbyte Z(9) I2cwbyte Z(10) I2cwbyte 0 I2cwbyte Systemtagby(1) I2cwbyte Systemtagby(2) I2cwbyte Systemtagby(3) I2cwbyte Systemtagby(4) I2cwbyte Sekdestagesby(1) I2cwbyte Sekdestagesby(2) I2cwbyte Sekdestagesby(3) I2cwbyte Sekdestagesby(4) I2cstop Waitms 10Return
Readnvram: I2cstart I2cwbyte Ds1307w I2cwbyte 8 I2cstart I2cwbyte Ds1307r I2crbyte Stset , Ack I2crbyte Wtset , Ack I2crbyte Lcd_blby(1) , Ack I2crbyte Lcd_blby(2) , Ack I2crbyte Plusminby(1) , Ack I2crbyte Plusminby(2) , Ack I2crbyte Sekundeby(1) , Ack I2crbyte Sekundeby(2) , Ack I2crbyte Sekundeby(3) , Ack I2crbyte Systemtagby(1) , Ack I2crbyte Systemtagby(2) , Ack I2crbyte Systemtagby(3) , Ack I2crbyte Systemtagby(4) , Ack I2crbyte Sekdestagesby(1) , Ack I2crbyte Sekdestagesby(2) , Ack I2crbyte Sekdestagesby(3) , Ack I2crbyte Sekdestagesby(4) , Nack I2cstopReturn
'#####################################################################'# Ende DS1307 Datum, Uhrzeit & Einstellungen auslesen und schreiben #'#####################################################################
'#####################################################################'# I2C EEPROM Sonnenauf/-untergangsdaten lesen und schreiben #'#####################################################################
Eepromwsonne:
N = 0
For X = 7 To 20
Adresse_sonne_high = High(adresse_sonne) Adresse_sonne_low = Low(adresse_sonne)
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_sonne_high I2cwbyte Adresse_sonne_low I2cwbyte Z(x) I2cstop
Waitms 10
Incr Adresse_sonne
- 49 -
Next
If Adresse_sonne > 1399 Then Adresse_sonne = 0
Return
'------------------
Function Eepromrsonne(adresse_sonne As Word) As String * 14
For X = 1 To 14
Adresse_sonne_high = High(adresse_sonne) Adresse_sonne_low = Low(adresse_sonne)
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_sonne_high I2cwbyte Adresse_sonne_low
I2cstart I2cwbyte Eeprr I2crbyte Sonnetagby(x) , Nack I2cstop
Incr Adresse_sonne
Next
Stageeprom = Sonnetagst Stageepromday = Left(stageeprom , 4)
If Stset = 1 And Wtset = 0 Then
Sahst = Mid(stageeprom , 5 , 2) Sarest = Mid(stageeprom , 7 , 3) Suhst = Mid(stageeprom , 10 , 2) Surest = Mid(stageeprom , 12 , 3)
Sahstn = Val(sahst) Incr Sahstn Sahst = Str(sahstn) Sahst = Format(sahst , "00")
Suhstn = Val(suhst) Incr Suhstn Suhst = Str(suhstn) Suhst = Format(suhst , "00")
Stageeprom = Stageepromday + Sahst + Sarest + Suhst + Surest
End If
Eepromrsonne = Stageeprom
End Function
'#####################################################################'# ENDE I2C EEPROM Sonnenauf/-untergangsdaten lesen und schreiben #'#####################################################################
'#####################################################################'# I2C EEPROM Termine lesen und schreiben #'#####################################################################
Eepromwtermine:
N = 0
For X = 5 To 31
Adresse_termine14k = 1400 + Adresse_terminw Adresse_termine_high14k = High(adresse_termine14k)
- 50 -
Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_termine_high14k I2cwbyte Adresse_termine_low14k I2cwbyte Z(x) I2cstop
Waitms 10 Incr Adresse_terminw
Next
Return
'------------------
Function Getterminadresse(heute As Integer) As Word
Maxadressew = Getmaxadressetermine(0)
For Adresse_termine = 0 To Maxadressew Step 27
Terminedate = Gettermintag(adresse_termine)
If Terminedate = Heute Then Alarm_heute = 1 Else Alarm_heute = 0
If Terminedate >= Heute Then Exit For
Next
Getterminadresse = Adresse_termine
End Function
'------------------
Function Gettermintag(adresse_termine As Word) As Integer
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine Adresse_termine_high14k = High(adresse_termine14k) Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_termine_high14k I2cwbyte Adresse_termine_low14k
I2cstart I2cwbyte Eeprr I2crbyte Termineby(x) , Nack I2cstop
Incr Adresse_termine
Next
Termine_t = Left(terminest , 2) Termine_m = Mid(terminest , 3 , 2) Termine_j = Mid(terminest , 7 , 2) Termine_jv = Mid(terminest , 5 , 4) Terminedatest = Termine_t + "." + Termine_m + "." + Termine_j Terminedate = Dayofyear(terminedatest)
Termine_ij = Val(termine_j) Schaltjahr = Termine_ij Mod 4
If Schaltjahr = 0 And Terminedate > 59 Then 'Schaltjahr Decr Terminedate End If
Gettermintag = Terminedate
End Function
- 51 -
'-------------------
Function Eepromrtermine(adresse_termine As Word) As String * 16
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine Adresse_termine_high14k = High(adresse_termine14k) Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_termine_high14k I2cwbyte Adresse_termine_low14k
I2cstart I2cwbyte Eeprr I2crbyte Termineby(x) , Nack I2cstop
Incr Adresse_termine
Next
Termine_t = Left(terminest , 2) Termine_m = Mid(terminest , 3 , 2) Termine_p = Mid(terminest , 16 , 10)
Terminelcdst = Termine_t + "." + Termine_m + " " + Termine_p
If Termine_t = "00" Then Terminelcdst = Space(16)
Eepromrtermine = Terminelcdst
End Function
'------------------
Function Getmaxadressetermine(adresse_termine As Word) As Word
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine Adresse_termine_high14k = High(adresse_termine14k) Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_termine_high14k I2cwbyte Adresse_termine_low14k
I2cstart I2cwbyte Eeprr I2crbyte Termineby(x) , Nack I2cstop
Incr Adresse_termine
Next
Maxadressest = Mid(terminest , 26 , 2) Maxadressew = Val(maxadressest) Maxadressew = Maxadressew * 27
Getmaxadressetermine = Maxadressew
End Function
'---------------------------
Function Eepromrtermine_alarm(adresse_termine As Word) As Long
For X = 1 To 27
Adresse_termine14k = 1400 + Adresse_termine
- 52 -
Adresse_termine_high14k = High(adresse_termine14k) Adresse_termine_low14k = Low(adresse_termine14k)
I2cstart I2cwbyte Eeprw I2cwbyte Adresse_termine_high14k I2cwbyte Adresse_termine_low14k
I2cstart I2cwbyte Eeprr I2crbyte Termineby(x) , Nack I2cstop
Incr Adresse_termine
Next
Termine_sek = Mid(terminest , 9 , 5) Termine_mu = Mid(terminest , 15 , 1) 'Musik abspielen? Termine_geburtstag = Mid(terminest , 14 , 1) 'Geburtstag oder Feiertag
Termine_alarml = Val(termine_sek)
Eepromrtermine_alarm = Termine_alarml
End Function
'#####################################################################'# ENDE I2C EEPROM Termine lesen und schreiben #'#####################################################################
'-------------------Toggle_colon: Timer1 = 7936 Toggle Colon_onoff If All_off = 1 Then Colon_onoff = 0Return
'------------------
Button1: Bitwait Pind.2 , Reset If Cntb1 = 3 Then Cntb1 = 0 Else Incr Cntb1 ClsReturn
'------------------
Button2: Bitwait Pind.3 , Reset If Cntb2 = 2 Then Cntb2 = 0 Else Incr Cntb2Return
'----------
Gotomain: Bitwait Pind.2 , Reset Cntb1 = 0 ClsReturn
'#####################################################'# LCD BL an/aus #'#####################################################
Lcd_blonoff:
Licht = Getadc(2) If Lcd_blst = "1" Then Lcd_bl = 1 Elseif Lcd_blst = "3" And Licht < 120 And _hour > 6 Then Lcd_bl = 1 Else Lcd_bl = 0 End If
- 53 -
Return
'#####################################################'# ENDE LCD BL an/aus #'#####################################################
'#####################################################'# Sommer-/Winterzeit einstellen #'#####################################################
Dst_onoff: If _month = 3 And _day > 24 And Weekday = 7 And _hour = 2 Then _hour = _hour + 1 Waitms 10 Call Settime Stset = 1 Wtset = 0 Waitms 10 Call Writenvram End If
If Wtset = 0 And _month = 10 And _day > 24 And Weekday = 7 And _hour = 3 Then _hour = _hour - 1 Waitms 10 Call Settime Wtset = 1 Stset = 0 Waitms 10 Call Writenvram End IfReturn
'#####################################################'# Ende Sommer-/Winterzeit einstellen #'#####################################################
'#####################################################'# Zeitkorrektur #'#####################################################
Zeitkorrektur:
Call Readnvram
Sysd = Sysday() Secd = Secofday() Sekundelong = Val(sekundest)
If Secd = 86399 Then Zeitkorrekturbit = 0
If Plusminst = "0" Then Korrektur = Sekdestages + Sekundelong If Plusminst = "1" Then Korrektur = Sekdestages - Sekundelong
If Sysd <> Systemtag And Secd = Sekdestages And Sekundelong <> 0 And Zeitkorrekturbit = 0 Then Time$ = Time(korrektur) Zeitkorrekturbit = 1 End IfReturn
'#####################################################'# Ende Zeitkorrektur #'#####################################################
'#####################################################'# Musik abspielen #'#####################################################
Sub Play_music(song_nr As String * 1)
If Lcd_bl = 0 Then Lcd_bl = 1
Select Case Song_nr
Case "1"
For I = 0 To 55 Note = Lookup(i , Happyb)
- 54 -
Incr I If Note = 0 Then Pause = Lookup(i , Happyb) Waitms Pause Else Laenge = Lookup(i , Happyb) Sound Speaker , Note , Laenge End If Next I
Case "2"
For I = 0 To 57 Note = Lookup(i , Merryx) Incr I If Note = 0 Then Pause = Lookup(i , Merryx) Waitms Pause Else Laenge = Lookup(i , Merryx) Sound Speaker , Note , Laenge End If Next I
End Select
End Sub
'#####################################################'# Ende Musik abspielen #'#####################################################
End
Weekdays:
Data "dummy" , "Montag" , "Dienstag" , "Mittwoch" , "Donnerstag" , "Freitag" , "Samstag" , "Sonntag"
Happyb:Data 65% , 587% , 65% , 587% , 147% , 523% , 131% , 587% , 175%Data 440% , 165% , 466% , 0% , 250% , 65% , 587% , 65% , 587% , 147%Data 523% , 131% , 587% , 196% , 392% , 175% , 440% , 0% , 250% , 65%Data 587% , 65% , 587% , 262% , 294% , 220% , 349% , 175% , 440% , 165%Data 466% , 147% , 523% , 0% , 125% , 117% , 330% , 117% , 330% , 220%Data 349% , 175% , 440% , 196% , 392% , 175% , 440%
Merryx:Data 147% , 523% , 196% , 392% , 98% , 392% , 110% , 349% , 98% , 392%Data 92% , 415% , 165% , 466% , 131% , 587% , 165% , 466% , 220% , 349%Data 110% , 349% , 124% , 311% , 110% , 349% , 98% , 392% , 185% , 415%Data 294% , 523% , 247% , 311% , 124% , 311% , 131% , 294% , 124% , 311%Data 110% , 349% , 196% , 392% , 165% , 466% , 73% , 523% , 73% , 523%Data 165% , 466% , 220% , 349% , 185% , 415% , 196% , 392%
- 55 -
AutoIt-Quellcode;------------------------------------------------------------------------------------------; Tool fuer die Geburtstagskalenderuhr; Benutzt CommMG.au3 V2.8 von Martin Gibson; http://www.autoitscript.com/forum/topic/45842-serial-port-com-port-udf/; http://www.mosaiccgl.co.uk/AutoItDownloads/confirm.php?get=COMMGv2.zip;; Berechnung der Zeiten für Sonnenauf bzw. -untergang aus dem AutoIt Skript; IsItDark von JustinTime ; http://www.autoitscript.com/forum/topic/20946-script-to-determine-sunrisesunset-times-etc/;; Berechnung des Osterdatums nach der Formel von Lichtenberg; http://de.wikipedia.org/wiki/Gau%C3%9Fsche_Osterformel;-------------------------------------------------------------------------------------------
#include <ButtonConstants.au3>#include <ComboConstants.au3>#include <DateTimeConstants.au3>#include <EditConstants.au3>#include <GUIConstantsEx.au3>#include <StaticConstants.au3>#include <WindowsConstants.au3>#include <Array.au3>#include <CommMG.au3>;or if you save the commMg.dll in the @scripdir use #include @SciptDir & '\commmg.dll'#Include <GuiListBox.au3>#include <File.au3>#include <GuiListView.au3>#Include <Date.au3>
Const $longitude = 9.935556 ; GoettingenConst $latitude = 51.533889 ; GoettingenConst $TZ = 1 ;ZeitzoneConst $pi = 3.1415926535897932384626433832795Const $isdst=0$RADEG=180/$pi$DEGRAD=$pi/180$MyDocsFolder = "::{450D8FBA-AD25-11D0-98A8-0800361B1103}"
Local $avArray[8]$avArray[0] = "Dummy"$avArray[1] = "Sonntag"$avArray[2] = "Montag"$avArray[3] = "Dienstag"$avArray[4] = "Mittwoch"$avArray[5] = "Donnerstag"$avArray[6] = "Freitag"$avArray[7] = "Samstag"$time = @HOUR & ":" & @MIN & ":" & @SEC $date1 = @YEAR & "/" & @MON & "/" & @MDAY $date = @MDAY & "." & @MON & "." & stringmid(@YEAR,3,2) #Region ### START Koda GUI section ### Form=$Form1_1 = GUICreate("Tool", 629, 515, 138, 42)$Tab1 = GUICtrlCreateTab(24, 24, 585, 465)$TabSheet1 = GUICtrlCreateTabItem("Einstellungen")$Combo1 = GUICtrlCreateCombo("COM1", 64, 110, 81, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))GUICtrlSetData(-1, "COM2|COM3|COM4|COM5|COM6|COM7|COM8|COM9|COM10|COM11|COM12")$TimeInp = GUICtrlCreateDate($time, 184, 174, 94, 21, BitOR($DTS_UPDOWN,$DTS_TIMEFORMAT))$DateInp = GUICtrlCreateDate($date, 64, 174, 94, 21, BitOR($DTS_SHORTDATEFORMAT,$DTS_UPDOWN))$Sommerzeit = GUICtrlCreateCheckbox("Sommerzeit", 472, 166, 97, 25)GUICtrlSetState(-1, $GUI_CHECKED)$Sysdate = GUICtrlCreateCheckbox("Systemdatum", 472, 198, 97, 25)GUICtrlSetState(-1, $GUI_CHECKED)$Systime = GUICtrlCreateCheckbox("Systemzeit", 472, 230, 97, 25)GUICtrlSetState(-1, $GUI_CHECKED)$Label1 = GUICtrlCreateLabel("COM-Port", 160, 110, 50, 17)$Sendtime = GUICtrlCreateButton("Datum / Zeit senden", 64, 222, 121, 41)$Sendtest = GUICtrlCreateButton("Test", 264, 102, 65, 33)$Input2 = GUICtrlCreateInput("", 344, 110, 208, 22, BitOR($GUI_SS_DEFAULT_INPUT,$ES_READONLY))
- 56 -
$Weekday = GUICtrlCreateCombo($avArray[@WDAY], 296, 174, 88, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))GUICtrlSetData(-1, "Sonntag|Montag|Dienstag|Mittwoch|Donnerstag|Freitag|Samstag")$Input4 = GUICtrlCreateInput("", 208, 230, 208, 22, BitOR($GUI_SS_DEFAULT_INPUT,$ES_READONLY));#####$Group1 = GUICtrlCreateGroup("LCD-Hintergrundbeleuchtung", 64, 289, 201, 57)$An = GUICtrlCreateRadio("An", 80, 313, 57, 17)GUICtrlSetState(-1, $GUI_CHECKED)$Aus = GUICtrlCreateRadio("Aus", 144, 313, 57, 17)$Auto = GUICtrlCreateRadio("Auto", 208, 313, 49, 17)GUICtrlCreateGroup("", -99, -99, 1, 1)$Group2 = GUICtrlCreateGroup("Korrektur", 312, 289, 225, 57)$plus = GUICtrlCreateRadio("+", 328, 313, 25, 18)GUICtrlSetState(-1, $GUI_CHECKED)$minus = GUICtrlCreateRadio("-", 368, 313, 25, 18)$Sekunden = GUICtrlCreateCombo("00", 402, 313, 51, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))GUICtrlSetData(-1, "01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30")$Label3 = GUICtrlCreateLabel("s in 24 h", 467, 313, 54, 18)GUICtrlCreateGroup("", -99, -99, 1, 1)$Sendsettings = GUICtrlCreateButton("Einstellungen senden", 64, 360, 121, 41, $BS_MULTILINE)$Input5 = GUICtrlCreateInput("", 210, 372, 208, 22, BitOR($GUI_SS_DEFAULT_INPUT,$ES_READONLY))$Sonnebutton = GUICtrlCreateButton(" Zeiten für Sonnenauf-/untergänge der nächsten 100 Tage senden ", 63, 420, 233, 41, $BS_MULTILINE)$ProgressSonne = GUICtrlCreateProgress(320, 424, 241, 33)$TabSheet2 = GUICtrlCreateTabItem("Geburtstage und Feiertage")$TDate = GUICtrlCreateDate($Date, 40, 72, 81, 22, 0)$Ttime = GUICtrlCreateDate($Time, 136, 72, 73, 22, BitOR($DTS_UPDOWN,$DTS_TIMEFORMAT))$TWh = GUICtrlCreateCombo("Geburtstag", 224, 72, 76, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))GUICtrlSetData(-1, "Feiertag")$TSound = GUICtrlCreateCombo("Keine Melodie", 312, 72, 105, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))GUICtrlSetData(-1, "Melodie 1|Melodie 2")$TInpEreig = GUICtrlCreateInput("Klaus", 432, 72, 113, 22)GUICtrlSetLimit(-1, 10)$Tadd = GUICtrlCreateButton("+", 560, 72, 25, 25)$TChange = GUICtrlCreateButton("Eintrag ändern", 432, 136, 113, 25)$TDel = GUICtrlCreateButton("Eintrag löschen", 432, 178, 113, 25)$TDelAll = GUICtrlCreateButton("Alle löschen", 432, 218, 113, 25)$TFeiertag = GUICtrlCreateButton("Feiertage hinzufügen", 432, 256, 113, 25)$Input3 = GUICtrlCreateInput("", 264, 449, 209, 22, BitOR($GUI_SS_DEFAULT_INPUT,$ES_READONLY))$TList = GUICtrlCreateListView("Datum|Uhrzeit|Anlass|Melodie|Text|#", 40, 121, 377, 314)GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 0, 70)GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 1, 70)GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 2, 60)GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 3, 60)GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 4, 90)GUICtrlSendMsg(-1, $LVM_SETCOLUMNWIDTH, 5, 0)$TSave = GUICtrlCreateButton("Speichern", 40, 448, 65, 25)$TLoad = GUICtrlCreateButton("Laden", 112, 448, 65, 25)$TSend = GUICtrlCreateButton("Senden", 184, 448, 65, 25)$TProgress = GUICtrlCreateProgress(480, 448, 113, 22)$TabSheet3 = GUICtrlCreateTabItem("Melodiegenerator")$MelodieName = GUICtrlCreateInput("Melodie", 52, 64, 169, 22)$Eingabe = GUICtrlCreateEdit("", 52, 97, 521, 137)$Ausgabe = GUICtrlCreateEdit("", 52, 309, 521, 161, BitOR($GUI_SS_DEFAULT_EDIT,$ES_READONLY)) ;$Generate = GUICtrlCreateButton("Code generieren", 200, 248, 217, 41)$DelAll = GUICtrlCreateButton("Alles löschen", 445, 248, 113, 41)GUICtrlCreateTabItem("")GUISetState(@SW_SHOW)#EndRegion ### END Koda GUI section ###
GUICtrlSetState($Systime, $GUI_CHECKED)GUICtrlSetState($Sysdate, $GUI_CHECKED)
- 57 -
While 1 Local $sportSetError $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $Sommerzeit Case $Sysdate Case $Systime Case $combo1 $setport = StringReplace(GUICtrlRead($Combo1), 'COM', '') _CommSetPort($setport, $sportSetError, 9600, 8, 0, 1, 0) if $sportSetError = '' Then MsgBox(262144, 'Verbunden','Verbunden mit COM' & $setport) Else MsgBox(262144, 'Verbindungsfehler', $sportSetError) EndIf $mode = 1 Case $Sendtest sleep (1000) GUICtrlSetData($input2, "") _CommSendString("TEST: Gesendet & Empfangen 1234") sleep (1000) $instr = _CommGetString() if $instr <> "" then GUICtrlSetData($input2, $instr) else GUICtrlSetData($input2, "Falscher Port oder Fehler") endif Case $Sendtime $a=GUICtrlRead($Sommerzeit) $b=GUICtrlRead($Sysdate) $c=GUICtrlRead($Systime) if $a=1 then $wt=0 $st=1 elseif $a <> 1 then $wt=1 $st=0 endif if $b=1 then $day=@MDAY $month=@MON $year2=stringmid(@YEAR,3,4) $date=$day & "." & $month & "." & $year2 & weekday2number($avArray[@WDAY]) else $date=stringmid(GUICtrlRead($DateInp),1,6) & stringmid(GUICtrlRead($DateInp),9,2) & weekday2number(GUICtrlRead($Weekday)) EndIf if $c=1 then $time=@HOUR &":"& @MIN &":"& @SEC else $time=GUICtrlRead($TimeInp) EndIf $Sendstr="TIME :" & $date & $wt & $st & $time & "xxxxxx" _CommSendString($Sendstr) sleep (1000) $instr = _CommGetString() if $instr <> "" then GUICtrlSetData($input4, $instr) else GUICtrlSetData($input4, "") GUICtrlSetData($input4, $sendstr) endif Case $Sendsettings if GUICtrlRead($an)=1 then $LCD=1
- 58 -
if GUICtrlRead($aus)=1 then $LCD=2 if GUICtrlRead($auto)=1 then $LCD=3 if GUICtrlRead($plus)=1 then $plusminus=0 if GUICtrlRead($minus)=1 then $plusminus=1 if Number(GUICtrlRead($Sekunden)) < 10 then $null=0 else $null = "" EndIf $Sendstrsett = "SETT: " & $LCD & $plusminus & GUICtrlRead($Sekunden) & "00000000000000000000x" _CommSendString($Sendstrsett) sleep (1000) GUICtrlSetData($input5,$Sendstrsett) Case $Sonnebutton $b=GUICtrlRead($Sysdate) if $b=1 then $day = ( 367 * (@YEAR) - int((7 * ((@YEAR) + (((@MON) + 9) / 12))) / 4) + int((275 * (@MON)) / 9) + (@MDAY) - 730530) else $Jahr=stringmid(GUICtrlRead($DateInp),7,4) $Monat=stringmid(GUICtrlRead($DateInp),4,2) $MTag=stringmid(GUICtrlRead($DateInp),1,2) $day = ( 367 * ($Jahr) - int((7 * (($Jahr) + ((($Monat) + 9) / 12))) / 4) + int((275 * ($Monat)) / 9) + ($MTag) - 730530) EndIf For $Iday =0 to 99 $nday=$day+$Iday $SunTimes=SunTimes($nday,0) $Sendstrsonne="SUNS: " & $nday-1 & $SunTimes & "0000000000x" _CommSendString($Sendstrsonne) GUICtrlSetData($input5,$Sendstrsonne) GUICtrlSetData($ProgressSonne, $Iday+1) sleep(500) Next Case $Tadd _GUICtrlListView_RegisterSortCallBack($TList) $TerminT=StringLeft(GUICtrlRead($Tdate),2) $TerminM=StringMid(GUICtrlRead($Tdate),4,2) $TerminDatum = $TerminM & $TerminT GUICtrlCreateListViewItem(GUICtrlRead($Tdate) & "|" & GUICtrlRead($Ttime) & "|" & GUICtrlRead($Twh) & "|" & GUICtrlRead($TSound) & "|" & StringFormat("%-10s",GUICtrlRead($TInpEreig)) &"|" & $TerminDatum, $TList) _GUICtrlListView_SortItems($TList,5) _GUICtrlListView_UnRegisterSortCallBack ($TList) Case $TChange $line = _GUICtrlListView_GetItemTextString($TList,Number(_GUICtrlListView_GetSelectedIndices($TList))) $linesplit = StringSplit($line,"|") $date_tchange=StringMid($linesplit[1],7,4) & "/" & StringMid($linesplit[1],4,2) & "/" & StringMid($linesplit[1],1,2) GUICtrlSetData($Tdate,$date_tchange) GUICtrlSetData($Ttime,$date_tchange & " " & $linesplit[2]) GUICtrlSetData($Twh, $linesplit[3]) GUICtrlSetData($Tsound, $linesplit[4]) GUICtrlSetData($TInpEreig, $linesplit[5]) _GUICtrlListView_DeleteItem($TList,Number(_GUICtrlListView_GetSelectedIndices($TList))) Case $Tdel _GUICtrlListView_DeleteItemsSelected($TList) Case $TDelall _GUICtrlListView_DeleteAllItems($TList) Case $TFeiertag _GUICtrlListView_RegisterSortCallBack($TList) GUICtrlCreateListViewItem("01.01." & @YEAR & "|" & "00:00:01" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "Neujahr " & "|" & "0101", $TList)
- 59 -
GUICtrlCreateListViewItem("01.05." & @YEAR & "|" & "12:00:00" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "1. Mai " & "|" & "0501", $TList) GUICtrlCreateListViewItem("08.05." & @YEAR & "|" & "12:00:00" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "Muttertag " & "|" & "0508", $TList) GUICtrlCreateListViewItem("03.10." & @YEAR & "|" & "12:00:00" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "D. Einheit" & "|" & "1003", $TList) GUICtrlCreateListViewItem("24.12." & @YEAR & "|" & "12:00:00" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "Heiligab. " & "|" & "1224", $TList) GUICtrlCreateListViewItem("25.12." & @YEAR & "|" & "12:00:00" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "1. Weihft." & "|" & "1225", $TList) GUICtrlCreateListViewItem("26.12." & @YEAR & "|" & "12:00:00" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "2. Weihft." & "|" & "1226", $TList) GUICtrlCreateListViewItem("31.12." & @YEAR & "|" & "12:00:00" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "Silvester " & "|" & "1231", $TList) $Osterdatum=Ostern(@YEAR) $OsternT=StringLeft($Osterdatum,2) $OsternM=StringMid($Osterdatum,4,2) $OsternMT=$OsternM & $OsternT If (@MON & @MDAY) > $OsternMT then $Osterdatum=Ostern(@YEAR+1) $OsternT=StringLeft($Osterdatum,2) $OsternM=StringMid($Osterdatum,4,2) $OsternY=StringMid($Osterdatum,7,4) $OsternMT=$OsternM & $OsternT GUICtrlCreateListViewItem($Osterdatum & "|" & "12:00:00" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "Ostersonn." & "|" &$OsternMT, $TList) Dim $KarfreitagY, $KarfreitagM, $KarfreitagT $Karfreitag= _DateToDayValue ($OsternY, $OsternM, $OsternT) -2 $Karfreitag= _DayValueToDate ($Karfreitag, $KarfreitagY, $KarfreitagM, $KarfreitagT) $Karfreitag = $KarfreitagT & "." & $KarfreitagM & "." & $KarfreitagY $KarfreitagMT = $KarfreitagM & $KarfreitagT GUICtrlCreateListViewItem($Karfreitag & "|" & "12:00:00" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "Karfreitag" & "|" & $KarfreitagMT, $TList) Dim $OstermontagY, $OstermontagM, $OstermontagT $Ostermontag = _DateToDayValue ($OsternY, $OsternM, $OsternT) + 1 $Ostermontag = _DayValueToDate ($Ostermontag, $OstermontagY, $OstermontagM, $OstermontagT) $Ostermontag = $OstermontagT & "." & $OstermontagM & "." & $OstermontagY $OstermontagMT = $OstermontagM & $OstermontagT GUICtrlCreateListViewItem($Ostermontag & "|" & "12:00:00" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "Ostermon. " & "|" &$OstermontagMT, $TList) Dim $HimmelfahrtY, $HimmelfahrtM, $HimmelfahrtT $Himmelfahrt= _DateToDayValue ($OsternY, $OsternM, $OsternT) + 39 $Himmelfahrt= _DayValueToDate ($Himmelfahrt, $HimmelfahrtY, $HimmelfahrtM, $HimmelfahrtT) $Himmelfahrt = $HimmelfahrtT & "." & $HimmelfahrtM & "." & $HimmelfahrtY $HimmelfahrtMT = $HimmelfahrtM & $HimmelfahrtT GUICtrlCreateListViewItem($Himmelfahrt & "|" & "12:00:00" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "Vatertag " & "|" & $HimmelfahrtMT, $TList) Dim $PfingstsonntagY, $PfingstsonntagM, $PfingstsonntagT $Pfingstsonntag= _DateToDayValue ($OsternY, $OsternM, $OsternT) + 49 $Pfingstsonntag= _DayValueToDate ($Pfingstsonntag, $PfingstsonntagY, $PfingstsonntagM, $PfingstsonntagT) $Pfingstsonntag = $PfingstsonntagT & "." & $PfingstsonntagM & "." & $PfingstsonntagY $PfingstsonntagMT = $PfingstsonntagM & $PfingstsonntagT GUICtrlCreateListViewItem($Pfingstsonntag & "|" & "12:00:00" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "Pfingstso." & "|" & $PfingstsonntagMT, $TList) Dim $PfingstmontagY, $PfingstmontagM, $PfingstmontagT
- 60 -
$Pfingstmontag = _DateToDayValue ($OsternY, $OsternM, $OsternT) + 50 $Pfingstmontag = _DayValueToDate ($Pfingstmontag, $PfingstmontagY, $PfingstmontagM, $PfingstmontagT) $Pfingstmontag = $PfingstmontagT & "." & $PfingstmontagM & "." & $PfingstmontagY $PfingstmontagMT = $PfingstmontagM & $PfingstmontagT GUICtrlCreateListViewItem($Pfingstmontag & "|" & "12:00:00" & "|" & "Feiertag" & "|" & "Keine Melodie" & "|" & "Pfingstmo." & "|" & $PfingstmontagMT, $TList) _GUICtrlListView_SortItems($TList,5) _GUICtrlListView_UnRegisterSortCallBack ($TList) Case $TSave $TerminFile=FileSaveDialog ( "Termine speichern", $MyDocsFolder, "Text (*.txt)" , 2,"termine.txt" ) Fileopen($TerminFile,2) For $iIndex = 0 to _GUICtrlListView_GetItemCount($TList)-1 FileWriteLine ($TerminFile, _GUICtrlListView_GetItemTextString($TList, $iIndex)) Next FileClose($TerminFile) Case $TLoad $TerminFile=FileOpenDialog ( "Termine öffnen", $MyDocsFolder, "Text (*.txt)" , 2,"termine.txt" ) _GUICtrlListView_DeleteAllItems($TList) $endoffile = _FileCountLines($TerminFile) Fileopen($TerminFile,0) For $I = 1 to $endoffile $line = FileReadLine($TerminFile,$I) $linesplit=StringSplit($line,"|") GUICtrlCreateListViewItem($linesplit[1] & "|" & $linesplit[2] & "|" & $linesplit[3] & "|" & $linesplit[4] & "|" & $linesplit[5] &"|" & $linesplit[6], $TList) Next FileClose($TerminFile) Case $Tsend _CommSendString("CDATxxxxxxxxxxxxxxxxxxxxxxxxxxx") Sleep(500) For $iIndex = 0 to _GUICtrlListView_GetItemCount($TList)-1 $TerminString=_GUICtrlListView_GetItemTextString($TList, $iIndex) $TerminSec=Secofday(Stringmid($TerminString,12,8)) $TerminSec=StringFormat("%5s",$TerminSec) $TerminSec=StringReplace($TerminSec," ","0") $TerminString=StringReplace($TerminString,".","",2) $TerminString=StringReplace($TerminString,":","",2) $TerminString=StringReplace($TerminString,"|","") $TerminString=StringReplace($TerminString,"Geburtstag","G") $TerminString=StringReplace($TerminString,"Feiertag","F") $TerminString=StringReplace($TerminString,"Keine Melodie","0") $TerminString=StringReplace($TerminString,"Melodie ","") $TerminString="DATE" & StringLeft($TerminString, 8) & $TerminSec & StringMid($TerminString,15,12) $TerminString=StringFormat("%-29s",$TerminString) $TerminString=$TerminString & StringFormat("%2s",string(_GUICtrlListView_GetItemCount($TList))) _CommSendString($TErminString) Sleep(1000) GUICtrlSetData($Input3,$TerminString) GUICtrlSetData($TProgress, (100*($iIndex+1))/(_GUICtrlListView_GetItemCount($TList))) Next Sleep(1000) _CommSendString("DATE000000000000000000000000000") Sleep(1000) _CommSendString("DATE000000000000000000000000000") Sleep(1000) Case $Generate ;http://www.mcselec.com/index.php?option=com_content&task=view&id=221&Itemid=57 ;http://www.xs4all.nl/~vbergen/ringtones/siemens/index_2000.html $AusgabeText=""
- 61 -
GUICtrlSetData($Ausgabe, $AusgabeText="") Dim $AusgabeText Dim $Zaehler Dim $mP $Zaehler=0 Dim $C1[2][6] = [["C1","C1(1)","C1(1/2)","C1(1/4)","C1(1/8)","C1(1/16)"],[1174,523,262,131,65,33]] Dim $Cis1[2][6] = [["Cis1","Cis1(1)","Cis1(1/2)","Cis1(1/4)","Cis1(1/8)","Cis1(1/16)"],[1108,555,277,139,69,35]] Dim $D1[2][6] = [["D1","D1(1)","D(1/2)","D(1/4)","D(1/8)","D(1/16)"],[1046,587,294,147,73,37]] Dim $Dis1[2][6] = [["Dis1","Dis1(1)","Dis(1/2)","Dis(1/4)","Dis(1/8)","Dis(1/16)"],[987,622,311,156,78,39]] Dim $E1[2][6] = [["E1","E1(1)","E1(1/2)","E1(1/4)","E1(1/8)","E1(1/16)"],[932,659,330,165,82,41]] Dim $F1[2][6] = [["F1","F1(1)","F1(1/2)","F1(1/4)","F1(1/8)","F1(1/16)"],[880,698,349,175,87,44]] Dim $Fis1[2][6] = [["Fis1","Fis1(1)","Fis1(1/2)","Fis1(1/4)","Fis1(1/8)","Fis1(1/16)"],[830,740,370,185,92,46]] Dim $G1[2][6] = [["G1","G1(1)","G1(1/2)","G1(1/4)","G1(1/8)","G1(1/16)"],[784,784,392,196,98,49]] Dim $Gis1[2][6] = [["Gis1","Gis1(1)","Gis1(1/2)","Gis1(1/4)","Gis1(1/8)","Gis1(1/16)"],[740,830,415,208,104,52]] Dim $A1[2][6] = [["A1","A1(1)","A1(1/2)","A1(1/4)","A1(1/8)","A1(1/16)"],[698,880,440,220,110,55]] Dim $Ais1[2][6] = [["Ais1","Ais1(1)","Ais1(1/2)","Ais1(1/4)","Ais1(1/8)","Ais1(1/16)"],[659,932,466,233,117,58]] Dim $B1[2][6] = [["B1","B1(1)","B1(1/2)","B1(1/4)","B1(1/8)","B1(1/16)"],[622,988,494,247,124,62]] Dim $H1[2][6] = [["H1","H1(1)","H1(1/2)","H1(1/4)","H1(1/8)","H1(1/16)"],[622,988,494,247,124,62]] Dim $C2[2][6] = [["C2","C2(1)","C2(1/2)","C2(1/4)","C2(1/8)","C2(1/16)"],[587,1047,523,262,131,65]] Dim $Cis2[2][6] = [["Cis2","Cis2(1)","Cis2(1/2)","Cis2(1/4)","Cis2(1/8)","Cis2(1/16)"],[554,1109,554,277,139,69]] Dim $D2[2][6] = [["D2","D2(1)","D2(1/2)","D2(1/4)","D2(1/8)","D2(1/16)"],[523,1175,587,294,147,73]] Dim $Dis2[2][6] = [["Dis2","Dis2(1)","Dis2(1/2)","Dis2(1/4)","Dis2(1/8)","Dis2(1/16)"],[494,1244,622,311,156,78]] Dim $E2[2][6] = [["E2","E2(1)","E2(1/2)","E2(1/4)","E2(1/8)","E2(1/16)"],[466,1318,659,330,165,82]] Dim $F2[2][6] = [["F2","F2(1)","F2(1/2)","F2(1/4)","F2(1/8)","F2(1/16)"],[440,1396,698,349,175,87]] Dim $Fis2[2][6] = [["Fis2","Fis2(1)","Fis2(1/2)","Fis2(1/4)","Fis2(1/8)","Fis2(1/16)"],[415,1480,740,370,185,92]] Dim $G2[2][6] = [["G2","G2(1)","G2(1/2)","G2(1/4)","G2(1/8)","G2(1/16)"],[392,1567,784,392,196,98]] Dim $Gis2[2][6] = [["Gis2","Gis2(1)","Gis2(1/2)","Gis2(1/4)","Gis2(1/8)","Gis2(1/16)"],[370,1661,831,415,208,104]] Dim $A2[2][6] = [["A2","A2(1)","A2(1/2)","A2(1/4)","A2(1/8)","A2(1/16)"],[349,1760,880,440,220,110]] Dim $Ais2[2][6] = [["Ais2","Ais2(1)","Ais2(1/2)","Ais2(1/4)","Ais2(1/8)","Ais2(1/16)"],[330,1862,932,466,233,117]] Dim $B2[2][6] = [["B2","B2(1)","B2(1/2)","B2(1/4)","B2(1/8)","B2(1/16)"],[311,1976,988,494,247,124]] Dim $H2[2][6] = [["H2","H2(1)","H2(1/2)","H2(1/4)","H2(1/8)","H2(1/16)"],[311,1976,988,494,247,124]] Dim $C3[2][6] = [["C3","C3(1)","C3(1/2)","C3(1/4)","C3(1/8)","C3(1/16)"],[294,2090,1047,523,262,131]] Dim $Cis3[2][6] = [["Cis3","Cis3(1)","Cis3(1/2)","Cis3(1/4)","Cis3(1/8)","Cis3(1/16)"],[277,2218,1109,554,277,139]] Dim $D3[2][6] = [["D3","D3(1)","D3(1/2)","D3(1/4)","D3(1/8)","D3(1/16)"],[262,2345,1175,587,294,147]] Dim $Dis3[2][6] = [["Dis3","Dis3(1)","Dis3(1/2)","Dis3(1/4)","Dis3(1/8)","Dis3(1/16)"],[247,2487,1245,622,311,156]] Dim $E3[2][6] = [["E3","E3(1)","E3(1/2)","E3(1/4)","E3(1/8)","E3(1/16)"],[233,2637,1319,659,330,165]] Dim $F3[2][6] = [["F3","F3(1)","F3(1/2)","F3(1/4)","F3(1/8)","F3(1/16)"],[220,2793,1397,698,349,175]] Dim $Fis3[2][6] = [["Fis3","Fis3(1)","Fis3(1/2)","Fis3(1/4)","Fis3(1/8)","Fis3(1/16)"],[208,2954,1480,740,370,185]] Dim $G3[2][6] = [["G3","G3(1)","G3(1/2)","G3(1/4)","G3(1/8)","G3(1/16)"],[196,3135,1568,784,392,196]] Dim $Gis3[2][6] = [["Gis3","Gis3(1)","Gis3(1/2)","Gis3(1/4)","Gis3(1/8)","Gis3(1/16)"],[185,3321,1661,831,415,208]] Dim $A3[2][6] = [["A3","A3(1)","A3(1/2)","A3(1/4)","A3(1/8)","A3(1/16)"],
- 62 -
[179,3432,1720,880,440,220]] Dim $Ais3[2][6] = [["Ais3","Ais3(1)","Ais3(1/2)","Ais3(1/4)","Ais3(1/8)","Ais3(1/16)"],[165,3724,1865,932,466,233]] Dim $B3[2][6] = [["B3","B3(1)","B3(1/2)","B3(1/4)","B3(1/8)","B3(1/16)"],[156,3938,1976,988,494,247]] Dim $H3[2][6] = [["H3","H3(1)","H3(1/2)","H3(1/4)","H3(1/8)","H3(1/16)"],[156,3938,1976,988,494,247]] Dim $P[2][6] = [["P","P(1)","P(1/2)","P(1/4)","P(1/8)","P(1/16)"],[0,2000,1000,500,250,125]] $MelodieText=GUICtrlRead($Eingabe) $MelodieText=StringReplace($MelodieText," ","x") $MelodieText=StringSplit($MelodieText,"x") For $m=1 to $MelodieText[0] $mP=$m+1 For $C= 0 to 5 If $MelodieText[$m] = $C1[0][$C] Then $AusgabeText=$AusgabeText & $C1[1][$C] & "%, " & $C1[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Cis1[0][$C] Then $AusgabeText=$AusgabeText & $Cis1[1][$C] & "%, " & $Cis1[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $D1[0][$C] Then $AusgabeText=$AusgabeText & $D1[1][$C] & "%, " & $D1[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Dis1[0][$C] Then $AusgabeText=$AusgabeText & $Dis1[1][$C] & "%, " & $Dis1[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $E1[0][$C] Then $AusgabeText=$AusgabeText & $E1[1][$C] & "%, " & $E1[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $F1[0][$C] Then $AusgabeText=$AusgabeText & $F1[1][$C] & "%, " & $F1[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Fis1[0][$C] Then $AusgabeText=$AusgabeText & $Fis1[1][$C] & "%, " & $Fis1[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $G1[0][$C] Then $AusgabeText=$AusgabeText & $G1[1][$C] & "%, " & $G1[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Gis1[0][$C] Then $AusgabeText=$AusgabeText & $Gis1[1][$C] & "%, " & $Gis1[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $A1[0][$C] Then $AusgabeText=$AusgabeText & $A1[1][$C] & "%, " & $A1[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Ais1[0][$C] Then $AusgabeText=$AusgabeText & $Ais1[1][$C] & "%, " & $Ais1[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $B1[0][$C] Then $AusgabeText=$AusgabeText & $B1[1][$C] & "%, " & $B1[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $H1[0][$C] Then $AusgabeText=$AusgabeText & $H1[1][$C] & "%, " & $H1[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $C2[0][$C] Then $AusgabeText=$AusgabeText & $C2[1][$C] & "%, " & $C2[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Cis2[0][$C] Then $AusgabeText=$AusgabeText & $Cis2[1][$C] & "%, " & $Cis2[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf
- 63 -
If $MelodieText[$m] = $D2[0][$C] Then $AusgabeText=$AusgabeText & $D2[1][$C] & "%, " & $D2[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Dis2[0][$C] Then $AusgabeText=$AusgabeText & $Dis2[1][$C] & "%, " & $Dis2[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $E2[0][$C] Then $AusgabeText=$AusgabeText & $E2[1][$C] & "%, " & $E2[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $F2[0][$C] Then $AusgabeText=$AusgabeText & $F2[1][$C] & "%, " & $F2[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Fis2[0][$C] Then $AusgabeText=$AusgabeText & $Fis2[1][$C] & "%, " & $Fis2[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $G2[0][$C] Then $AusgabeText=$AusgabeText & $G2[1][$C] & "%, " & $G2[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Gis2[0][$C] Then $AusgabeText=$AusgabeText & $Gis2[1][$C] & "%, " & $Gis2[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $A2[0][$C] Then $AusgabeText=$AusgabeText & $A2[1][$C] & "%, " & $A2[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Ais2[0][$C] Then $AusgabeText=$AusgabeText & $Ais2[1][$C] & "%, " & $Ais2[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $B2[0][$C] Then $AusgabeText=$AusgabeText & $B2[1][$C] & "%, " & $B2[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $H2[0][$C] Then $AusgabeText=$AusgabeText & $H2[1][$C] & "%, " & $H2[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $C3[0][$C] Then $AusgabeText=$AusgabeText & $C3[1][$C] & "%, " & $C3[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Cis3[0][$C] Then $AusgabeText=$AusgabeText & $Cis3[1][$C] & "%, " & $Cis3[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $D3[0][$C] Then $AusgabeText=$AusgabeText & $D3[1][$C] & "%, " & $D3[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Dis3[0][$C] Then $AusgabeText=$AusgabeText & $Dis3[1][$C] & "%, " & $Dis3[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $E3[0][$C] Then $AusgabeText=$AusgabeText & $E3[1][$C] & "%, " & $E3[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $F3[0][$C] Then $AusgabeText=$AusgabeText & $F3[1][$C] & "%, " & $F3[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Fis3[0][$C] Then $AusgabeText=$AusgabeText & $Fis3[1][$C] & "%, " & $Fis3[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $G3[0][$C] Then $AusgabeText=$AusgabeText & $G3[1][$C] & "%, " & $G3[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Gis3[0][$C] Then
- 64 -
$AusgabeText=$AusgabeText & $Gis3[1][$C] & "%, " & $Gis3[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $A3[0][$C] Then $AusgabeText=$AusgabeText & $A3[1][$C] & "%, " & $A3[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $Ais3[0][$C] Then $AusgabeText=$AusgabeText & $Ais3[1][$C] & "%, " & $Ais3[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $B3[0][$C] Then $AusgabeText=$AusgabeText & $B3[1][$C] & "%, " & $B3[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $H3[0][$C] Then $AusgabeText=$AusgabeText & $H3[1][$C] & "%, " & $H3[1][0] & "%, " $Zaehler=$Zaehler+1 EndIf If $MelodieText[$m] = $P[0][$C] Then $AusgabeText=$AusgabeText & $P[1][0] & "%, " & $P[1][$C] & "%, " $Zaehler=$Zaehler+1 EndIf Next Next $PrgCode = "For I = 0 To " & $Zaehler*2-1 & Chr(13) & Chr(10) & " Note = Lookup(I, " & GUICtrlRead($MelodieName) & ")" & Chr(13) & Chr(10) $PrgCode = $PrgCode & " Incr I" & Chr(13) & Chr(10) $PrgCode = $PrgCode & " If Note = 0 Then" & Chr(13) & Chr(10) & " Pause = Lookup(I ," & GUICtrlRead($MelodieName) & ")" & Chr(13) & Chr(10) $PrgCode = $PrgCode & " Waitms Pause" & Chr(13) & Chr(10) & " Else" & Chr(13) & Chr(10) $PrgCode = $PrgCode & " Laenge = Lookup(I, " & GUICtrlRead($MelodieName) & ")" & Chr(13) & Chr(10) $PrgCode = $PrgCode & " Sound Speaker , Note , Laenge " & Chr(13) & Chr(10) & " End If" & Chr(13) & Chr(10) & "Next I" & Chr(13) & Chr(10) & Chr(13) & Chr(10) $PrgCode = $PrgCode & GUICtrlRead($MelodieName) & ":" & Chr(13) & Chr(10) & "Data " $AusgabeText = StringTrimRight ($AusgabeText,2) GUICtrlSetData($Ausgabe,$PrgCode & $AusgabeText) Case $DelAll $AusgabeText="" GUICtrlSetData($Ausgabe, "") GUICtrlSetData($Eingabe, "") EndSwitch WEnd Func weekday2number (ByRef $Weekday) if $Weekday = "Montag" then $Weekdayn=1 if $Weekday = "Dienstag" then $Weekdayn=2 if $Weekday = "Mittwoch" then $Weekdayn=3 if $Weekday = "Donnerstag" then $Weekdayn=4 if $Weekday = "Freitag" then $Weekdayn=5 if $Weekday = "Samstag" then $Weekdayn=6 if $Weekday = "Sonnabend" then $Weekdayn=6 if $Weekday = "Sonntag" then $Weekdayn=7 Return $Weekdayn Endfunc Func SecOfday (ByRef $Ttime) $SecOfDay=Number(StringLeft($Ttime,2))*60*60+Number(StringMid ($Ttime,4,2))*60+Number(StringMid ($Ttime,7,2)) Return $SecOfDay EndFunc Func Ostern (Byref $Jahr) ;Ostern Wikipedia nach Lichtenberg $K = $Jahr / 100 $M = Int(15 + (3*$K + 3) / 4 - (8*$K + 13) / 25) $S = Int(2 - (3*$K + 3) / 4) $A = Mod($Jahr, 19) $D = Mod((19*$A + $M), 30)
- 65 -
$R = Int(($D + $A / 11) / 29) $OG = 21 + $D - $R $SZ = 7 - Mod(Int(($Jahr + $Jahr / 4 + $S)), 7) $OE = 7 - Mod(($OG - $SZ), 7) $OS = $OG + $OE If $OS > 31 then $OS=$OS -31 $Monat="04" Else $Monat="03" EndIf $OS=StringFormat("%02s",$OS) $Osterdatum = $OS &"."& $Monat& "." & $Jahr Return $Osterdatum EndFunc ; aus IsItDark von JustinTime Func SunTimes ($day, $isdst)Dim $day, $n, $i, $w, $m, $l, $e, $e1, $a, $xv, $yv, $v, $xs, $ys, $xe, $ecl, $lonsun, $ye, $ze, $ra, $dec, $h, $r, $E1Dim $GMST0, $UT_Sun_in_south, $LHA, $hour_rise, $hour_set, $min_rise, $min_set
; Orbital elements of the Sun: $N = 0.0 $i = 0.0 $w = 282.9404 + 0.0000470935 * $day $a = 1.000000 $e = 0.016709 - 0.000000001151 * $day $M = 356.0470 + 0.9856002585 * $day $M = rev($M) $ecl = 23.4393 - 0.0000003563 * $day $L = $w + $M if ($L < 0 OR $L > 360) then $L = rev($L) Endif; position of the Sun $E1 = $M + $e*(180/$pi) * sind($M) * ( 1.0 + $e * cosd($M) ) $xv = cosd($E1) - $e $yv = sqrt(1.0 - $e * $e) * sind($E1) $v = atan2d($yv, $xv) $r = sqrt($xv * $xv + $yv * $yv) $lonsun = $v + $w if ($lonsun < 0 OR $lonsun > 360) then $lonsun = rev($lonsun) Endif $xs = $r * cosd($lonsun) $ys = $r * sind($lonsun) $xe = $xs $ye = $ys * cosd($ecl) $ze = $ys * sind($ecl) $RA = atan2d($ye, $xe) $Dec = atan2d($ze, (sqrt(($xe * $xe)+($ye * $ye)))) $h=-0.833 $GMST0 = $L + 180 if ($GMST0 < 0 OR $GMST0 > 360) then $GMST0 = rev($GMST0) Endif $UT_Sun_in_south = ( $RA - $GMST0 - $longitude ) / 15.0 if ($UT_Sun_in_south < 0) then $UT_Sun_in_south=$UT_Sun_in_south + 24 Endif $LHA= (sind($h) - (sind($latitude) * sind($Dec)))/(cosd($latitude) * cosd($Dec)) if ($LHA > -1 AND $LHA < 1) then $LHA=acosd($LHA)/15 else $SunTimes = "No sunrise;No sunset" return $suntimes
- 66 -
Endif $hour_rise=$UT_Sun_in_south - $LHA $hour_set=$UT_Sun_in_south + $LHA $min_rise=int(($hour_rise-int($hour_rise)) * 60) $min_set=int(($hour_set-int($hour_set)) * 60) $hour_rise=(int($hour_rise) + ($TZ + $isdst)) $hour_set=(int($hour_set) + ($TZ + $isdst)) if ($min_rise < 10) then $min_rise = StringRight("0000" & $min_rise, 2) Endif if ($min_set < 10) then $min_set = StringRight("0000" & $min_set, 2) Endif ;slightly modified the formatting of the following line format from original version. if $hour_rise < 10 then $null=0 else $null = "" EndIf $SunTimes = $null & $hour_rise & ":" & $min_rise & $hour_set & ":" & $min_set Return $SuntimesEndFunc ;Now all the Support FuncsFunc sind($qqq) $sind = sin(($qqq) * $DEGRAD) return $sindEndFuncFunc cosd($qqq) $cosd = cos(($qqq) * $DEGRAD) return $cosdEndFuncFunc tand($qqq) $tand = tan(($qqq) * $DEGRAD) return $tandEndFuncFunc atand($qqq) $atand = ($RADEG * atan($qqq)) return $atandEndFuncFunc asind($qqq) $asind = ($RADEG * asin($qqq)) return $asindEndFuncFunc acosd($qqq) $acosd = ($RADEG * acos_new($qqq)) return $acosdEndFuncFunc atan2d ($qqq, $qqq1) $atan2d = ($RADEG * atan2($qqq, $qqq1)) return $atan2dEndFuncFunc rev($qqq) Dim $x $x = ($qqq - int($qqq/360.0) * 360.0) if ($x <= 0) then $x = $x + 360 Endif $rev = $xreturn $revEndFuncFunc atan2($ys,$xs); from the Draw Arrows tip; @ http://www.devx.com/upload/free/features/VBPJ/techtips/techtips11.pdf; by —Jim Deutch, Syracuse, New York
- 67 -
Dim $theta If $xs <> 0 Then $theta = Atan($ys / $xs) If $xs < 0 Then $theta = $theta + $pi Endif Else If $ys < 0 Then $theta = 3 * $pi / 2 ;90 Else $theta = $pi / 2 ;270 Endif Endif $atan2 = $thetareturn $atan2EndFuncFunc acos_new($x) $acos_new = Atan(-$X / Sqrt(-$X * $X + 1)) + 2 * Atan(1) return $acos_newEndFunc
- 68 -