Ansteuerung der Funkschalter FS20 mit dem Tiny13

von Victor Klein 

Die von Conrad und ELV vertrieben Funkschalter FS20 ST2/3 aus den FS20-System werden auf dem 868 MHz-Band angesteuert. Dazu verwendet man den Tiny13-Controller aus dem Lernpaket Mikrocontroller, das HF-Sendemodul 868 MHz  (von ELV, etwa 15  €)  und eine kleine Ansteuerschaltung zur Pegelwandlung.

 

 

Der Sender wird mit 2-3 V betrieben, hier kommt ein Spannungsregler 78L02 zum Einsatz, der 2,6 V liefert, was für Experimente völlig ausreichend ist.

 

 

Die Datenansteuerung des Senders geschieht über einen Spannungsteiler mit 1,4 kOhm und 1 kOhm, sodass am Dateneingang des Senders bei aktiven Pegel etwa 2,1 V liegen. Eine LED dient zur Sendekontrolle und wird über einen zweiten Port des Tiny 13 angesteuert.

 

 

Software:

Der Tiny13 wird über einen USB-Seriellwandler über das RS-232-Protokoll mit 9600 Baud mit den Befehlsdaten versorgt. Sind die Daten vollständig erfasst, so beginnt der Sendevorgang, der zeitkritisch ist. In dem FS20-Protokoll wird eine 1 mit einem 600 us langen Sendeimpuls übertragen, eine Null ist 400 us lang. Das Programm ist in Assembler geschrieben. Es setzt voraus, dass der Tiny 13 mit 1,2 MHz (das ist der Standard im Lernpaket) läuft.


.equ transmit = 3 ; PB3

fs20_Send_One:
sbi portb,transmit
rcall warte600us
cbi portb,transmit
rcall warte600us
ret
; sende eine 0
fs20_Send_zero:
sbi portb,transmit
rcall warte400us
cbi portb,transmit
rcall warte400us
ret
Jede Datensequenz wird im FS20-Protokoll mit 12*0 und 1*1 eingeleitet, also 12 Nullen und eine Eins. Dann folgt der Hauscode, aufgeteilt auf HC1 und HC2 , die Adresse des Schalters, der Befehl und eine Prüfsumme. Das Programm wartet in einer Kommandoschleife auf ein Kommando.
Zum Testen sind noch einige Hilfsmittel implementiert:
Befehl 1 : Fragt nacheinander HC1,HC2, Adresse und Befehl ab
Befehl 2 : fragt nur Adressen und Befehl ab, HC1 und HC2 sind fest codiert
Befehl 3 : Zum Testen ohne Sender mit einer LED zwischen Data und GND kann die Datenübertragung gestestet werden, dabei werden beide LED für etwa 2 sec angeschaltet. Ohne die zweite LED kann hier die Spannung auf Data kontrolliert werden. Sie sollte knapp unter der Versorgungsspannung von 2,6V liegen.

Befehl 4 : Sendet 1,1,1,1 und die Prüfsumme 4+6=10
 
Für die Berechnung des Hauscodes gilt:

Die Übersetzung von an Sendern eingegebenen Adresscodes und Hauscodes erfolgt durch Herabsetzen der Tastennummer um 1 und Hintereinandersetzen der Halbnibbles vom ersten als höchstwertigen bis zum letzten als niedrigstwertigen
 
Ein Beispiel:

Der Hauscode wurde in einem Schalter als 12344433 eingegeben. Dies entspricht 01233322 zur Basis 4, das ist 1BFA zur Basis 16. HC1 ist damit 0x1B, HC2 ist 0xFA,

Man teilt 01233322 Teilgruppen 01  23 33 22 zur Basis 4 , also ergibt sich 0*4 +1 = 1;  2 * 4 + 3 = 11 = B ; 3*4+3=15=F; 2*4+2=10 = A, also 1BFA  damit HC1 = 1B HC2 = FA
 
Die Geräteadresse und der Befehl werden genauso berechnet.
Für das erste Gerät gilt  11 und 11 , also 00 und 00  : 0 = 0*4 +0 = 0, und 0*0 +0 = 0; als0 adr = 00
Für den Befehl aus gilt 0 , für an kann man alles >= 1 und < 18 verwenden. Die Sender verwenden meistens 17.

