Forum: Mikrocontroller und Digitale Elektronik 433Mhz RF link kit PIC16F688


von Sterngleiter S. (sterngleiter) Benutzerseite


Lesenswert?

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 :)

von Jürgen S. (jurs)


Lesenswert?

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.

von Jürgen S. (jurs)


Lesenswert?

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.

von Sterngleiter S. (sterngleiter) Benutzerseite


Lesenswert?

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).

von Sterngleiter S. (sterngleiter) Benutzerseite


Lesenswert?

Mehr dazu schreibe ich sobald ich Zuhause bin

von Sterngleiter S. (sterngleiter) Benutzerseite


Lesenswert?

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?

von Jürgen S. (jurs)


Lesenswert?

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.

von Sterngleiter S. (sterngleiter) Benutzerseite


Lesenswert?

Du hast oben die Prüfsumme erwähnt dies habe ich schon öfters gehört was 
bewirkt es

von Jürgen S. (jurs)


Lesenswert?

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.

von Sterngleiter S. (sterngleiter) Benutzerseite


Lesenswert?

Wenn soviele Daten sende dann müsste ich die ja beim empfànger in einem 
Array sammeln oder

von Jürgen S. (jurs)


Lesenswert?

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.

von Sterngleiter S. (sterngleiter) Benutzerseite


Lesenswert?

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

von Jürgen S. (jurs)


Lesenswert?

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?

von Sterngleiter S. (sterngleiter) Benutzerseite


Lesenswert?

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.

von Jürgen S. (jurs)


Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.