The Man
08.09.2007, 19:22
Ich verwende das 130428 Sende-Empfangsset von Corad.
Allerdings habe ich eben gesehen, dass die Dinger gut an Preis zugelegt haben...
Bis jetzt habe ich nur den Empfangsseitigen Teil beschrieben. Hoffe, dass ist was geworden. Wenn das jemand komplett ließt, bin ich für eine kurze Meinung zu haben - also von wegen sinnvoller Aufbau der Beschreibung etc. Das Prog ist sicher noch nicht optimal, aber es arbeitet. Vor dem lesen am besten erst mal das Bild ansehen, ich weiß leider nicht, wie ich das mache, dass man es nicht extra öffnen muss, sondern so sehen kann.
Normalerweise muss man den Sender mit Manchestercode versorgen, den ich aber nicht codieren kann.
Da ich dann raugefunden habe, dass es auch möglich ist, bis zu einer bestimmten Frequenz HIGH LOW
Signale zu übertragen, bin ich dazu übergegangen, über Pulsweiten log. einsen und nullen zu
übertragen. Zudem ist die Eigenschaft wichtig, dass durch dauerhaftes anlegen eines High Signales am Sender
der Empfänger definiert LOW gehalten werden kann, außerdem wird der Empfänger ohne Signal von anderen Quellen
gestört.
Grobes Prinzip der Übetragung:
Das Prinzip des Senders ist, dass in ein Register ein Bitmuster geladen wird.
An diesem Register wird das MSB auf eins oder null getestet. Anhand vom Ergebnis wird die nächste
Pulsweite entweder lang oder kurz. Danach wird ein logic left shift ausgeführt. Das Ganze dann acht mal.
Im Empfänger wird auf ein Register ERST (und das ist wichtig) ein lsl angewendet und dann
je nach Pulslänge das Register mit einer ori 0b00000001 Operation erhöht oder auch nicht. Auch
dass muss sinngemäß achtmal passieren. Gemessen wird
die Dauer zwischen zwei externen Interrupten. Dabei wird bei jedem logik Wechsel getriggert.
Sind die achtmal erreicht, wird das Register ausgelesen und entsprechend der Kodierung eine Aktion
ausgeführt.
Für das Verständis des Systems ist es am besten auf der Empfangsseite anzufangen.
Bei der Entwicklung des Sederprog´s wurde auch hier begonnen.
Das erste Problem das es zu behandeln gilt ist, dass solange der Sender kein Signal gibt, der Empfänger
undefiniert schaltet. Deshalb befinden sich die prozessrelevanten Register in einem
undefinierten Zustand.
Das sind:
TCCR wird nicht im INIT Code gesetzt
TCNT zur Teitmessung
shf das Register aus dem das gesendete Bitmuster ausgelesen wird
shfc in diesem Register wird gezählt, wie oft der ext. INT. erfolgte (das c steht für counter)
Um genau das zu beheben, dient die lange Pulsdauer zu Beginn des Sigales. Im Empfänger wird bei einem
Comparematch mit OCR2 = 100 ein Interrupt ausgelößt, in dessen ISR (definiren) die oben genannten
Register = 0 gesetzt werden.
Ab dem ersten LOW Pegel danach sind die Intervalle zu kurz, um einen Comparematch zu triggern
und es läuft nur noch die ISR des ext Int. (inter). Zu jedem Anfang wird der TIMER mit Prescaler = 64 gestartet,
obwohl das nur beim ersten mal nötig währe.
Das nullsezten von TCNT passiert "manuell" am Edne der ISR.
Für das spätere verstehen der Programme ist es wichtig, zu beachten, das shfc nach dem Fall der ersten
Flanke bereits = 1 ist, ohne das schon ein Bit übertragen wurde.
Steigt die Flanke wieder, passiert das selbe. Erst ab dem Fallen des rot makierten HIGH Pegels findet
die erste relevante Zeitmessung statt. Diese Zeit wird aber erst während des grün makierten LOW Pegels ausgewertet.
Aus diesem Zusammenhang folgert bereits, das ein Pegel mehr existiert (gelb), als man vielleicht erstmal für nötig hält.
Daher endet shfc letztendlich auch bei 11, die sich im Sendeprogramm wiederfinden wird!
Diese 11 sind 3 mehr, als für das einlesen von 8 Bit nötig sind und OH, welch wunder, diese Differenz findet sich
im Proramm des Empfängers. (Kommentar dazu im Code)
Hat shfc den WERT 11 errreicht, wird shf ausgelesen.
.include "m8def.inc"
.def shf = r20
.def tmp = r16
.def shfc = r21
.def aus = r22
.def zeit = r23
.def merker = r24
.def an = r25
.def timer = r17
.org 0x0000
rjmp reset
.org INT1addr
rjmp inter
.org OC2addr
rjmp definieren
reset:
;Stack wird bei Interrupts benötigt!
ldi r16,HIGH(RAMEND)
out SPH,r16
ldi r16,LOW(RAMEND)
out SPL,r16
ldi tmp,0b00000100
out MCUCR,tmp ;int @ ext logicchange
ldi tmp,0b10000000
out GICR,tmp
ldi tmp,0b11110111
out DDRD,tmp
com tmp
out PORTD,tmp
ldi tmp,0b00001000
out DDRB,tmp
ldi tmp,0b10000000
out TIMSK,tmp ;int @ OCR2
ldi timer,0b00000100
;out TCCR2,timer
ldi tmp,100
out OCR2,tmp
sei
ldi aus,0
ldi an,255
mainloop:
; wie cool, das Programm läuft
; ohne einen MAIN Code - BÄM!
rjmp mainloop
definieren:
out TCCR2,aus
ldi shf,0
ldi shfc,0
;out PORTD,aus
out TCNT2,aus
reti
inter:
inc shfc
out TCCR2,timer
cpi shfc,2 ;da der shfc Wert des letzten Pegels keine Rolle spielt,
brlo later ;da dort nur die letzte Zeit verarbeitet wird,
lsl shf ;ergibt sich mit der 2 die Different von drei
in tmp,TCNT2
cpi tmp,45 ;Schwellwert für log eins oder null
brlo lognull
ori shf,1
lognull:
;________________________________________
cpi shfc,10 ;
brlo later ;wenn shfc 10 ist,
;wurden die 8 BIT in shf
cpi shf,0b00010001 ;eingelesen und können verarbeitet
breq on ;werden. Hier mit dem setzten oder
cpi shf,0b00010010 ;löschen vom PINB 3
breq off ;
rjmp nocommand ;
;
on: ;
ldi tmp,0b00001000 ;
out PORTB,tmp ;
rjmp nocommand ;
off: ;
ldi tmp,0 ;
out PORTB,tmp ;
nocommand: ;_________________________________________
mov tmp,shf
andi tmp,0b11110111
out PORTD,tmp ;dient zur visuellen Kontrolle des eingegangenen Befehls
ldi shfc,0 ; und während der Entwicklungszeit für so manche Überraschung^^
ldi shf,0
out TCCR2,aus
later:
out TCNT2,aus
reti
[/url]
Allerdings habe ich eben gesehen, dass die Dinger gut an Preis zugelegt haben...
Bis jetzt habe ich nur den Empfangsseitigen Teil beschrieben. Hoffe, dass ist was geworden. Wenn das jemand komplett ließt, bin ich für eine kurze Meinung zu haben - also von wegen sinnvoller Aufbau der Beschreibung etc. Das Prog ist sicher noch nicht optimal, aber es arbeitet. Vor dem lesen am besten erst mal das Bild ansehen, ich weiß leider nicht, wie ich das mache, dass man es nicht extra öffnen muss, sondern so sehen kann.
Normalerweise muss man den Sender mit Manchestercode versorgen, den ich aber nicht codieren kann.
Da ich dann raugefunden habe, dass es auch möglich ist, bis zu einer bestimmten Frequenz HIGH LOW
Signale zu übertragen, bin ich dazu übergegangen, über Pulsweiten log. einsen und nullen zu
übertragen. Zudem ist die Eigenschaft wichtig, dass durch dauerhaftes anlegen eines High Signales am Sender
der Empfänger definiert LOW gehalten werden kann, außerdem wird der Empfänger ohne Signal von anderen Quellen
gestört.
Grobes Prinzip der Übetragung:
Das Prinzip des Senders ist, dass in ein Register ein Bitmuster geladen wird.
An diesem Register wird das MSB auf eins oder null getestet. Anhand vom Ergebnis wird die nächste
Pulsweite entweder lang oder kurz. Danach wird ein logic left shift ausgeführt. Das Ganze dann acht mal.
Im Empfänger wird auf ein Register ERST (und das ist wichtig) ein lsl angewendet und dann
je nach Pulslänge das Register mit einer ori 0b00000001 Operation erhöht oder auch nicht. Auch
dass muss sinngemäß achtmal passieren. Gemessen wird
die Dauer zwischen zwei externen Interrupten. Dabei wird bei jedem logik Wechsel getriggert.
Sind die achtmal erreicht, wird das Register ausgelesen und entsprechend der Kodierung eine Aktion
ausgeführt.
Für das Verständis des Systems ist es am besten auf der Empfangsseite anzufangen.
Bei der Entwicklung des Sederprog´s wurde auch hier begonnen.
Das erste Problem das es zu behandeln gilt ist, dass solange der Sender kein Signal gibt, der Empfänger
undefiniert schaltet. Deshalb befinden sich die prozessrelevanten Register in einem
undefinierten Zustand.
Das sind:
TCCR wird nicht im INIT Code gesetzt
TCNT zur Teitmessung
shf das Register aus dem das gesendete Bitmuster ausgelesen wird
shfc in diesem Register wird gezählt, wie oft der ext. INT. erfolgte (das c steht für counter)
Um genau das zu beheben, dient die lange Pulsdauer zu Beginn des Sigales. Im Empfänger wird bei einem
Comparematch mit OCR2 = 100 ein Interrupt ausgelößt, in dessen ISR (definiren) die oben genannten
Register = 0 gesetzt werden.
Ab dem ersten LOW Pegel danach sind die Intervalle zu kurz, um einen Comparematch zu triggern
und es läuft nur noch die ISR des ext Int. (inter). Zu jedem Anfang wird der TIMER mit Prescaler = 64 gestartet,
obwohl das nur beim ersten mal nötig währe.
Das nullsezten von TCNT passiert "manuell" am Edne der ISR.
Für das spätere verstehen der Programme ist es wichtig, zu beachten, das shfc nach dem Fall der ersten
Flanke bereits = 1 ist, ohne das schon ein Bit übertragen wurde.
Steigt die Flanke wieder, passiert das selbe. Erst ab dem Fallen des rot makierten HIGH Pegels findet
die erste relevante Zeitmessung statt. Diese Zeit wird aber erst während des grün makierten LOW Pegels ausgewertet.
Aus diesem Zusammenhang folgert bereits, das ein Pegel mehr existiert (gelb), als man vielleicht erstmal für nötig hält.
Daher endet shfc letztendlich auch bei 11, die sich im Sendeprogramm wiederfinden wird!
Diese 11 sind 3 mehr, als für das einlesen von 8 Bit nötig sind und OH, welch wunder, diese Differenz findet sich
im Proramm des Empfängers. (Kommentar dazu im Code)
Hat shfc den WERT 11 errreicht, wird shf ausgelesen.
.include "m8def.inc"
.def shf = r20
.def tmp = r16
.def shfc = r21
.def aus = r22
.def zeit = r23
.def merker = r24
.def an = r25
.def timer = r17
.org 0x0000
rjmp reset
.org INT1addr
rjmp inter
.org OC2addr
rjmp definieren
reset:
;Stack wird bei Interrupts benötigt!
ldi r16,HIGH(RAMEND)
out SPH,r16
ldi r16,LOW(RAMEND)
out SPL,r16
ldi tmp,0b00000100
out MCUCR,tmp ;int @ ext logicchange
ldi tmp,0b10000000
out GICR,tmp
ldi tmp,0b11110111
out DDRD,tmp
com tmp
out PORTD,tmp
ldi tmp,0b00001000
out DDRB,tmp
ldi tmp,0b10000000
out TIMSK,tmp ;int @ OCR2
ldi timer,0b00000100
;out TCCR2,timer
ldi tmp,100
out OCR2,tmp
sei
ldi aus,0
ldi an,255
mainloop:
; wie cool, das Programm läuft
; ohne einen MAIN Code - BÄM!
rjmp mainloop
definieren:
out TCCR2,aus
ldi shf,0
ldi shfc,0
;out PORTD,aus
out TCNT2,aus
reti
inter:
inc shfc
out TCCR2,timer
cpi shfc,2 ;da der shfc Wert des letzten Pegels keine Rolle spielt,
brlo later ;da dort nur die letzte Zeit verarbeitet wird,
lsl shf ;ergibt sich mit der 2 die Different von drei
in tmp,TCNT2
cpi tmp,45 ;Schwellwert für log eins oder null
brlo lognull
ori shf,1
lognull:
;________________________________________
cpi shfc,10 ;
brlo later ;wenn shfc 10 ist,
;wurden die 8 BIT in shf
cpi shf,0b00010001 ;eingelesen und können verarbeitet
breq on ;werden. Hier mit dem setzten oder
cpi shf,0b00010010 ;löschen vom PINB 3
breq off ;
rjmp nocommand ;
;
on: ;
ldi tmp,0b00001000 ;
out PORTB,tmp ;
rjmp nocommand ;
off: ;
ldi tmp,0 ;
out PORTB,tmp ;
nocommand: ;_________________________________________
mov tmp,shf
andi tmp,0b11110111
out PORTD,tmp ;dient zur visuellen Kontrolle des eingegangenen Befehls
ldi shfc,0 ; und während der Entwicklungszeit für so manche Überraschung^^
ldi shf,0
out TCCR2,aus
later:
out TCNT2,aus
reti
[/url]