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







Zitieren

Lesezeichen