Forum: Compiler & IDEs Problem mit RC5


von Fragender (Gast)


Lesenswert?

Hallo,

ich versuche mit folgendem Code RC5 mit einem TSOP1736 zu empfangen, die 
Fernbedienung sendet RC5.

SIGNAL(SIG_INTERRUPT0)
{
 uint8_t foo,i;
 //GICR &= ~(1<<INT0); // Externen Interrupt deaktivieren
 char wert[30] = "interrupt!!!";
 char test[30] = "1";
 send_string(wert);
 for(i=0;i<=14;i++) {
  foo = (PIND && (1<<3));
  if(foo==1) {
  send_string(test);}
  _delay_us(1778);
  foo = 0;
 }

Das Problem ist, ich bekomme immer 15 Einser, egal welche Taste ich 
drücke, eigentlich dürfte ich doch nur soviele Einser bekommen, wie auch 
tatsächlich im Code vorkommen?!
CPU ist ein ATMEGA8, 16Mhz.
Gruss
Fragender

von Matthias L. (Gast)


Lesenswert?

1
SIGNAL(SIG_INTERRUPT0)
2
{
3
...
4
  _delay_us(1778);

HO-ECKER! Sie sind raus!



Beitrag "Fernbedien RC5 Empfänger"

von Stefan E. (sternst)


Lesenswert?

Mal davon abgesehen, dass der ganze Ansatz relativ untauglich ist ...

> foo = (PIND && (1<<3));

foo ist hier immer dann 1, wenn irgendein Pin an Port D High ist.

von Fragender (Gast)


Lesenswert?

Das hilft mir jetzt leider nicht wirklich weiter.. was ist an dem delay 
falsch? Das sollte doch noch im Bereich des Erlaubten sein oder?
Und nach meinem Verständnis wird wird damit der PIND3 eingelesen.

von Matthias L. (Gast)


Lesenswert?

>delay falsch?
Ein Warte_Zeit_X hat in einer ISR NICHTS , aber auch GARNICHTS zu 
suchen.
Dort hängt der µC ja sonst fest.

Meiner (persönlichen) Meinung, sind Warteschleifen jeglicher Art  (warte 
auf irgendein Bit/Zeit,..) ein absolutes No-Go. SOwas realisiert man mit 
verschiedenen Task und Schrittketten...

>(PIND && (1<<3)); ... PIND3 eingelesen.

wenn dann so:
1
foo = (PIND & (1<<3));
2
// foo = 0     , wenn PD3 low
3
// foo = (1<<3), wenn PD3 high

von Fragender (Gast)


Lesenswert?

Aber ich will ja gerade, dass das Programm dort "festhängt", damit der 
RC5 Code gelesen wird und dann kann es ja normal weitergehen, neue 
Interrupts in dieser Zeet sind unerwünscht!

von Fragender (Gast)


Lesenswert?

So, habs jetzt nochmal komplett neugestrickt, und zwar interuptbasiert:
1
SIGNAL(SIG_INTERRUPT0)
2
{
3
 TIMSK |= (1<<TOIE0);
4
 char last_bit = 1;
5
 char test[3];
6
 uint8_t i;
7
 if(TCNT0<139 && bitnummer <= 14 && last_bit == 1) {
8
  gesamt[bitnummer] = 1;
9
  last_bit = 1;
10
  TCNT0 = 0;
11
  bitnummer++;
12
  }
13
 if(TCNT0>139 && TCNT0<194 && bitnummer <= 14 && last_bit == 1) {
14
  gesamt[bitnummer] = 0;
15
  last_bit = 0;
16
  TCNT0 = 0;
17
  bitnummer++;
18
  }
19
 if(TCNT0<139 && bitnummer <= 14 && last_bit == 0) {
20
  gesamt[bitnummer] = 0;
21
  last_bit = 0;
22
  TCNT0 = 0;
23
  bitnummer++;
24
  }
25
 if(TCNT0>139 && TCNT0<194 && bitnummer <= 14 && last_bit == 0) {
26
  gesamt[bitnummer] = 1;
27
  last_bit = 1;
28
  TCNT0 = 0;
29
  bitnummer++;
30
  }
31
 if(bitnummer == 14) {
32
  gesamt[1] = 1;
33
  send_string(ergebnis);
34
  last_bit = 1;
35
  bitnummer = 1;
36
  TIMSK &= ~(1<<TOIE0);
37
  TCNT0 = 0;
38
  rdy = 1;
39
  }
40
} 
41
   
42
   
43
int main(void)
44
{
45
 init_usart();
46
 init_rc5();
47
 sei();
48
 uint8_t i;
49
 char test[3];
50
 char wert[10] = "RC5:";
51
 for(;;)
52
 {
53
  if(rdy==1) {
54
  send_string(wert);
55
  for(i=1;i<=14;i++) {
56
    itoa(ergebnis[i],test,10);
57
    send_string(test);
58
    }
59
  rdy = 0;
60
  }
61
  
62
 };
63
}
Leider bekomme ich als Ergebnis eine ellenlange Zahl, und nicht das 
gewünschte :( zumindest die Geräteadresse müsste ja 0 sein. Wär schön 
wenn sich jemand den Code mal durchlesen würde, wenn Fragen zum Code da 
sind, bitte fragen!

von Fragender (Gast)


Lesenswert?

Und noch die Initialisierung + Variablen:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <math.h>
#include <inttypes.h>
#include <compat/deprecated.h>





volatile char s_bit;
volatile uint8_t addresse;
volatile uint8_t code;
volatile char rdy;
volatile uint16_t gesamt[14];


volatile uint8_t bitnummer = 0;
volatile char ergebnis[20] = "RC5 fertig!";

void init_rc5()
{
 MCUCR |= (1<<ISC01) | (1<<ISC00);;  //wait rising edge
 GICR |= (1<<INT0);    //enable INT0
 TCCR0 |= (1<<CS02);   //Prescaler 256
 cbi(DDRD,PD2);
}

von Stefan E. (sternst)


Lesenswert?

1
SIGNAL(SIG_INTERRUPT0)
2
{
3
  TIMSK |= (1<<TOIE0);
4
...
5
  TIMSK &= ~(1<<TOIE0);
6
...
Wieso hantierst du mit TOIE0, du hast doch gar keinen Timer-Interrupt.

1
 if(TCNT0>139 && TCNT0<194 && bitnummer <= 14 && last_bit == 1) {
2
  gesamt[bitnummer] = 0;
3
  last_bit = 0;
4
  TCNT0 = 0;
5
  bitnummer++;
6
  }
7
 if(TCNT0<139 && bitnummer <= 14 && last_bit == 0) {
8
  gesamt[bitnummer] = 0;
9
  last_bit = 0;
10
  TCNT0 = 0;
11
  bitnummer++;
12
  }
Wenn das erste if zutrifft, trifft auch das zweite automatisch zu (noch 
im selben Interrupt), außer "bitnummer" wird durch das erste if größer 
als 14.

1
volatile uint16_t gesamt[14];
2
...
3
if( ... && bitnummer <= 14 && ... ) {
4
  gesamt[bitnummer] = 0;
Du schreibst hinter das Ende des Array.

1
  for(i=1;i<=14;i++) {
2
    itoa(ergebnis[i],test,10);
3
    send_string(test);
4
    }
Wieso "ergebnis", die eingelesenen Bits stehen doch in "gesamt".
Und der Array-Index würde auch hier nicht stimmen.

PS: Das ist nur das, was mir auf die Schnelle aufgefallen ist. Es gibt 
vermutlich noch mehr Problemstellen.

von Fragender (Gast)


Lesenswert?

Hallo,
hab deine Anmerkungen ausgebessert, hilft aber leider nich twirklich 
weiter, ich schaue mir jetzt die adressbits an und die sind leider 
meistens 11111 oder es kommt gar nichts. hier der korrigierte code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <math.h>
4
#include <inttypes.h>
5
#include <compat/deprecated.h>
6
7
volatile char s_bit;
8
volatile uint8_t addresse;
9
volatile uint8_t code;
10
volatile char rdy;
11
volatile uint16_t gesamt[14];
12
13
volatile uint8_t bitnummer = 1;
14
volatile char ergebnis[20] = "RC5 fertig!";
15
16
void init_rc5()
17
{
18
 MCUCR |= (1<<ISC01) | (1<<ISC00);;  //wait rising edge
19
 GICR |= (1<<INT0);    //enable INT0
20
 TCCR0 |= (1<<CS02);   //Prescaler 256
21
 cbi(DDRD,PD2);
22
}
23
24
//****************************************************USART******************************
25
26
void init_usart(void)
27
{
28
 UBRRL |= 0b01100111;
29
 UCSRB = (1<<TXEN) | (1<<RXEN);
30
 UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
31
}
32
33
void send_char(unsigned char s)
34
{
35
 while (!(UCSRA & (1<<UDRE)));
36
 UDR = s;
37
}
38
39
void send_string(char *s)
40
{
41
 while(*s != '\0')
42
  {
43
   send_char(*s);
44
   s++;
45
  }
46
}
47
48
//**********************************************************USART-ENDE********************
49
50
51
SIGNAL(SIG_INTERRUPT0)
52
{
53
 TIMSK |= (1<<TOIE0);
54
 char last_bit = 1;
55
 char test[3];
56
 uint8_t i;
57
 if(last_bit == 1) {
58
 if(TCNT0<139 && bitnummer <= 14) {
59
  gesamt[bitnummer] = 1;
60
  last_bit = 1;
61
  TCNT0 = 0;
62
  bitnummer++;
63
  }
64
 if(TCNT0>139 && TCNT0<194 && bitnummer <= 14) {
65
  gesamt[bitnummer] = 0;
66
  last_bit = 0;
67
  TCNT0 = 0;
68
  bitnummer++;
69
  }
70
 }
71
 if(last_bit == 0) {
72
 if(TCNT0<139 && bitnummer <= 14) {
73
  gesamt[bitnummer] = 0;
74
  last_bit = 0;
75
  TCNT0 = 0;
76
  bitnummer++;
77
  }
78
 if(TCNT0>139 && TCNT0<194 && bitnummer <= 14) {
79
  gesamt[bitnummer] = 1;
80
  last_bit = 1;
81
  TCNT0 = 0;
82
  bitnummer++;
83
  }
84
 }
85
 if(bitnummer == 14) {
86
  gesamt[1] = 1;
87
  send_string(ergebnis);
88
  last_bit = 1;
89
  bitnummer = 1;
90
  TIMSK &= ~(1<<TOIE0);
91
  TCNT0 = 0;
92
  rdy = 1;
93
  }
94
} 
95
   
96
   
97
int main(void)
98
{
99
 init_usart();
100
 init_rc5();
101
 sei();
102
 uint8_t i;
103
 char test[3];
104
 char wert[10] = "RC5:";
105
 for(;;)
106
 {
107
  if(rdy==1) {
108
  send_string(wert);
109
  for(i=4;i<=8;i++) {
110
    itoa(gesamt[i],test,10);
111
    send_string(test);
112
    }
113
  rdy = 0;
114
  }
115
  
116
 };
117
}

von Stefan E. (sternst)


Lesenswert?

> hab deine Anmerkungen ausgebessert

Ich hatte 4 Sachen angemerkt. Zwei sind unverändert, eines hast du 
geändert, allerdings das Problem dadurch nicht beseitigt (if-Sache).

Und bei der letzten Sache
1
  for(i=4;i<=8;i++) {
2
    itoa(gesamt[i],test,10);
3
    send_string(test);
4
    }
verstehe ich das 4 bis 8 nicht.

von Fragender (Gast)


Lesenswert?

http://www.roboternetz.de/phpBB2/viewtopic.php?p=387615#387615 Habs da 
geändert, sorry da ist das auch leichter mit Editieren.

von Stefan E. (sternst)


Lesenswert?

9 bis 14 ist für mich auch nicht verständlicher.

"gesamt" auf 16 zu vergrößern, behebt zwar das "hinter das Array 
schreiben"-Problem, geht das Problem aber von der falschen Seite her an.
Wieso beschreibst du das Array von 1 bis 14 und nicht von 0 bis 13?
Gibt es da vielleicht bei dir noch Defizite beim Verständnis von 
Array-Indexen?

Das if-Problem besteht weiterhin.
Das "if(last_bit == 0)" nützt dir da nichts, da du ja im if-Block vorher 
"last_bit = 0;" stehen hast. Eine "if ... else if ..."-Konstruktion 
würde hier helfen.

Allerdings ist auch der Ansatz schon falsch. Du kannst bei 
Manchester-Codierung die Bits nicht so einfach aus dem Abstand zwischen 
zwei steigenden Flanken ermitteln.

von Fragender (Gast)


Lesenswert?

Hallo,
hab das mit else if geändert, mit dem 9 bis 14 wollte ich lediglich die 
Datenbits auslesen. Wenn es nützlich ist, kann ich den Code nochmal 
posten. Warum geht das mit den steigenden Flanken nicht? Wenn ich weiss, 
ob das letzte Bit eine 1 oder 0 war, geht das doch?!

von Stefan E. (sternst)


Lesenswert?

Eine einfache Betrachtung zeigt, dass deine Methode so nicht gehen kann:
Du ermittelst zu jeder steigenden Flanke ein Bit, du hast also eine 
1:1-Relation von steigenden Flanken und Bits. Jetzt zeichne dir mal den 
Manchester-Code zur Bitfolge 010101... auf. Da hast du mehr Bits, als 
steigende Flanken. Wie soll dein Algorithmus diese Bitfolge also 
rekonstruieren können?

von Fragender (Gast)


Lesenswert?

Hallo,
das hast du recht :/. Hast du vielleicht einen Tip, wie ich es sonst 
angehen könnte? Ich mag auf keinen Fall einen fertigen Code verwenden, 
hab da mittlerweile soviel Zeit reingesteckt, dass ich das einigermssen 
in Eigenregie zum Laufen bringen möchte.

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.