PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : CCPRO M128: DCF Clock 1 (CCPRO BASIC)



Dirk
13.06.2009, 16:49
Hallo Leute,

nach meinem 1. DCF-Decoder mit Softclock hier:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=48432
... und hier:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=48434
... jetzt eine ZWEITE Version in CCPRO BASIC, die keine eigene Softclock (mit den Variablen Sekunde, Minute, Stunde usw.) mehr hat (so wie in der mitgelieferten DCF_Lib.cc).
Stattdessen nutzt dieser DCF-Decoder die interne Clock des CCPRO-Betriebssystems, die mit den Befehlen Clock_GetVal(), Clock_SetTime() usw. gelesen oder gestellt werden kann.

Viel Spaß damit!

Demoprogramm (RP6_DCFClock.cbas):

/************************************************** *****************************
* RP6 C-Control PRO M128 Erweiterungsmodul
* ----------------------------------------------------------------------------
* RP6_DCFClock Testprogramm 1 - CCPRO BASIC
* ----------------------------------------------------------------------------
* RP6_DCFClock: DCF Uhr
* DCF Empfänger erforderlich
* Mega128: DCF-Eingang PE5 (PortE.5, RP6: INT1)
* Der DCF-Eingang kann in RP6DCFClockCClib.cbas geändert werden.
* erforderliche Library: IntFunc_Lib.cc und neue
* RP6DCFClockCClib.cbas (v. 1.xx).
*
* Über den zusätzlich erforderlichen DCF Empfänger (Art-Nr. 641138) wird
* das DCF Signal empfangen.
* Auf dem LCD-Display werden die Zeit und das Datum der internen Clock
* (Anleitung Abschnitt 6.5 Clock), die so oft wie möglich mit den DCF
* Informationen gestellt wird, angezeigt.
* Die LED1 blinkt im Sekundentakt.
*
* ************************************************** ***************************
* Der Roboter bewegt sich in diesem Beispielprogramm NICHT und kann
* am Rechner angeschlossen bleiben!
************************************************** ****************************/

' WICHTIG: Immer die RP6CCLib mit einbinden:
#include "../../RP6CCLib/RP6CCLib.cbas"

' Die neue RP6DCFClockCCLib einbinden:
#include "../../RP6CCLib/RP6DCFClockCClib.cbas"

Dim irqcnt As Integer ' globale Variablendeklaration
Dim cnt1, alte_sekunde As Byte

Sub main()
' WICHTIG! Immer als erstes aufrufen:
RP6_CCPRO_Init() ' Auf Startsignal warten, LCD und andere Dinge initialisieren !

' ------------------------------------------------------

' Zwei Zeilen Text mit dem LCD anzeigen:
showScreenLCD("RP6 CCPRO M128", "RP6 DCF Clock 1")

' Zweimal piepsen:
beep(200, 300, 100) ' Format: beep (<tonhöhe>, <dauer>, <pause>)
beep(100, 100, 100)

' Text über serielle Schnittstelle ausgeben:
newline() ' Neue Zeile
println(" ________________________")
println(" \\| RP6 ROBOT SYSTEM |/")
println(" \\_-_-_-_-_-_-_-_-_-_/ ")
newline()
println(" Let's go! ")
newline()

' 2 Sekunden Pause:
AbsDelay(2000)

' ------------------------------------------------------
' DCF-Hauptprogramm:

Port_WriteBit(PORT_LED1, PORT_OFF) ' LED1 aus
clearLCD() ' Display löschen

Time_Init() ' Funktionsaufruf zur Festlegung
' von Startzeit und Startdatum.

initDCF() ' Initialisierung des DCF Modus

Irq_SetVect(INT_TIM2COMP, INT_10ms) ' ISR definieren
' Timer2: 10ms Interrupt
Do While True ' Endlosschleife
If cnt1 = 50 Then
Port_WriteBit(PORT_LED1, PORT_OFF) ' LED1 aus
End If

If cnt1 = 100 Then ' Sekundentakt
Port_WriteBit(PORT_LED1, PORT_ON) ' LED1 an
cnt1 = 0
End If
If alte_sekunde <> Clock_GetVal(CLOCK_SEC) Then
alte_sekunde = Clock_GetVal(CLOCK_SEC)
#ifndef DEBUG
showCLOCK()
' showSTATUS()
#endif
#ifdef DEBUG
showDEBUGINFO()
#endif
End If
End While
End Sub

