\documentclass[11pt,a4paper]{article} % save as utf-8-emacs-unix % 2006-07-07 EW Adventures-1.tex % 2006-07-22 EW Adventures-2.tex % 2006-08-14 EW Adventures-2a.tex % 2007-01-10 EW Adventures-3.tex % 2007-01-13 EW Adventures-4.tex % 2008-11-14 EW Adventures-5.tex % 2011-01-07 EW Adventures-6.tex: rs485+mpc % 2011-02-14 EW Adventures-7.tex: list % 2011-04-30 EW Adventures-8.tex: vocabulary % Adventures-9.tex: rfm12 Grundlagen % % % language support \usepackage[german]{babel} %\usepackage{german} \usepackage[utf8]{inputenc} % can use Umlauts now ü instead of "u %\usepackage{lmodern} % better fonts %\usepackage{pslatex} % use native PostScript fonts %\usepackage{cm-super} \usepackage{url} % \url{} \path{} with correct "hyphenation" % \voffset-10mm % \pagestyle{empty} % \pagestyle{plain} % \pagestyle{headings} % \renewcommand{\baselinestretch}{1.08} %\usepackage{xspace} \parindent=0pt %\newcommand{\amforth}{\texttt{amforth}} %\newcommand{\zB}{z.\,B.\ } \begin{document} \title{Adventures 10: Technoline Funksensoren belauschen!} \ifx\shorttitle\undefined\else \shorttitle{Funksensoren belauschen} \fi \author{Erich Wälde und Martin Bitter} \maketitle %\begin{multicols}{2} % -------------------------------------------------------------------- %\section{Intro} %\label{sec:intro} \begin{abstract}\itshape Es kommt der Tag im Leben eines \emph{Kontrollettis}\footnote{a. zwanghaft Kontrolle ausübender Mensch; b. Mikrokontroller programmierender Mensch}, wo es was zu messen gibt, an einer Stelle, an der ein Kabel (Strom, Kommunikation) keine Option ist. Das ist der Tag, wo er sich vielleicht daran erinnert, dass es bei Pollin [\ref{pollin}] so nette kleine Module mit dem Namen \emph{rfm12} gibt, die auf den ISM--Funkbändern senden und empfangen. Also flugs welche bestellt und bekommen. Damit geht der Ärger aber erst richtig los. Stellt sich heraus, dass die Module kleine Primadonnen sind, die richtig gestreichelt werden wollen, bevor das mit der drahtlosen Datenübertragung halbwegs funktioniert. Im ersten Artikel [\ref{Adv9}] beleuchteten wir die Grundlagen. Dieser Artikel zeigt, wie man käufliche Außensensoren für übliche Wetterstationen (Technoline, [\ref{techoline}]) erfolgreich belauscht. Ein dritter Teil wird zeigen, wie man seine eigene Funkstrecke aufzieht, beispielsweise um damit den Wasserstand in der dunklen Zisterne zu vermelden. Neu in diesem Artikel ist die Verwendung der Assemblerworte \verb|c!@spi| und \verb|!@spi|. Das erste wurde unter dem alten Namen \verb|spirw| schon bisher verwendet. Ein zusätzliches Wort, welches eine Zelle und nicht ein Byte überträgt (vorher \verb|>|<-- null -->| \end{verbatim} } Das Funkmodul wird so konfiguriert, dass es die Präsenz des Funksignals direkt auf dem Pin \texttt{DATA} ausgibt. Der Kontroller muss das Signal selbst abtasten und interpretieren. Das kann auf verschiedene Weise geschehen: (a.) der Kontroller liest den Pegel periodisch (b.) der Kontroller vermisst die Pulslänge mit einem Timer im \textit{Input--Capture}--Verfahren (c.) der Kontroller detektiert die Pulsflanken an einem externen Interrupt--Pin und steuert damit einen Timer. Ich habe mich für die letzte Variante entschieden: Der \texttt{DATA}--Pin des Funkmoduls wird mit dem \texttt{INT1}--Pin des Kontrollers verbunden. Pegelwechsel lösen einen Interrupt aus. Die Interrupt--Service--Routine startet bei der steigenden Flanke \texttt{timer1}. Bei der fallenden Flanke wird der Zählwert von \texttt{timer1} ausgelesen, bewertet (war es eine Null oder eine Eins?) und gespeichert. Die Daten der Sensoren kommen in Paketen zu 44 Bit. Jedes Paket wird nach einer kurzen Pause wiederholt. Misst der Sensor nicht nur die Temperatur, sondern auch die relative Luftfeuchtigkeit, dann wird diese in einem zweiten, ebenfalls wiederholten, Datenpaket gesendet. So eine Sequenz mit zwei oder vier Paketen wird jede Minute ein Mal verschickt. Die Pulsdauer ist deutlich von den Betriebsbedingungen (Versorgungsspannung, Temperatur) abhängig. Wenn die Dauer der Eins--Pulse unter 400\,$\mu$s fällt, ist es angeblich Zeit für neue Batterien. % -------------------------------------------------------------------- \section{Das große Lauschen} Die Verbindung zwischen Kontroller und Funkmodul bekommt lediglich eine weitere Verbindung im Vergleich zur Beschreibung im letzten Artikel: \begin{tabular}{lcl} \multicolumn{3}{l}{SPI Schnittstelle} \\ {\rule{3ex}{0pt}\small\texttt{MOSI}} & $\rightarrow$ & {\small\texttt{DIN}} \\ {\rule{3ex}{0pt}\small\texttt{MISO}} & $\leftarrow$ & {\small\texttt{DOUT}} \\ {\rule{3ex}{0pt}\small\texttt{SCK}} & $\rightarrow$ & {\small\texttt{CLK}} \\ \multicolumn{3}{l}{Chip Select} \\ {\rule{3ex}{0pt}\small\texttt{PORTC.2}} & $\rightarrow$ & {\small\texttt{/CS}} \\ \multicolumn{3}{l}{OOK--Datenleitung} \\ {\rule{3ex}{0pt}\small\texttt{INT1}} & $\leftarrow$ & {\small\texttt{DATA}} \\ \end{tabular} Der Pin \texttt{DATA} wird außerdem über einen schwachen Pullup--Widerstand ($10$\,k$\Omega$) mit der Versorgungsspannung verbunden, um jederzeit einen gültigen Pegel sicherzustellen. Die Initialisierung für den OOK--Betrieb ist ähnlich aufwändig wie für den Empfangsbetrieb im ersten Artikel (s.\,nächsten Abschnitt, Funktion \texttt{rfm12.init-ook}). % -------------------------------------------------------------------- \section{ASCII--Signale} Um den Empfang der Sensordaten erst einmal grob anzuzeigen, schreibt man eine Schleife, die lediglich den Pegel des Pins \texttt{INT1} anzeigt: ein Punkt für niedrige Pegel, einen senkrechten Strich für hohe Pegel. Außerdem werden zwei der LEDs abwechselnd geschaltet, so dass man es flackern sieht, wenn Pegelwechsel erkannt werden. {\small \begin{verbatim} include lib/bitnames.frt include atmega32.frt PORTB 2 portpin: led_2 PORTB 3 portpin: led_3 PORTB 5 portpin: _mosi PORTB 6 portpin: _miso PORTB 7 portpin: _clk PORTC 2 portpin: _rfm12 \ rfm12 select PORTD 3 portpin: _data \ int1, rfm12 data include ewlib/spi.fs include ewlib/rfm12.fs : rfm12.init-ook ( -- ) $8017 >wc \ EL EF ... $C431 >wc \ @POW ... $a608 >wc \ 433.92 MHz ? $94c2 >wc \ VDI FAST ... $C220 >wc \ AL, !m1 ... $82D8 >wc \ !er !ebb ... $CA00 >wc \ FIFO8, SYNC ... $CC67 >wc \ ? $C623 >wc \ baud rate ? ; \ LED/ASCII-oszi for pin INT1 -- DATA : .data _data pin_high? if led_2 low led_3 high [char] | else led_2 high led_3 low [char] . then emit ; : init1 led_2 high led_2 pin_output led_3 high led_3 pin_output -jtag +spi +rfm12 rfm12.init-ook _data pin_input ; : run1 init1 w.status cr begin .data key? until ; \end{verbatim} } Solchermaßen ausgerüstet, startet man das Programm \texttt{run1}. Wem das Warten auf die ersehnten Daten zu lange dauert (so eine Minute vor dem Rechner zu warten, ist schon elend lang), der nimmt aus dem Sensor kurz die Batterie raus und legt sie wieder rein. Das erzwingt einen Neustart des Außensensors, der dann ein paar Datensätze alle 15 Sekunden verschickt. Die sehen dann etwa so aus: {\small \begin{verbatim} ................................................... .............................|||||.|||||.|||||.|||| ..||..||||.|||.|||||.||||..||||..||||.|||||.|||||.| ||||.||||..||..||||.|||||.|||.|||||.||||..||.|||.|| |.|||||.||||..||..||||.|||||.|||.|||.||||..||||..|| .|||.|||.|||||.|||||.||..||||.|||||.|||.||||..||... ................................................... ................||||.|||||.||||..|||||.||..||||.||| .|||||.|||||.||||..||||..||||.|||||.|||||.||||..||. .||||.|||||.|||.||||..|||||.||..||.|||.|||||.||||.. ||..||||..||||.|||.|||.||||..||||..||.|||.|||.||||| .||||..||..||||.|||||.|||.|||||.||................. ................................................... \end{verbatim} } Zwar kann man hier die einzelnen Bits nicht identifizieren, aber man sieht sehr deutlich, dass das eine Struktur mit zwei Blöcken ist. Es handelt sich um eine Sequenz von 2 mal 2 Paketen zu jeweils 44 Bit. Im Geflacker der LEDs erkennt man diese 4 Pakete ebenfalls ganz gut. Wer an diesen Punkt gelangt, hat erwiesenermaßen funktionierendes Gerät. Glückwunsch! % -------------------------------------------------------------------- \section{Blinksignale} Im nächsten Schritt überlassen wir das Erkennen der Flanken und das Schalten der LEDs den Interruptfähigkeiten des Kontrollers. {\small \begin{verbatim} : int1-isr _data pin_high? if \ leading edge led_2 low else \ trailing edge led_2 high then GIFR c@ $80 or GIFR c! \ clear int1 ; : +int1 ['] int1-isr INT1Addr int! \ register isr MCUCR c@ $04 or MCUCR c! \ irq on change GIFR c@ $80 or GIFR c! \ clear int1 GICR c@ $80 or GICR c! \ enable int1 ; : -int1 GIFR c@ $80 or GIFR c! \ clear int1 GICR c@ $80 invert and GICR c! \ disable ; \end{verbatim} } Nach dem Aufruf von \texttt{init1} aus dem ersten Beispiel braucht es lediglich das Aktivieren des Interrupts: \texttt{+int1}, dann sollte die LED wie von Geisterhand flackern, wenn ein Datenblock empfangen wird. Damit wäre bewiesen, dass die Registrierung der Interrupt--Service--Routine und die Aktivierung des Interrupts erfolgreich war. % -------------------------------------------------------------------- \section{Signale vermessen} Zum Vermessen der Pulslänge soll \texttt{timer1} verwendet werden. Die zugehörigen Register finden sich wie immer im Datenblatt. Ich benutze vorzugsweise einen Baudraten--Quarz der Frequenz $11.059200$\,MHz. Wenn ich \texttt{timer1} mit einem Vorteiler von 64 aus der Frequenz der CPU speise, dann sind das $172800$\,Hz, ein \texttt{timer1}--Schritt entspricht dann $5.8\,\mu$s. Nach $2^{16}$ Zyklen oder $379$\,ms läuft der Zähler über. Eine Eins mit ca. $600\,\mu$s sollte einen Zählerstand von etwa $100$ erreichen, eine Null ($1300\,\mu$s) erreicht dann etwa $225$. Diese Zahlen muss man sich zur Bestätigung ausgeben lassen. Gemessen habe ich Werte von ca.\ $150$ und $295$. Die Grenze, um die beiden Bitwerte zu unterscheiden (\verb|bit=1|), habe ich mutwillig auf $200$ festgelegt. Zu kurze oder zu lange Pulse werden nicht als fehlerhaft erkannt. Bei anderen Quarzfreqenzen muss man das entsprechend anpassen. Zunächst definieren wir Worte, die den Zähler starten, anhalten, löschen und den aktuellen Zählwert lesen. Die zugehörige Interrupt--Service--Routine von \texttt{timer1} stoppt und löscht den Zähler. Sie wird beim Überlauf des Zählers aufgerufen und sorgt außerdem dafür, dass zu kurze (oder fehlerhaft empfangene) Telegramme verworfen werden (\verb|bit#| löschen). Der Empfänger wird nicht länger blockiert, weil er nicht mehr auf vermeintlich fehlende Bits wartet. {\small \begin{verbatim} decimal 44 constant bits/telegram variable bit# \ with timer1 driven by f_cpu/64 (11059200/64= \ 172800Hz) a pulse indicating a one (~ 600 \mu \ seconds) results in counts ~ 150. A zero pulse \ (~1300 \mu seconds) results in counts ~ 300. So \ counts below 200 are counted as logical 1 200 constant bit=1 variable RXtmp \ shift collector for bits : t1_start $03 TCCR1B c! ; : t1_stop $00 TCCR1B c! ; : t1_clear $00 TCNT1H c! $00 TCNT1L c! ; : t1_reset $04 TIFR c! ; : t1_get TCNT1L c@ >< TCNT1H c@ or >< ; : t1-overflow-isr t1_stop t1_reset 0 bit# ! ; : +timer1 t1_clear 0 TCCR1A c! t1_reset \ clear t1ovfl flag t1_start \ normal mode, f/64 \ register timer1 overflow isr ['] t1-overflow-isr TIMER1_OVFAddr int! \ enable timer1 overflow int TIMSK c@ $04 or TIMSK c! ; : -timer1 \ disable timer1 overflow int TIMSK c@ $04 invert and TIMSK c! ; \end{verbatim} } Die Interrupt--Service--Routine des externen INT1--Interrupts benutzt \texttt{timer1}: eine steigende Flanke bewirkt ein löschen und starten des Zählers. Eine fallende Flanke liest den aktuellen Zählerwert aus. Ist der kürzer als 200, dann wird der empfangene Puls als logische 1 gewertet. Das Bit wird in die Variable \texttt{RXtmp} geschoben. Die empfangenen Bits werden gezählt (Variable \verb|bit#|). Sind 4 Bit empfangen, wird der Wert in einem Datenblock abgelegt. Wurden 44 Bit empfangen, dann wird über die Variable \texttt{fQueue} angezeigt, dass ein vollständiges Telegramm eingegangen ist. {\small \begin{verbatim} 44 constant RXsize variable RXbuf RXsize cells allot \ receive buffer variable RXtmp \ nibble shift register : int1-isr _data pin_high? if \ leading edge t1_clear t1_start led_2 low else \ trailing edge \ store bit t1_get \ -- t_diff RXtmp @ 1 lshift \ -- t_diff tmp<<1 swap \ -- tmp<<1 t_diff bit=1 < if \ 1 1+ \ -- tmp<<1 + 1 \ else \ 0 + \ -- tmp<<1 + 0 then \ -- tmp' RXtmp ! \ store nibble bit# @ 4 mod 3 = if RXtmp @ RXbuf bit# @ 4 / + c! 0 RXtmp ! then 1 bit# +! bit# @ bits/telegram = if 0 bit# ! 1 fQueue +! then led_2 high then GIFR c@ %10000000 or GIFR c! \ clear int1 ; \end{verbatim} } Die Daten werden in Nibble (4 Bit) zusammengefasst und gespeichert. Damit wird zwar die Hälfte des Speichers ungenutzt verschenkt, aber die Deutung der Daten beruht ohnehin auf Nibble, und deren Handhabung wird damit einfacher. Das Wort \texttt{.data} zeigt die empfangenen Daten ohne weitere Interpretation. {\small \begin{verbatim} : .data hex bits/telegram 4 / 0 do RXbuf i + c@ 2 u0.r space loop ; \end{verbatim} } Die Funktion \texttt{init1} wird um ein paar Zeilen erweitert {\small \begin{verbatim} : init3 ... RXbuf RXsize cells erase 0 fQueue ! +timer1 +int1 ; \end{verbatim} } In der Hauptschleife des Programms werden die empfangenen Daten ausgegeben: {\small \begin{verbatim} : run3 .. begin fQueue @ 0 > if .data cr 0 fQueue ! then key? until ... ; \end{verbatim} } % -------------------------------------------------------------------- \section{Daten!} Hat man das Programm soweit erfolgreich am Laufen (siehe \texttt{main-3.fs}), dann wird man mit einer Ausgabe ähnlich dieser belohnt (die hinzugefügten Leerzeilen dienen der besseren Lesbarkeit): {\small \begin{verbatim} 00 0A 0E 03 04 06 00 00 06 00 0B 00 0A 0E 03 04 06 00 00 06 00 0B 00 0A 00 03 0B 07 03 09 07 03 05 00 0A 00 03 0B 07 03 09 07 03 05 00 0A 0E 03 0B 05 02 00 05 02 04 00 0A 0E 03 0B 05 02 00 05 02 04 00 0A 00 05 08 07 05 01 07 05 00 00 0A 00 05 08 07 05 01 07 05 00 00 0A 0E 05 09 03 07 00 03 07 0A 00 0A 0E 05 09 03 07 00 03 07 0A 00 0A 00 03 05 07 01 04 07 01 06 00 0A 00 03 05 07 01 04 07 01 06 00 0A 0E 03 04 06 00 00 06 00 0B 00 0A 0E 03 04 06 00 00 06 00 0B 00 0A 00 03 0B 07 03 09 07 03 05 00 0A 00 03 0B 07 03 09 07 03 05 \end{verbatim} } Die Deutung der Daten kann man in dem schon erwähnten Dokument von Marko Piering nachlesen (Daten aus der ersten Zeile der Ausgabe von oben, in der Ausgabe ist immer eine führende Null, das ist der verschenkte Speicher): \begin{itemize} \item \textbf{Nibble 0:} (\texttt{0}) das Startnibble hat immer den Wert Null \item \textbf{Nibble 1,2:} (\texttt{AE}) diese beiden Nibble bilden das höhere Byte der Sensor--Adresse. \texttt{A0} ist die Kennzeichnung eines Temperatursensors, \texttt{AE} die Kennzeichnung eines Feuchtesensors. \item \textbf{Nibble 3,4:} (\texttt{34}) 7 Bit dieser beiden Nibble bilden das niedrige Byte der Sensor--Adresse (Bits 7\ldots1). Das niedrigste Bit ist ein Paritätsbit. \item \textbf{Nibble 5:} (\texttt{6}) Messwert, Zehnerstelle: Bei Temperaturdaten sind von der empfangenen Zehnerstelle $5$ abzuziehen. Damit werden negative Temperaturen bis $-50^\circ$\,C als Daten $>= 0$ übertragen. \item \textbf{Nibble 6:} (\texttt{0}) Messwert, Einerstelle \item \textbf{Nibble 7:} (\texttt{0}) Messwert, Zehntelstelle \item \textbf{Nibble 8:} (\texttt{6}) wie Nibble 5 \item \textbf{Nibble 9:} (\texttt{0}) wie Nibble 6 \item \textbf{Nibble 10:} (\texttt{B}) Checksumme der Nibble 1 bis 9 (Addition ohne Überlauf) \end{itemize} Mit dieser Information kann man den oben gezeigten Block schon sezieren. \begin{itemize} \item Es finden sich Datenblocks von Temperatur und Luftfeuchte. \item Alle Datenblocks werden wiederholt \item Es finden sich 3 verschiedene Sensoren mit den niedrigen Adressen \texttt{3A}, \texttt{58} und \texttt{34} \item Die Feuchtigkeiten betragen $52$, $37$ und $60$\,\%. \item Die Temperaturen betragen $23.9$, $25.1$ und $21.4$ Grad. \end{itemize} Es ist ein Einfaches, die einzelnen Nibble der empfangenen Daten auszugeben, aber natürlich wollen wir den Inhalt nicht selbst deuten. Das nachfolgende Wort nimmt uns das ab, allerdings ist es nicht sehr elegant programmiert. {\small \begin{verbatim} include ewlib/format.fs 11 constant frame.size : .D ( addr -- ) hex dup >r \ --- raw dump of data --- frame.size 0 do dup i + c@ 2 u0.r space loop cr drop \ --- address --- r@ 1 + c@ 12 lshift r@ 2 + c@ 8 lshift + r@ 3 + c@ 4 lshift + r@ 4 + c@ + $fffe and \ addr ." addr:" space 4 u0.r cr \ --- value and unit --- r@ 5 + c@ r@ 2 + c@ 0= if 5 - then \ temperature? minus 5 100 * r@ 6 + c@ 10 * + r@ 7 + c@ + \ value decimal r@ 2 + c@ 0= if ." T C:" else ." rF %:" then space 1 +.f cr \ --- checksum --- r@ 0 frame.size 1- 0 do over i + c@ + loop swap drop $000f and \ crc hex dup ." crc:" space 4 u0.r space r@ frame.size 1- + c@ dup space 4 u0.r space = if ." ok." else ." invalid" then cr r> drop ; \end{verbatim} } Wird \texttt{RXbuf .D} anstelle von \texttt{.data} in der Schleife von \texttt{run3} verwendet, dann ergibt sich beispielsweise folgende Ausgabe: {\small \begin{verbatim} 10 0A 00 03 04 07 01 00 07 01 01 addr: A034 T C: +21.0 crc: 0001 0001 ok. 00 0A 00 03 04 07 01 00 07 01 01 addr: A034 T C: +21.0 crc: 0001 0001 ok. 00 0A 0E 03 04 07 04 00 07 04 05 addr: AE34 rF %: +74.0 crc: 0005 0005 ok. 00 0A 0E 03 04 07 04 00 07 04 05 addr: AE34 rF %: +74.0 crc: 0005 0005 ok. \end{verbatim} } \section{Datenverwaltung} Der Rest ist viel Fleißarbeit. Es empfiehlt sich, den vollständig empfangenen Block schleunigst umzukopieren in eine Art Ringpuffer. Dann können immer 4 Telegramme gesammelt und ausgewertet werden. Auf dem Kontroller kann man die Daten eine Weile sammeln und auf ein Speichermedium schreiben. Man kann die Daten auch regelmäßig einsammeln, wenn ein Rechner ständig in Betrieb ist. Man kann die Daten auch nur auf einem LCDisplay anzeigen. All das hängt vom individuellen Ziel und der verfügbaren Zeit ab. So ein Projekt ist erfahrungsgemäß nicht mal geschwind an einem Wochenende erledigt. Wenn die Daten dann ordentlich eingesammelt sind, wollen sie auf dem Rechner genauso ordentlich abgespeichert werden (Dateien oder Datenbank) und als Kurven angezeigt und bestaunt werden. Versionsverwaltung des kompletten Projekts und ausreichende Dokumentation\footnote{praktischerweise auch als Artikel in der VD!} sind auch für Gelegenheitsprogrammierer kein Luxus. Nota bene: der arme Tropf, der in zwei Jahren den wildgewordenen Programm--Code entziffern muss, weil irgendetwas nicht so tut wie gewünscht, der bist Du selbst. % -------------------------------------------------------------------- \section{So Sachen} Beim ersten Sezieren der Daten war mir noch entgangen, dass bei Temperaturen die Zehnerstelle um $5$ erhöht übertragen wird. Und da es gerade einigermaßen passte, hegte ich den Verdacht, dass die Temperaturen in Fahrenheit übertragen werden --- sowas wundert mich ja nicht. Allerdings wollten die Daten auf der Anzeige und die von mir umgerechneten Daten einfach nicht zusammenpassen. Martin hat mich netterweise von meinem Holzweg geholt. Die Deutung der übertragenen Daten steht sehr ausführlich in der Dokumentation von Marko Piering. An dieser Stelle sei auch darauf hingewiesen, dass die Sensoren zwar alle 58 Sekunden Daten verschicken, dass die gekaufte Empfangsstation aber lediglich zwei Mal in 10 Minuten überhaupt Daten empfängt. Das kann unsere Selbstbaustation jetzt schon besser. Außerdem berichtet Martin, dass die Selbstbaustation immer noch wacker Daten empfängt und auswertet, wenn die gekaufte Empfangsstation nur noch drei langweiligeStriche anzeigt. Deren Empfänger ist wohl nicht so gut wie das rfm12--Funkmodul. Die Fernbedienung der neuen Rollos sendet ebenfalls deutlich sichtbar im $434$--MHz--Band. Und ab und zu findet sich auch eine Station von Nachbars in den Daten. Werden in einen Außensensor neue Batterien eingelegt, dann ändert sich dessen Adresse, was ziemlich unpraktisch ist. Als Erstes wird ein Telegramm geschickt, welches spezielle Informationen zum Thema enthält, aber damit habe ich mich bislang nicht beschäftigt. Spezieller Dank geht an Martin Bitter, der diesen Betriebsmodus mit bemerkenswerter Ausdauer erkundet hat, an Marko Piering, der das Protokoll entziffert und seine Erkenntnisse in sehr ordentlicher Form veröffentlicht hat, an Matthias Trute für die ständige Verbesserung von \texttt{amforth} und an die Teilnehmer des mittwöchlichen IRC--Treffens, für allerhand Rat und Tat. \end{multicols} % -------------------------------------------------------------------- \section{Referenzen} \begin{enumerate} %\item \label{Adv1} E. Wälde, Adventures in Forth, Die 4. Dimension 3/2006, Jahrgang 22 % gforth-ec r8c, i2c von Hand, Thermometer %\item \label{Adv2} E. Wälde, Adventures in Forth 2, Die 4. Dimension 4/2006, Jahrgang 22 % timeup Uhr und Kalender, twotask %\item \label{Adv3} E. Wälde, Adventures in Forth 3, Die 4. Dimension 1/2007, Jahrgang 23 % usart0, redirection %\item \label{Adv4} E. Wälde, Adventures in Forth 4, Die 4. Dimension 1/2007, Jahrgang 23 % dcf-77 Uhr %\item \label{Adv5} E. Wälde, Adventures in Forth 5, Die 4. Dimension 4/2008, Jahrgang 24 % Umstieg auf amforth, bit flags, sensor:, filter_mean: %\item \label{Adv6} E. Wälde, Adventures in Forth 6, Die 4. Dimension 1/2011, Jahrgang 27 % rs485, -emit, mpc %\item \label{Adv7} E. Wälde, eine einfache Liste, Die 4. Dimension 2/2011, Jahrgang 27 % list.add list.walk %\item \label{Adv8} E. Wälde, amforth: Wortliste sperren, Die 4. Dimension 3/2011, Jahrgang 27 % also sealed \item \label{Adv9} E.\ Wälde und M.\ Bitter, Funklöcher!, Die 4. Dimension 3/2011, Jahrgang 27 % rfm12 tranceiver, 1.Teil %\item \label{r8c-ds} Renesas R8C/13 datasheet auf \url{www.renesas.com} %\item \label{Koenig} A.\ König und M.\ König, Das PICmicro Profi Buch, Franzis % Verlag 1999, ISBN 3-7723-4284-1 %\item \label{SPelc} Stephen Pelc, Programming Forth, \\ \url{http://www.mpeforth.com/arena/ProgramForth.pdf} %\item \label{Deliano} \url{http://www.embeddedforth.de/emb3.pdf} S.\ 9 %\item \label{dcf} \url{http://de.wikipedia.org/wiki/DCF77} und Verweise darin %\item \label{willem} ByteForth von Willem Ouwerkerk,\\ \url{http://www.forth.hccnet.nl/byteforth.htm} \item \label{amforth} \url{http://amforth.sourceforge.net/} %\item \label{ron} Ron Minke, Forth von der Pike auf Die 4. Dimension 3+4/2005 \ldots 4/2006, sowie Sonderheft AVR und 3+4/2007 %\item \label{namedbits} M. Kalus, M. Trute, Named Bits, Die 4. Dimension 2/2007, Jahrgang 23 %\item \label{lubos} Lubo\v{s} P\v{e}kn\'{y}s Seite: \url{http://www.forth.cz} %\item \label{RS485} Wikipedia (RS485) \url{de.wikipedia.org/wiki/RS485} %\item \label{RS485a} \url{www.mikrocontroller.net/articles/RS-485} %\item \label{g4.fs} Michael Kalus: g4.fs \url{www.forth-ev.de/repos/g4/g4.fs} %\item \label{atmega32} atmega32 Datenblatt (doc2503.pdf) \url{www.atmel.com} % %\item \label{brodie1} Leo Brodie --- Starting Forth, 1987, Prentice Hall, S.\,219ff %\item \label{rather} Elizabeth D.\ Rather --- Forth Application Techniques, 2006, Forth Inc., S.\,107ff %\item \label{vack} Gert-Ulrich Vack --- Programmieren mit FORTH, 1990, Verlag Technik Berlin, S.\,189ff \item \label{pollin} \url{http://www.pollin.de} \item \label{techoline} technoline TX3--TH o.ä. \item \label{tx234}\url{http://ccintern.dharlos.de/TX2TX4_433MHz_Wetterstation_1_0.zip} %\item \label{ism} \url{http://de.wikipedia.org/wiki/ISM-Band} \item \label{hoperf} \url{http://www.hoperf.com} %\item \label{elektor} Funk für den Controller --- Elektor Januar 2009 (\url{www.elektor.de}) %\item \label{mic-net} \url{http://www.mikrocontroller.net/articles/RFM12} %\item \label{rfm12.sample.code} \url{hoperf sample code} \end{enumerate} \begin{figure} \centering \includegraphics[angle=-90,width=0.9\textwidth]{2011-04/Waelde_Adv10_Data.ps} % cd Forth/HausBus/trunk/rhea/viewer % ./viewer-vd.pl -C viewer.vd.sensors.conf -f ../db/Wetter4-20111114.sqlite -F "2011-11-08 00:00:00" -T "2011-11-15 00:00:00" -L \caption{Mit dem vorgestellten Programm aufgenommene Daten für Lufttemperatur (rot, Striche) und relative Luftfeuchtigkeit (blau, Punkte). In den Temperaturdaten finden sich Ausreißer, deren Ursache im Moment unklar ist. Die Doppelspitze mittags kommt durch Beschattung des Sensors zustande. Der Sensor befindet sich auf der Südseite, die Mittagstemperaturen sind deutlich zu hoch.} \end{figure} %\newpage % -------------------------------------------------------------------- \section{Listings} Bei den Listings ist zu beachten, dass ich mein Funkmodul über den Pin PortA.7 mit Strom versorge. Dementsprechend gibt es die Worte \texttt{\_w\_pwr}, \texttt{rfm12.power.on} und \texttt{rfm12.power.off}. Diese Worte können natürlich weggelassen werden, wenn das Funkmodul immer mit Strom versorgt wird. \begin{quote} \begin{small} \begin{multicols}{2} \listinginput[1]{1}{2011-04/adv10/main-1.fs} \listinginput[1]{1}{2011-04/adv10/part-1.fs} \listinginput[1]{1}{2011-04/adv10/words/spirw.asm} \listinginput[1]{1}{2011-04/adv10/words/2spirw.asm} \listinginput[1]{1}{2011-04/adv10/ewlib/spi.fs} \listinginput[1]{1}{2011-04/adv10/ewlib/rfm12.fs} \listinginput[1]{1}{2011-04/adv10/main-2.fs} \listinginput[1]{1}{2011-04/adv10/main-3.fs} \listinginput[1]{1}{2011-04/adv10/rfm12_timer1.fs} \listinginput[1]{1}{2011-04/adv10/rfm12_int1.fs} \listinginput[1]{1}{2011-04/adv10/ewlib/format_edited.fs} \end{multicols} \end{small} \end{quote} \end{document}