Forum: Mikrocontroller und Digitale Elektronik rc5 decoder Atmega16 funktioniert nicht


von Max W. (max96)


Lesenswert?

Hallo,
ich habe mal wieder ein kleines Problem. Ich bin gerade dabei mir einen 
Vorverstärker mit Atmega16 und TDA7439 als Herzstück zu bauen. Alles 
läuft soweit einwandfrei (LCD und TDA). Nun möchte ich das ganze um 
einen RC5-Empfänger ergänzen. An PB2 habe ich einen TSOP1136 
angeschlossen, mit 10k Pullup. Als Code verwende ich eine angepasste 
Version hiervon: 
http://www.rn-wissen.de/index.php/RC5-Decoder_f%C3%BCr_ATMega, weil mein 
Timer0 schon mit dem Drehimpulsgeber beschäftigt ist und INT0 und INT1 
vom LCD belegt werden. meine rc5.h:
1
 #ifndef _RC5_H_
2
#define _RC5_H_
3
4
#include <inttypes.h>
5
6
#define RC5_INT2 2
7
8
#define RC5_ALL 0xff
9
10
typedef struct
11
{
12
  volatile uint8_t code;
13
  volatile uint8_t addr;
14
  volatile signed char flip;
15
} rc5_t;
16
17
extern rc5_t rc5;
18
extern void rc5_init (uint8_t addr);
19
20
#endif /* _RC5_H_ */

meine rc5.c:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#include "rc5.h"
5
6
#ifndef RC5_PRESCALE
7
#define RC5_PRESCALE 64
8
#endif  /* RC5_PRESCALE */
9
10
/* ******************************************************************************** */
11
12
rc5_t rc5;
13
14
/* ******************************************************************************** */
15
16
#ifndef F_CPU
17
#error Please define F_CPU
18
#endif /* !F_CPU */
19
20
/* µs for a whole bit of RC5 (first & second part) */
21
#define RC5_BIT_US   (64*27)
22
23
#define RC5_TICKS \
24
        ((uint8_t) ((uint32_t) (F_CPU / 1000 * RC5_BIT_US / 1000 / RC5_PRESCALE)))
25
26
#define RC5_DELTA \
27
        (RC5_TICKS / 6)