Bei ELV gibt es ein PDF-Dokument, dass tabellarisch die Umrechnung zeigt. Man findet es in der Software eventghost, dort im Verzeichnis des FS20 PCE –PlugIn.

Sehr empfehlenswert ist es,  sich den Bausatz für den FS20PCE Empfänger von ELV zu besorgen. Alle SMD-Arbeiten sind erledigt und man muss nur noch ein Kabel und eine LED einlöten, sowie den Empfänger über 3 Pins. Der Empfänger wird über USB angeschlossen.

Mit der Software Eventghost und dem FS20PCE-PlugIn kann man genau mitverfolgen, was von einem FS20-Sender gesendet wird. Mit der Software ist auch das Problem gelöst, wie man an die Daten aus dem USB-Empfänger herankommt. Das ist erheblich komplizierter als nur einen Befehl zu senden, da der Empfänger ein Signal erkennen und an den Rechner einen Event senden muss.

Funktioniert der Sender am Tiny13 korrekt, so muss dann die LED am Empfänger kurz verlöschen und ein neuer Eintrag im Log erscheinen.

Download: FS20_01.asm


; Ansteuerung eines FS20 Gerätes, nur senden
// --------------------------------------------------------------
//
// vom Rechner aus über RS232
// Schreiben : 1 senden Rückgabe 1
// : HC1 Adresse senden Rückgabe HC1
// : Hc2 Adresse senden Rückgabe HC2
// : Adresse senden Rückgabe Adress
// : Kommando senden Rückgabe Kommando
// : Checksumme wird intern berechnet
// Rückgabe : 111 nach Abschluss

// Kurzform mit hart codiertem Hauscode
// Schreiben : 2 senden Rückgabe 2
// HC1 und HC2 vorgegeben
// Adresse senden Rückgabe Adress
// Kommando senden Rückgabe Kommando
// Checksumme wird intern berechnet
// Rückgabe : 222 nach Abschluss
//
// Testkommando 3 , dann müssen beide LED kurz blitzen

// Testkommando 4:
// Zum Test des Signals mit dem Oszillographen
// sendet 1 1 1 1 mit checksum 6+4=10 , beachte chks startet mit 6
// eventghost sollte mit FS20PCE.11121112.dodim6% antworten

// Version 01 vom29.4.2010
// noch einige Kontrollausgaben zum Debuggen



// todo
// Warum 6 wiederholungen?
// Rückgabe der Durchläufe nicht programmiert

.include "tn13def.inc"

.def A = r16
.def B = r17
.def C = r18
.def D = r19
.def E = r20
.def Count = r21
.def Delay = r22
.def loop01 = r23
.def loop10 = r24
.def Index = r25



;Port B
.equ TXD = 1
.equ RXD = 2
.equ transmit = 3 ; PB3
.equ led = 4 ; PB4



rjmp Anfang
Anfang:
sbi ddrb,TXD ;Datenrichtung TXD
sbi ddrb,transmit
sbi ddrb,led

Schleife:
rcall RdCom
mov Index,A
cpi Index,1
brne K2

befSendeFS20:
rcall WrCom
rcall tueSendeFS20
ldi A,111
rcall WrCom ; Kontrollausgabe Befehl ausgefuehrt
rjmp Schleife

K2: cpi Index,2
brne k3

kurzBefSendeFS20:
rcall WrCom
rcall tuekurzBefSendeFS20
ldi A,222
rcall WrCom ; Kontrollausgabe Befehl ausgefuehrt
rjmp Schleife

K3: cpi Index,3
brne k4

irgendwas:
rcall WrCom
rcall tueIrgendwas
rjmp Schleife


K4: cpi Index,4
brne kGroesser

testsignal:
rcall WrCom
rcall tuetestsignal
rjmp Schleife


Kgroesser:
Rcall WrCom
rjmp Schleife