' -----------------------------------------------------------------------------
' Festlegung von Startzeit und Startdatum
'
Sub Time_Init()
Clock_SetTime(12, 0, 0, CLOCK_CORR) ' Uhr Startzeit: 12:00:00
' (CLOCK_CORR ist in der RP6DCFClockCClib definiert!)
Clock_SetDate(30, 4, 9) ' Uhr Startdatum: 31.05.2009
' (Tag und Monat sind nullbasiert!)
End Sub

' -----------------------------------------------------------------------------
' Interrupt Routine
'
Sub INT_10ms()
cnt1 = cnt1 + 1 ' Zähler für Blinken der LED1

decodeDCF() ' DCF77 Decoder

irqcnt = Irq_GetCount(INT_TIM2COMP) ' Interrupt Request Counter
End Sub

' -----------------------------------------------------------------------------

Bibliothek (RP6DCFClockCClib.cbas), Teil 1:

/* ************************************************** **************************
* _______________________
* \| RP6 ROBOT SYSTEM |/
* \_-_-_-_-_-_-_-_-_-_/ >>> CCPRO M128
* ----------------------------------------------------------------------------
* ----------------------- [c]2009 - Dirk -------------------------------------
* ************************************************** **************************
* File: RP6DCFClockCClib.cbas
* Version: 1.0 - CCPRO BASIC
* Target: RP6 CCPRO M128 - C-Control PRO M128 @14.7456MHz
* mit optionalem LC-Display 16x2 Zeichen (CONRAD 190911)
* [oder OLED Textdisplay 16x2 Zeichen (CONRAD 197622)]
* und einem DCF77 Empfänger Modul (z.B. CONRAD 641138)
* Author(s): Dirk
* ************************************************** **************************
* Beschreibung:
* Dies ist meine DCF77 Bibliothek für die RP6 CCPRO M128, die mit der
* internen Clock (Anleitung Abschnitt 6.5 Clock) zusammen arbeitet.
* Der DCF-Empfänger wird an PE5 (XBUS INT1, SPI_I/O: Pin 7) der CCPRO M128
* angeschlossen.
*
* ANMERKUNG: Ein 10kOhm Pulldown-Widerstand (R34) ist auf dem RP6 Mainboard
* mit E_INT1 verbunden und damit auch mit INT1 auf der CCPRO M128.
* Normalerweise haben DCF Empfänger einen open-collector Ausgang
* und benötigen einen PULLUP Widerstand zur korrekten Funktion.
* Der interne Pullup-Widerstand des ATMEGA128 kann den Pulldown-
* Widerstand auf dem RP6 Mainboard nicht kompensieren.
* Deshalb muss man einen PULLUP-Widerstand zwischen +5V und den
* DCF Empfängerausgang legen. Bei meinem DCF Empfänger klappt es
* gut mit einem 2,2kOhm Widerstand.
*
* ************************************************** **************************
* CHANGELOG FINDEN SIE AM ENDE DIESER DATEI!
* ************************************************** **************************
*/

' Alles nur EINMAL einbinden!
#ifndef __RP6DCFCLOCKCCLIB__
#define __RP6DCFCLOCKCCLIB__


/************************************************** ****************************/
' Defines:

' RP6 CCPRO M128 DCF Empfänger Anschluß:
#define DCF_IN 37 ' DCF Eingangs Signal an PortE.5 (RP6: INT1)
' #define DCF_IN 13 ' DCF Eingangs Signal an PortB.5 (SERVO_1 PB5)

#define BIT_0 0x00 ' 0b00000000
#define BIT_1 0x80 ' 0b10000000
#define LETZTESBIT_0 0x40 ' 0b01000000
#define LETZTESBIT_1 0xc0 ' 0b11000000
#define BIT_FEHLER 0x01 ' 0b00000001

/************************************************** ************/
' AUFBAU DES DCF77 TELEGRAMMS:
' Bit 0: DCF Bit 0 (immer 0)
' Bits 1..14: Codierte Wetter Infos (Meteo Time GmbH)
' Bits 15..20 (DCF Flags):
' Flag R: Ruf Bit 15 für PTB Angestellte
' Flag A1: Ankündigung eines Zeitzonenwechsels
' Flag Z1: Zeitzone 1 [0 = MEZ, 1 = MESZ] (Z1 <> Z2)
' Flag Z2: Zeitzone 2 [1 = MEZ, 0 = MESZ] (Z2 <> Z1)
' Flag A2: Ankündigung einer Schaltsekunde
' Flag S: Start Bit 20 (immer 1)
' Bits 21..27: Minute (BCD)
' Bit 28 [P1]: Minutenparität
' Bits 29..34: Stunde (BCD)
' Bit 35 [P2]: Stundenparität
' Bits 36..41: Tag (BCD)
' Bits 42..44: Wochentag
' Bits 45..49: Monat (BCD)
' Bits 50..57: Jahr (BCD)
' Bit 58 [P3]: Datumsparität
' [Bit 59: Schaltsekundenbit (immer 0)]
/************************************************** ************/

