\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|><spi|), gab Anlass zur
  Umbenennung. Die Worte sind im Repository von amforth ab der Version 4.6,
  erhältlich oder im Anhang.
\end{abstract}

\begin{multicols}{2}

% --------------------------------------------------------------------
\section{Technoline TX Außensensoren}


Außensensoren von Technoline (z.\,B.\ TX3--TH) werden mit einigen
Funkwetterstationen verwendet. Die Station steht irgendwo im Haus, die
Außensensoren für Temperatur und Luftfeuchte senden regelmäßig ihre
Messwerte per Funk. Die Daten werden auf der Station angezeigt, falls der
Empfang gut genug war. Die Außensensoren senden im $433$--MHz--ISM Band, es
sollte also möglich sein, mit einem rfm12--Modul diesen Datenverkehr zu
belauschen. 



\begin{figure}
  \centering
  \includegraphics[scale=0.06]{2011-04/adv10/technoline-TX3-TH-sensor}
  \caption{Ein Außensensor von Technoline (TX3--TH) für Temperatur und
    Luftfeuchte} 
\end{figure}

% --------------------------------------------------------------------
\section{Das Übertragungsprotokoll}

Es stellt sich heraus, dass Marko Piering sehr erfolgreich das
Übertragungsgeschehen belauscht und entziffert hat [\ref{tx234}]. Seine
Dokumentation ist sehr lesenswert. Sie beschreibt im Detail den Prozess, das
zunächst unbekannte Protokoll zu verstehen.


Die Sensoren senden auf $433.92$\,MHz. Diese Frequenz hat Martin in
länglichen Versuchsreihen als die günstigste ermittelt. Funkamateure mit
besserer Ausrüstung kommen da wahrscheinlich deutlich schneller zum Ziel.
Die Sensoren senden im sogenannten \textit{on--off--keying} (OOK--Betrieb).
Das ist wie Morsen: der Sender ist an (Puls) oder aus (Pause). Wie beim
Morsen werden kurze (ca.\ $600\,\mu$s) und lange (ca.\ $1300\,\mu$s) Pulse
unterschieden. Die Pause zwischen zwei Pulsen bleibt immer gleich und
beträgt etwa $900\,\mu$s. Ein kurzer Puls wird als logische Eins
betrachtet, ein langer Puls als logische Null.

{\small
\begin{verbatim}
|^^^^^|________|^^^^^^^^^^^|______|^^
|<--  eins  -->|<--     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 <wordlist> 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}
