Voor het basisstation hebben we ook een toetsen nodig. Je kunt natuurlijk ze rechtstreeks aan de pic koppelen, maar het kan ook via een chip. In mijn geval met de pcf8574. Het mooie van dit ic is dat het een interrupt uitgang heeft. Het uitlezen is heel makkelijk, Zodra er een toets is ingedrukt springen we naar de uitleesroutine en zetten de waarde op het scherm. Het grootste probleem is het instellen van de interrupts daarvoor moet je echt de datasheet van de pic lezen.
In dit geval heb ik 'on interrupt' gebruikt maar je zou de afhandeling ook na het sleep commando kunnen doen (nap 7). In het basisstation gaan we meerdere interrupts gebruiken. De toetsen op rb0, de ook ontvanger op rb1 en een timer interrupt voor het tonen van de tijd.
Device 18F4620
Xtal 20
ADCON1=7
LCD_DTPin PORTB.4
LCD_ENPin PORTB.3
LCD_RSPin PORTB.2
SCL_Pin = PORTC.3 ' i2c
SDA_Pin = PORTC.4
'portB rb0 input
TRISB = 000001
INTCON.4 = 1
INTCON2.6 = 0
INTCON2.7 = 0
Dim bus As Byte
Cls
DelayMS 100
On Interrupt GoTo keyin
' voor de zekerheid alle poorten hoog zetten.
BusOut $70,[255] 'adres voor pcf8574ap met a0,a1,a2 op 0
While 1=1
INTCON.1=0
nap 7
Wend
Disable
keyin:
BusIn $70,[bus]
DelayMS 50
Print At 1,1,Bin bus
Resume
Enable
End
Eenvoudige projecten voor de microchip microcontrollers geschreven in picbasic, proton+.
vrijdag 23 september 2011
donderdag 22 september 2011
DS1307 klok in combinatie met DCF77
In het basisstation wil ook graag een nauwkeurig klok het liefst met DCF77
Op het internet vind je verschillende beschrijvingen voor een DCF77 klok.
Ik ben hiermee aan het experimenteren gegaan met de bedoeling om een
DS1307 met de juiste tijd in te stellen. Ik ontvang twee keer een minuut van de dcf77
ontvanger zit hier een idd een minuut tussen dan zetten we de dcf77 tijd in de ds1307
en zijn we klaar. De tijd word alleen gezet als de ds1307 nog niet gestart is.
Wat er verder nog moet gebeuren is dat de tijd op een bepaald tijdstip op de dag
de ds1307 weer gesynchroniseerd word met de dcf77 ontvanger.
Device 18F4620
Xtal 20
ADCON1=7
LCD_DTPin PORTB.4 'lcd 16x2 op portb
LCD_ENPin PORTB.3
LCD_RSPin PORTB.2
'I2c op c.3 en c.4
SCL_Pin = PORTC.3 '
SDA_Pin = PORTC.4
Symbol ds1307 = %11010000 'adres ds1307
Symbol Dcfin = PORTC.0 'portc.0 dcf77 ontvanger ingang (positief)
Symbol Blok = 255
Dim SignaalCheck As Word
Dim Teller As Word
Dim Bittijdtel As Word
Dim Sec As Byte
Dim Minuut As Byte
Dim Uur As Byte
Dim Startbyte As Byte
Dim Ontvbyte As Byte
Dim Dag As Byte
Dim Week As Byte
Dim Maand As Byte
Dim Jaar As Byte
Dim I As Byte
Dim N As Byte
Dim Dcfmin As Byte
Dim Fout As Bit
Dim Ontvbit As Bit
Dim ParBit As Bit
Dim Loops As Bit
DelayMS 100 ' opstarttijd disp
BusIn ds1307,$00,[Sec] 'controleer of de klok loopt zo niet instellen met dcf77
If Sec.7=1 Then Call setklok
Cls
' tijd uitlezing met ds1307
main:
BusIn ds1307,0,[Sec,Minuut,Uur,Week,Dag,Maand,Jaar]
Print At 1,1,Hex2 Dag, "-", Hex2 Maand, "-", Hex2 Jaar
Print At 2,9,Hex2 Uur, ":", Hex2 Minuut, ":", Hex2 Sec
GoTo main
setklok:
Cls
Clear
Print At 1,1, "DCF77"
Print At 2,1, "Wacht op start"
GoSub Wachtopstartbit
'we hebben de startbit gevonden
init:
Print At 1,7, Rep " " \ 10
Print At 2,1,"Wacht op tijd "
Clear Sec
Clear ParBit
For I = 0 To 20 '0 TOT 20 OVERSLAAN
GoSub Eenbitontv
Next
N = 7
GoSub Bytesontv '21-27 MINUUT
Minuut = Ontvbyte
GoSub Eenbitontv '28 PARITY
If ParBit = 1 Then setklok
N = 6
GoSub Bytesontv '29-34 UUR
Uur = Ontvbyte
GoSub Eenbitontv '35 PARITY
If ParBit = 1 Then setklok
N = 6
GoSub Bytesontv '36-41 DAG
Dag = Ontvbyte
N = 3
GoSub Bytesontv '42-44 WEEK
Week = Ontvbyte
N = 5
GoSub Bytesontv '45-49 MAAND
Maand = Ontvbyte
N = 8
GoSub Bytesontv '50-57 JAAR
Jaar = Ontvbyte
GoSub Eenbitontv '58 PARITY
If ParBit = 1 Then setklok ' fout opgetreden
' we gaan twee keer de tijd binnenhalen en controleren of er een minuut
' verschil is. zo ja dan gaan we tijd in de ds1307 zetten.
' we nemen de overgang van 59 naar 0 voor lief
Select Case Loops
Case 0
Dcfmin = Minuut
Loops = 1
GoTo init
Case 1
If Dcfmin <> Minuut - 1 Then setklok
End Select
DelayMS 1000 ' 1 seconde wachten (sec59)
BusOut ds1307,$00,[0,Minuut,Uur,Week,Dag,Maand,Jaar]
Return
Wachtopstartbit:
' routine voor opstart tijd voor de DCF77 ontvanger bij power-on
Clear Teller
While Dcfin = 0
Inc Teller
DelayMS 1
If Teller > 50000 Then ErrorOntvangst
Wend
Clear Sec
Clear Startbyte
While Startbyte = 0
Clear Bittijdtel
Clear Teller
While Dcfin = 1
Inc Teller
DelayMS 1
If Teller > 5000 Then ErrorOntvangst ' meer dan 5 seconden een 1 dan error
Wend
While Dcfin = 0
Bittijdtel = Bittijdtel + 1
DelayMS 10
If Bittijdtel > 500 Then ErrorOntvangst ' meer dan 5 sec een 0 dan error
Wend
If Bittijdtel > 100 Then Startbyte = 1
Inc Sec
If Sec > 65 Then Clear Sec ' langer bezig dan 65 sec dan geen blokjes meer
Print At 1,7+(Sec/7),Blok
Wend
Return
Eenbitontv:
Clear Teller
Clear Bittijdtel
While Dcfin = 0
DelayMS 1
Inc Teller
If Teller > 3000 Then ErrorOntvangst
Wend
While Dcfin = 1
Bittijdtel = Bittijdtel + 1
DelayMS 10
Wend
If Bittijdtel > 16 Then
Ontvbit = 1
Else
Ontvbit = 0
EndIf
ParBit = ParBit + Ontvbit
Inc Sec
Print At 1,7+(Sec/6),Blok
Return
Bytesontv:
Clear Ontvbyte
For I = 0 To N - 1
GoSub Eenbitontv
If Ontvbit = 1 Then SetBit Ontvbyte, I
Next I
Return
ErrorOntvangst:
Print At 1,7, Rep " " \ 10
Print At 2,1, "Ontvangst slecht"
Repeat
Clear
Fout = Dcfin
While Dcfin = Fout ;Wacht op signaal verandering
Inc SignaalCheck
DelayMS 1
Wend
Fout = Fout ^ 1
While Dcfin = Fout ;Wacht op signaal verandering
Inc SignaalCheck
DelayMS 1
Wend
Until SignaalCheck < 500
GoTo setklok
Op het internet vind je verschillende beschrijvingen voor een DCF77 klok.
Ik ben hiermee aan het experimenteren gegaan met de bedoeling om een
DS1307 met de juiste tijd in te stellen. Ik ontvang twee keer een minuut van de dcf77
ontvanger zit hier een idd een minuut tussen dan zetten we de dcf77 tijd in de ds1307
en zijn we klaar. De tijd word alleen gezet als de ds1307 nog niet gestart is.
Wat er verder nog moet gebeuren is dat de tijd op een bepaald tijdstip op de dag
de ds1307 weer gesynchroniseerd word met de dcf77 ontvanger.
Device 18F4620
Xtal 20
ADCON1=7
LCD_DTPin PORTB.4 'lcd 16x2 op portb
LCD_ENPin PORTB.3
LCD_RSPin PORTB.2
'I2c op c.3 en c.4
SCL_Pin = PORTC.3 '
SDA_Pin = PORTC.4
Symbol ds1307 = %11010000 'adres ds1307
Symbol Dcfin = PORTC.0 'portc.0 dcf77 ontvanger ingang (positief)
Symbol Blok = 255
Dim SignaalCheck As Word
Dim Teller As Word
Dim Bittijdtel As Word
Dim Sec As Byte
Dim Minuut As Byte
Dim Uur As Byte
Dim Startbyte As Byte
Dim Ontvbyte As Byte
Dim Dag As Byte
Dim Week As Byte
Dim Maand As Byte
Dim Jaar As Byte
Dim I As Byte
Dim N As Byte
Dim Dcfmin As Byte
Dim Fout As Bit
Dim Ontvbit As Bit
Dim ParBit As Bit
Dim Loops As Bit
DelayMS 100 ' opstarttijd disp
BusIn ds1307,$00,[Sec] 'controleer of de klok loopt zo niet instellen met dcf77
If Sec.7=1 Then Call setklok
Cls
' tijd uitlezing met ds1307
main:
BusIn ds1307,0,[Sec,Minuut,Uur,Week,Dag,Maand,Jaar]
Print At 1,1,Hex2 Dag, "-", Hex2 Maand, "-", Hex2 Jaar
Print At 2,9,Hex2 Uur, ":", Hex2 Minuut, ":", Hex2 Sec
GoTo main
setklok:
Cls
Clear
Print At 1,1, "DCF77"
Print At 2,1, "Wacht op start"
GoSub Wachtopstartbit
'we hebben de startbit gevonden
init:
Print At 1,7, Rep " " \ 10
Print At 2,1,"Wacht op tijd "
Clear Sec
Clear ParBit
For I = 0 To 20 '0 TOT 20 OVERSLAAN
GoSub Eenbitontv
Next
N = 7
GoSub Bytesontv '21-27 MINUUT
Minuut = Ontvbyte
GoSub Eenbitontv '28 PARITY
If ParBit = 1 Then setklok
N = 6
GoSub Bytesontv '29-34 UUR
Uur = Ontvbyte
GoSub Eenbitontv '35 PARITY
If ParBit = 1 Then setklok
N = 6
GoSub Bytesontv '36-41 DAG
Dag = Ontvbyte
N = 3
GoSub Bytesontv '42-44 WEEK
Week = Ontvbyte
N = 5
GoSub Bytesontv '45-49 MAAND
Maand = Ontvbyte
N = 8
GoSub Bytesontv '50-57 JAAR
Jaar = Ontvbyte
GoSub Eenbitontv '58 PARITY
If ParBit = 1 Then setklok ' fout opgetreden
' we gaan twee keer de tijd binnenhalen en controleren of er een minuut
' verschil is. zo ja dan gaan we tijd in de ds1307 zetten.
' we nemen de overgang van 59 naar 0 voor lief
Select Case Loops
Case 0
Dcfmin = Minuut
Loops = 1
GoTo init
Case 1
If Dcfmin <> Minuut - 1 Then setklok
End Select
DelayMS 1000 ' 1 seconde wachten (sec59)
BusOut ds1307,$00,[0,Minuut,Uur,Week,Dag,Maand,Jaar]
Return
Wachtopstartbit:
' routine voor opstart tijd voor de DCF77 ontvanger bij power-on
Clear Teller
While Dcfin = 0
Inc Teller
DelayMS 1
If Teller > 50000 Then ErrorOntvangst
Wend
Clear Sec
Clear Startbyte
While Startbyte = 0
Clear Bittijdtel
Clear Teller
While Dcfin = 1
Inc Teller
DelayMS 1
If Teller > 5000 Then ErrorOntvangst ' meer dan 5 seconden een 1 dan error
Wend
While Dcfin = 0
Bittijdtel = Bittijdtel + 1
DelayMS 10
If Bittijdtel > 500 Then ErrorOntvangst ' meer dan 5 sec een 0 dan error
Wend
If Bittijdtel > 100 Then Startbyte = 1
Inc Sec
If Sec > 65 Then Clear Sec ' langer bezig dan 65 sec dan geen blokjes meer
Print At 1,7+(Sec/7),Blok
Wend
Return
Eenbitontv:
Clear Teller
Clear Bittijdtel
While Dcfin = 0
DelayMS 1
Inc Teller
If Teller > 3000 Then ErrorOntvangst
Wend
While Dcfin = 1
Bittijdtel = Bittijdtel + 1
DelayMS 10
Wend
If Bittijdtel > 16 Then
Ontvbit = 1
Else
Ontvbit = 0
EndIf
ParBit = ParBit + Ontvbit
Inc Sec
Print At 1,7+(Sec/6),Blok
Return
Bytesontv:
Clear Ontvbyte
For I = 0 To N - 1
GoSub Eenbitontv
If Ontvbit = 1 Then SetBit Ontvbyte, I
Next I
Return
ErrorOntvangst:
Print At 1,7, Rep " " \ 10
Print At 2,1, "Ontvangst slecht"
Repeat
Clear
Fout = Dcfin
While Dcfin = Fout ;Wacht op signaal verandering
Inc SignaalCheck
DelayMS 1
Wend
Fout = Fout ^ 1
While Dcfin = Fout ;Wacht op signaal verandering
Inc SignaalCheck
DelayMS 1
Wend
Until SignaalCheck < 500
GoTo setklok
zaterdag 17 september 2011
Vervolg onweer detector.
Inmiddels draait de onweer detector alweer een tijdje.
Hij hangt op zolder met een stukje draad verticaal als antenne. Het bereik is ca 50km. Ik heb de software uitgebreid met een aflezing per minuut en het totale aantal strikes. Het totale aan strikes word opgeslagen in het eeprom van de pic. Op portb.1 kun je een speaker aansluiten, zodra er meer dan 25strikes zijn per 5 minuten hoor je een piepje elke minuut. Tevens wordt de data draadloos verstuurd. Hier de source.
Device 16F628A
Xtal 4
LCD_DTPin PORTA.0
LCD_ENPin PORTB.3
LCD_RSPin PORTB.4
TRISB=000001 ' PortB.0 as input
'ANSEL = 0 ' all Portb.7 digital
CMCON = 7
PORTB.7 = 0
Dim teller As Byte
Dim zendtel As Byte
Dim mantel As Byte
Dim strikes[5] As Word
Dim strikes5m As Word
Dim strikestotal As Dword
Dim strikesmc As Word
Dim manchestin As Byte
Dim manchestout As Word
Dim tempdata As Bit
Dim manchestsl As Word
Dim manchestsh As Word
Dim manchests5h As Word
Dim manchests5l As Word
Dim manchestst0 As Word
Dim manchestst1 As Word
Dim manchestst2 As Word
Dim manchestst3 As Word
Dim manchestck As Word
Dim manchestzd As Word
Dim checksum As Byte
Symbol zender = 2
Symbol adres = 1
Symbol zendout = PORTB.7
Symbol startman = $55
Symbol dataman = $aa
Clear
manchestin = zender
Call manchesterdata
manchestzd = manchestout
strikestotal = ERead adres
Cls
DelayMS 100
Print At 1,1,"Lightning"
Print At 2,1,"Detector 1.0"
main:
For teller = 0 To 4
strikes[teller] = Counter PORTB.0,60000
strikes5m = strikes[0] + strikes[1] + strikes[2] + strikes[3] + strikes[4]
Print At 1,1,Dec3 strikes[teller]," S/m ",Dec3 strikes5m," S/5m"
If strikes5m > 25 Then Sound PORTB.1,[122,25]
If strikes[teller] > 2 Then strikestotal = strikestotal+strikes[teller]
Print At 2,1,Dec6 strikestotal," Tstrikes"
strikesmc = strikes[teller]
manchestin = strikesmc.HighByte
Call manchesterdata
manchestsh = manchestout
manchestin = strikesmc.LowByte
Call manchesterdata
manchestsl = manchestout
manchestin = strikes5m.HighByte
Call manchesterdata
manchests5h = manchestout
manchestin = strikes5m.LowByte
Call manchesterdata
manchests5l = manchestout
manchestin = strikestotal.Byte0
Call manchesterdata
manchestst0 = manchestout
manchestin = strikestotal.Byte1
Call manchesterdata
manchestst1 = manchestout
manchestin = strikestotal.Byte2
Call manchesterdata
manchestst2 = manchestout
manchestin = strikestotal.Byte3
Call manchesterdata
manchestst3 = manchestout
checksum = zender + strikes[teller] + strikes5m + strikestotal.Byte0 + strikestotal.Byte1 + strikestotal.Byte2 + strikestotal.Byte3 - 1
manchestin = checksum
Call manchesterdata
manchestck = manchestout
For zendtel = 1 To 3
SerOut zendout, 49965,[startman,dataman,manchestzd.HighByte,manchestzd.LowByte,manchestsh.HighByte,manchestsh.LowByte,manchestsl.HighByte,manchestsl.LowByte,manchests5h.HighByte,manchests5h.LowByte,manchests5l.HighByte,manchests5l.LowByte]
SerOut zendout, 49965,[manchestst0.HighByte,manchestst0.LowByte,manchestst1.HighByte,manchestst1.LowByte,manchestst2.HighByte,manchestst2.LowByte,manchestst3.HighByte,manchestst3.LowByte,manchestck.HighByte,manchestck.LowByte]
DelayMS 10
Next zendtel
Next teller
EWrite adres,[strikestotal]
GoTo main
manchesterdata:
For mantel = 0 To 7
tempdata = GetBit manchestin,mantel
If tempdata = 0 Then
ClearBit manchestout,(mantel*2)
SetBit manchestout,(mantel*2+1)
Else
SetBit manchestout,(mantel*2)
ClearBit manchestout,(mantel*2+1)
EndIf
Next mantel
Return
End
Hij hangt op zolder met een stukje draad verticaal als antenne. Het bereik is ca 50km. Ik heb de software uitgebreid met een aflezing per minuut en het totale aantal strikes. Het totale aan strikes word opgeslagen in het eeprom van de pic. Op portb.1 kun je een speaker aansluiten, zodra er meer dan 25strikes zijn per 5 minuten hoor je een piepje elke minuut. Tevens wordt de data draadloos verstuurd. Hier de source.
Device 16F628A
Xtal 4
LCD_DTPin PORTA.0
LCD_ENPin PORTB.3
LCD_RSPin PORTB.4
TRISB=000001 ' PortB.0 as input
'ANSEL = 0 ' all Portb.7 digital
CMCON = 7
PORTB.7 = 0
Dim teller As Byte
Dim zendtel As Byte
Dim mantel As Byte
Dim strikes[5] As Word
Dim strikes5m As Word
Dim strikestotal As Dword
Dim strikesmc As Word
Dim manchestin As Byte
Dim manchestout As Word
Dim tempdata As Bit
Dim manchestsl As Word
Dim manchestsh As Word
Dim manchests5h As Word
Dim manchests5l As Word
Dim manchestst0 As Word
Dim manchestst1 As Word
Dim manchestst2 As Word
Dim manchestst3 As Word
Dim manchestck As Word
Dim manchestzd As Word
Dim checksum As Byte
Symbol zender = 2
Symbol adres = 1
Symbol zendout = PORTB.7
Symbol startman = $55
Symbol dataman = $aa
Clear
manchestin = zender
Call manchesterdata
manchestzd = manchestout
strikestotal = ERead adres
Cls
DelayMS 100
Print At 1,1,"Lightning"
Print At 2,1,"Detector 1.0"
main:
For teller = 0 To 4
strikes[teller] = Counter PORTB.0,60000
strikes5m = strikes[0] + strikes[1] + strikes[2] + strikes[3] + strikes[4]
Print At 1,1,Dec3 strikes[teller]," S/m ",Dec3 strikes5m," S/5m"
If strikes5m > 25 Then Sound PORTB.1,[122,25]
If strikes[teller] > 2 Then strikestotal = strikestotal+strikes[teller]
Print At 2,1,Dec6 strikestotal," Tstrikes"
strikesmc = strikes[teller]
manchestin = strikesmc.HighByte
Call manchesterdata
manchestsh = manchestout
manchestin = strikesmc.LowByte
Call manchesterdata
manchestsl = manchestout
manchestin = strikes5m.HighByte
Call manchesterdata
manchests5h = manchestout
manchestin = strikes5m.LowByte
Call manchesterdata
manchests5l = manchestout
manchestin = strikestotal.Byte0
Call manchesterdata
manchestst0 = manchestout
manchestin = strikestotal.Byte1
Call manchesterdata
manchestst1 = manchestout
manchestin = strikestotal.Byte2
Call manchesterdata
manchestst2 = manchestout
manchestin = strikestotal.Byte3
Call manchesterdata
manchestst3 = manchestout
checksum = zender + strikes[teller] + strikes5m + strikestotal.Byte0 + strikestotal.Byte1 + strikestotal.Byte2 + strikestotal.Byte3 - 1
manchestin = checksum
Call manchesterdata
manchestck = manchestout
For zendtel = 1 To 3
SerOut zendout, 49965,[startman,dataman,manchestzd.HighByte,manchestzd.LowByte,manchestsh.HighByte,manchestsh.LowByte,manchestsl.HighByte,manchestsl.LowByte,manchests5h.HighByte,manchests5h.LowByte,manchests5l.HighByte,manchests5l.LowByte]
SerOut zendout, 49965,[manchestst0.HighByte,manchestst0.LowByte,manchestst1.HighByte,manchestst1.LowByte,manchestst2.HighByte,manchestst2.LowByte,manchestst3.HighByte,manchestst3.LowByte,manchestck.HighByte,manchestck.LowByte]
DelayMS 10
Next zendtel
Next teller
EWrite adres,[strikestotal]
GoTo main
manchesterdata:
For mantel = 0 To 7
tempdata = GetBit manchestin,mantel
If tempdata = 0 Then
ClearBit manchestout,(mantel*2)
SetBit manchestout,(mantel*2+1)
Else
SetBit manchestout,(mantel*2)
ClearBit manchestout,(mantel*2+1)
EndIf
Next mantel
Return
End
Abonneren op:
Posts (Atom)