Um rc5-Code auszuwerten verwende ich folgenden Code:
1
#include"base.h"
2
#include"uart.h"
3
#include<avr/interrupt.h>
4
volatileintoldstate=0;
5
volatileintstate;
6
volatileintsamples=0;
7
volatileintrc5data[29];
8
volatileintpos=0;
9
volatileintcomplete=0;
10
volatileintbitcount=0;
11
12
ISR(TIMER0_OVF_vect)
13
{
14
if(pos!=28){
15
state=!(PINB&(1<<PINB0));
16
if(state==oldstate){
17
bitcount++;
18
}
19
if(state!=oldstate){
20
if(12<=bitcount<=14){
21
rc5data[pos]=state;
22
pos++;
23
}
24
if(26<=bitcount<=28){
25
rc5data[pos]=state;
26
pos++;
27
rc5data[pos]=state;
28
pos++;
29
}
30
bitcount=0;
31
oldstate=state;
32
}
33
}
34
else{
35
complete=1;
36
}
37
PORTD^=(1<<PD7);
38
39
40
}
41
42
43
intmain(void){
44
uart_init();
45
DDRD|=(1<<PD7);
46
TCCR0|=(1<<CS00);
47
sei();
48
TIMSK|=(1<<TOIE0);
49
uart_putc('a');
50
while(complete==0){
51
asmvolatile("nop");
52
}
53
TIMSK&=~(1<<TOIE0);
54
uart_putc('b');
55
inti=0;
56
while(i!=28){
57
uart_puts(intToString(rc5data[i],1));
58
i++;
59
}
60
61
62
}
Der Ansatz: Der Interrupt wird alle 64us aktiviert und misst die Zeit in
der das Signal konstant ist.
Das Problem: Wenn ich eine Taste auf der Fernbedienung 1x drücke,
passiert nix. Erst nach fünfmaligem Drücken erhalte ich Datenmüll. Wo
liegt der Fehler?
Alles @ Atmega32 @ 4MHz
Alan wrote:
> 1) Was tut der Ausdruck denn dann?
Das Ergebnis des <=-Operators ist 0 oder 1, und der Linke wird zuerst
ausgewertet. Dann steht dort also (je nach dem Wert von bitcount)
"(0 <= 28)" oder "(1 <= 28)".
"(26 <= bitcount <= 28)" ist also immer wahr.
> 2) wie mache ich das?
((26 <= bitcount) && (bitcount <= 28))
Ach so, das "wie mache ich das?" bezog sich wohl auf die
16-Bit-Variablen, sorry. ;-)
Indem du außerhalb der Interrupt-Routine vor dem Zugriff auf die
Variable die Interrupts sperrst, und danach wieder freigibst. Wenn ich
das richtig sehe, kannst du aber auch aus allen deinen int einfach
8-Bit-Variablen machen, dann hast du das Problem nicht.
viel zu strikt.
Du erlaubst gerade mal eine Variation in bitcount von 3 Einheiten.
Bei einem voll laufenden 8-Bit Timer sind das gerade mal ~750
Takte. Nicht gerade viel Spielraum für den Sender um das Timing
einzuhalten.
Warum gehst du nicht einfach her und sagst:
Wenn der bitcount < 20 ist, dann werte ich das als Zustand 1
und alles darüber ist Zustand 2.
In deinem Programm passiert ja soweiso nichts, wenn das Timing
ausserhalb der von dir eingeführten Grenze liegt. Wenigstens
eine Fehlerled würde ich anmachen, damit man auch verfolgen kann,
dass das Timing nicht gestimmt hat.
Jetzt bekomme ich: 1011011011011011011011011011 und das egal, welche
Taste gedrückt wurde. Manchmal passiert auch gar nichts, wenn die taste
nur kurz gedrückt wurde, wenn ich sie lang drücke, kommt wieder das
obige :(
Ich kann dir nicht mehr viel weiterhelfen, weil ich die
Signalform nicht kenne.
Das wirds zwar nicht sein, da du hast mir ein paar if
zuviel, die eigentlich nicht nötig sind.
if( a == b )
...
if( a != b )
...
Das zweite if ist unnötig
if( a == b )
...
else
...
macht dasselobe und ist simpler.
Genauso hier (da ist auch ein kleiner Fehler drin)
if( a < 81 )
...
if( a > 81 )
...
Das > muesste natürlich >= lauten. Aber abgesehen davon,
wenn a nicht kleiner als 81 ist, dann muss a größer/gleich
81 sein. Was solls denn sonst sein?
Also
if( a < 81 )
...
else
...
Ich denke aber nicht, dass das mit deinem eigentlichen Problem
zu tun hat (bitcount exakt 81 könnte aber tatsächlich ein
Problem sein, wenn auch eher unwahrscheinlich)
Bleibt nur noch: Timing noch mal checken. Timereinstellungen.
Läuft der µC auch wirklich mit der Taktfrequenz die du glaubst
und mit der du die Timereinstellungen ausgerechnet hast.
Sonst fällt mir auch nichts ein.
PS: Stimmt da eigentlich, dass eine 1 immer doppelt ins Array
kommt? Schaut irgendwie seltsam aus.
Edit: Ich würde mir höchstens mal die gemessenen bitcount Werte
ausgeben lassen. Vielleicht sieht man da was.
Moment.
Die Information steckt doch in der Pulslänge. Oder irre ich mich
da?
Warum speicherst du dann state?
Das ist doch Nonsense. state sagt dir doch nur wie das Signal
zur Zeit aussieht. Klar das das immer abwechselnd 0 oder 1 sein
muss. Was solls denn sonst sein?
Bei der steigenden Flanke setzt du bitcount auf 0, denn da
beginnt der Puls und bei der fallenden Flanke wertest du den
bitcount aus
1
if(state!=oldstate){// eine Flanke
2
3
// welche wars?
4
if(state)// es war eine steigende
5
bitcount=0;
6
7
else{// es war eine fallende Flanke
8
if(bitcount<83)// war es ein kurzer 0 Puls ?
9
rc5data[pos]=0;
10
else// oder war es ein langer 1 Puls ?
11
rc5data[pos]=1;
12
pos++;
13
}
14
}
15
16
else
17
bitcount++;
Kann natürlich sein, dass ich völlig falsch liege. Denn wie gesagt:
Ich kenne die Signalcodierung nicht.
pos = 28 soll wohl die Abbruchbedingung sein. Da pos aber in einem Int
auch um 2 erhöht werden kann, kann diese Grenze "übersprungen" werden.
Ich vermute allerdings (genau wie Karl Heinz), dass dieses doppelte
Abspeichern falsch ist. Es führt ja z.B. auch dazu, dass eine
unterschiedliche Anzahl an Bits gesampelt wird, je nach dem wie das
Verhältnis von Nullen zu Einsen ist. Und ich kann mir nicht so recht
vorstellen, dass das so gewollt ist.
Alan wrote:
> Entweder habe ich die manchester-Kodierung falsch verstanden ...
Kommt darauf an, was du eigentlich machen willst. In mir keimt nämlich
jetzt der Verdacht, dass du das gar nicht dekodieren, sondern eher
"aufzeichnen" willst. In dem Fall ist aber dein Ansatz, pos als
Abbruchbedingung heranzuziehen, untauglich.
Alan wrote:
> Also erstmal danke für die Mühe...> Den Vorschlag von kbuchegg kann ich nur nicht ganz nachvollziehen.
Ich wusste bis vor 30 Sekunden nicht, dass du einen Manchester
Code auswerten willst. Ich ging von einem Pulscode aus, der 1/0
über die Pulslänge ermittelt.
Mein Fehler: Ich hätte mich über den RC5 informieren sollen,
bevor ich hier loslege.
Fällt mir auch erst jetzt auf, dass das "Auswerten" im Threadtitel ein
bisschen deplatiert ist ...
Das Auswerten macht dann eine andere Funktion, mir geht es erstmal ums
Aufzeinchen
Ne fertige Lib nehmen kann ja jeder, mir geht's u.a. um den Lerneffekt
(weshalb ich BASCOM verabscheue)...
Nach etwas Überlegung muss ich meine obige Aussage revidieren. Dein
Ansatz sollte prinzipiell funktionieren. Du hast allerdings einen Fall
nicht abgedeckt. Wenn im letzten Bit der Flankenwechsel zum Ruhepegel
hin geht, dann hast du nach dem Bit keinen Flankenwechsel mehr. Das 28.
"Halbbit" ist dann also nicht durch eine Flanke "abgeschlossen".
Ist auch problematisch, oder ist die Pause zwischen zwei Bitfolgen auf
jeden Fall mindestens so groß?
Ich würde die Tatsache ausnutzen, dass zwischen pos 26 und 27 immer ein
Flankenwechsel sein muss.
Also etwa so:
Die Impluslänge ist 1.778ms
14Bits
1.778 / 14 = 0.127ms pro Bit
0.127ms = 0.000127s
1 / 0.000127 = 7874
Wieso steht oben 8000 Überläufe pro Sekunde??
Wie kann ich das auf meinen 14745600MHz Quarz umrechnen?
Danke
Egal wie ich es rechne, ich komme immer an 231 oder 26.
Leider funktioniert es aber nicht!
Wann soll der Timer einen Überlauf-Interrupt machen?
Nach 1.778ms oder nach 0.125ms??
Ich denke nach 1.778ms...