PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Funkmodule 130428-99 von Conrad



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]

The Man
16.09.2007, 09:15
M´kay, nachdem jetzt der Empfänger abgehandelt ist,
wollen wir uns mal der Generierung des Sendesingnales zuwenden.
Bei dem ersten Blick, fälllt bereits auf, dass es hier etwas wüster zugeht,
als im Empfänger.


Als Kern der eigentlichen Senderroutine wird hier der Comparematch mit dem OCR2 Register
zur Pulsweiten Variation genutzt. Dazu an gegebener Stelle mehr.

Der erste Teil in der Mainschleife soll den Befehl aufnehemen,
der gesendet werden soll. In diesem ersten Prog ist das nur einmal das Bitmuster
00010001 oder 00010010. Der eine Befehl schaltet eine Lampe ein, der andere aus.
Es ist auf jeden Fall ratsam, immer min. zwei BIT´s 1 zu setzen, um eine gewisse
Störsicherheit zu erreichen. Jedoch reicht auch das auf längere Zeit nicht. Ich werde
daher dazu übergehen, 16 BIT´s zu kodieren.


Nach diesem ersten Teil wird getestet, ob der neue Befehl auch tatsächlich neu ist und nicht
bereits gesendet wurde, wovon abhängt, ob dann überhaupt gesendet wird. Da muss man sich aber
überlegen, ob das nötig ist. Z.B. würden erhöhende und erniedrigende Befehle
auch mehrmals Sinn machen.

Nachdem das alles abgehandlet ist, wird der PIN, an dem der Sender hängt HIGH gesetz,
und eine Warteschleife aufgerufen, die bis TCNT2 = 250 dauert. An dieser Stelle ist
der Interrupt Enable für OCR2 noch inaktiv.
Nach dieser Funktion wird der zu sendende Befehl in einem zweiten Register zum späteren
vergleichen abgespeichert.

Darauf folgt die INIT Funktion, in welcher der Interrupt des Comparematches aktiv wird, der TNCT2
wird null gesetzt, an OCR2 der Wert 60 übergeben und der zu sendede Befehl in das shift Register shf
kopiert. Auf dieses wird später die LSL Operation angewendet.

Nun kommt endlich der interessante Teil, die eigentliche Senderoutine.
In diese ist eine Schleife progammiert, die elf mal durchlaufen wird.
In shfc wird festgehalten, wie oft die ISR aufgerufen wurde.

mehr1:
cpi shfc,11 (aus irgendeinem Grund
brlo mehr1 ist die doppelte abfrage
cpi shfc,11 nötig, sonst wird die Schleife
brlo mehr1 einen Zyklus zu früh verlassen -
ldi shfc,0 hat was mit einem der Statusbits zu tun)

Die Erklärung für die elf Mal
findet sich in der Erläuterung des Empfangprog´s.
Diese Schleife kann erst nach dem senden aller Datenbits verlassen werden. Vorher
wird sie mit der Verarbeitungsgeschwindigkeit wiederholt. Unterbrochen wird das nur
durch einen Comparematch mit OCR2, also beim ersten Mal bei TCNT2 = 60.
Daraufhin wird die ISR "hitvalue" aufgerufen.

Dort wird als erstes der logische Pegel, an dem der Sender sitzt, ivertiert. Das geht
Hand in Hand mit der Einstellung des Empfängers, der bei einem logischen Wechsel an INT1
interruptet.
Als zweites wird geprüft, ob die ISR im ersten Durchlauf ist, denn dann war der Interrupt zum
initialisieren des Empfängers.
Ist es jedoch mindestens der zweite Durchlauf, wird in Abhängigkeit des M(ost) S(inificant) B(it)
von shf die nächste Pulsdauer bestimmt und die besagte LSL Op auf shf gemacht.

ldi dauer,60
sbrs shf,7
ldi dauer,30
lsl shf

Als letztes wird shfc um eins erhöht.
Dann wird über reti wieder in die Schleife der Funktion senden1

cpi shfc,11
brlo mehr1
cpi shfc,11
brlo mehr1

zurückgesprungen.

Sind die elf Mal erreicht, wird der Interrupt durch OCR2 wieder deaktiviert und eine Warteschleife
auf Basis von TCNT0 bis 30 ausgeführt.
Danach wird der PIN wierder LOW gesetzt und nach MAIN zurückgekehrt.

Die Ganze Fummelei mit dem TIMSK könnte man im Prinzip auch mit sei; und cli machen, aber villeicht will man ja mal noch andere Interrupte nutzten, Tastermatrix z.B.



.include "m8def.inc"

.def shf = r17
.def shfc = r18
.def dauer = r19
.def zwischen = r20
.def tmp = r21
.def timermaskon = r22
.def timermaskoff = r23
.def befehl = r24
.def t = r25
.org 0x0000
rjmp reset
.org OC2addr ; OCR2 Interrupt Vector Address
rjmp hitvalue
reset:

;Stack wird bei Interrupts benötigt!
ldi r16,HIGH(RAMEND)
out SPH,r16
ldi r16,LOW(RAMEND)
out SPL,r16
ldi r16,0b01100000 ;internal Vref - Channel 0
out ADMUX,r16
ldi r16,0b10001110 ;singleconversion - prescaler 32 - int.enable
out ADCSRA,r16
ldi r16,0b11111110
out DDRC,r16
;out PORTC,r16
ldi r16,0b11110111
out DDRD,r16
ldi r16,0b00000011
out TCCR0,r16
ldi timermaskoff,0
ldi tmp,0b00001100 ;interuppt on comparematch - presc 128
out TCCR2,tmp
;ldi r16,255
;out OCR2,r16
ldi timermaskon,0b10000000
sei

mainloop:
wdr

sbic PIND,3
rjmp open
sbis PINB,5
ldi befehl,0b00010001
sbis PINB,4
ldi befehl,0b00010010
open:



cp zwischen,befehl
breq unten
ldi tmp,255
out PORTC,tmp
rcall pause
mov zwischen,befehl
rcall init
rcall senden1
ldi t,0
hoch:
sbic PIND,3
rjmp hoch
unten:
rjmp mainloop

pause:
ldi tmp,0
out TCNT0,tmp
warten:
in tmp,TCNT0
cpi tmp,250
brlo warten
ldi tmp,0
out TCNT0,tmp

ret

init:
ldi tmp,0
out TCNT2,tmp
ldi tmp,60
out OCR2,tmp
mov shf,befehl
out TIMSK,timermaskon
ret

senden1:
mehr1:
cpi shfc,11
brlo mehr1
cpi shfc,11
brlo mehr1
ldi shfc,0
out TCNT0,shfc
out TIMSK,timermaskoff
warten2:
in tmp,TCNT0
cpi tmp,30
brlo warten2
ldi tmp,0
out TCNT0,tmp
ldi tmp,0
out PORTC,tmp
ret

hitvalue:
in tmp,PORTC
com tmp
out PORTC,tmp

cpi shfc,1
brlo senden

ldi dauer,60
sbrs shf,7
ldi dauer,30
lsl shf

out PORTD,dauer
out OCR2,dauer
senden:
inc shfc
reti


Kommentar:

Nch dem schreiben sind mir einoge Dinge aufgefallen, die noch nicht perfekt sind. Zum ersten kann ich sicher das erste INIT Bit schon als Datenbit nutzten und zum anderen in der senden1 Funktion die Warteschleife mit dem TCNT0 müsste auch wie zuvor über den Interrupt gehen.
Und wenn jemand weiß, woran das liegt, das ich die elfer Schleife zweimal brauche, bin ich dankbar für eine Erklärung.

Wenn ich dann mal die Zeit habe, mache ich mal eine Schaltungsskizze.

The Man

roboterheld
16.09.2007, 14:14
sau teuer die dinger bei c , wer die jetzt kauft hat selber schuld.
ausserdem sind die nicht sehr leistungsfähig.
hatte ich auch mal wo die sehr günstig waren, habe die bald aus dem fenster geschmissen, der letzte dreck.

habe mir funk-rs232 von robotikhardware geholt.

mf

The Man
16.09.2007, 16:22
Also ich finde nicht, dass der Ton Not tut.
Das man seine Meinung hat ist natürlich in Ordnung,
nur ein bisschen differenzierter darf´s schon sein.

roboterheld
16.09.2007, 17:33
habe ich nicht deutlich geschrieben. du wirst deine erfahrungen da noch mit machen, wenn es um eine sichere übertragung gehen soll und nicht nur eben mal einpaar bytes rüberschieben nach dem motto : oh, guck mal die 16 euro-dinger machen ja etwas !

mfg

The Man
16.09.2007, 18:42
Da hast du natürlich Recht, als ich mich an die max Frequenz rangetastet habe, war bald klar, das ich von Kib/s weit weg bin. Bei mir geht´s auch letztendlich nur um ein paar an aus etc. Signale.
Aber seit dem die an Preis zugelegt haben, werde ich doch auf die POLLIN rfm 12 zurückgreifen...

roboterheld
16.09.2007, 19:27
...SPI-Schnittstelle kann das Modul leicht mit einem Microcontroller programmiert und angesteuert werden......


leicht ist übertrieben.

hier gibt es ein thread dafür, der ist schon über 455 antworten lang.
machen auch schön schwierigkeiten.

http://www.mikrocontroller.net/forum/mikrocontroller-elektronik?filter=rfm12

http://www.mikrocontroller.net/topic/65984#new