28
29
typedef union
30
{
31
        uint16_t w;
32
        uint8_t  b[2];
33
} code_t;
34
35
static code_t code;
36
static uint8_t rc5_addr;
37
38
/* Number of Bits received so far */
39
/* Number of Interrupts occured so far */
40
static uint8_t nbits;
41
static uint8_t nint;
42
43
/* ******************************************************************************** */
44
45
void rc5_init (uint8_t addr)
46
{
47
        nint  = 0;
48
        nbits = 0;
49
        rc5.flip = -1;
50
51
        rc5_addr = addr;
52
53
#if (RC5_PRESCALE==1024)
54
        TCCR2 |= ((1 << CS22) | (1 << CS20) | (1 << CS21));
55
#elif   (RC5_PRESCALE==256)
56
        TCCR2 |= ((1 << CS22) | (1 << CS21));
57
#elif   (RC5_PRESCALE==64)
58
        TCCR2 |= (1 << CS22);
59
#else
60
#error This RC5_PRESCALE is not supported
61
#endif /* RC5_PRESCALE */
62
63
        /* INTx on falling edge */
64
        /* clear pending INTx */
65
        /* enable INTx interrupt */
66
MCUCR &= ~(1 << ISC2);
67
GIFR |= (1 << INTF2);
68
GICR |= (1 << INT2);
69
}
70
71
/* ******************************************************************************** */
72
73
ISR(TIMER2_OVF_vect)
74
{
75
        TIMSK &= ~(1 << TOIE2);
76
77
        uint8_t _nbits = nbits;
78
        code_t _code = code;
79
80
        if (26 == _nbits)
81
        {
82
                _nbits++;
83
                _code.w <<= 1;
84
        }
85
86
        if (27 == _nbits
87
                && _code.b[1] >= 0x30 /* AGC == 3 */
88
                && 0 > rc5.flip)
89
        {
90
                uint8_t _rc5_code;
91
                uint8_t _rc5_addr;
92
                /* we do the bit manipulation stuff by hand, because of code size */
93
                _rc5_code = _code.b[0] & 0x3f; /* 0b00111111 : #0..#5 */
94
                _code.w <<= 2;
95
                _rc5_addr = _code.b[1] & 0x1f; /* 0b00011111 : #6..#10 */
96
97
                if ((rc5_addr & 0x80)
98
                        || rc5_addr == _rc5_addr)
99
                {
100
                        rc5.code = _rc5_code;
101
                        rc5.addr = _rc5_addr;
102
                        signed char flip = 0;
103
                        if (_code.b[1] & 0x20) /* 0b00100000 : #11 */
104
                                flip = 1;
105
                        rc5.flip = flip;
106
                }
107
        }
108
109
        nint = 0;
110
        nbits = 0;
111
112
        /* INTx on falling edge */
113
        /* clear pending INTx */
114
        /* enable INTx interrupt */
115
116
MCUCR &= ~(1 << ISC2);
117
GIFR |= (1 << INTF2);
118
GICR |= (1 << INT2);
119
120
}
121
122
/* ******************************************************************************** */
123
124
125
ISR(INT2_vect)
126
{
127
        code_t _code = code;
128
        uint8_t _nint = nint;
129
130
        uint8_t tcnt0 = TCNT2;
131
        TCNT2 = 0;
132
133
        if (0 == _nint)
134
        {
135
136
            MCUCR &= ~(1 << ISC2);
137
138
                TIFR |= (1 << TOV2);
139
                TIMSK |= (1 << TOIE2);
140
                _code.w = 0;
141
        }
142
        else
143
        {
144
                /* Number of bits of the just elapsed period */
145
                uint8_t n = 1;
146
147
                /* Bits received so far */
148
                uint8_t _nbits = nbits;
149
150
                /* is TCNT0 close to RC5_TICKS or RC5_TICKS/2 ? */
151
                if (tcnt0 > RC5_TICKS + RC5_DELTA)
152
                        goto invalid;
153
                else if (tcnt0 < RC5_TICKS/2 - RC5_DELTA)
154
                        goto invalid;
155
                else if (tcnt0 > RC5_TICKS - RC5_DELTA)
156
                        n = 2;
157
                else if (tcnt0 > RC5_TICKS/2 + RC5_DELTA)
158
                        goto invalid;
159
160
                /* store the just received 1 or 2 bits */
161
                do
162
                {
163
                        _nbits++;
164
                        if (_nbits & 1)
165
                        {
166
                                _code.w <<= 1;
167
                                _code.b[0] |= _nint & 1;
168
                        }
169
                }
170
                while (--n);
171
172
                if (0)
173
                {
174
                        invalid:
175
176
                        /* disable INTx, run into Overflow0 */
177
                        GICR &= ~(1 << INT2);
178
179
                        _nbits = 0;
180
                }
181
182
                nbits = _nbits;
183
        }
184
185
        code = _code;
186
        nint = 1+_nint;
187
}

der restliche relevante Teil:
1
...
2
#include "rc5.h"
3
...
4
void main()
5
{
6
...
7
  rc5_init(RC5_ALL);
8
  sei(); 
9
        while(1) {
10
           if (-1 == rc5.flip){}
11
           else {
12
            GLCD_ClearScreen();
13
            GLCD_WriteInt(rc5.code);
14
            rc5.flip = -1;
15
          
16
       }
17
   }
18
}
Ich habe jetzt schon 2 Universalfernbedienungen mit den verschiedensten 
Codes von Philips probiert und bekomme keinen einzigen code. Könnt ihr 
mir irgendwie weiterhelfen? An der Form kann man sicher noch arbeiten 
aber es sollte lesbar sein.

Vielen Dank für eure Hilfe.

von c-hater (Gast)


Lesenswert?

Max W. schrieb:

