Guten Abend, Ich bräuchte mal eure Hilfe. Und zwar habe ich mir letzten ein paar 433 MHz Sender geholt, es handelt sich dabei um ein FS1000A. Dazu gab es auch passende Empfänger aller Dings nach denn Bewertungen, sollen diese wohl nur in kurzer Reichweite funktionieren. Das kann ich selber bestätigen. Mehr als 2 Meter ist dort bei einer Spannung von 5V am Sender nicht drin. Deswegen habe ich mir dazu noch denn RXB6 Empfänger von Wingoneer bestellt. Mit dem komme ich schon sehr weit so um die 7-8 Meter durch 2 Wände. Was für mein Projekt mehr als ausreichend ist. Dann habe ich mein Sender/Empfänger paar erst in der Arduino IDE mit der Library "VirtualWire" ausprobieren. Und naja was soll ich sagen es hat funktioniert. Da aber mein bestehendes Projekt in C programmiert(Atmel Studio 7) ist, musste also eine andere Lösung her. Im Forum habe ich dann gelesen dann man auch IRMP bzw. IRSND verwenden kann. Dieses war ja eigentlich für Infrarot gedacht. Habe es also auch ausprobiert. Leider gibt es dort aber so ein paar Probleme. Und zwar sende ich mit dem Sender auf dem Protokoll RC5, als Adresse 10(0x0A) und als Command auch 10. Kein Flag. Der Empfänger ist im Moment so programmiert das wenn er was empfängt das er es dann ausgibt also welches Protokoll welche Adresse ... Jedoch kommt dort nur Müll raus. Als Protokoll kommt dort immer 7 also RC5 raus. Das stimmt schon mal. Alles andere wie Adresse, Command und Flag stimmt überhaupt nicht. Da ist alles dabei mal Flag 1 dann wieder 0. Adresse ist meistens 11 oder 14 ganz selten ist Sie auch mal richtig 10. Command ist entweder 42 oder 106. Der Sender wird mit +5V versorgt. Der Ausgang(OC2B) ist direkt mit dem DATA pin des Sender verbunden. Der Empfänger wird auch mit +5 Volt versorgt und der DATA Pin geht auf denn Interrupt Pin 0(PortD 2) verwendet wird hier ein ATMega328P mit 16 MHz Externen Quarz Woran liegt das? Werden die Daten zu "unsauber" gesendet? Und was könnt man da gegen tun. Meine beiden Main klassen des Senders und Empfängers habe ich angehängt. Lg Felix
Felix N. schrieb: > Woran liegt das? Werden die Daten zu "unsauber" gesendet? Und was könnt > man da gegen tun. Meine beiden Main klassen des Senders und Empfängers > habe ich angehängt Das ist ein Fall, bei dem man vermutlich nicht weiterkommt ohne sich anzusehen, was wirklich an den Sender geht und was bei Empfänger rauskommt. Was passiert denn, wenn Du Sender und Empfänger direkt ohne die 433MHz-Module verbindest? Wenn es dann funktioniert kommst Du ohne Oszi und vbielleicht Logicanalyser nicht weiter. Wenn dann nicht funktioniert solltest Du die einstellungen zum Prozessortakt prüfen.
IRSND moduliert die IR LED mit einer Trägerfrequenz von ca. 36kHz, was du bei einem 433MHz Sender nicht tun solltest, der hat ja schon die 433MHz Träger. Du musst also umschreiben und die Tastung des Modulationstimers direkt auf den Sender schicken.
:
Bearbeitet durch User
Matthias S. schrieb: > Du musst also umschreiben und die Tastung des Modulationstimers direkt > auf den Sender schicken. Im Prinzip hast du ja Recht, aber ob der TO (der eine "Lib" anwendet) das auch verstanden hat und die Konsequenzen daraus ziehen kann .... ? Ich denke da nur beispielhaft an folgende Aussagen: Felix N. schrieb: > Und naja was soll ich sagen es hat funktioniert. Felix N. schrieb: > Im Forum habe ich dann gelesen dann man auch IRMP bzw. IRSND verwenden > kann. Felix N. schrieb: > Da aber mein bestehendes Projekt in C programmiert(Atmel > Studio 7) ist, musste also eine andere Lösung her. Mein lieber Felix, alles was sich in der Programmier-Welt VirtualWire nennt ist in C programmiert. Oder in C++, was in deinem Zusammenhang keine Rolle spielt. Auch nicht dass du Atmel Studio 7 benutzt. Übrigens, falls du es nicht bemerkt haben solltest, es gibt die VirtualWire Implementierung sowohl "in Arduino" als auch ohne.
Fernbedienungsfunker schrieb: > Im Prinzip hast du ja Recht, aber ob der TO (der eine "Lib" > anwendet) das auch verstanden hat und die Konsequenzen daraus > ziehen kann .... ? Da IRMP und IRSND im Titel vorkommen, bin ich mir fast sicher, das Frank (ukw) über kurz oder lang hier auftaucht und dem TE Hinweise geben könnte, an welcher Stelle die Tastung des 36kHz Timers erfolgt. Aber solange kann der TE ja schon mal suchen. IRSND ist ja recht übersichtlich und der Timer schnell gefunden.
Matthias S. schrieb: > Aber solange kann der TE ja schon mal suchen. Wenn man es nicht verstanden hat wird auch jegliches Suchen keinen Sinn haben. Jedes Wort des Eingangsbeitrages spricht Bände.
Felix N. schrieb: > Im Forum habe ich dann gelesen dann man auch IRMP bzw. IRSND verwenden > kann. Dieses war ja eigentlich für Infrarot gedacht. Habe es also auch > ausprobiert. Dann überlege mal, was an einem empfangenen Infrarot-Signal anders ist, als bei 433MHz AM. Erstens empfängst du mit dem 433MHz Empfänger das Rauschen der Welt und natürlich auch sämtlichen HF-Dreck der bei dir rumgeistert. Irgendwelches ominöses Forumsgeschreibsel ist da wenig hilfreich. Guck dir einfach mal an, was dein Empfänger zu sehen meint, wenn dein Sender schweigt und dann überlege dir, wie deine Software damit klar kommen soll. Mit den Modulen sind 100m kein Problem https://www.youtube.com/watch?v=jpkceV7qg0o
Felix N. schrieb: > der DATA Pin geht auf denn Interrupt Pin 0(PortD 2) Und genau das sollte man sich unbedingt ansehen – entweder mit einem Oszilloskop oder wenigstens mit Audacity. http://rayshobby.net/wordpress/wp-content/uploads/2012/06/rfsniff_signal_example.jpg
Matthias S. schrieb: > Da IRMP und IRSND im Titel vorkommen, bin ich mir fast sicher, das Frank > (ukw) über kurz oder lang hier auftaucht [...] Bin schon da, gerade gelesen :-) > und dem TE Hinweise geben > könnte, an welcher Stelle die Tastung des 36kHz Timers erfolgt Siehe unten. Fernbedienungsfunker schrieb: > Wenn man es nicht verstanden hat wird auch jegliches Suchen > keinen Sinn haben. Statt hier rumzumeckern, hättest Du die Zeit besser nutzen können und selbst schon mal suchen können ;-) Jetzt zum Thema: Es wird tatsächlich eine PWM benutzt, die je nach Protokoll zwischen 32 und 56 kHz liegt. Die muss weg. Entscheidend dafür sind die drei Funktionen irsnd_init(), irsnd_on() und irsnd_off() in irsnd.c. Hier wird die PWM ein- und wieder ausgeschaltet. Stattdessen müssen wir hier den Pin einfach auf Low bzw. High bringen. AVR-Teil von irsnd_init():
1 | # else // AVR
|
2 | IRSND_PORT &= ~(1<<IRSND_BIT); // set IRSND_BIT to low |
3 | IRSND_DDR |= (1<<IRSND_BIT); // set IRSND_BIT to output |
4 | |
5 | # if IRSND_OCx == IRSND_OC2 // use OC2
|
6 | TCCR2 = (1<<WGM21); // CTC mode |
7 | # if AVR_PRESCALER == 8
|
8 | TCCR2 |= (1<<CS21); // start Timer 2, prescaler = 8 |
9 | # else
|
10 | TCCR2 |= (1<<CS20); // start Timer 2, prescaler = 1 |
11 | # endif
|
12 | # elif IRSND_OCx == IRSND_OC2A || IRSND_OCx == IRSND_OC2B // use OC2A or OC2B
|
13 | TCCR2A = (1<<WGM21); // CTC mode |
14 | # if AVR_PRESCALER == 8
|
15 | TCCR2B = (1<<CS21); // start Timer 2, prescaler = 8 |
16 | # else
|
17 | TCCR2B = (1<<CS20); // start Timer 2, prescaler = 1 |
18 | # endif
|
19 | # elif IRSND_OCx == IRSND_OC0 // use OC0
|
20 | TCCR0 = (1<<WGM01); // CTC mode |
21 | # if AVR_PRESCALER == 8
|
22 | TCCR0 |= (1<<CS01); // start Timer 0, prescaler = 8 |
23 | # else
|
24 | TCCR0 |= (1<<CS00); // start Timer 0, prescaler = 1 |
25 | # endif
|
26 | # elif IRSND_OCx == IRSND_OC0A || IRSND_OCx == IRSND_OC0B // use OC0A or OC0B
|
27 | TCCR0A = (1<<WGM01); // CTC mode |
28 | # if AVR_PRESCALER == 8
|
29 | TCCR0B = (1<<CS01); // start Timer 0, prescaler = 8 |
30 | # else
|
31 | TCCR0B = (1<<CS00); // start Timer 0, prescaler = 1 |
32 | # endif
|
33 | # else
|
34 | # error wrong value of IRSND_OCx
|
35 | # endif
|
36 | irsnd_set_freq (IRSND_FREQ_36_KHZ); // default frequency |
37 | # endif //PIC_C18
|
Das kürzen wir auf:
1 | # else // AVR
|
2 | IRSND_PORT &= ~(1<<IRSND_BIT); // set IRSND_BIT to low |
3 | IRSND_DDR |= (1<<IRSND_BIT); // set IRSND_BIT to output |
4 | # endif //PIC_C18
|
Es bleiben also nur diese 2 Zeilen übrig. Der AVR-Teil der Funktion irsnd_on() sieht folgendermaßen aus:
1 | # else // AVR
|
2 | # if IRSND_OCx == IRSND_OC2 // use OC2
|
3 | TCCR2 |= (1<<COM20)|(1<<WGM21); // toggle OC2 on compare match, clear Timer 2 at compare match OCR2 |
4 | # elif IRSND_OCx == IRSND_OC2A // use OC2A
|
5 | TCCR2A |= (1<<COM2A0)|(1<<WGM21); // toggle OC2A on compare match, clear Timer 2 at compare match OCR2A |
6 | # elif IRSND_OCx == IRSND_OC2B // use OC2B
|
7 | TCCR2A |= (1<<COM2B0)|(1<<WGM21); // toggle OC2B on compare match, clear Timer 2 at compare match OCR2A (yes: A, not B!) |
8 | # elif IRSND_OCx == IRSND_OC0 // use OC0
|
9 | TCCR0 |= (1<<COM00)|(1<<WGM01); // toggle OC0 on compare match, clear Timer 0 at compare match OCR0 |
10 | # elif IRSND_OCx == IRSND_OC0A // use OC0A
|
11 | TCCR0A |= (1<<COM0A0)|(1<<WGM01); // toggle OC0A on compare match, clear Timer 0 at compare match OCR0A |
12 | # elif IRSND_OCx == IRSND_OC0B // use OC0B
|
13 | TCCR0A |= (1<<COM0B0)|(1<<WGM01); // toggle OC0B on compare match, clear Timer 0 at compare match OCR0A (yes: A, not B!) |
14 | # else
|
15 | # error wrong value of IRSND_OCx
|
16 | # endif // IRSND_OCx
|
17 | # endif // C18
|
Den können wir jetzt rigoros zusammenstreichen:
1 | # else // AVR
|
2 | IRSND_PORT |= (1<<IRSND_BIT); // set IRSND_BIT to high |
3 | # endif // C18
|
Jetzt zu irsnd_off(). Der AVR-Teil besteht aus:
1 | # else //AVR
|
2 | |
3 | # if IRSND_OCx == IRSND_OC2 // use OC2
|
4 | TCCR2 &= ~(1<<COM20); // normal port operation, OC2 disconnected. |
5 | # elif IRSND_OCx == IRSND_OC2A // use OC2A
|
6 | TCCR2A &= ~(1<<COM2A0); // normal port operation, OC2A disconnected. |
7 | # elif IRSND_OCx == IRSND_OC2B // use OC2B
|
8 | TCCR2A &= ~(1<<COM2B0); // normal port operation, OC2B disconnected. |
9 | # elif IRSND_OCx == IRSND_OC0 // use OC0
|
10 | TCCR0 &= ~(1<<COM00); // normal port operation, OC0 disconnected. |
11 | # elif IRSND_OCx == IRSND_OC0A // use OC0A
|
12 | TCCR0A &= ~(1<<COM0A0); // normal port operation, OC0A disconnected. |
13 | # elif IRSND_OCx == IRSND_OC0B // use OC0B
|
14 | TCCR0A &= ~(1<<COM0B0); // normal port operation, OC0B disconnected. |
15 | # else
|
16 | # error wrong value of IRSND_OCx
|
17 | # endif // IRSND_OCx
|
18 | IRSND_PORT &= ~(1<<IRSND_BIT); // set IRSND_BIT to low |
19 | # endif //C18
|
Den kürzen wir auf eine Zeile:
1 | # else // AVR
|
2 | IRSND_PORT &= ~(1<<IRSND_BIT); // set IRSND_BIT to low |
3 | # endif //PIC_C18
|
Das wars schon. Eventuell muss man diese beiden übriggebliebenen Zeilen in irsnd_on() und irsnd_off() noch vertauschen. Das kommt auf die Polarität an, die der Sender an seinem Eingangpin erwartet. Wenn man sie vretauschen muss, dann sollte man die eine Zeile in irsnd_init() von der Polarität auch noch anpassen. Wenn man es noch perfekt machen will, kann man noch die Funktion irsnd_set_freq() an der AVR-Stelle leeren, denn nun muss keine PWM-Frquenz mehr berechnet und eingestellt werden. AVR-Teil:
1 | # else // AVR
|
2 | |
3 | # if IRSND_OCx == IRSND_OC2
|
4 | OCR2 = freq; // use register OCR2 for OC2 |
5 | # elif IRSND_OCx == IRSND_OC2A // use OC2A
|
6 | OCR2A = freq; // use register OCR2A for OC2A and OC2B! |
7 | # elif IRSND_OCx == IRSND_OC2B // use OC2B
|
8 | OCR2A = freq; // use register OCR2A for OC2A and OC2B! |
9 | # elif IRSND_OCx == IRSND_OC0 // use OC0
|
10 | OCR0 = freq; // use register OCR2 for OC2 |
11 | # elif IRSND_OCx == IRSND_OC0A // use OC0A
|
12 | OCR0A = freq; // use register OCR0A for OC0A and OC0B! |
13 | # elif IRSND_OCx == IRSND_OC0B // use OC0B
|
14 | OCR0A = freq; // use register OCR0A for OC0A and OC0B! |
15 | # else
|
16 | # error wrong value of IRSND_OCx
|
17 | # endif
|
18 | # endif //PIC_C18
|
einfach leeren auf:
1 | # else // AVR
|
2 | # endif //PIC_C18
|
Viel Spaß! [Edit] Leerstellen vor Kommentaren verkürzt, damit die Forensoftware möglichst wenig Umbrüche erzeugt.
:
Bearbeitet durch Moderator
Zusatz: Ich weiß leider nicht, ob der 433-MHz-Sender die ganze Zeit sendet oder nur bei einem der beiden möglichen Pegel und der andere sowieso Ruhepegel ist. Da kenne ich mich nicht aus. Damit der Sender nicht die Umgebung "verschmutzt", sollte man den Sender, solange er nichts sendet, per Enable-Pin abschalten - sofern er da einen hat. Vor dem Senden dann per Enable einschalten und eventuell ein wenig abwarten (x msec?), damit erstmal ein Ruhepegel vorhanden ist. Dann irsnd_send_data() aufrufen. Man kann dann zyklisch in einer while-Schleife irsnd_is_busy() aufrufen, um festzustellen, ob noch gesendet wird. Sobald das Busy-Flag 0 ist, kann man den Sender dann wieder abschalten.
:
Bearbeitet durch Moderator
Frank M. schrieb: > Vor dem Senden dann per Enable einschalten und eventuell > ein wenig abwarten (x msec?), damit erstmal ein Ruhepegel vorhanden ist. Der FS1000A hat gewöhnlich genau drei Pins. Neben der Versorgungsspannung gibt es also genau einen Pin zum Steuern und da kommen die Daten rein. Damit wird der Sender ein- und aus geschaltet. Ob der Sender gerade aktiv ist (Polarität Eingangssignal) sieht man wahrscheinlich an der Stromaufnahme.
Wolfgang schrieb: > Damit wird der Sender ein- und aus geschaltet. Ob der Sender gerade > aktiv ist (Polarität Eingangssignal) sieht man wahrscheinlich an der > Stromaufnahme. Alles klar, danke für die Info. Dann muss man ja nur den Ruhepegel herausbekommen - Low oder High. Eventuell muss man dann beim Empfänger in irmp.c auch den Pegel invertieren, wenn der Ruhepegel nicht HIGH ist wie bei einem IR-Empfänger. Aber das wäre dann eine einfache Änderung in irmp.h. Alt:
1 | # define input(x) ((x) & (1 << IRMP_BIT))
|
Neu:
1 | # define input(x) !((x) & (1 << IRMP_BIT))
|
Einfach im AVR-Teil ein ! vor den Ausdruck schreiben. Das Herausbekommen des Ruhepegels überlassen wir jetzt mal dem TO ;-)
:
Bearbeitet durch Moderator
Frank M. schrieb: > Siehe unten. Hallo, cool Danke. Muss ich auch denn Code am Empfänger bearbeiten? Frank M. schrieb: > Das kommt auf die > Polarität an, die der Sender an seinem Eingangpin erwartet. Mein Sender will ein High Puls um zu senden und mit ein Low Signal ist er im Ruhezustand. Also ich habe die irsnd.c mal so bearbeitet wie Du es oben beschrieben hast. Allerdings ist es noch nicht ganz richtig. Ein Bild wie das Pin am Senden ist angehängt. Aber es kommt immer noch nicht das richtige an. Wenn ich denn Sende Pin des einen Atmega direkt mit ein Kabel auf denn Empfänger Atmega verbinde, kommt auch nicht das richtige an. Das erste mal wo der Sender sendet(Hier direkte Kabel verbindung) kommt nix im UART beim Empfänger an erst beim zweiten mal dann aber auch nur Protokoll 7, Adresse 11, Command 43. Beim ersten mal kommt Flag 0 an und dann immer Flag 1. Der Code zum Senden und Empfängen in der Main's.c habe ich nicht geändert. Lg Felix //EDIT: Habe dein Beitrag mit irmp.h zu spät gesehen. Mit direkter Kabel verbindung kommt nun das richtige muss nun mal denn Sender/Empfänger anschließen anstatt ein Kabel.
:
Bearbeitet durch User
So Hallo nochmal, Nachdem ich in der irmp.h das Ausrufezeichen hinzugefügt habe und meine direkte Kabel Verbindung zwischen denn beiden µC entfernt habe und mein Sender/Empfänger angeschlossen habe. Habe ich festgestellt das es funktioniert. Aber nicht ohne Fehler. Damit meine ich das Daten nicht empfangen werden bzw. verloren gehen. Ich habe es im Moment so gemacht das in 13 Sekunden 26 Daten gesendet werden einfach ein Counter der bis 26 hochzählt. Und dieses als Command festgelegt(irmp_data.command = counter). Counter ist ein uint16_t. Mit der direkten Kabel Verbindung kommen alle 26 Daten immer über. Mit denn Modulen immer unterschiedlich mal nur 20 mal nur 15 mal auch 26. Ich weiß nicht ob es jetzt an mein Sender bzw. am Empfänger liegt. Oder an IRMP bzw. IRSND. Ich würde jetzt mal mehr auf denn Empfänger tippen. Da mit der Kabel Verbindung ja alles ankommt. Nur wie kann ich dieses Problem beheben falls es der Empfänger sein sollte. Lg Felix
Felix N. schrieb: > Nur wie kann ich dieses Problem beheben > falls es der Empfänger sein sollte. Es ist weder der Sender noch der Empfänger sondern die Übertragungsstrecke die störempfindlich ist. Alle Welt sendet auf dieser Frequenz. Statistisch gesehen kommt eben nur ein Prozentsatz deiner Telegramme störungsfrei an. Aber du willst ja auf Gedeih und Verderb von den hervorragenden Übertragungseigenschasften der VirtualWire Implementierung wegkommen.
So nochmal ne Rückmeldung von mir. Ich habe jetzt mal ein bisschen mit der Software rum probiert. Habe ich denn Fehler behoben und zwar liegt es am Protokoll. Das RC5 Protokoll ist nicht dafür geeignet wenn man dort alle 2,5 Sekunden was sendet kommt wenn man glück hat mal alle 5 bis 7,5 Sekunden Daten an. Bei denn Exotischen Protokollen kommt gar nicht an! Ich habe 100 mal auf zwei Exotischen Protokoll(Nikon, Panasonic Beamer) gesendet dort kam gar nix an. Am besten eigenen sich die Standard Protokoll von Sony, NEC, Samsung, Matsushita und Kaseikyo. Bei diesen Protokollen konnte ich fest stellen das keine Daten verloren gehen. Was auch noch wichtig wäre ist die Delay Zeit zwischen denn einzeln Senden der Datenpakete alles unter 600 ms führt zu teilweisen Datenverlusten. Wenn die Daten noch schneller gesendet werden mit 250 ms oder 350 ms. Kommen von 50 gesendeten Daten nur 20-25 an. Bei einer Delay Zeit zwischen 600 - 10 sec(hab nur bis 10 Sekunden getestet) kommen alle Daten an. Nur so mal als Hinweiß falls jemand mal das gleiche Problem hat und auf diesen Thread stößt. In so fern möchte ich mich bei allen Bedanken die mir geholfen habe! Vielen Dank! Mfg Felix
Felix N. schrieb: > Am besten eigenen sich die Standard Protokoll von Sony, NEC, Samsung, > Matsushita und Kaseikyo. Bei diesen Protokollen konnte ich fest stellen > das keine Daten verloren gehen. Dass sich viele IR-Protokolle wie zum Beispiel RC5 für die Funkübertragung nicht eignen, kann ich wohl erklären: Die 433-MHz-Empfänger brauchen zu Beginn eine längere Präambel (also ein langes Start-Bit), um sich auf den Funkpegel einzustellen. Diejenigen IR-Protokolle, die lediglich ein kurzes Start-Bit verwenden, fallen damit als "funkuntauglich" raus. Dazu gehören neben RC5, RECS80, LEGO und DENON noch einige andere IR-Protokolle mit zu kurzen Start-Bits. Welche, kann man aus der Tabelle unter IRMP: Die IR-Protokolle im Detail entnehmen. Die von Dir als funktauglich eingestuften Protokolle haben alle einen Start-Bit-Puls mit einer Länge von mehr als 2,5 msec (Sony), viele sogar mindestens 4,5 msec (z.B. Samsung). Bei NEC und Verwandten sind es sogar ganze 9 msec. Meine Empfehlung: Nimm NEC. Da hast Du durch die Datenredundanz eine relativ hohe Datensicherheit. Außerdem ist das Start-Bit hinreichend lang. Zu den von Dir empirisch gemessenen notwendigen Pausen von 600msec zwischen den Frames: Da müsste man sich mal die Daten auf Empfängerseite mit dem Oszi näher anschauen, wenn man die Pausen langsam schrittweise verringert.
:
Bearbeitet durch Moderator
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.