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.
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
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
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.
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.
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 ;-)
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.
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.
Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang