Hallo,
Ich habe vor kurzem die nachfolgende
(http://www.seeedstudio.com/wiki/433Mhz_RF_link_kit )
433Mhz RF-Modul gekauft um ein Fernbedienung zu bauen.
Da ich ein Hobby Bastler bin besitze ich wenig Erfahrung im bereich RF
und PIC.
Ich will eigentlich nur Taste => LED_ON oder Taste => LED_OFF
Es klappt auch aber irgendwie nur einmal hin und wieder nicht stabil.
SENDER:
void main()
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_comparator(NC_NC);
setup_vref(FALSE);
while(1)
{
int8 c=0;
int TasteY;
int Tastex;
Tastex=input(PIN_A1);
if(Tastex==1)
{
c=1;
printf("%x\n\r",c);
}
TasteY=input(PIN_A4);
if (TasteY==1)
{
c=2;
printf("%x\n\r",c);
}
}
EMPFÄNGER:
void main()
{
int8 c=0;
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_comparator(NC_NC);
setup_vref(FALSE);
// TODO: USER CODE!!
while(1)
{
c=getc();
if (c==1)
{
output_high(PIN_A1);
}
else
if (c==2)
{
output_low(PIN_A1);
}
}
Bitte um Hilfe :)
Mal ganz abgesehen von Deinem Code, von dem ich als
Arduino-Programmierer nicht alles verstehe, ein paar Anmerkungen zu den
Fehlerquellen und Hintergründen, die mir zu diesen Sendesets einfallen.
Der Empfänger in Deinem Set ist ein sogenannter "Regenerativempfänger",
der nach dem Prinzip eines automatisch geregelten Rückkopplungs-Audions
arbeitet.
Das heißt: Der Empfänger regelt seine Empfangsempfindlichkeit selbst
immer nach, je nachdem, was er empfängt. Empfängt er nichts, weil gerade
kein starker Sender sendet, dann regelt er die Empfangsempfindlichkeit
so weit hoch, bis er was empfängt. Sofern das dann nicht gerade das
Nutzsignal ist, empfängt er also regelmäßig Datenmüll. Viel Datenmüll.
Wertest Du nur ein einziges Byte aus, dann brauchst Du nur lange genug
warten, bis im Datenmüll-Strom irgendwann das gewünschte Byte kommt -
voila!
Das kann dann das absichtlich gesendete Byte sein. Oder auch nicht.
Auf die Art kannst Du nichts schalten.
Und es geht weiter: Der Empfänger regelt nicht nur seine Empfindlichkeit
automatisch bis zum Empfang von irgendwelchem Datenmüll hoch, wenn
nichts gesendet wird, sondern je nach empfangenen Daten regelt er nach:
kommen viele kurze Null-Bits im Datenstrom, geht die
Empfängeremfindlichkeit hoch. Aber kommen im Datenstrom viele lange
Eins-Bits, regelt er die Empfängerempfindlichkeit runter.
Um dieses laufende Hoch- und Runterregeln der Empfängerempfindlichkeit
zu vermeiden, solltest Du für diese Art Empfängertyp aus dem Set am
besten eine "ausgeglichene Bitfolge" senden, bei der Null-Bits und
Eins-Bits immer schön gemischt gesendet werden, in gleicher Anzahl und
möglichst nur höchstens drei gleiche Bits in Folge bis wieder ein
Bitwechsel auftritt.
Schlechte Bit-Sendefolge für so einen Regenerativempfänger (mehr als
drei Bits in Folge identisch):
00000001
11111110
11110000
Gute Bit-Sendefolgen (ausgeglichene Bitfolgen):
01010101
10101010
01101100
10101001
Für diese Art Empfänger mußt Du immer ein bestimmtes Sendeprotokoll
aussenden, mit schönen, ausgeglichenen Bitfolgen. Nur dann ist eine
vernünftige Reichweite mit solchen Sende-/Emfpängersets erzielbar.
Und auf der Empfangsseite mußt Du ein paar Plausibilitätsprüfungen
durchführen, ob die empfangenen Bytes auch tatsächlich das sein können,
was empfangen werden soll.
Beispiel für ein Sendeprotokoll:
Sende ein paar schöne "Start-Bits" als Folgen von 0-Bits und 1-Bits, zum
Beispiel fünfmal das Byte 0x2a gefolgt von zwei Start-Bytes, vielleicht
0xcc und 0x96, danach Deinen Schaltcode, und zwar einen, bei dem die
Bits schön gemischt vorkommen, nicht gerade 0x01, sondern vielleicht
0x93 zum Einschalten und 0xd2 zum Ausschalten. Am Ende möglichst noch
eine Prüfsumme zur Absicherung des Protokolls, aber das lasse ich mal
weg.
Dann sendest Du zum Einschalten:
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0xcc, 0x96, 0x93
und zum Ausschalten:
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0xcc, 0x96, 0xd2
Also schön gemischte Bitfolgen, und zu Anfang immer die Trainingsbits
aus 0x2a, zwei Startbytes und dann erst das Nutz-Byte
Auf der Empfängerseite sähe die Empfangslogik dann so aus:
- Lauern auf die Startbits in Form von Zeichen 0x2a
(die ersten davon werden möglicherweise nicht sauber empfangen)
- Egal wie oft 0x2a kommt, danach müssen 0xcc, 0x96 kommen
- und dann ist das nächste Byte Dein zu übertragender Schaltbefehl
Ohne ein von Dir festgelegtes Sendeprotokoll, ohne ausgeglichene
Bitfolgen, ohne Trainingsbits am Anfang der Aussendung, kannst Du mit
diesen billigen Modulen keine Reichweite und keine sichere
Datenübertragung erzielen, sondern nur ganz viel Datenmüll im Empfänger
empfangen.
Ich finde diese Transmitter-Receiver-Sets ja klasse, insbesondere des
Preises wegen: Bei China-Versendern im Set für zusammen zwei Euro,
billiger als damit bekommt man eine Funkstrecke nicht hin.
Aber um mit diesen Modulen auch eine ordentliche Reichweite zu erzielen
und "sichere" Daten zu übertragen, kann man eben nicht nur einfach seine
Nutzdaten in den Sender geben und erwarten, dass diese vom Empfänger
genau so empfangen werden, sondern man muß sich bemühen, ein
Funkprotokoll mit ausgeglichenen Bitfolgen zu übertragen.
Vielleicht helfen dir diese Angaben ja, Deine Übertragung "sichererer"
zu bekommen.
Hier noch ein Nachtrag noch zu meinem Posting von gestern, in dem ich
gestern erklärt habe, was man über ASK/OOK-Funkmodule mit
Regenerativempfänger am besten per Funk sendet und wie ein
Übertragungsporotokoll für solche billigen Module aussehen könnte.
Nun noch zum Anschluss der Module und zu Deinem Code, den ich wie gesagt
nicht komplett verstehe, weil ich nirgends erkennen kann, dass die Daten
über eine serielle Schnittstelle gehen sollen.
Am einfachsten programmierbar (aber nicht unbedingt für eine gute
Reichweite am besten) schliesst man diese Module doch an einer seriellen
Schnittstelle an. Dann braucht man sich um das Timing der Bits beim
Senden und Empfangen nämlich keinen Kopf zu machen, das erledigt die
serielle Schnittstelle.
Beim Sender
Data Pin des Sendermoduls ==> Serial TX am Controller
Beim Empfänger:
Data Pin des Empfängermoduls ==> Serial RX am Controller
Und dann haust Du beim Sender die Daten über die serielle Schnittstelle
raus, bzw. sie trudeln beim Empfänger über die serielle Schnittstelle
rein.
In Deinem Code sehe ich beim Sender:
printf("%x\n\r",c);
Und beim Empfänger:
c=getc();
Mal eine Rückfrage zu Deinem Entwicklungssystem:
Wo hast Du in Deiner Entwicklungsumgebung festgelegt, dass im Programm
die Standardausgabe auf TX einer seriellen Schnittstelle umgeleitet
werden soll und wo, dass die Standardeingabe von RX einer seriellen
Schnittstelle kommen soll? Geht das bei Deinem Programmiersystem? Ich
als Arduino-Programmierer müßte die Ein-/Ausgabeumleitung in den Code
meines Programms reinschreiben, damit es funktioniert.
Ich sehe aber nirgends etwas in Deinem Code, mit dem:
- die Standardein-/ausgabe auf eine serielle Schnittstelle umlenkt wird
- irgendwo eine Baudrate gesetzt wird
Wo passiert das?
Kannst Du bei Deinem Entwicklungssystem für die serielle Schnittstelle
irgendwelche Compiler-Direktiven in der Entwicklungsumgebung einstellen,
dass standardmäßig eine serielle Schnittstelle als
Standardein-/ausgabekanal verwendet wird? Ohne eine einzige Codezeile?
Bei mir unter Arduino müßte ich eine Ein-/Ausgabeumleitung auf eine
serielle Schnittstelle per Code erstmal im Programm definieren. Oder ein
"Serial" Objekt aus der Arduino-Library im Programm initialisieren und
die Daten darüber senden und empfangen.
Und welche Baudrate hast Du eingestellt?
Diese billigen Sender/Empfänger können meist nicht viel mehr als 4800
Baud. Falls Du versuchst, die Daten mit deutlich mehr als 4800 Baud zu
senden, also mal die Baudrate auf 4800 oder weniger einstellen.
Hallo Jürgen ,
Ich danke dir zuerst für die Informationen.
Jetzt habe ich wenigstens mein Fehler eingekreist.
Klar der Code sieht nicht informativ aus es sollte ja auch nur ein
Beispiel sein.
Die serielle Schnittstelle ist in der Header Datei deklariert die
baudrate auch.
Der pic16f688 hat die pins RC5 (rx) und RC4 (tx).
wie gesagt die Deklarationen finden in einem anderen Datei statt.
Ich bin zufällig auf diese Module gestoßen dachte mir das es einfach
wäre
aber leider.
Werde heute Abend erneut versuchen und dein Rat befolgen.
Hast du Erfahrung mit solchen Modulen wenn ja welche würdest du mir
empfehlen?
Ugur Onur schrieb:> Hast du Erfahrung mit solchen Modulen wenn ja welche würdest du mir> empfehlen?
Ja, ich finde diese billigen Module sind super. Genau solche funken bei
mir die Wetterdaten wie Temperatur, Luftfeuchte und Regenmenge aus dem
Garten ins Haus, wo sie weiter verarbeitet und ausgewertet werden.
Alerdings habe ich mit dem Funken extrem wenig Aufwand: Für die
Arduino-Plattform gibt es eine sehr schöne C++-Library ("VirtualWire"),
die den gesamten Programmieraufwand in Library-Funktionen kapselt und
das eigentliche "Funken mit Protokoll" ist dann quasi nur noch ein
Einzeiler im selbstgeschriebenen Programm.
Ugur Onur schrieb:> Du hast oben die Prüfsumme erwähnt dies habe ich schon öfters gehört was> bewirkt es
Zusätzliche Sicherheit bei der Datenübertragung.
Wenn Du über Deine Nutzdaten eine Prüfsumme bildest und hinter den
Nutzdaten mitsendest, dann kann der Empfänger die Nutzdaten und
Prüfsumme empfangen und ebenfalls die Prüfsumme anhand der empfangenen
Nutzdaten nochmals selbst errechnen. Wenn die im Empfänger errechnete
Prüfsumme nicht mit der per Funk empfangenen Prüfsumme übereinstimmt,
ist die Übertragung fehlerhaft gewesen.
Ugur Onur schrieb:> Wenn soviele Daten sende dann müsste ich die ja beim empfànger in einem> Array sammeln oder
Die Trainings-Bytes (0x2a) speicherst Du nie in einem Array. Die
Trainings-Bytes dienen nur dazu, dass der Empfänger seine
Empfangsverstärkung auf die Feldstärke Deines Senders optimal einregeln
kann, um den Sender mit so einem billigen Regenerativempfänger klar und
stark und bitgenau zu empfangen.
In Sachen Trainings-Bytes prüfst Du auf Empfängerseite nur, ob eine
ausreichende Anzahl von Trainingsbytes in Folge empfangen wurde und
zählst mit.
Mein Vorschlag (siehe oben) wäre, senderseitig sechs Trainings-Bytes
0x2a zu senden und empfängerseitig zu prüfen, ob mindestens vier dieser
Trainings-Bytes in Folge fehlerfrei empfangen wurden.
In einem Array sammelst Du dann ggf. ab dem ersten Nicht-Trainingsbyte.
Das muss immer das festgelegte erste Startbyte sein. Als zusätzliche
Sicherheit empfehle ich die Verwendung von zwei Startbytes.
Ich poste nochmal meinen Vorschlag von oben mit 6x Trainings-Bytes, 2
verschiedene Start-Bytes und ein Nutz-Byte:
Zum Einschalten senden:
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0xcc, 0x96, 0x93
und zum Ausschalten senden:
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0xcc, 0x96, 0xd2
Du sammelst Bytes dann in einem 3-Bytes Array nur "alles nach 0x2a", und
zwar erst, nachdem mindestens viermal 0x2a empfangen wurde.
Programmlogik des Empfängers:
- empfange vier oder mehr Trainings-Bytes 0x2a in Folge
- dann packe die drei nächsten Bytes in ein 3-Byte-Array
(also erst ab dem ersten Nicht-Trainingsbyte im Array sammeln)
- wenn die ersten zwei Bytes im Array dann 0xcc, 0x96 sind, ist das
dritte Byte das "Schalt-Byte"
(und wenn nicht, starte die Programmlogik neu)
Damit hast Du eine recht hohe Sicherheit für die Erkennung Deiner
Schaltimpulse sogar ohne Prüfsummen oder CRC-Prüfung.
Um es nochmal klar zu sagen: Diese billigen Regenerativ-Empfänger
empfangen immer einen ständigen Strom von Datenmüll, weil sie einfach
ihre Empfangsempfindlichkeit automatisch so weit hochregeln, bis sie was
empfangen, auch wenn nichts da ist außer Rauschen. Deshalb ist es keine
gute Strategie, einfach nur zu lauschen, ob nützliche Signale kommen.
Stattdessen ist die passende Strategie, den Sender zuerst
Trainings-Bytes mit "guten Bitfolgen" senden zu lassen, die der
Empfänger dafür nutzt, die Empfindlichkeit so zu regeln, dass er genau
das Signal dieses einen Senders gut empfängt, des jeweils stärksten
Senders im Umkreis. Und erst wenn der Empfänger die Folge der
festgelegten Trainings-Bytes klar und deutlich empfängt, lauscht er auf
die nachfolgenden Daten, üblicherweise nach einem (oder besser zwei)
fest vereinbarten Start-Bytes mit vorab festgelegtem Wert.
Ich habe gestern Nacht dein Rat befolgt aber ein ganz anderer Problem
ist aufgetreten und zwar auf der Empfänger Seite.ich sende Hex oder Byt
empfangen wird ein Bit .ich versuche die ganze zeit den Syntax zum
empfangen der Daten herauszufinden aber erfolglos
Ugur Onur schrieb:> Ich habe gestern Nacht dein Rat befolgt aber ein ganz anderer Problem> ist aufgetreten und zwar auf der Empfänger Seite.ich sende Hex oder Byt> empfangen wird ein Bit .ich versuche die ganze zeit den Syntax zum> empfangen der Daten herauszufinden aber erfolglos
Seit wann gibt es für eine serielle Schnittstelle Routinen zum Empfang
von nur einzelnen Bits?
Ich kenne nur Routinen zum Einlesen ganzer Bytes über die serielle
Schnittstelle.
Du verwendest doch die serielle Schnittstelle zum Senden/Empfangen, oder
nicht?
Ja klar ich benutze die serielle Schnittstelle bei Pic Controller ist es
so.
Nach der Einstellungen wird in der Schleife auf die Daten gewartet die
über die Schnittstelle kommen.Da ich unter C programmiere haben ich die
Befehle getc() für ein Bit gets(String ) für ein String gefunden.get()
läuft aber nur ein Bit das andere nicht.ist ja zum verrückt werden den
Internet habe ich schon rauf und runter durchsucht.
Ugur Onur schrieb:> Ja klar ich benutze die serielle Schnittstelle bei Pic Controller ist es> so.
"Es ist so"? Man KANN diese billigen Sender und Empfänger an die
serielle Schnittstelle hängen, dann hat man extrem wenig Arbeit mit dem
Programmieren des Funks. Maximale Reichweite erzielt man auf diese
einfache Art und über Anschluss an den seriellen Schnittstellen beim
Senden und Empfangen aber NICHT.
Meine batteriebetriebenen Wettersensoren, die mir mit genau solchen
Modulen Daten zu Temperatur, Luftfeuchte und Regenmenge vom Garten ins
Haus funken, hängen mit ihren Modulen daher auch NICHT an der seriellen
Schnittstelle des Mikrocontrollers, sondern werden softwaretechnisch
intelligenter und aufwändiger angesteuert. Mehr Reichweite nur durch
intelligentere Ansteuerung bei gleicher Sendeleistung.
Leider gewinne ich mit zunehmender Länge des Threads den Eindruck, dass
die eigentlichen Probleme bei Dir nicht erst beim Funken anfangen,
sondern schon beim Auslesen von Zeichen über die serielle Schnittstelle
irgendwas nicht klappt.
Ich hege zum Beispiel die starke Vermutung, dass
> wird in der Schleife auf die Daten gewartet> die über die Schnittstelle kommen
überhaupt nicht zutrifft. Es wird zwar ausgelesen, aber es wird beim
Ausgelesen nicht gewartet, bis überhaupt ein Zeichen zum Auslesen an der
seriellen Schnittstelle anliegt. Also tatsächlich: Ständiges Auslesen
ohne dass was zum Auslesen vorhanden ist.
Nur so eine Vermutung von mir, ich kenne Dein Entwicklungssystem und
Deine Funktion getc() nicht. Bedauere, ich kann Dir leider nicht
weiterhelfen und wollte eigentlich auch nur ein paar grundsätzliche
Dinge zu diesen billigen Sender-Empfänger-Pärchen mitgeteilt haben.