von Victor Klein
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.
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.
.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
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.
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