tuetestsignal: rcall fs20_sendsync
ldi A,1
rcall fs20_send_byte
ldi A,1
rcall fs20_send_byte
ldi A,1
rcall fs20_send_byte
ldi A,1
rcall fs20_send_byte
ldi A,10 ; beachte Checksumme faengt mit 6 an
rcall fs20_send_byte
rcall fs20_send_zero;
rcall warte10ms

rcall fs20_sendsync
ldi A,1
rcall fs20_send_byte
ldi A,1
rcall fs20_send_byte
ldi A,1
rcall fs20_send_byte
ldi A,1
rcall fs20_send_byte
ldi A,10
rcall fs20_send_byte
rcall fs20_send_zero;
rcall warte10ms
rcall fs20_sendsync
ldi A,1
rcall fs20_send_byte
ldi A,1
rcall fs20_send_byte
ldi A,1
rcall fs20_send_byte
ldi A,1
rcall fs20_send_byte
ldi A,10
rcall fs20_send_byte
rcall fs20_send_zero;
rcall warte10ms
ret

tueIrgendwas: sbi portb,led ; nur zum Testen kurz Blinken
sbi portb,transmit
rcall warte255
cbi portb,transmit
cbi portb,led
ret

tuekurzBefSendeFS20:
; Parameter von der RS232 lesen
ldi A,xxx ; testHC1, hier richtigen Wert eintragen
mov B,A ; HC1 nach B

ldi A,xxx ; Test HC2, hier richtigen Wert eintragen
mov C,A ; HC2 nach C

rcall RdCom
mov D,A ; Adresse nach D
rcall WrCom
rcall RdCom
mov E,A ; Befehl nach E
rcall WrCom

ldi XL,96 ; Ram-Pointer vorbereiten
ldi XH,0
mov A,B
st X+,A ; HC1 sichern
mov A,C
st X+,A ; HC2 sichern
mov A,D
st X+,A ; Adresse sichern
mov A,E
st x+,A ; Befehl sichern

rcall SendeFS20Kommando
ret

tueSendeFS20: ; Parameter von der RS232 lesen
rcall RdCom
mov B,A ; HC1 nach B
rcall WrCom
rcall RDCom
mov C,A ; HC2 nach C
rcall WrCom
rcall RdCom
mov D,A ; Adresse nach D
rcall WrCom
rcall RdCom
mov E,A ; Befehl nach E
rcall WrCom

ldi XL,96 ; Ram-Pointer vorbereiten
ldi XH,0
mov A,B
st X+,A ; HC1 sichern
mov A,C
st X+,A ; HC2 sichern
mov A,D
st X+,A ; Adresse sichern
mov A,E
st x+,A ; Befehl sichern

rcall SendeFS20Kommando
ret

SendeFS20Kommando: ; die Parameter liegen auf im RAM ab 96 . HC1 , HC2, Adresse, Befehl
push E
push D
push A
sbi portb,led ; LED einschalten nicht fuer Test, siehe fs20_SendOne

ldi E,3 ; 3 mal wiederholen

sendeschleife: rcall fs20_sendsync
mov A,E
//rcall WrCom ; Kontrollausgabe Schleifenindex

ldi D,6 ; checksum faengt mit 6 an!!!
ldi XL,96 ; Ram pointer setzen
ldi XH,0

ld A,X+ ; HC1 aus Ram
add D,A ; checksumme erhoehen
rcall fs20_send_byte ; HC1 senden

ld A,X+ ; HC2 aus Ram
add D,A ; checksumme erhoehen
rcall fs20_send_byte ; HC2 senden

ld A,X+ ; Adresse aus Ram
add D,A ; checksumme erhoehen
rcall fs20_send_byte ; Adress senden

ld A,X+ ; Befehl aus Ram
add D,A ; checksumme erhoehen
rcall fs20_send_byte ; Befehl senden

mov A,D
rcall fs20_send_byte ; Checksumme senden
rcall fs20_send_zero;

rcall warte10ms
mov A,E

dec E
brne sendeschleife

exitS: ; wird nur im Test benutzt
cbi portb,led ; LED ausschalten
pop A
pop D
pop E
ret



