;V-1 ;Compileren met Crownhill Proton+ PIC Basic compiler. ;Ontvangt DCF77 data van een standaard DCF module en geeft datum/tijd weer op een 16x2 LCD. ;Het is belangrijk dat de DCF77 ontvangst optimaal is. ;Voor DCF77 info, schema en bediening: www.picbasic.nl ; PIC16F628A: +--v--+ ; Een puls per seconde <[ ]> Puls voor gong ; Hoog = zomerijd, laag = wintertijd <[ ] ; [ ] ; [ ]> Freq. 10kHz voor hogere voltage SAB0600 ; GND [ ] +5V ; DCF77 module signaal >[ ]> DB7 LCD ;Verbonden met GND = Geen halfuur gong >[ ]> DB6 LCD ; LCD EN <[ ]> DB5 LCD ; LCD RS <[ ]> DB4 LCD ; +-----+ ;There is an English version too / Er is ook een Engelse versie ;www.picbasic.nl / Frits Kieftenbelt, Raalte, Netherlands (Frizie) DEVICE = 16F628A CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF ;Interne RC-oscillator ALL_DIGITAL TRUE ;Normale aliases (constanten) SYMBOL Karakter = 255 ;Maximaal 255: 255 is de ASCII code voor een blokje op de LCD tijdsbalk SYMBOL LCD_Char = 16 ;Minimaal 16: Aantal karakters per regel (afhankelijk van het gebruikte LCD type) SYMBOL MaxVindTijd = 61 ;Minimaal 61: (Sec) Tijd om seconde 00 te vinden SYMBOL OpStartTijd = 45000 ;Maximaal 65535: (mSec) 45 seconden opstart tijd voor de DCF77 module na power-on SYMBOL PulsLengte = 30 ;Maximaal 400: (mSec) Pulslengte voor iedere seconde op een uitgangspin ;Logische aliases (constanten) SYMBOL AAN = 0 ;Omgekeerd ON SYMBOL FALSE = 0 SYMBOL OFF = 0 SYMBOL ON = 1 SYMBOL TRUE = 1 SYMBOL UIT = 1 ;Omgekeerd OFF ;Poort aliases SYMBOL Gong = PORTA.1 ;Elk heel en half uur komt hier een puls voor aansturing gong SYMBOL SecondePuls = PORTA.2 ;Iedere seconde een korte puls (Pulslengte afhankelijk van constante 'PulsLengte') SYMBOL Zomertijd = PORTA.3 ;Hoog als het zomertijd is SYMBOL VoltageUp = PORTA.6 ;Levert een 10kHz frequentie voor spanningsverhoger voor de SAB0600, die op 7...11V werkt SYMBOL DCF_Signaal = PORTB.0 ;Ingang voor de DCF77 module (ontvanger) signaal (bv. Conrad BN641138) SYMBOL GongHalf = PORTB.1 ;Ingang open laten, elk half uur een gong / ingang verbonden met GND, alleen elk heel uur een gong ; 76543210 TRISA = %10110001 TRISB = %11111111 PORTB_PULLUPS ON ;Pull-up voor o.a. DCF77 ontvanger ;WORD DIM SignaalCheck AS WORD DIM Teller AS WORD ;BYTE DIM AlgemeneTeller AS BYTE DIM BitAantal AS BYTE DIM CursorPos AS BYTE ;Cursor x-positie op de LCD DIM Dag AS BYTE DIM Jaar AS BYTE DIM Maand AS BYTE DIM Minuut AS BYTE DIM OntvangByte AS BYTE DIM Seconde AS BYTE DIM Uur AS BYTE DIM WeekDag AS BYTE DIM BD1 AS BYTE ;Byte Dummy 1 ;BIT DIM Initialiseren AS BIT ;TRUE bij initialiseren DIM OntvangBit AS BIT DIM Signaal AS BIT ;TRUE als er een signaal is (gevonden) DIM ID1 AS BIT ;Bit Dummy 1 CLEAR DELAYMS 200 ;LCD stabilisering CLS PRINT "Signaal zoeken" Initialiseren = TRUE GOTO HoofdLus ;Spring over de subroutines ;SUBROUTINES OntvangBitAantal: ;Vul het ontvangstbyte met het opgegeven aantal bits in BCD mode CLEAR OntvangByte FOR BD1 = 0 TO BitAantal - 1 GOSUB OntvangEenBit IF OntvangBit = 1 THEN SETBIT OntvangByte, BD1 NEXT OntvangByte = ((OntvangByte >> 4) * 10) + (OntvangByte & 15) ;BCD (Binary-Coded Decimal) naar byte conversie RETURN OntvangEenBit: ;Ontvang een bit en bewaar dit in OntvangBit CLEAR Teller WHILE DCF_Signaal = AAN DELAYMS 1 INC Teller IF Teller > 3000 THEN ErrorOntvangst WEND DELAYMS 155 ;135 - 175msec OntvangBit = DCF_Signaal IF Initialiseren = TRUE THEN CursorPos = Seconde / ((60 / LCD_Char) + 1);Bereken waar de cursor moet staan (afhankelijk van de wachttijd en LCD type) PRINT AT 2, CursorPos , Karakter ;Maak tijdsbalk actueel ELSE CursorPos = LCD_Char - 1 ;Bereken waar de cursor moet staan (afhankelijk van LCD type) PRINT AT 1, CursorPos, DEC2 Seconde ;Zet de seconden op het LCD ENDIF INC Seconde ;Omdat we toch elke seconde in deze routine zijn, gebruiken we het ook om de seconden te tellen SecondePuls = ON ;Uitgangssignaal seconde puls DELAYMS PulsLengte ;(De constante PulsLengte mag een maximale waarde hebben van 400 (mSec)) SecondePuls = OFF RETURN ;HOOFDPROGRAMMA HoofdLus: CLEAR AlgemeneTeller Seconde = 00 ;Start met de eerste seconde Signaal = FALSE WHILE Signaal = FALSE ;Wacht tot het DCF signaal hoog is CLEAR Teller WHILE DCF_Signaal = UIT INC Teller DELAYMS 1 IF Teller > OpStartTijd THEN ErrorOntvangst ;Opstart tijd voor de DCF77 ontvanger bij power-on WEND CLEAR Teller WHILE DCF_Signaal = AAN ;Meet de tijd tussen de pulsen INC Teller DELAYMS 10 IF Initialiseren = FALSE THEN SELECT CASE Teller CASE 100 - (PulsLengte / 10) PRINT AT 1, 15, "59";xx:xx:59, zet de niet uitgezonden seconde '59' op het LCD SecondePuls = ON CASE 100 SecondePuls = OFF CASE 250 GOTO ErrorOntvangst;Signaal is niet binnen de tijd van niveau veranderd ENDSELECT ELSE IF Teller > (OpStartTijd / 10) THEN ErrorOntvangst ;Opstart tijd voor de DCF77 ontvanger bij power-on ENDIF WEND IF AlgemeneTeller >= MaxVindTijd THEN ErrorOntvangst ;Als er meer dan 'MaxVindTijd' seconden zijn geteld dan hebben we een probleem INC AlgemeneTeller IF Teller > 100 THEN Signaal = TRUE ;We tellen per 10mSec, dus we hebben minstens 100x10mSec nodig om het begin te vinden IF Initialiseren = TRUE THEN CursorPos = AlgemeneTeller / ((MaxVindTijd / LCD_Char) + 1) ;Bereken waar de cursor moet staan (afhankelijk van de wachttijd en LCD type) PRINT AT 1, 1, "Signaal gevonden" PRINT AT 2, CursorPos , Karakter ;Zet blok karakters op het LCD tijdens wachten op het init signaal ENDIF WEND IF Initialiseren = TRUE THEN CLS PRINT "Initialiseren..." PRINT AT 2, 1, REP "_" \ (LCD_Char - 2) ;Teken een dunne lijn die aangeeft hoe lang de tijdsbalk wordt ELSE CursorPos = LCD_Char - 7 ;X-positie van tijd op het LCD CURSOR 1, CursorPos IF Uur < 10 THEN PRINT " " ;Wis de eerste nul (08:00:00 --> 8:00:00) (Nul onderdrukking) PRINT DEC Uur, ":", DEC2 Minuut, ":00" ;Zet elke minuut de actuele tijd op het LCD IF Minuut = 00 THEN GongSignaal ;Elk heel uur een gong signaal IF Minuut = 30 AND GongHalf = ON THEN GongSignaal ;Ook elk halfuur een gong signaal als ingangspin GongHalf hoog is (opengelaten is) ENDIF IF Signaal = TRUE THEN ;Startbit succesvol ontvangen, start met het vullen van data FOR BD1 = 0 TO 14 ;0...14: de eerste 15 bits zijn gereserveerd (info zie www.picbasic.nl --> DCF77 info) GOSUB OntvangEenBit NEXT Verder: ;Als de gong klinkt, worden bits 0 t/m 14 genegeerd, na de gong, wordt hier verder gegaan GOSUB OntvangEenBit ;15: Welke zend antenne is gebruikt? ; IF OntvangBit = 0 THEN... ;Signaal is verzonden door de standaard antenne, dit bit wordt niet gebruikt in dit programma ; IF OntvangBit = 1 THEN... ;Signaal is verzonden door een reserve antenne, dit bit wordt niet gebruikt in dit programma GOSUB OntvangEenBit ;16: Omschakeling naar summer/winter volgend uur? ; IF OntvangBit = 1 THEN... ;Dit bit wordt niet gebruikt in dit programma GOSUB OntvangEenBit ;17: Zomer- of wintertijd? IF OntvangBit = 1 THEN Zomertijd = ON ;Zomer ELSE Zomertijd = OFF ;Winter ENDIF FOR BD1 = 18 TO 19 ;18...19: Deze bits worden niet gebruikt (Time Zone bit 2 en schrikkel-seconde bit) GOSUB OntvangEenBit NEXT GOSUB OntvangEenBit ;20: Startbit, normaal altijd 1, dit bit wordt niet gebruikt in dit programma ; IF OntvangBit = 0 THEN... ;Dit bit wordt niet gebruikt in dit programma BitAantal = 7 ;21...27: Ontvang minuut (7 bits) GOSUB OntvangBitAantal Minuut = OntvangByte GOSUB OntvangEenBit ;28: Pariteitsbit 1, dit bit wordt niet gebruikt in dit programma BitAantal = 6 ;29...34: Ontvang uur (6 bits) GOSUB OntvangBitAantal Uur = OntvangByte GOSUB OntvangEenBit ;35: Pariteitsbit 2, dit bit wordt niet gebruikt in dit programma BitAantal = 6 ;36...41: Ontvang dag (6 bits) GOSUB OntvangBitAantal Dag = OntvangByte BitAantal = 3 ;42...44: Ontvang weekdag (3 bits) GOSUB OntvangBitAantal WeekDag = OntvangByte BitAantal = 5 ;45...49: Ontvang maand (5 bits) GOSUB OntvangBitAantal Maand = OntvangByte BitAantal = 8 ;50...57: Ontvang jaar (8 bits) GOSUB OntvangBitAantal Jaar = OntvangByte GOSUB OntvangEenBit ;58: Pariteitsbit 3, dit bit wordt niet gebruikt in dit programma IF Initialiseren = TRUE THEN Initialiseren = FALSE ;Klaar met initialiseren CLS ENDIF PRINT AT 1, 1, REP " " \ LCD_Char - 8 ;Wis de dag op het LCD PRINT AT 2, 1, REP " " \ LCD_Char ;Wis de hele tweede lijn CURSOR 1, 1 SELECT CASE WeekDag CASE 1: PRINT "Ma" CASE 2: PRINT "Di" CASE 3: PRINT "Wo" CASE 4: PRINT "Do" CASE 5: PRINT "Vr" CASE 6: PRINT "Za" CASE 7: PRINT "Zo" ENDSELECT PRINT AT 2, 1, DEC Dag, " " SELECT CASE Maand CASE 1: PRINT "Januari" CASE 2: PRINT "Februari" CASE 3: PRINT "Maart" CASE 4: PRINT "April" CASE 5: PRINT "Mei" CASE 6: PRINT "Juni" CASE 7: PRINT "Juli" CASE 8: PRINT "Augustus" CASE 9: PRINT "September" CASE 10: PRINT "Oktober" CASE 11: PRINT "November" CASE 12: PRINT "December" END SELECT PRINT " '", DEC2 Jaar ELSE ;Else 'Signaal' = FALSE, geen signaal gevonden GOTO ErrorOntvangst ENDIF GOTO HoofdLus GongSignaal: CursorPos = LCD_Char - 1 ;Afhankelijk van het LCD-type, bereken de cursor positie voor de seconden, tijdens het afgaan van de gong Gong = ON ;Gong pin hoog FOR Seconde = 0 TO 14 SOUND VoltageUp, [127, 20] ;Het sound IC SAB0600 heeft een voeding van 7...11V nodig, hier maken we een frequentie van 10kHz (charge pump) PRINT AT 1, CursorPos, DEC2 Seconde ;Tegelijkertijd tellen de seconden gewoon verder SecondePuls = ON ;Ondertussen gaat ook de seconde puls gewoon door SOUND VoltageUp, [127, PulsLengte / 12] ;Met behulp van de instructie SOUND, wordt een 10kHz signaal opgewekt Gong = OFF ;Gong pin laag SecondePuls = OFF SOUND VoltageUp, [127, 60 - (PulsLengte / 12)] NEXT GOTO Verder ;Ga verder met het lezen van de DCF77 bits vanaf bit 15 (We slaan de DCF77 bits 0...14 over) ErrorOntvangst: CLS PRINT "Geen signaal" ;Startbit niet gevonden of geen signaal? REPEAT CLEAR ;Wis alle RAM ID1 = DCF_Signaal WHILE DCF_Signaal = ID1 ;Wacht op signaal verandering INC SignaalCheck DELAYMS 1 WEND ID1 = ID1 ^ 1 WHILE DCF_Signaal = ID1 ;Wacht op signaal verandering INC SignaalCheck DELAYMS 1 WEND UNTIL SignaalCheck < 990 Initialiseren = TRUE ;Na een error moet er weer worden geinitialiseerd GOTO HoofdLus