> Ich habe jetzt schon 2 Universalfernbedienungen mit den verschiedensten
> Codes von Philips probiert und bekomme keinen einzigen code.

Ähem...

Wackelt denn überhaupt irgendwas am Pin, wenn du einen Knopf auf der FB 
drückst?

Weil: ohne Signal kannst du nix decodieren. Es macht also überhaupt 
keinen Sinn, bei der Fehlersuche mit dem Decoderprgramm anzufangen. 
Erstmal muß geklärt sein, ob es überhaupt ein Signal zum Decodieren 
gibt.

Und nein: längst nicht jede RC5-FB (auch nicht die von Philips) sendet 
mit 36kHz Träger! Und dein TSSOP kann nur 36kHz empfangen.

von Sascha W. (sascha-w)


Lesenswert?

c-hater schrieb:
> Max W. schrieb:
> Und nein: längst nicht jede RC5-FB (auch nicht die von Philips) sendet
> mit 36kHz Träger! Und dein TSSOP kann nur 36kHz empfangen.
ich weiß ja nicht wie das bei den TSOP11xx ist, aber die 15xx waren so 
breitbandig, das bei Entfernungen <=1m jede FB geht.

Sascha

von Oliver (Gast)


Lesenswert?

Auch wenn RC5 überall bei den Mikrocontroller-Beispielen das am 
weitesten verbreitetste Sendeformat zu sein scheint, in realen 
Fernbedienungen kam das wohl nur äußerst selten vor. Deine 
Universalfernbedienung kann also duchaus auch bei Philips-Emulation was 
ganz anderes senden.

Ansonsten, wie schon gesagt, erst einmal schauen, ob überhaupt ein 
Signal am Pin ankommt.

Oliver

von c-hater (Gast)


Lesenswert?

Oliver schrieb:

> Auch wenn RC5 überall bei den Mikrocontroller-Beispielen das am
> weitesten verbreitetste Sendeformat zu sein scheint, in realen
> Fernbedienungen kam das wohl nur äußerst selten vor.

HEUTE ist das bei Neugeräten tatsächlich so. Vor zehn Jahren sah das 
noch ganz anders aus.

Allerdings: Die Chance, bei Universal-FBs unter Philips-Codes welche mit 
RC5-Codierung zu finden, ist auch heute noch extrem hoch, denn die 
Dinger enthalten naturgemäß ausschließlich die Codes von Geräten der 
Vergangenheit und nicht der Gegenwart oder gar der Zukunft.

Auch Denken will gelernt sein!

von Wusel D. (stefanfrings_de)


Lesenswert?

> Vor zehn Jahren sah das noch ganz anders aus.

Nee, da war das war schon immer so. Da gibt's nichtmal einen 
einheitlichen Standard pro Marke.

von Max W. (max96)


Lesenswert?

So ich konnte erst jetzt am Projekt weiterarbeiten, war über das 
Wochenende verreist. Ein Signal kommt am TSOP an. getestet habe ich das 
Ganze mit der Fernbedienung von meinem Philips BDP7500MKII. Demnach muss 
der Fehler im Code liegen. Wie kann ich jetzt weiter vorgehen?

von Εrnst B. (ernst)


Lesenswert?

Max W. schrieb:
> Wie kann ich jetzt weiter vorgehen?

Du könntest einen anderen RC5-Decoder-Code ausprobieren, z.B. einen der 
ohne externen Interrupt auskommt, und nur mit dem Timer arbeitet:

z.B. den Klassiker von PeDa:
Beitrag "Fernbedien RC5 Empfänger"

oder gleich IRMP

von spess53 (Gast)


Lesenswert?

Hi

Software gibt es auch von ATMEL

AVR410: RC5 IR Remote Control Receiver on tinyAVR and megaAVR devices

MfG Spess

von Max W. (max96)


Lesenswert?

Ich habe es jetzt mit dem Code von Peter Dannegger zum laufen bekommen. 
Meine OneForAll Fernbedienung hat sogar einen RC5-Code dabei, 
funktioniert wunderbar. Danke für eure Hilfe.

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.