Moin,
ich möchte meinem Mikrocontroller signale per IR zusenden. Hierfür würde
ich gerne IRSND und IRMP nutzen. Ich habe mir einen Emfänger (TSOP4838)
und eine IR-LED besorgt. Ich bin noch ein Anfänger auf diesem Gebiet und
weiß noch nicht genau wie ich das Ganze an den Mikrocontroller
anschließe. Die Schaltung im IRSND-Beitrag mit Transistor und Co. habe
ich schon aufgebaut und kann auch über ein GPIO-Pin die LED toggeln.
Jetzt meine Frage, an welche Anschlüsse vom MIkrocontroller muss die
Schaltung damit das funktioniert? LED an einen PWM-Ausgang und der
Emfänger dann an einen ADC-EIngang?
Danke
@ IR-Bastelei (Gast)
>Jetzt meine Frage, an welche Anschlüsse vom MIkrocontroller muss die>Schaltung damit das funktioniert?
Gibt es keine Schaltpläne bei den IRSND/IRMP Projekten?
>LED an einen PWM-Ausgang und der
Ja.
>Emfänger dann an einen ADC-EIngang?
Nein, der kommt an ein normales, digitales IO-Pin. Denn der Ausgang des
IR-Empfängers ist auch "nur" digital.
Ich habe das Ganze jetzt einmal angeschlossen und habe mit dem
Programmieren angefangen. Ich habe beim Sender wie im IRSND-Beitrag
geschrieben nur die "irsnd.h" in mein Projekt inkludiert. Ansonsten habe
ich mich zunächst an dem mitgelieferte Beispiel orientiert. Leider
bekomme ich beim Übersetzen folgende Fehlermeldungen:
Error 1 undefined reference to `irsnd_ISR'
...IR_Sender_Empfänger\Sender\Sender\Release\Sender.c
Error 2 undefined reference to `irsnd_init'
...\IR_Sender_Empfänger\Sender\Sender\Release\Sender.c
Error 3 undefined reference to `irsnd_send_data'
...\IR_Sender_Empfänger\Sender\Sender\Release\Sender.c 1 1 Sender
Error 4 ld returned 1 exit status collect2.exe
Software ist Atmel Studio 6.2. Weiß jemand wieso er die Referenzen nicht
findet? Ich habe alle Dateien aus dem IRSND-Archiv in den Projektordner
entpackt. Die Header-Dateien scheint der Compiler ja auch zu finden.
Danke
IR-Bastelei schrieb:> LED an einen PWM-Ausgang ...
Ja. In irsndconfig.h sind die Pins aufgeführt, die möglich sind.
> und der Emfänger dann an einen ADC-EIngang?
Wie Falk schon sagte: Irgendein I/O-Pin, einstellbar in irmpconfig.h.
Um welchen µC handelt es sich überhaupt?
Im Kommentar steht eigentlich alles drin.
Der ATmega328 ist nur ein größerer ATmega88. Also hast Du zur Auswahl:
OC2A und OC2B. Notfalls geht auch noch OC0A und OC0B, dann muss man halt
den Timer0 statt Timer2 zur Modulation verwenden. Das ist auch im
IRSND-Artikel so dokumentiert.
Am einfachsten ist es mit
1
# define IRSND_OCx IRSND_OC2B // use OC2B
bzw.
1
# define IRSND_OCx IRSND_OC2A // use OC2A
Gehe dann einfach so vor wie im Artikel beschrieben.
Danke zusammen.
Ja genau. Wie im Beitragtitel geschrieben handelt es sich um einen bzw.
zwei Mega 328P.
Die Pins habe ich mittlerweile auch gefunden und in den Configdateien
von IRSND und IRMP angepasst. Mit der Fotokamera habe ich auch schonmal
kontrolliert. Die LED blinkt jede Sekunde wie programmiert auf. Über den
zweiten MC möchte ich die empfangenen Daten per UART weiterleiten. UART
funktioniert auch allerdings kommt auf dem MC der die Auswertung des
IR-Detektors per IRMP übernehmen soll noch nichts an. Bzw. in meinem
Hterm kommt nichts über die serielle Schnittstelle an. Ich lade die
beiden .c-Files mal mit hoch, aber an sich ist das nahezu identisch mit
dem was auch im Beispiel passiert. Die IR-LED hängt an PD3 also OC2B
und der Output des Detektors am PB6.
Danke schonmal
Das solltest Du aus den .c-Dateien Empfaenger.c und Sender.c rausnehmen:
#define F_CPU 8000000UL
und stattdessen in den Projekt-Einstellungen setzen, damit für alle
c-Files dieselben Einstellungen gelten. Ich weiß auch nicht, wie Du
irmp.c und irsnd.c überhaupt ohne diese globale Einstellung übersetzen
konntest. Diese meckern nämlich dann. Oder hast Du diese auch mit diesem
#define "geimpft"?
Das ist das falsche Vorgehen. Wenn Du mal den Takt änderst, musst Du das
in allen c-Dateien korrigieren. Fehler sind da vorprogrammiert.
Das hier:
#define BAUD 9600UL
benutzt Du leider gar nicht im Source.
Stattdessen das hier:
1
voidUARTinit(){
2
UBRR0H=(unsignedchar)(51>>8);
3
UBRR0L=(unsignedchar)51;
4
UCSR0B=(1<<TXEN0)|(1<<RXEN0);
5
UCSR0C=(1<<UCSZ00)|(1<<UCSZ01);
6
7
}
Hier kann niemand ohne größere Anstrengungen nachvollziehen, ob die
Baudrate tatsächlich 9600Bd ergibt. Ohne es nachrechnen zu wollen: Ich
bezweifele, dass dies die richtigen Werte für UBBR0H bzw. UBRR0L sind.
Benutze besser das hier, das ist portabel und läuft auf allen AVRs:
Frank M. schrieb:> und stattdessen in den Projekt-Einstellungen setzen
ja hatte ich an andere Stelle im Forum bereits gelesen, konnte es aber
in AS 6.2 nicht finden wo genau das geht. In den anderen .c-Dateien habe
ich nix umgestellt. Gab allerdings beim Übersetzen weder eine Warnung
noch einen Fehler.
Frank M. schrieb:> #define BAUD 9600UL>> benutzt Du leider gar nicht im Source.
ich weiß..der Berechnugsteil ist darunter auskommentiert. Den Wert 51
habe ich dem Datenblatt entnommen. Die UART-Übertragung funktioniert
soweit auch ohne Fehler. Sicher, wenn der Takt sich später ändert muss
man es jedesmal manuell umstellen. Bin ja noch am Anfang.
Frank M. schrieb:> Die CKDIV-Fuse hast Du entsprechend eingestellt
Jap der Haken ist rausgenommen sind somit 8 MHz :)
Sooo..ich habe den Takt jetzt global auf 8000000UL gestellt. Danke
Frank.
Leider kommt bei mir im Hterm immer noch nichts an. Teststrings kann ich
generell per UART senden die kommen dann auch an. Also muss der Fehler
irgendwo anders liegen. Leider finde ich ihn nicht. Es ist ja ansonsten
komplett das Beispielprogramm.
Ich habe mal testweise eine String in der Interrupt-Routine ausgegeben.
Der kommt nicht an. Also scheint irgendwie auch der Interrupt nicht
ausgelöst zu werden.
Frank M. schrieb:> Viel Spaß!
Danke! Macht es.
Ich habe allerdings schon wieder ein Problem, dass ich nicht verstehe.
Ich übertrage immer nacheinander 3 Buchstaben. Das funktioniert auch
alles top. Aber nur wenn ich an einen der zwei Mikrocontroller mein ISP
(Diamex ISP) angeschlossen habe. Sobald ich ihn entferne kommt über den
UART nix mehr in hterm an. Habe schon kontrolliert die IR-LED blink
munter weiter. Es ist auch egal an welchem Chip der ISP hängt.
Emfängerseite oder Senderseite. Ist er dran funktioniert es, wenn er ab
ist nicht. Wie kann das sein?
An den beiden Chips hängt außer der Grundbeschaltung sonst nix dran. Von
V_cc zu GND hängen jeweils 100 nF Kerkos und ansonsten die
LED-/Transistorschaltung auf der Senderseite und der Detektor an der
Empfängerseite. Empfägerseitig ist noch der UART zu USB Adapter
(FT232R). Spannungsversorgung kommt aus zwei 18650 Zellen mit 7805
Spannungsregler dahiner. Jemand eine Idee was der Grund sein könnte?
IR-Bastelei schrieb:> Aber nur wenn ich an einen der zwei Mikrocontroller mein ISP (Diamex> ISP) angeschlossen habe.
Das hört sich nach einer fehlenden Masseverbindung an.
Frank M. schrieb:> Das hört sich nach einer fehlenden Masseverbindung an.
Wieder einmal korrekt gelegen. Das UART Modul hatte kein Verbindung zu
GND. Jetzt behoben und es funktioniert.
Ich hab nun schon ein bisschen mit der Bibliothek experimentiert und
muss sagen, dass ich echt begeistert bin. Hut ab!
Ich übertrage momentan im NEC Protokoll. Was ich mich frage ist, ob es
Protokolle gibt, die Daten schneller übertragen können. Klar ich könnte
jetzt bei allen die Bitzeiten zusammenrechnen aber eventuell lässt sich
das ja beschleunigen :) Sagen wir einmal ich möchte maximal dreistellige
Zahlen übertragen. Im NEC Protokoll ist eine Frame 67,5 ms lang das
bedeutet ja pro Sekunde 14 Übertragungen (Eigl. 14,8 aber kommen ja noch
die Stopbits dazu) Ist das schon das maximale was per Infrarot geht oder
kann man mehr rausholen?
Desweiteren steh ich ein wenig auf dem Schlauch was das Format der
Übertragung angeht. Das Kommando, sagen wir einmal beim NEC Protokoll,
ist 8 Bit lang (+ Invertierung). Demnach sollten ja theoretisch Werte
im Bereich von 0-255 mit einem Sendevorgang übertragbar sein, oder?
Jetzt lassen sich soweit ich das verstanden habe die Daten ja "nur" in
hex-Darstellung übertragen. Ich würde aber gerne mit Zahlen im
Dezimalformat arbeiten. Wie kann ich denn beispielsweise eine
übertragene "0x009A" nach dem Senden als "154" darstellen. Und was ist
wenn beispielsweise die Zahl "456" übertragen werden soll. Macht es dann
Sinn die Zahl in "45" + "6" zu trennen, in zwei Sendevorgängen zu
übertragen und anschließend wieder zusammenzufügen?
Danke
IR-Bastelei schrieb:> Ich übertrage momentan im NEC Protokoll. Was ich mich frage ist, ob es> Protokolle gibt, die Daten schneller übertragen können.
Beim NEC Protokoll in der Standard-Fassung gilt:
1
8 Bit Adresse + 8 Bit invertierte Adresse + 8 Bit Daten + 8 Bit invertierte Daten
Wenn Du die Adresse (8 bit) immer gleich hältst, kannst Du pro Frame nur
8 Bit Daten, also ein Byte übertragen.
Beim NEC-Protokoll in der Extended Fassung gilt:
1
16 Bit Adresse + 8 Bit Daten + 8 Bit invertierte Daten
Wenn Du Dich hier auf eine 8-Bit-Adresse beschränkst, kannst Du in den
zweiten 8 Bit weitere 8 Bit Daten reinstecken. Damit erhöhst Du die
Datenrate auf 16 Bits (= 2 Bytes) pro Frame. Allerdings ist das
Verfrachten von jeweils 8 Bit in die Geräteadresse ein wenig tricky und
daher nicht so elegant.
Alternative wäre ein anderes Protokol mit weniger Overhead, z.B. LEGO:
https://www.mikrocontroller.net/articles/IRMP#LEGO
Das verwendet überhaupt keine Adresse, sondern lediglich 16 Bit Daten,
die Du komplett nutzen kannst. Solange Du keine weitere
LEGO-Fernbedienung in demselben Raum verwendest, sollte es also kein
Kollisions-Problem geben. Zudem ist der LEGO-Frame recht kurz, nämlich
zwischen 8,0 (alles Nullen) und 12,5 msec (alles Einsen).
Damit solltest Du 5 mal soviele Frames wie bei NEC versenden können.
Nutzt Du die Datenbreite von 16 Bit gegenüber 8 Bit beim
Standard-NEC-Protokoll, bist Du bereits bei der 10-fachen
Geschwindigkeit.
LEGO war jetzt nur ein Beispiel, andere von IRMP unterstützte Protokolle
findest Du hier:
https://www.mikrocontroller.net/articles/IRMP#Die_IR-Protokolle_im_Detail
Da kannst Du dann die jeweiligen Framelängen mit dem Taschenrechner
zusammenrechnen. Ich halte LEGO jedoch wegen der fehlenden Adresse schon
für recht schmal und damit auch für schnell. Wegen der fehlenden
Redundanz hast Du aber keine so hohe Datensicherheit wie bei NEC.
Welche Datenrate schwebt Dir denn vor?
> Macht es dann Sinn die Zahl in "45" + "6" zu trennen, in zwei> Sendevorgängen zu übertragen und anschließend wieder zusammenzufügen?
Im Prinzip ja. Nur würde ich sie nicht dezimal trennen, sondern binär.
Denn das kann der µC viel schneller mit weniger Aufwand.
465 = 0000 0001 1100 1000
Also zwei Bytes. Die sendest du einfach nacheinander.
0000 0001
1100 1000
IR-Bastelei schrieb:> Sagen wir einmal ich möchte maximal dreistellige Zahlen übertragen.
Wie Stefan schon schrieb: Ich würde sie nicht im ASCII-Format, also
"456", sondern binär übertragen. Dann brauchst Du nicht 3 Bytes für die
3 ASCII-Ziffern, sondern lediglich 2 Bytes, also genau 16 Bits. Dann
hast Du einen Zahlenbereich von 0 bis 65535 statt nur 0 bis 999.
Dafür schreibst Du im Sender:
1
uint16_tvalue=456;// irgendein Wert zwischen 0 und 65535
2
3
irmp_data.protocol=IRMP_LEGO_PROTOCOL;// use LEGO protocol
Frank M. schrieb:> Welche Datenrate schwebt Dir denn vor?
Das ganze soll irgendwann mal ein Spiel werden, bei dem es teilweise
auch auf Reaktionszeit ankommt. Genaueres dazu kann ich noch nicht
sagen, da sehr in der Überlegungsphase. Deswegen gilt leider nur der
unqualifizierte Spruch: "Je schneller , desto besser". Gleichzeitig
sollte es aber auch zuverlässig sein. Da es mehrere Spieler geben wird,
die Signale empfangen ist eine Adressierung schon wichtig. Allerdings
könnte ich von den 16 Bit ja die ersten 4 für die Adressierung
hernehmen, was dann maximal 16 Spieler ermöglicht. Die Übrigen 12 Bit
reichen an Datenvolumen mehr als aus. Sollte ja eigentlich
funktionieren.
Stefan U. schrieb:> Also zwei Bytes. Die sendest du einfach nacheinander.> 0000 0001> 1100 1000
Klingt sinnvoll. Ich habe die Protokolle nicht implementiert, aber
soweit ich das verstanden habe müssen die Daten im Hexadezimalsystem
übertragen werden?!
IR-Bastelei schrieb:> Da es mehrere Spieler geben wird, die Signale empfangen ist eine> Adressierung schon wichtig.
Das muss aber nicht unbedingt die IR-Geräteadresse sein. Wenn Du das
(schnellere) LEGO-Protokoll nutzt, kannst Du die vorhandenen 16 Bit ja
selbst unterteilen, nämlich:
- 4 Bit Spieler-Adresse ((möglicher Bereich 0...15)
- 12 Bit Wert (möglicher Bereich 0...4095)
Dann wäre obiges LEGO-Beispiel folgendermaßen abzuändern:
1
uint16_tplayer=3;// irgendein Wert zwischen 0 und 15
2
uint16_tvalue=456;// irgendein Wert zwischen 0 und 4095
3
4
irmp_data.protocol=IRMP_LEGO_PROTOCOL;// use LEGO protocol
5
irmp_data.address=0;// not used by LEGO
6
irmp_data.command=(player<<12)|value;// value 0...65535
player=(irmp_data.command&0xF000)>>12);// upper 4 bit
9
value=irmp_data.command&0x0FFF;// lower 12 bit
10
11
if(player==MY_PLAYER_ID)
12
{
13
// do something with player and value
14
}
15
}
IR-Bastelei schrieb:> aber soweit ich das verstanden habe müssen die Daten im> Hexadezimalsystem übertragen werden?!
Nein, die Übertragung ist binär. Einfach den gewünschten Wert in
irmp_data.command reinschreiben bzw. rauslesen, siehe Beispiel.
P.S.
Ich persönlich würde nur 15 Spieler (1...15) vorsehen und die Spielernr.
0 als Broadcast-Adresse vorsehen. Dann kannst Du bei einem
Reaktionsspiel zum Beispiel allen Empfängern einen gemeinsamen
Start-Befehl schicken, falls das sinnvoll ist.
Frank M. schrieb:> Das muss aber nicht unbedingt die IR-Geräteadresse sein. Wenn Du das> (schnellere) LEGO-Protokoll nutzt, kannst Du die vorhandenen 16 Bit ja> selbst unterteilen, nämlich:>> - 4 Bit Spieler-Adresse ((möglicher Bereich 0...15)> - 12 Bit Wert (möglicher Bereich 0...4095)
Vielen Dank. So war das
IR-Bastelei schrieb:> Allerdings> könnte ich von den 16 Bit ja die ersten 4 für die Adressierung> hernehmen, was dann maximal 16 Spieler ermöglicht. Die Übrigen 12 Bit> reichen an Datenvolumen mehr als aus. Sollte ja eigentlich> funktionieren.
auch gemeint.
Frank M. schrieb:> Dann kannst Du bei einem> Reaktionsspiel zum Beispiel allen Empfängern einen gemeinsamen> Start-Befehl schicken, falls das sinnvoll ist.
Gute Idee soetwas kann nie schaden ! Dankesehr. Ich werde die Tage mal
ein bisschen mit dem LEGO Protokoll experimentieren. Beim schnellen
Überfliegen der anderen Protokolle ist mir kein "schnelleres" ins Auge
gesprungen.
IR-Bastelei schrieb:> Beim schnellen> Überfliegen der anderen Protokolle ist mir kein "schnelleres" ins Auge> gesprungen.
Es steht dir natürlich frei ein eigenes Protokoll zu erfinden was genau
die benötigte Datenmenge mit entsprechender Bitrate überträgt.
IRMP ist ja darauf ausgelegt Signale von handelsüblichen Fernbedienungen
zu dekodieren um eigene Elektronik damit zu steuern, oder Signale zu
kodieren um mit eigener Elektronik vorhandene Geräte zu steuern.
Dabei kannst du dich ja an ein vorhandenes Protokoll anlehnen und dieses
für deine Zwecke anpassen. Entscheidend ist ja nur wie die Bits kodiert
sind (Pulsdauer, Manchaster, ...), wie die Päambel aussieht und welche
Prüfinformationen hinzugefügt werden.
Sascha
Sascha W. schrieb:> Es steht dir natürlich frei ein eigenes Protokoll zu erfinden was genau> die benötigte Datenmenge mit entsprechender Bitrate überträgt.
Danke werde ich drüber nachdenken. Gibt es dort Grenzen, wie lang/kurz
die Pulsdauer für 1/0 etc. sein dürfen?
Frank M. schrieb:> Dann wäre obiges LEGO-Beispiel folgendermaßen abzuändern:
Ich habe mein Programm entsprechend umgeändert. Leider scheint das noch
nicht ganz so zu funktionieren. Erstmal was habe ich geändert:
1. In dem Data-Struct das Protokoll auf LEGO geändert und die Adresse
rausgenommen. ( =0)
2. LEGO-Protokoll in beiden Konfigdateien aktiviert und den Interrupt
auf "20000" gestellt.
Bei mir in Hterm kommt zwar was an aber zum einen sehr unregelmäßig,
wirkt fast willkürlich und zum anderen auch nicht das Richtige.Schreibe
ich beispielsweise in die Variable "value" eine "1245" und lass mir das
im Ascii-Format im Hterm anzeigen kommt dort eine "04DD". (Auch wenn das
die hex-Darstellung der Zahl ist aber zumindest die Umrechnung stimmt)
So weit so gut. Stell ich die Einstellung aber auf Dezimal werden die
Zeichen der Ascii-Tabelle einsprechend einzelnd umgerechnet (siehe
Screenshot). Wie bekomme ich es hin, dass ich tatsächlich die
Dezimalzahl übertragen bekomme und woran könnte es liegen dass die
Übertragung so langsam (gefühlt kommen Daten alle 2 Sekunden und dann
manchmal viele auf einmal) und unregelmäßig kommen?
Danke nochmal für eure Hilfe!
Die Dezimal Zahl 1245 ist in hexadezimaler Darstelleung 04DD.
Finde heraus, was der Unterschied zwischen einer Zahl und einer
Zeichenkette ist. Danach findest du heraus, wie die drei gängigen
Darstellungsformen für Zahlen funktionieren: Dezimal, Hexadezimal und
Binär.
> Wie bekomme ich es hin, dass ich tatsächlich die> Dezimalzahl übertragen bekomme
Deine Schnittstelle überträgt Bits. Wie die Dezimalzahl in Bits codiert
wird und Empfängerseitig wieder decodiert wird, bleibt Dir überlassen.
Es hängt ganz von deinem Programm ab.
Wenn du in HTerm die Anzeige auf "Decimal" stellst, dann geht HTerm
davon aus, daß jeweils 8 Bits eine Zahl bedeuten. Soweit ich mitbekommen
habe, hast du dich jedoch dazu entschlossen, mehr als 8 Bits für eine
Zahl zu übertragen. Daher passt die Darstellungsform von HTerm nicht zu
deinem Sende-Programm.
Daß HTerm überhaupt Dezimale Ausgabe unterstützt, ist schon eine
Besonderheit. Der gemeinsame Nenner, den alle Terminalprogramme
Standardmäßig unterstützen ist ASCII Codierung (siehe Wikipedia).
Im C Programm kannst du die Funktionen atoi(), itoa(), printf() und
eventuell scanf() benutzen, um zwischen Binärer und Dezimaler
Darstellung zu konvertieren.
IR-Bastelei schrieb:> Wie bekomme ich es hin, dass ich tatsächlich die Dezimalzahl übertragen> bekomme
Du bekommst eine Zahl übertragen und nichts anderes. Dass dies im
Binärformat geschieht, brauchst Du nicht zu wissen. Du steckst eine Zahl
rein und Du bekommst dieselbe Zahl auch wieder raus.
Ob das eine Dezimal- oder Hexadezimalzahl ist, ist lediglich eine Frage
der Darstellung bei der Ausgabe, nicht programmintern. Da ist es
einfach eine Zahl - und nichts anderes.
Wenn Du schreibst
1
intch=10;
oder Du schreibst
1
intch=0x0A;
dann ist das absolut identisch. In der Variablen ch steht nachher der
identische Wert.
> und woran könnte es liegen dass die Übertragung so langsam> (gefühlt kommen Daten alle 2 Sekunden und dann manchmal viele auf> einmal) und unregelmäßig kommen?
Ich vermute mal, dass dies an der Erhöhung der Interrupts auf 20000/sec
liegt. Das scheint für Dein Programm ein bisschen viel zu sein und das
Timing kommt ins Schleudern. Du könntest den Takt per Quarz auf 16 MHz
verdoppeln. Dann bist Du auf der sicheren Seite.
Es wäre nicht schlecht, wenn Du Deinen bisherigen Code auch mal zeigen
würdest. Ich hoffe, beim Compilieren ist die Optimierung
eingeschaltet... oder testest Du im Debug-Modus ohne jegliche
Optimierung?
Danke für eure Antworten. Ich hatte einfach einen Denkfehler. Mit dem
NEC-Protokoll klappt jetzt alles so wie ich mir das vorgestellt habe.
Ich habe das LEGO-Protokoll nochmal ausprobiert. Es bleibt aber das
Verzögerungsproblem. Dann liegt es vielleicht echt an dem Timing. Einen
externen Quarz möchte ich eigentlich vermeiden. Deswegen such ich noch
andere Protokolle. Ich habe das DENON ausprobiert, welches von den Bits
auch passen würde allerdings wollte das auch nicht so recht. Außerdem
das NETBOX-Protokoll aber da kam gar nix an. Steht aber ja auch bei,
dass es ein Prototyp ist.
Der Gedanke ein Protokoll zu schreiben oder anzupassen kommt mir immer
naheliegender. Dafür muss ich aber erstmal den gesamten Code durchgehen
um zu schauen wo ich da anfange. An sich wäre eine Datenbreite von 12-13
Bits ideal. 2-3 als Adressbits und 10 Bits als Nutzdaten. Meinen Code
häng ich nochmal an.
Für zuverlässige UART Kommunikation (Hterm) wirst du allerdings kaum um
einen Quarz herum kommen. Die UART Schnittstelle verlangt einen Takt mir
maximal 2% Abweichung. Davon musst du noch die Ungenauigkeit des
Baudraten-Generator subtrahieren.
Stefan U. schrieb:> Für zuverlässige UART Kommunikation (Hterm) wirst du allerdings kaum um> einen Quarz herum kommen.
Die läuft eigentlich zuverlässig. Hab zumindest bisher keine Probleme
bemerken können. Ist momentan aber sowieso hauptsächlich zum debuggen..
Frank M. schrieb:> Ich hoffe, beim Compilieren ist die Optimierung> eingeschaltet...
steht momentan auf "-O2"
> Die läuft eigentlich zuverlässig.> Hab zumindest bisher keine Probleme bemerken können.
Dann lege die Platine mal vorher zwei Stunden in die Sonne. Oder im
Winter auf eine kalte Marmortreppe.
Stefan U. schrieb:> Dann lege die Platine mal vorher zwei Stunden in die Sonne. Oder im> Winter auf eine kalte Marmortreppe.
Ja das wären natürlich unschöne Zustände. Ist aber erstmal relativ
unrealistisch. Ich weiß natürlich dass du damit grundlegend
Temperaturschwankungen meinst. Im Endeffekt kommen die Platinen aber in
Gehäuse und sind auch nur für den Einsatz im Haus/Tisch. Also sind so
große Temperaturschwankungen nicht zu erwarten. Probieren würde ich es
erstmal gerne ohne Quarz. Nachrüsten könnte ich den ja immer noch nach
einer Testphase. Wie verhalten sich denn Allgemein Quarze bzw.
Mikrocontroller. Kann so ein Gehäuse mit Platine drin auch mal im
hektischen Spielgeschehen aus Tischhöhe auf den Boden fallen oder sind
dann direkt Schäden zu erwarten? Hab gerade bisschen in Datenblättern
von Quarzen und Atmel geguckt. Konnte da nichts zu finden.
Danke
IR-Bastelei schrieb:> Sascha W. schrieb:>> Es steht dir natürlich frei ein eigenes Protokoll zu erfinden was genau>> die benötigte Datenmenge mit entsprechender Bitrate überträgt.>> Danke werde ich drüber nachdenken. Gibt es dort Grenzen, wie lang/kurz> die Pulsdauer für 1/0 etc. sein dürfen?
ja die Grenzen gibt dir der TSOP vor, im Datenblatt findest du Angaben
zur minimalen und zur maximalen Dauer der Bursts sowie des minimalen
Zwischenabstands (meist in Perioden der Modulationsfrequenz) damit die
Demodulation noch funktioniert.
Sascha
> Im Endeffekt kommen die Platinen aber in Gehäuse und sind> auch nur für den Einsatz im Haus/Tisch. Also sind so> große Temperaturschwankungen nicht zu erwarten.
Sicher? Mal angenommen, du schaltest das Gerät bei 20°C ein und benutzt
es ein paar Stunden. 30°C bis 50°C sind durchaus üblich.
> Kann so ein Gehäuse mit Platine drin auch mal im> hektischen Spielgeschehen aus Tischhöhe auf den Boden> fallen oder sind dann direkt Schäden zu erwarten?
Du bist doch sicher älter als 3 Jahre und hast mit diesen Situationen
bereits Erfahrungs gemacht. Dann müsste Dir absolut klar sein, daß
Geräte häufig wenn nicht gar meisten kaputt gehen, wenn sie vom Tisch
fallen.
Quarze sind prinzipiell auch Stoßempfindlich, mir ist aber noch nie
einer zerbrochen.
Stefan U. schrieb:> Sicher? Mal angenommen, du schaltest das Gerät bei 20°C ein und benutzt> es ein paar Stunden. 30°C bis 50°C sind durchaus üblich.
Sicher kann man sich natürlich nie sein. Das wird sich erst zeigen wenn
man es testet. Über mehrere Stunden werden die Geräte aber mit hoher
Wahrscheinlichkeit nicht laufen. Und bei den geringen Strömen die
fließen werden kann ich mir keine 50 °C vorstellen. Aber wie
gesagt...wird sich zeigen.
Stefan U. schrieb:> Du bist doch sicher älter als 3 Jahre
Gerade so. Leider eher in dem Alter in dem das mit dem Zählen nicht mehr
so ernst genommen wird.
Stefan U. schrieb:> Dann müsste Dir absolut klar sein, daß> Geräte häufig wenn nicht gar meisten kaputt gehen, wenn sie vom Tisch> fallen.
Im Gegenteil. Mir sind schon häufig Geräte runtergefallen und sie
überleben es meistens. Manchmal sind ICs ja auch vergossen. Allerdings
weiß ich nicht, ob das zum Schutz des Innenlebens des Chips oder zum
Schutz der Lötstellen oder zur Abschirmung ist..
IR-Bastelei schrieb:> Frank M. schrieb:>> Ich hoffe, beim Compilieren ist die Optimierung>> eingeschaltet...>> steht momentan auf "-O2"
Stell das mal auf '-Os', denn dann sind auch die Delay Routinen passend.
NEC oder RC5 sind schon robuste Protokolle, optimal wäre es, wenn du mit
einem von den beiden klarkommst.
Stefan U. schrieb:> Quarze sind prinzipiell auch Stoßempfindlich, mir ist aber noch nie> einer zerbrochen.
Mir (und meinen Kunden) dagegen schon des öfteren. Auch Resonatoren
mögen hohe Beschleunigungen nicht.
Matthias S. schrieb:> optimal wäre es, wenn du mit> einem von den beiden klarkommst.
Puuuhh..ganz schön viel Code. Was ich mich frage : Kann man das
NEC-Protokoll vielleicht so anpassen, dass eben nicht 16 Bit Adresse +
16 Bit Kommando übertragen werden, sondern eben 4 Bit Adresse und 20 Bit
Kommando? Das wären immerhin schon 8 Bit gespart. Ich habe bisher nur
diesen Abschnitt in "irmpprotocols.h" finden können.
habe dort einfach mal spaßeshalber versucht die Werte anzupassen. Aber
dann kam wie ich bereits erwartet hatte nichts mehr an.. Das wäre ja
auch zu einfach. Wie tief muss man in den Code einsteigen, um ein
Protokoll dementsprechend anzupassen? Und geht das überhaupt?
Matthias S. schrieb:> Stell das mal auf '-Os'
Wird gemacht. Werden Delays ansonsten "wegoptimiert" ?
Matthias S. schrieb:> Auch Resonatoren> mögen hohe Beschleunigungen nicht
Erfahrung? Oder kennst du Orte an denen man das nachlesen könnte?
Dankesehr nochmals!
IR-Bastelei schrieb:> Puuuhh..ganz schön viel Code.
Ich hatte sowieso schon immer mal dran gedacht, in IRMP und IRSND ein
spezielles Protokoll mit Pulse-Distance-Coding einzubauen, das lediglich
dafür gedacht ist, Daten zwischen zwei µCs zu übertragen. Ich würde es
als Frame mit 16-Bit-Daten realisieren, wo man die Grenze zwischen
Adresse und Daten frei wählen kann.
Ich kümmere mich heute abend mal darum und melde mich.
> Wie tief muss man in den Code einsteigen, um ein Protokoll> dementsprechend anzupassen? Und geht das überhaupt?
Das geht schon, ist aber eher etwas für erfahrene Programmierer, da es
sich hier um eine ziemlich komplexe Statemachine handelt, um den
empfangenen Code schon während des Empfangs ohne Zwischenspeicherung des
IR-Frames zu dekodieren.
Aber es wurden durchaus einige exotische Protokolle von anderen Leuten
im IRMP/IRSND eingebaut und mir dann zur weiteren Verwendung zur
Verfügung gestellt. Glaub mir: soviele Fernbedienungen habe ich nicht
;-)
IR-Bastelei schrieb:> Leider scheint das noch nicht ganz so zu funktionieren.
Ich habe beim Durchsehen des IRMP-Sources festgestellt, warum Dein Test
mit LEGO fehlschlug: 4 der 16 Bit werden intern als CRC benutzt, so dass
netto nur noch 12 Byte zur freien Verfügung stehen.
Sorry, das hatte ich vergessen und Dich mit dem LEGO-Protokoll auf den
falschen Weg geführt. Immerhin ist jetzt der Grund klar, warum es mit
LEGO nicht geklappt hat.
Wie ich ja eben schrieb, dachte ich sowieso daran, mal ein
IRMP-spezifisches Protokoll zwecks Datenübertragung einzubauen.
Ich habs eben mal gemacht:
- Neue Version 3.0.8
- Neues Protokoll: IRMP16
Die Sources können über den Download-Link von IRMP und IRSND
heruntergeladen werden.
Das IRMP16-Protokoll benutzt 16 Bit Daten in irmp.command und keine
Adressbits. Die 16 Bit sind völlig transparent 1:1 frei verwendbar.
Im untenstehenden Anwendungsbeispiel habe ich die 16 Bit aufgeteilt in:
4 Bit Spielernummer 0-15
12 Bit Werte 0-4095
Sender:
1
uint16_tplayer=3;// irgendein Wert zwischen 0 und 15
2
uint16_tvalue=456;// irgendein Wert zwischen 0 und 4095
3
4
irmp_data.protocol=IRMP_IRMP16_PROTOCOL;// use IRMP16 protocol
5
irmp_data.address=0;// not used by IRMP16
6
irmp_data.command=(player<<12)|value;// value 0...65535
IR-Bastelei schrieb:> Matthias S. schrieb:>> Stell das mal auf '-Os'>> Wird gemacht. Werden Delays ansonsten "wegoptimiert" ?
Wegoptimiert nicht, aber die Zeiten stimmen nicht. Die avr-libc geht bei
den Routinen von '-Os' aus, weil das die Einstellung ist, die den
kleinsten Code erzeugt und deswegen bevorzugt wird.
Frank M. schrieb:> Ich habs eben mal gemacht:
Ui das ging schnell. Danke !!
Hab es gerade ausprobiert. Ist super flott allerdings bekomme ich Fehler
bei der Übertragung. Im Anhang mal ein Auschnitt von dem was bei mir in
Hterm ankommt. Die zu übertragende Zahl war "899". Woran könnte das
liegen? Außer dem Protokoll habe ich nichts geändert..
IR-Bastelei schrieb:> Hab es gerade ausprobiert. Ist super flott allerdings bekomme ich Fehler> bei der Übertragung. Im Anhang mal ein Auschnitt von dem was bei mir in> Hterm ankommt.
Zeige bitte mal den Source der Senderoutine.
Die Toleranzwerte habe ich hier enger gefasst, nämlich von 40 auf 20
Prozent, also XXX_TOLERANCE_40 auf XXX_TOLERANCE_20 geändert.
Grund: Die Unterschiede der Pausenlängen für 1 und 0 sind recht eng
beieinander. Bei den meisten Protokollen liegen die weiter auseinander
(3-4 faches). Ich wollte aber die Frames relativ kurz halten, deshalb
sind die Pausenverhältnisse lediglich im Verhältnis 1:2 statt 1:3 oder
gar 1:4. Bei 40% Toleranz gibt es aber schon knapp überlappende
Bereiche, die sich durch ein leicht abweichendes Timing der beiden µCs
(ohne Quarz!) durchaus auwirken können.
Wenn das auch nicht reicht, solltest Du folgenden Block in
irmpprotocols.h austauschen:
1
#define IRMP16_START_BIT_PULSE_TIME 842.0e-6 // 842 usec pulse (32 x 1/38kHz)
2
#define IRMP16_START_BIT_PAUSE_TIME 1684.0e-6 // 1684 usec pause (64 x 1/38kHz)
3
#define IRMP16_PULSE_TIME 421.0e-6 // 421 usec pulse (16 x 1/38kHz)
4
#define IRMP16_1_PAUSE_TIME 1263.0e-6 // 1264 usec pause (48 x 1/38kHz)
5
#define IRMP16_0_PAUSE_TIME 421.0e-6 // 421 usec pause (16 x 1/38kHz)
6
#define IRMP16_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms
Dann sind die Verhältnisse 1:3 statt 1:2.
Übrigens: Du kannst noch, um die Abstände zwischen den Frames kürzer zu
halten, den letzten Wert IRMP16_FRAME_REPEAT_PAUSE_TIME von 40.0e-3 auf
10.0e-3 ändern.
Schön, wenn ein Plan funktioniert aber um simple Datenwörter zu
übertragen, kann man auch gleich die UART nehmen, das ist etwas
effizienter, als immer die ganze Protokollerkennung und ständiges
Port-Polling zur Empfangsbereitschaft laufen zu lassen.
Bei der TxD muß man natürlich noch die Modulation einschleifen und
Frame/Baudrate sinnvoll einrichten.
batman schrieb:> Schön, wenn ein Plan funktioniert aber um simple Datenwörter zu> übertragen, kann man auch gleich die UART nehmen, das ist etwas> effizienter, als immer die ganze Protokollerkennung und ständiges> Port-Polling zur Empfangsbereitschaft laufen zu lassen.> Bei der TxD muß man natürlich noch die Modulation einschleifen und> Frame/Baudrate sinnvoll einrichten.
Danke für die Anmerkung. Du meinst den OUT vom TSOP direkt an den TX vom
UART hängen? Ich bin noch sehr am Anfang meiner Programmierkarriere aber
wenn du mir ein paar genauere Informationen geben könntest wie du das
meinst denke ich da gerne drüber nach. Effizient ist immer gut!
Hallo zusammen,
ich melde mich mal wieder zurück. Bin bei der Entwicklung schon ein
wenig weiter und ich bin mir leider relativ sicher, dass am Ende die
Datenrate welche ich mit IRMP und IRSND erreiche nicht ausreichen wird.
Mit dem IRMP16-Protokoll sind rein rechnerisch ca. 30 Messwerte
erreichbar (Alle Bits ==1 ). Die kann ich per "Messung" auch bestätigen.
Jetzt aber angenommen es sind 8 Spieler mit in der Runde, dann sind es
schon < 4 Messwerte pro Sekunde, denn es wird so sein, dass ein Spieler
auch mal Signale an mehrere Spieler gleichzeitig aussenden muss.
Ich habe bereits versucht, die Puls- und Pausenzeiten anzupassen. Ich
hab mich dabei an der minimalen Pausenzeit des TSOPs orientiert. Laut
Datenblatt muss die Pause nach einem Puls mindestens 12 Zyklen lang
sein, was bei 38 kHz ca. 315 µs wären. Darunter ging tatsächlich gar nix
mehr. Mit 350 µs hat es noch funktioniert. Die anderen Werte habe ich
natürlich auch dementsprechend angepasst. Außerdem habe ich die Zeit
zwischen den Frames bis auf 7 ms reduziert. So kam ich letztenendes auf
ca. 47 Übertragungen pro Sekunden. Auch keine große Steigerung. Ich habe
auch noch versucht die Bitzahl auf 12 Bit zu reduzieren, allerdings hat
das nicht so ohne weiteres funktioniert und ich konnte auch nicht
festellen welche Funktion das verursacht hat. (Die letzten vier Bits
waren immer abgeschnitten, es konnte also nur Zahlen in 16er Schritten
übertragen werden. Ich hatte zunächst bei der "Bitreverse"-Funktion
etwas vermutet konnte es aber nicht beheben)
Ich hab mich jetzt also noch weiter zum Thema Infrarot-Übertragung
belesen und habe überlegt IrDA zu nutzen. Damit sind ja wesentlich
höhere Datenraten nötig. Das ganze sollte allerdings nicht unendlich
kompliziert werden und ich würde gerne meine Atmega328p weiterverwenden.
Eventuell muss ich dann doch über externe Quarze nachdenken. Ich habe
mir den Schnittstellen-IC MCP2120 angeschaut. Seh ich das richtig, dass
ich meine RX/TX-Leitungen vom MC einfach an den Chip hänge, und der
übernimmt die Modulation/Demodukation und an der Empfängerseite kommt
das Gesendete wieder raus? Tranceiver muss natürlich auch noch an den
IC.
Danke schonmal.