' #define DEBUG ' Debug Modus
' Der Debug Modus dient zum Abgleich der Pausenlängen (PAUSE_xxxMS).
' Das LCD zeigt die vom Decoder erkannten Pausenlängen an. Wenn es
' eine deutliche Abweichung gibt, können die Pausenlängen angepaßt
' werden.

' #define REPARATUR ' Reparatur Modus
' Im Reparatur Modus wird in dieser Programm Version nur eine Er-
' kennung von Spikes ermöglicht. Damit sinkt die Störanfälligkeit.
' In weiteren Programmversionen kann hier ggf. noch eine "echte"
' Reparatur von fehlerhaften DCF Telegrammen erfolgen.

' #define WETTER ' Wetter Infos decodieren
' Wenn man die in den DCF Bits 1..14 enthaltenen Wetter Informationen
' einsehen möchte, muss man das Programm mit definiertem "WETTER"
' kompilieren. Da die Infos verschlüsselt sind, wird man in der Regel
' diese Bits nicht sinnvoll verwenden können.

' Korrekturfaktor für die Clock:
#define CLOCK_CORR 0 ' Siehe Anleitung Abschnitt 6.5 Clock!

#define PAUSE_800MS 80 ' Bit 1 Pausenlänge
#define PAUSE_900MS 90 ' Bit 0 Pausenlänge
#define PAUSE_1800MS 180 ' Letztes Bit 1 Pausenlänge
#define PAUSE_1900MS 190 ' Letztes Bit 0 Pausenlänge
#define PAUSE_ABWEICHUNG 5 ' Pausenlänge Abweichung
' Das DCF77 Telegramm wird in einer ganzen Minute für die Folgeminute
' übertragen. In jeder Sekunde wird ein DCF Bit codiert. Senderseitig
' wird dazu die Sendeleistung 100ms lang für ein 0-Bit oder 200ms lang
' für ein 1-Bit auf 25% abgesenkt. Danach ist für den Rest der Sekunde
' (900ms bzw. 800ms) Pause, also 100% Sendeleistung. Für einen DCF De-
' coder ist das Ende des Telegramms dadurch erkennbar, dass das letzte
' Bit (DCF Bit 58) eine Pause von 1900ms bzw. 1800ms besitzt. Damit
' können die o.g. 4 Pausendauern (PAUSE_XXXMS) unterschieden werden.
' Da der DCF Decoder alle 10ms aufgerufen wird, wird er etwa 80-mal den
' selben Pegel am Eingang feststellen, wenn die Pause nach einem 1-Bit
' gesendet wird.
' Durch "PAUSE_ABWEICHUNG" wird festgelegt, welche Abweichung vom Soll
' zugelassen wird. Beim Wert 5 erkennt der Decoder ein 1-Bit, wenn er
' zwischen 75- und 84-mal (= 750..840ms) den selben Pegel feststellt.

#define VALIDITAETSSTANDARD 1 ' Validitätszähler Grenze
' (1: Jedes DCF Telegramm nutzen!)
' Als INTAKT gilt ein Telegramm, wenn folgende Bedingungen erfüllt sind:
' 1. DCF Bit 0 ist 0
' 2. DCF Bits 17 und 18 sind ungleich
' 3. DCF Bit 20 ist 1
' 4. Die Paritätsbits 28, 35, 58 enthalten eine korrekte gerade Parität
' 5. Es wurden genau 58 DCF Bits decodiert
' 6. Fall Schaltsekunde: DCF Bit 59 ist 0 und DCF Bit 19 ist 1
' Nicht PLAUSIBEL ist ein Telegramm, wenn Werte außerhalb des möglichen
' Bereichs liegen. Ein Wert von 9 für den Wochentag ist z.B. nicht
' plausibel. Allgemeiner könnte man sagen, dass ein DCF Telegramm nicht
' plausibel ist, wenn es nicht die Folgeminute der aktuellen Minute ab-
' bildet.
' Ein Telegramm ist VALIDE (= gültig), wenn es intakt UND plausibel ist.
' Jedes valide DCF Telegramm wird gezählt. Ist VALIDITAETSSTANDARD 1,
' dann wird jedes valide Telegramm zum Stellen der Uhr verwendet. Man
' kann den Wert erhöhen, wenn man ein Stellen der Uhr nur bei sehr guten
' Empfangsbedingungen erlauben will. Setzt man VALIDITAETSSTANDARD z.B.
' auf 3, dann wird ein Telegramm nur dann zum Stellen der Uhr verwendet,
' wenn es das dritte valide Telegramm in Folge ist.

/************************************************** ****************************/
' Variablen:

Dim DCF_DOW As Byte ' Wochentag [1..7 = MO..SO]
Dim DCF_DST As Byte ' Zeitzone [0 / 1 = MEZ / MESZ]

#ifdef WETTER
Dim DCF_WEATHER As Word ' Codierte Wetter Informationen
#endif ' (DCF Bits 1..14; Bit 0 immer 0)

Dim dcfflags As Byte ' DCF Flags (DCF Bits 15..20):
#define FLAG_R 1 ' R: Ruf Bit 15 für PTB Angestellte
#define FLAG_A1 2 ' A1: Ankündigung eines Zeitzonenwechsels
#define FLAG_Z1 4 ' Z1: Zeitzone 1 [0 = MEZ, 1 = MESZ]
#define FLAG_Z2 8 ' Z2: Zeitzone 2 [1 = MEZ, 0 = MESZ]
#define FLAG_A2 16 ' A2: Ankündigung einer Schaltsekunde
#define FLAG_S 32 ' S: Start Bit 20 (immer 1)

Dim dcfstatus As Byte ' Status Flags (Bits 0..5 nur lesen!):
#define STATUS_FEHLER 1 ' Telegramm Fehler
#define STATUS_MINPARITAET 2 ' Minutenparität ok
#define STATUS_STDPARITAET 4 ' Stundenparität ok
#define STATUS_DATPARITAET 8 ' Datumsparität ok
#define STATUS_DCFBIT58 16 ' 58 (oder 59) DCF Bits decodiert
#define STATUS_TELEGRAMMINTAKT 32 ' Telegramm intakt
#define STATUS_UHRGESTELLT 64 ' Uhr einmal gestellt
#define STATUS_DCF_AN 128 ' DCF77 Decoder AN

Dim validitaetszaehler As Byte ' Zähler für intakte und
' plausible DCF Telegramme
Dim validitaetsgrenze As Byte ' Grenze Validitäts Zähler

#ifdef DEBUG
Dim pause_1_laenge As Byte
Dim pause_0_laenge As Byte
Dim letztepause_1_laenge As Byte
Dim letztepause_0_laenge As Byte
#endif

/************************************************** ****************************/
' Funktionen:

/**
* INIT DCF
*
* Unbedingt einmal aufrufen, bevor die DCF77 Funktion benutzt wird!
*
*/
Sub initDCF()
Port_DataDirBit(DCF_IN, 0) ' Port = Eingang
Port_WriteBit(DCF_IN, 1) ' Pullup Widerstand ein
validitaetszaehler = 0 ' Validitätszähler zurücksetzen
validitaetsgrenze = VALIDITAETSSTANDARD ' Grenze setzen
dcfstatus = STATUS_DCF_AN ' DCF77 Decoder AN
End Sub

/**
* DCF DECODER AN
*
* Der DCF77 Decoder wird eingeschaltet.
* Immer wenn ein intaktes DCF Telegramm decodiert wurde, kann die
* Uhr mit den aktuellen DCF Informationen gestellt werden.
*
*/
Sub DCFon()
dcfstatus = dcfstatus Or STATUS_DCF_AN ' Status Bit 7 setzen
End Sub

/**
* DCF DECODER AUS
*
* Der DCF77 Decoder wird ausgeschaltet.
* Die interne Uhr (Clock) läuft weiter.
*
*/
Sub DCFoff()
' Alle Status Bits löschen, nur Status Bit 6 bleibt unverändert:
dcfstatus = dcfstatus And STATUS_UHRGESTELLT
End Sub

/**
* BCD to DEC
*
* Diese Funktion wandelt einen BCD- in einen Dezimalwert um.
*
*/
Sub BCDtoDEC(bcd As Byte) As Byte
Return (bcd >> 4) * 10 + (bcd And 0x0f)
End Sub

Bibliothek Teil 2 folgt (einfach mit Copy/Paste anfügen)!

Gruß Dirk