Ich habe bei ett-online eine 3 Kanal-Funkwetterstation FWS-100 der Firma Xue Zhi You für ca. 25EUR gekauft. Ein zusätzlicher 2. und 3. Funksensor kostet einzeln 12EUR und misst Temperatur und Luftfeuchtigkeit.
http://www.google.de/search?hl=de&q=...ion&btnG=Suche
Es entstand die Idee damit einen billigen Datenlogger zu basteln.
Ich habe in der Wetterstation das Signal vom Empfänger zum Microcontroller abgezweigt und direkt einem Atmega32 zugeführt. Intern wird der 433Mhz Empfänger mit 3 Drähten an die µC der Wetterstation angebunden. (Rot=+ / Gelb=Signal / Schwarz=GND)
Davon ziehe ich 2 Drähte raus (Signal und GND).
Das Signal hat einen batterieabhängigen Pegel von ca. 2,5V, so dass ich zur Signalerfassung den Analog Comparator des Atmega genutzt habe. Die Referenzspannung habe ich über den Spannungsabfall einer Diode erzeugt.
Die Codierung des Signals ist eine Puls-Frequenz-Modulation (d.h. keine Manchester Codierung!).
Der Comparator erzeugt einen Interrupt, der die Impulsbreite des Signals misst. Dabei dauert eine 0 ca. 1,6ms und eine 1 ca. 3,3ms.
Bild hier
Graphik zum zeitlichen Verlauf - die Spannungen sind irrelevant
Der Sender schickt in gewissen Abständen mehrmals 40Bit zum Empfänger nach folgendem Muster:
CCCCCCCC DDDDTTTT TTTTTTTT BHHHHHHH SSSSSSSS
C = 8 Bit Channal - Codierung des Senders
D = 4 Bit laufender Code
T = 12 Bit Temperatur in 1/10 Grad mit Vorzeichen
B = 1 Bit Batteriestatus
H = 7 Bit Luftfeuchtigkeit (0-99%)
S = 8 Bit invertierte Prüfsumme der ersten 4 Byte
Programmlänge ca. 1950 Byte:
Code:
'Anbindung einer Funkwetterstation FWS-100 an Atmega
'Auswertung des Signal (ca. 0-2,5V) mit dem Analog Comparator
' AIN0 Eingangspegel um Diode mit Pufferkondensator reduziert
' AIN1 direkter Eingang mit 10kohm
'Codierung mit Puls-Frequenz-Modulation
$regfile = "m32def.dat" 'Die Anweisung bestimmt Controllertyp, hier AVR Mega 32
$framesize = 32 'Stackanweisungen, nicht optimiert
$swstack = 32
$hwstack = 64
$crystal = 16000000 'Die Frequenz des verwendeten Quarzes
$baud = 38400 'Die Baudrate für RS232 Ausgabe.
Config Pina.0 = Output
Led1 Alias Porta.0
Porta = 0
'Pins des LCD-Modules setzen ggf. an eigene Anschlüsse anpassen
' Config Lcdpin = Pin , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portc.6 , Db7 = Portc.7 , E = Portc.2 , Rs = Portc.3
' Config Lcdmode = Port
' Config Lcdbus = 4 '4 bit mode
'Alternativ, da schneller
$lib "lcd4busy.lib"
Const _lcdport = Portc
Const _lcdddr = Ddrc
Const _lcdin = Pinc
Const _lcd_e = 2
Const _lcd_rs = 3
Const _lcd_rw = 1
Config Lcd = 20 * 4
Initlcd
Cls
Deflcdchar 1 , 12 , 18 , 18 , 12 , 32 , 32 , 32 , 32 ' LCD Zeichen für °C
Config Timer0 = Timer , Prescale = 1024 'Takt: 64µs
On Timer0 Timer_irq Nosave 'Timerüberlauf ISR
Const Timervorgabe = 0
Dim Ueberlauf As Byte 'wegen Assembler als Byte
Config Aci = On , Compare = Off , Trigger = Falling
On Aci Isr_port
'ACSR=&B00000000
'Timing
Const Samples_0_min = 10 'Flanke 0 frühestens nach xx Takten
Const Samples_0_max = 37 'Flanke 0 spätestens nach yy Takten
Const Samples_1_min = 46 'Flanke 1 frühestens nach xx Takten
Const Samples_1_max = 60 'Flanke 1 spätestens nach yy Takten
'Variablen
Dim Ir_data_tmp(6) As Byte 'Bitstream mit 1 Byte Reserve
Dim Ir_bitcount As Byte 'Anzahl gelesener bits
Dim Data_byte As Byte , Data_bit As Byte
Dim I As Byte , K As Byte
Dim Timer_old As Byte
Dim Valid As Bit , Valid_old As Bit
Dim Value As Bit
Dim Channel As Byte , Temp As Integer , Humidity As Byte
Dim Summ As Byte , Batt As Byte
Dim Ausgabe As Bit , Temp_low As Word
Dim Ausgabe_count As Byte
Dim Convert_s As String * 10
Enable Timer0 'Hier werden die Timer aktiviert
Enable Aci
Enable Interrupts
Do
If Ausgabe = 1 And Ueberlauf = 1 Then 'warten bis Ruhe
Disable Aci
'xx bits gelesen?
Ausgabe = 0
Convert_s = Str(temp) 'Temperatur ausgeben
Convert_s = Format(convert_s , "+00.0")
Cls
Lcd "CH" ; Channel ; " " ; Convert_s ; Chr(1) ; "C " ; Humidity ; "% #" ; Ausgabe_count
If Batt = 1 Then Lcd " Batt!"
Enable Aci
End If
Led1 = Not Acsr.5 'Debug ACI ***********
Loop
End
Isr_port:
Timer_old = Timer0
Timer0 = 0
Reset Valid
If Ueberlauf = 1 Then
Ueberlauf = 0
Ir_bitcount = 0
Else 'kein Überlauf
If Timer_old > Samples_0_min Then
If Timer_old < Samples_0_max Then
Value = 0
Set Valid
Else
If Timer_old < Samples_1_max Then
Value = 1
Set Valid
End If
End If
End If
If Valid = 1 Then
Data_byte = Ir_bitcount / 8
Incr Data_byte 'Array beginnt mit 1
Data_bit = Ir_bitcount Mod 8
Data_bit = 7 - Data_bit 'Höherwertige Bit zuerst
Ir_data_tmp(data_byte).data_bit = Value
Incr Ir_bitcount
Else
Ir_bitcount = 0
End If
If Ir_bitcount > 39 Then '40 Bit gelesen
Summ = Ir_data_tmp(1) + Ir_data_tmp(2)
Summ = Summ + Ir_data_tmp(3)
Summ = Summ + Ir_data_tmp(4)
Summ = Not Summ
If Summ = Ir_data_tmp(5) Then
Ausgabe = 1
Incr Ausgabe_count
Channel = Ir_data_tmp(1)
Temp = Ir_data_tmp(2)
Shift Temp , Left , 8
Temp = Temp Or Ir_data_tmp(3)
Shift Temp , Left , 4
Temp = Temp / 16 'Umwandlung 12-16 Bit für negative Temp
Humidity = Ir_data_tmp(4) And &B01111111
Batt = Ir_data_tmp(4).7
End If
Ir_bitcount = 0
End If
End If
Return
Timer_irq:
'Nosave ISR -> save used register
push r24
in r24,sreg
push r24
'Timer0 laden
ldi r24, Timervorgabe
!out Tcnt0 , R24
'Set Ueberlauf
ldi r24, $01
sts {Ueberlauf}, r24
'restore used register
pop r24
!out sreg,r24
pop r24
Return
Lesezeichen