fs20_sendsync: rcall fs20_Send_zero
rcall fs20_Send_zero
rcall fs20_Send_zero
rcall fs20_Send_zero
rcall fs20_Send_zero
rcall fs20_Send_zero
rcall fs20_Send_zero
rcall fs20_Send_zero
rcall fs20_Send_zero
rcall fs20_Send_zero
rcall fs20_Send_zero
rcall fs20_Send_zero
rcall fs20_Send_one
ret


fs20_send_byte: ; Wert in A erwartet
push Count
push C
push D
push A
ldi Count,8 ; Schleife über 8 Bit
ldi C,0 ; fuer Parityberechnung

schleife1:
sbrc A,7 ; Teste ob Bit 7 gesetzt ( im Ausgabewert)
rjmp Bit7on
rjmp Bit7off
Bit7on:
ldi D,1
eor C,D
rcall FS20_Send_One
rjmp clockit

Bit7off: ldi D,0
eor C,D ; XOR mit E
rcall fs20_Send_Zero
rjmp clockit
clockit:

lsl A ; A Shiftleft
dec Count ; nachstes Bit
brne schleife1 ; alle Bits bearbeitet?

sbrc C,0 ; Teste ob Paritiybit nicht gesetzt wird
rjmp parityoff
rjmp parityon
parityon:
rcall fs20_Send_zero
rjmp paritydone

parityoff:
rcall fs20_send_One
rjmp paritydone
paritydone:
pop A
pop D
pop C
pop Count
ret


; sendet eine 1 für den ersten Test ist es sinnvoll hier auch die led ein und auszuschalten
; dann kann man 0 und 1 unterscheiden wenn der Sender durch eine led ersetzt ist
fs20_Send_One:
; sbi portb.led ; beim Test
Sbi portb,transmit
rcall warte600us
cbi portb,transmit
rcall warte600us
; cbi portb,led ; beim Test
ret
; sende eine 0
fs20_Send_zero:
sbi portb,transmit
rcall warte400us
cbi portb,transmit
rcall warte400us
ret

warte400us: rcall warte01ms
rcall warte01ms
rcall warte01ms
rcall warte01ms
ret

warte600us: rcall warte01ms
rcall warte01ms
rcall warte400us
ret



; Warteschleife für 0,1 ms = 100 microsec

warte01ms:
ldi Loop01, 17 ; Beim Nachmessen mit dem Oszi sind es aber nur 17
L01: ;rcall warte255 ; lange Warteschleife bei Test um die Bits zu zaehlen
nop ; 1 Takt
nop ; 1 Takt
nop ; 1 Takt
dec Loop01 ; 1 Takt
brne L01 ; 2 Takte also 6*20 = 120 Zyklen bei 1,2 MHz
ret

; Warteschleife für 10 ms

warte10ms:
ldi Loop10,100
L10:
rcall warte01ms
dec Loop10
brne L10
ret


RdCOM: sbis pinb,RXD ;Empfangen
rjmp RdCOM
ldi Delay,58
D1: dec Delay
brne D1
ldi A,0
ldi Count,8
L1: lsr A
sbic pinb,RXD
ori A,128
ldi Delay, 38
D2: dec Delay
brne D2
dec Count
brne L1
ldi Delay, 38
D3: dec Delay
brne D3
com A
ret

WrCOM: sbi portb,TXD ;Senden
ldi Delay,38
D4: dec Delay
brne D4
ldi Count,8
L2: sbrc A,0
rjmp OFF
rjmp ON
ON : sbi portb,TXD
rjmp BitD
OFF: cbi portb,TXD
rjmp BitD
BitD: ldi Delay,38
D5: dec Delay
brne D5
lsr A
dec Count
brne L2
cbi PORTB,TXD
ldi Delay,38
D6: dec Delay
brne D6
ret


// nur zum Testen
warte255: ; zum Testen wartet zusaetzlich etwa 500ms
push count
ldi count,255
L255: rcall warte255innen
dec count
brne L255
pop count
vret
warte255innen:
push index
ldi index,255
Li255:
rcall warte01ms
dec index
brne Li255
pop index
ret





zurück