Nabend,
ich habe ein kleines Problem mit meinem IR-Empfänger.
Ich nutze die IRMP-Bibliothek aus dem Tutorial.
Als Empfänger nutze ich den TSOP31256.
Und zwar reagiert meine Software anscheinend nicht auf den Empfänger.
Dazu gesagt habe ich für die ISR-Routine den Timer2 meines Atmega32
benutzt.
Diesen habe ich folgendermaßen initialisert:
TCCR2=(1<<WGM21)|(1<<CS20);//CTC Mode an, prescaler = 1
21
TIMSK=1<<OCIE2;//Timer2 Interrupt eingeschaltet
22
23
24
lcd_init();
25
irmp_init();
26
IRMP_DATAirmp_data;
27
sei();
28
while(1){
29
if(irmp_get_data(&irmp_data)){
30
lcd_string_xy(0,0,"gelesen");
31
_delay_ms(500);
32
_delay_ms(500);
33
34
}else{
35
lcd_clear();
36
}
37
38
39
}
40
41
return0;
42
}
Wie zu erkennen ist soll der Atmega mir ein kleines Feedback auf mein
LCD schreiben wenn es etwas erkannt hat.
Die ISR wird aufgerufen. Das habe ich mit einer Ausgabe auf dem LCD
getestet.
Der IR-Empfänger erkennt ebenfalls die Signale wie ich per Oszi
überprüft habe.
Nun vermute ich meinen Fehler in der Software. Habe ich einen Fehler bei
der initialisierung des Timers oder des Interrupts gemacht oser was könt
ihr erkennen.
Vielen Dank schonmal.
Hallo,
wichtig für das Funktionieren des IRMP ist es, genügend oft einen
Interrupt auszulösen, so wie es das favorisierte Protokell erfordert,
also im Bespiel 10000 ... 15000 IRQs pro Sekunde. Desweiteren müssen per
defines diejenigen Protokolle eingeschaltet sein, die es empfangen
können soll. Es müßte also zumindest das eine Protokoll aktiviert sein,
das Deine Fernbendienung liefert. Falls nur die falschen Protokolle
aktiviert sind, wird auch nichts empfangen.
ebenso muß der Richtige Eingangs-Pin eingestellt sein und in IRMP.c die
passenden Protokolle aktiviert sein.
hier mal ein kleiner Auszug aus IRMP.h:
"/*---------------------------------------------------------------------
------------------------------------------------------------------------
------
* Change F_INTERRUPTS if you change the number of interrupts per
second, F_INTERRUPTS should be in the range from 10000 to 15000
*-----------------------------------------------------------------------
------------------------------------------------------------------------
----
*/
#define F_INTERRUPTS 10000
// interrupts per second
#define IRMP_SIRCS_PROTOCOL 1
// Sony
#define IRMP_NEC_PROTOCOL 2
// NEC, Pioneer, JVC, Toshiba, NoName etc.
#define IRMP_SAMSUNG_PROTOCOL 3
// Samsung
#define IRMP_MATSUSHITA_PROTOCOL 4
// Matsushita
#define IRMP_KASEIKYO_PROTOCOL 5
// Kaseikyo (Panasonic etc)
#define IRMP_RECS80_PROTOCOL 6
// Philips, Thomson, Nordmende, Telefunken, Saba
#define IRMP_RC5_PROTOCOL 7
// Philips etc
#define IRMP_DENON_PROTOCOL 8
// Denon
#define IRMP_RC6_PROTOCOL 9
// Philips etc
#define IRMP_SAMSUNG32_PROTOCOL 10
// Samsung32: no sync pulse at bit 16, length 32 instead of 37
#define IRMP_APPLE_PROTOCOL 11
// Apple, very similar to NEC
#define IRMP_RECS80EXT_PROTOCOL 12
// Philips, Technisat, Thomson, Nordmende, Telefunken, Saba
#define IRMP_NUBERT_PROTOCOL 13
// Nubert"
IRMP.c:
"#include "irmp.h"
/*----------------------------------------------------------------------
------------------------------------------------------------------------
-----
* Change settings from 1 to 0 if you want to disable one or more
decoders.
* This saves program space.
* 1 enable decoder
* 0 disable decoder
*-----------------------------------------------------------------------
------------------------------------------------------------------------
----
*/
#define IRMP_SUPPORT_SIRCS_PROTOCOL 1 // flag: support
SIRCS uses ~100 bytes
#define IRMP_SUPPORT_NEC_PROTOCOL 1 // flag: support
NEC + APPLE uses ~250 bytes
#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 // flag: support
Samsung + Samsung32 uses ~250 bytes
#define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1 // flag: support
Matsushita uses ~50 bytes
#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1 // flag: support
Kaseikyo uses ~50 bytes
#define IRMP_SUPPORT_RECS80_PROTOCOL 1 // flag: support
RECS80 uses ~50 bytes
#define IRMP_SUPPORT_RC5_PROTOCOL 1 // flag: support
RC5 uses ~250 bytes
#define IRMP_SUPPORT_DENON_PROTOCOL 1 // flag: support
DENON uses ~250 bytes
#define IRMP_SUPPORT_RC6_PROTOCOL 1 // flag: support
RC6 uses ~200 bytes
#define IRMP_SUPPORT_RECS80EXT_PROTOCOL 1 // flag: support
RECS80EXT uses ~50 bytes
#define IRMP_SUPPORT_NUBERT_PROTOCOL 1 // flag: support
NUBERT uses ~50 bytes
/*----------------------------------------------------------------------
------------------------------------------------------------------------
-----
* Change hardware pin here:
*-----------------------------------------------------------------------
------------------------------------------------------------------------
----
*/
#ifdef PIC_CCS_COMPILER // PIC CCS
Compiler:
#define IRMP_PIN PIN_D2 // use PD2 as IR
input on PIC
#else // AVR:
#define IRMP_PORT PORTD
#define IRMP_DDR DDRD
#define IRMP_PIN PIND
#define IRMP_BIT 2 // use PB6 as IR
input on AVR
#define input(x) ((x) & (1 << IRMP_BIT))
#endif
"
______________________________________________________
Du scheinst nirgends die gelesenen Daten aufs Display zu schreiben.
funktionierende Lösung im mir vorliegenden Beispiel:
....main...
for (;;)
{
if (irmp_get_data (&irmp_data))
{
// ir signal decoded, do something here...
// irmp_data.protocol is the protocol, see irmp.h
// irmp_data.address is the address/manufacturer code of ir
sender
// irmp_data.command is the command code
#if IRMP_LOGGING != 1
lcd_clrscr();
lcd_puts("R: Code: ");
lcd_puts(Proto[irmp_data.protocol-1]);
lcd_gotoxy(0,1);
lcd_puts("A: ");
lcd_puts(itoa(irmp_data.address,s,16));
lcd_puts(" C: ");
lcd_puts(itoa(irmp_data.command,s,16));
uart_putc(0x0A);
uart_puts("R: Code: ");
uart_puts(Proto[irmp_data.protocol-1]);
uart_puts(" A: ");
uart_puts(itoa(irmp_data.address,s,16));
uart_puts(" C: ");
uart_puts(itoa(irmp_data.command,s,16));
}"
____________________________
Die konfiguration ist gar nicht so einfach.
mit freundlichem Gruß
Vielen Dank für die ausführliche Antwort.
Habe vergessen zu sagen, dass die irmpconfig.h bereits eingestellt ist.
Ich habe zum testen erstmal nahezu alle protokolle aktiviert und der
Eingangspin ist eingestellt.
Die Interrupts habe ich auf 15000 belassen.
Gehe ich recht in der Annahme, dass es daran liegen könnte dass der
Timer2 des Atmegas ein 8Bit-Timer ist und die 15000 Interrupts mit
meinen Einstellungen nicht liefern kann?
Wenn ja worauf muss ich achten? In welchem Modus bekomme ich den Timer2
auf die nötige Gesvhwindigkeit?
Achso.. nein ich schreibe die gelesenen Daten momentan nicht aufs
Display.
Vielmehr schreibe ich das Wort "gelesen" aufs LCD wenn überhaupt
irgendein IR-Signal erkannt wurde. Halt zum Testen obs erstmal
grundsätzlich läuft.
Gruß
roehrenvorheizer schrieb:> Lief bei mir schon mal.
Ja bei mir lief es auch schonmal. Aber halt mit Timer1(wie in deinem
Beispiel) Timer1 ist im Gegensatz zu Timer2 allerdings ein 16bit Timer.
Ich möchte den Interrupt aber von dem 8Bit-Timer auslösen.
Ich werde nochmal schauen müssen wie ich den CompareWert für OCR2 für
den 8Bit-Timer ausrechnen muss.
Kann mir da vielleicht wer einen Tipp geben?
Hallo,
Timer2 kann beliebig "schnell" eingestellt werden, siehe Mega48 88 168
Datenblatt:
• Bit 2:0 – CS22:0: Clock select
The three Clock Select bits select the clock source to be used by the
Timer/Counter, see Table
18-9.
If external pin modes are used for the Timer/Counter0, transitions on
the T0 pin will clock the
counter even if the pin is configured as an output. This feature allows
software control of the
counting.
Table 18-9. Clock select bit description.
CS22 CS21 CS20 Description
0 0 0 No clock source (timer/counter stopped)
001clkT2S/(no prescaling)
010clkT2S/8 (from prescaler)
011clkT2S/32 (from prescaler)
100clkT2S/64 (from prescaler)
101clkT2S/128 (from prescaler)
110clkT2S/256 (from prescaler)
111clkT2S/1024 (from prescaler)
Um auf den gewünschten Wert zu kommen, braucht es noch einen
"reload"-Wert, mit dem man das Timer-Register bei jedem Interrupt
beschreibt.
mfG
Sorry aber ich hab das Gefühl du kopierst nur Auszüge. Das Hilft mir
nicht und war auch nicht meine Frage.
Nochmal die Frage:
Wir errechne ich den Wert für einen 8bitTimer(Prescaler1,
Ctc-Modus,interner Takt 8Mhz) den ich in OCR2 schreiben muss um auf
15000 Interrupts zu kommen?
Eine kleine Formel reicht mir ;-D ansonsten werde ich es heute
Nachmittag mal damit versuchen den Wert vom timer1 über
verhältnisrechnung an timer2 anzupassen. Oder begehe ich damit einen
völlig falschen weg?
Hans B. schrieb:> Nochmal die Frage:>> Wir errechne ich den Wert für einen 8bitTimer(Prescaler1,> Ctc-Modus,interner Takt 8Mhz) den ich in OCR2 schreiben muss um auf> 15000 Interrupts zu kommen?>> Eine kleine Formel reicht mir
Warum entnimmst du sie dann nicht einfach dem Datenblatt, da steht die
nämlich drinne?
Aber natürlich zeigt schon eine überschlägige Rechnung, daß es so nicht
funktionieren kann. 8.000.000/256=31.250.
256 ist der maximale Zählumfang eines 8Bit-Timers, d.h.: die
Interruptfrequenz kann bei 8MHz Timertakt niemals geringer als 31kHz
werden, jedenfalls nicht im CTC-Modus.
Du wirst also entweder einen anderen Prescaler oder einen anderen
Basistakt oder einen anderen Timermodus verwenden müssen, um deine 15kHz
Interruptfolgefrequenz zu erreichen.
Hans B. schrieb:> Eine kleine Formel reicht mir ;-D ansonsten werde ich es heute> Nachmittag mal damit versuchen den Wert vom timer1 über> verhältnisrechnung an timer2 anzupassen. Oder begehe ich damit einen> völlig falschen weg?
Besser wäre es zu verstehen, wie die einzelnen Werte zusammen hängen.
Das ist tatsächlich wirklich nicht schwer.
FAQ: Timer
Hallo,
und nun? Geht's jetzt?
"Ich möchte den Interrupt aber von dem 8Bit-Timer auslösen.
Ich werde nochmal schauen müssen wie ich den CompareWert für OCR2 für
den 8Bit-Timer ausrechnen muss.
"
Man könnte ja per Oszilloskop schauen, wieviele Interrupts pro Sekunde
an einem extra dafür angesteuerten Pin ausgelöst werden und einfach
mehrere Einstellungen ausprobieren. Interessant ist auch der entstehende
Jitter zu beobachten.
mfG
Soo.. letzendlich wirklich simpel.
Ich stand nur extrem auf dem Schlauch scheinbar.
Also es lag an dieser Zeile:
1
OCR2=(F_CPU/F_INTERRUPTS)-1;
Und zwar kommt bei der Rechnung mit den Werten 8Mhz und 15000 Interrupts
ein Wert von 532 heraus.
Da es sich bei dem Timer2 um ein 8-bit-Timer handelt lässt sich dieser
Wert nicht in OCR2 ablegen da man mit 8 bit nur bis 256 kommt.
Meine Lösung war folgende:
1
OCR2=((F_CPU/F_INTERRUPTS)/8)-1;
2
TCCR2=(1<<WGM21)|(1<<CS21);
Und zwar setzte ich en Prescaler des Timer2 auf 8 und dividierte dann
den Wert für OCR2 ebenfalls durch acht. Damit kam ich auf einen Wert von
65, welcher sich nun bequem in das 8Bit-Register OCR2 schreiben lässt.
Durch C-haters kleinen Tipp kam die erleuchtung und die Hand an die
Stirn ;-)
Der tatsächliche Wert für F_INTERRUPTS wäre dann also 15152.
Setze ihn also auf 15152, dann arbeitet IRMP genauer.
Dann musst Du aber noch folgende Zuweisung korrigieren, sonst koppelt
die Korrektur von F_INTERRUPTS zurück in den Wert von OCR2 wegen
(falscher) konsequenter Abrundung:
1
OCR2=(uint8_t)((F_CPU/F_INTERRUPTS)/8)-1+0.5);
Diese Zuweisung wird dann noch auf den besten Integer gerundet - in
diesem Fall von 64,99 auf 65 aufgerundet. Keine Angst, Du fängst Dir
damit keine Floating-Point-Rechnung ein. Das macht der Preprocessor at
Compile-Time.
> Und zwar setzte ich en Prescaler des Timer2 auf 8 und dividierte dann> den Wert für OCR2 ebenfalls durch acht. Damit kam ich auf einen Wert von> 65, welcher sich nun bequem in das 8Bit-Register OCR2 schreiben lässt.
Ich werde die obige Methode im IRMP-Artikel als Alternative zum
Timer1 dokumentieren.