Forum: Projekte & Code Fernbedien RC5 Empfänger


von Richard B. (rbrose)


Lesenswert?

Christian R. wrote:
> Warum setzt du das i=200 bei gleichem Toggle Bit? Und deine main
> Schleife arbeitet doch trotzdem immer alles durch, egal, ob da eine neue
> Taste gedrückt wurde oder nicht?

Richtig. In der Main-Schleife wird alles abgearbeitet. Ich setze i=200 
weil der Befehl 200 nicht kommt von der Fernbediegung.
Ich brauche NUR die Tasten 0 bis 9, Taste 13 und die Taste 46. Wenn ich 
i auf 200 setze wird keine Zahl hinzugefügt!

> Du musst halt gucken, ob LastToggle ungleich Toggle ist, und erst dann
> dein restlichen Zeugs abarbeiten.
> Und wieso i=200 bei i=0? Gibts keine Fernbedienung mit GeräteCode 0 und
> Befehl 0? Was ist mit Taste "0" beim TV?

Nein gibt es nicht.
Das Problem wieso ich es nicht so mache:
1
  if((LastCommand == Command) && (LastAddress == Address))
2
  {
3
    if(LastToggle != Toggle)  //Prüfung auf Änderung des Toggle-Bits
4
    {
5
      for(x=1;x<10;x++)
6
      {
7
        if( get_key_press(i, x) )
8
        {                      
9
          if(liednummerCount < 4)
10
          {
11
            liednummer =  liednummer*10+x;
12
            liednummerCount++;        
13
          }                
14
        }
15
      }  
16
17
      if( get_key_press(i, 0) )
18
      {      
19
        if(liednummerCount < 4 && liednummerCount > 1)
20
        {
21
          liednummer =  liednummer*10+0;
22
          liednummerCount++;
23
        }                  
24
      }
25
26
      if( get_key_press(i, 13) )
27
      {            
28
        liednummer =0;
29
        liednummerCount = 1;      
30
      }
31
      if( get_key_press(i, 46) )
32
      {      
33
        convertIntToSendString();            
34
      }  
35
    }
36
  }
37
  else    //Direkte Ausgabe, wenn neue Taste gedrückt
38
  {
39
    for(x=1;x<10;x++)
40
    {
41
      if( get_key_press(i, x) )
42
      {                      
43
        if(liednummerCount < 4)
44
        {
45
          liednummer =  liednummer*10+x;
46
          liednummerCount++;        
47
        }                
48
      }
49
    }  
50
51
    if( get_key_press(i, 0) )
52
    {      
53
      if(liednummerCount < 4 && liednummerCount > 1)
54
      {
55
        liednummer =  liednummer*10+0;
56
        liednummerCount++;
57
      }                  
58
    }
59
60
    if( get_key_press(i, 13) )
61
    {            
62
      liednummer =0;
63
      liednummerCount = 1;      
64
    }
65
    if( get_key_press(i, 46) )
66
    {      
67
      convertIntToSendString();            
68
    }
69
  }

ist weil es viel zu viel Speicher wegnimmt und mein AVR schon fast voll 
ist:
1
AVR Memory Usage
2
----------------
3
Device: attiny2313
4
5
Program:    2020 bytes (98.6% Full)
6
(.text + .data + .bootloader)
7
8
Data:         31 bytes (24.2% Full)
9
(.data + .bss + .noinit)

Deshalb muss ich es mit einem Flag machen. Und i=200 ist das Flag für 
die For-schleifen das die nicht true sind.

Die Frage ist ... wieso ich sowieso bei gehaltenen Taste die Tasten 
werte alle bekomme.

von Benjamin A. (beni0664)


Lesenswert?

Also jetzt gebe ich auch nochmal meinen Senf dazu ;-)!

@peter d.

Danke für den super Code!

Nur einen kleinen Verbesserungs vorschlag hätte ich noch:
1
 TCCR0 = 1<<CS02;      //divide by 256
2
  TIMSK = 1<<TOIE0;      //enable timer interrupt
3
4
  UBRRL = bauddivider;      //set baud rate

Ich würde hier nur das entsprechende Bit setzen, sonst überschreibt man 
alle event. schon vorhandenen Flags!

Also so:
1
 TCCR0 |= (1<<CS02);      //divide by 256
2
  TIMSK |= (1<<TOIE0);      //enable timer interrupt
3
4
  UBRRL = bauddivider;      //set baud rate

mfg beni

von Juris (Gast)


Lesenswert?

Hello all,
i am sorry that i dont speak german and understand just a little of it. 
I would like to ask popular nice RC5 code author Peter Dannegger: is 
there maybe a more recent version of RC5 code that would also accept 
RC5X signals?
Thank You very much in advance!

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Den Code aus dem allerersten Post dieses Threads habe ich auf das Pollin 
Funk AVR Board angepasst. µC ist ein Attiny2313 bei 8 MHz:
http://www.mikrocontroller.net/articles/Pollin_Funk-AVR-Evaluationsboard#RC5_Empf.C3.A4nger

von Jan -. (Firma: --) (bravo)


Lesenswert?

Hallo Leute !
Sehr Interressant.
Hat auch einer eine RC5 Senderoutine fertig ?
So eine Art Lernbare Fernbedienung ?
Oder hat jeman ein Tipp wie ich da dran gehen soll?

Danke für jede Hilfe.
Jan

von Oliver (Gast)


Lesenswert?

>Oder hat jeman ein Tipp wie ich da dran gehen soll?

Senden ist doch straightforward. Man weiß, wann es losgeht, es gibt 
keine Störungen und Abbruchbedingungen. Einfach RC5-Codebeschreibung 
lesen, Timer entsprechend initialisieren, damit die Pulse und die 
Grundfrequenz erzeugen und über LED raustickern, fertig.

>So eine Art Lernbare Fernbedienung ?

Was willste denn lernen? RC5 ist RC5. Andere Protokolle sind ganz anders 
aufgebaut, haben andere Grundfrequenzen, etc. Eine lernbare Universal-FB 
nachzubauen wird da ernsthaft aufwendig.

Oliver

von Oliver (Gast)


Lesenswert?

Nachtrag:

Hier
http://www.sbprojects.com/knowledge/ir/ir.htm
gibt es eine schöne Zusammenfassung, mit (Assembler-)Software. Deren 
Prinzip lässt sich aber serh schön und einfach auch in C umsetzen.

Oliver

von Di P. (drpepper) Benutzerseite


Lesenswert?

Neue Frage, gleiches Thema:

Was tut die Zeile
1
  TCNT0 = -2;     // 2 * 256 = 512 cycle
?
Wieso wird ins TIMER-Count Register eingegriffen?

Ich möchte den Timer2 eines AtMega88 für rc5 und Sekundenerzeugung 
zusammen benutzen, und bin mir unsicher über den Prescaler, den ich 
wählen sollte.
Momentan verwende ich den Prescaler 256 auf 8MHz und erzeuge Sekunden so 
(Timer2 zählt nur bis 250):
1
ISR (TIMER2_OVF_vect) {
2
  if(t1 < 125) {
3
    t1++;
4
  }
5
  else {
6
    t1 = 0;
7
    newsecond = 1;
8
  }
9
}

von David (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich wollte euch kurz darum bitten meinen Source anzuschauen. Irgendwo 
ist der Wurm drin.
Ich verwende einen Attiny2313, gcc version 4.3.2 (WinAVR 20090313). Ich 
drehe bald durch. Mit der version habe ich es geflasht und ging und 
jetzt nicht mehr warum?????
- Warum meckert der bei AVRStudio4 wenn ich mit volatile rc5_data habe
und
- Warum meckert der bei AVR-GCC wenn ich mit extern rc5_data habe

ICH krieg echt die kriese ich schmeiße alles aus dem Fenster, seit einer 
Woche mache ich da rum.

TSOP ist bei PD2 angeschlossen
Quarz: 3,6864 Mhz

Ich bedanke mich jetzt schon f+r euere muehe

von U. E. (Gast)


Lesenswert?

Hi,
habe mich als AVR-Neuling ein paar Tage mit dem Code (und dem STK600) 
gequält. Nach ein paar ärgerlichen Anfängerfehlern, kam ich schließlich 
dahinter, daß der Tipp weiter oben, die Variable "rc5_data" als volatile 
zu deklarieren, der Schlüssel zum Erfolg war - ich verwende den avr-gcc 
in der Version 4.3.2. Ich kann mich für den Tipp nur bedanken, für den 
Code ohnehin ;-) Dies hat mir wirklich ein Erfolgserlebnis gegeben!

Grüße
schnack

von Richard B. (Gast)


Lesenswert?

Hallo Peter,

beinhaltet rc5_data alle RC5 Bits?
Also

ein Toggelbit (abwechselnd "1" oder "0")
5 Adressbits
6 Kommandobits

von Peter D. (peda)


Lesenswert?

Richard B. schrieb:
> Hallo Peter,
>
> beinhaltet rc5_data alle RC5 Bits?
> Also
>
> ein Toggelbit (abwechselnd "1" oder "0")
> 5 Adressbits
> 6 Kommandobits

Ja.

Peter

von U. E. (Gast)


Lesenswert?

Hallo Peter,
für das HCAN Hausautomatisierungsprojekt (http://www.iuse.org/) würde 
ich gerne den Empfänger-Code  - ein wenig modifiziert - einbringen.
Ich würde natürlich den Urhebervermerk belassen, ergänzt um einen 
Änderungsvermerk.
Die HCAN-Automatisierung steht unter GPL. Ich bin kein Anwalt, deshalb 
frage ich mich, ob ich die so entstandene SW dort "contributen" kann.

Das gleiche gilt auch für Deinen DCF77-Code in 
Beitrag "DCF77-Uhr mit ATTINY12".

Gibt es von Deiner Seite Bedenken?
Grüße
Christoph

von Peter D. (peda)


Lesenswert?

C. D. schrieb:

> Gibt es von Deiner Seite Bedenken?

Nein.
GPL ist o.k.


Peter

von Malte _. (malte) Benutzerseite


Lesenswert?

Hallo hier eine kleine Verbesserung für alle, die den Code mit hoher 
Taktfrequenz verwenden:
1
#define PULSE_MIN  (uchar)(F_CPU / 2048 * RC5TIME * 0.4 + 0.5)
2
#define PULSE_1_2  (uchar)(F_CPU / 2048 * RC5TIME * 0.8 + 0.5)
3
#define PULSE_MAX  (uchar)(F_CPU / 2048 * RC5TIME * 1.2 + 0.5)
4
5
TCNT2 = -8;          // 8 * 256 = 2048 cycle

dies sorgt bei 16MHz dafür, dass nicht ganz so viele Takte nur für den 
RC5 Empfang verbraten werden. Mit einem Teiler von 4096 wollte der Code 
leider nur noch sporadisch laufen, somit sollte bei 8MHz maximal ein 
Teiler von 1024 funktionieren.

Der Grund für die Änderungen ist der:
Fügt man einen Funktionsaufruf ein, der die dekodierten Daten entgegen 
nimmt (statt der globalen Variable), sichert der Compiler jedes mal 
zusätzliche Register (auch wenn die Funktion nur selten wirklich 
aufgerufen wird). Somit wird dann der ursprüngliche Code alle ~556 Takte 
aufgerufen (512 Takte + Register sichern) und braucht zum Durchlauf ~100 
Takte. Somit ist der AVR 1/5 aller Takte nur damit beschäftigt auf rc5 
Starts zu achten. Bei mir kommt noch hinzu, dass der Stack im 
langsamerem externen RAM liegt und er somit alle ~588 Takte aufgerufen 
wird und ~164 Takte zum Durchlauf braucht = ~28%. Das war natürlich viel 
zu viel. Die obige Änderung reduziert den Anteil bei mir erstmal auf 
7,7%. Ich würde den Anteil gerne noch auf unter 1% drücken, mal sehnen 
ob sich da noch ein Weg findet.

Der sich durch das Register sichern aufsummierende Messfehler der Zeiten 
wird ebenfalls reduziert.

von Peter D. (peda)


Lesenswert?

Malte __ schrieb:
> Fügt man einen Funktionsaufruf ein, der die dekodierten Daten entgegen
> nimmt (statt der globalen Variable), sichert der Compiler jedes mal
> zusätzliche Register (auch wenn die Funktion nur selten wirklich
> aufgerufen wird).

Ja, Funktionsaufrufe in Interrupts sollte man vermeiden.

Aber wenn es unbedingt sein muß, gib einfach den SPM-Interrupt frei und 
packe da dann Deine Funktion rein.
Der SPM-Befehl ist ja im Applikations-Flash wirkungslos und somit läßt 
sich dessen Interrupt prima als SW-Interrupt nutzen.


Peter

von Christian T. (shuzz)


Lesenswert?

Ich wollte mich bei Peter gerne für den Code bedanken.

Funktioniert absolut problemlos zusammen mit einer RGB-PWM Routine.

Ursprünglich war der Plan, sowohl der PWM als auch der RC5-Erkennung 
jeweils nen eigenen Timer zu spendieren, aber das hat aus mir 
unerfindlichen Gründen nicht geklappt.

Nun habe ich beides in einem Timer laufen und es funktioniert wunderbar!
(PWM wird bei jedem Overflow abgearbeitet, RC5 nur bei jedem vierten, 
basierend auf dem Tipp von Malte.)

Momentan führt das Empfangen einer gültigen RC5-Sequenz lediglich zum 
ein- bzw. ausschalten der PWM, die Codes selbst werden (noch) nicht 
unterschieden.

Der Grund ist einfach: Ich habe keine Ahnung wie die Codes welche von 
der FB kommen aussehen... ^^

Deshalb noch eine Frage in die Runde: Hat jemand ne Idee wie ich die 
Werte nun am geschicktesten lesbar mache? Ich habe leider keinen Max232 
o.Ä. verfügbar, daher scheidet UART leider aus.
Ich tendiere zu zwei Schieberegistern und ner Latte von LEDs, somit 
könnte ich die entstehenden Bitmuster einfach per #define in meinen Code 
übernehmen.
Aber vllt. hat jemand von euch ja noch ne bessere Idee. UART wäre ja 
schon schick, aber ich fürchte das geht nicht nur mit ein paar 
Widerständen oder? ;)

von Di P. (drpepper) Benutzerseite


Lesenswert?

http://www.stefan-buchgeher.info/elektronik/rc5/rc5.html

hier steht zuminddest drin, was bei welchem knopf aus der FB rauskommt.

das hilft dir vllt. weiter :)

von Christian T. (shuzz)


Lesenswert?

Dank an den Doktor, aber vermutlich wird mir das nicht weiterhelfen.

Die FB die ich verwenden möchte ist ein Fernost-All-in-one-teil mit 
Ein-Knopf-Programmierung... ^^

D.h. mein Plan ist, zunächst die FB so einstellen dass sie RC5 "spricht" 
und dann auszuknobeln welche Codes von welchen Tasten kommen.

Ich hoffe, das wird halb so wild. Auf dem Steckbrett daheim ist bereits 
alles aufgebaut, jetzt muss ich "nur" noch mitschreiben. ;)

Aber für alle (zukünftigen) Fälle hab ich mir mal ein paar MAX232 bei 
Maxim geordert, dann bin ich für die nächste FB gerüstet. ^^

von Johannes T. (johnsn)


Lesenswert?

Habe den Programmcode auch erfolgreich getestet. Allerdings habe ich 
mehrere Stunden gebraucht, bis ich kapiert hab, dass meine Samung RC 
keine RC5 Codes schickt, sondern auch was proprietäres.

Kennt jemand die genauen Codes von Samsung?

von Gast (Gast)


Lesenswert?

Nochmal 'laut' gedacht zum Toggle Bit und der weiteren Auswertung der 
RC-5 Pakete:

Eingabemethoden
 1 Einfacher Tastendruck gilt für alle Befehle
 2 Dauerfeuer, gilt nur für z.B. Lautstärke (nicht für An/Aus :-)

Fehlerquellen:
 Sendeleistung reicht nicht
 Sichtverbindung blockiert und keine Reflexion
 Empfänger gestört (durch IR oder EMV z.B. Leuchtstofflampe, Sonne)

Bei einem Tastendruck wird das Toggle-Bit umgeschaltet.
Wird die Taste gedrückt gehalten, ändert sich das Toggle Bit (TB) nicht, 
und das Paket wird alle 114 ms wiederholt (also ca 90 ms später).

Der Empfänger guckt erstmal, ob die Adresse stimmt.
Das letzte Paket hat er sich gemerkt (TB, ggf. Befehl).

Ist das TB gleich, kann das bedeuten:
 der letzte Befehl ist nicht angekommen (out of synch)
 die Taste wird gedrückt gehalten
 der Befehl wird zur Sicherheit mehrfach gesendet (?)

Ist es verschieden
 der letzte Befehl ist nicht angekommen (out of synch)
 eine neue Taste wurde/wird gedrückt


Was müsste der Empfänger also machen?
  das TB ignorieren, falls seit 114 ms nichts empfangen
Dann sind Sender/Empfänger wieder synchron.

Beim nächsten mal
  TB gleich -> prüfen, ob der Befehl Dauerfeuer akzeptiert, wenn ja, 
ausführen.


Sonst noch was? Wie ist das mit der Mehrfachsendung?


--
http://www.sbprojects.com/knowledge/ir/rc5.htm
http://en.wikipedia.org/wiki/RC-5

von Malte _. (malte) Benutzerseite


Lesenswert?

Gast schrieb:
> Fehlerquellen:
>  Sendeleistung reicht nicht
>  Sichtverbindung blockiert und keine Reflexion
>  Empfänger gestört (durch IR oder EMV z.B. Leuchtstofflampe, Sonne)
>
> Sonst noch was?
Interrupt wird möglicherweise zu lange durch einen andere Interrupt 
blockiert, so dass die Zeiten nicht mehr stimmen.
Abhilfe:
1. Statt Overflow, Compare Interrupt verwenden und 2. Clear Timer on 
Compare benutzen, damit sich Verzögerungen wenigstens nicht aufaddieren.

von pille1990 (Gast)


Lesenswert?

ich habe eine software eintwickelt die 3 leds per pwm dimmen kann (alle 
einzeln). die timer im atmega32 laufen alle 3 im fast pwm mode.

kann ich hier die rc5 routine auch verwenden?

gruß pille

von Peter D. (peda)


Lesenswert?

pille1990 schrieb:
> ich habe eine software eintwickelt die 3 leds per pwm dimmen kann (alle
> einzeln). die timer im atmega32 laufen alle 3 im fast pwm mode.
>
> kann ich hier die rc5 routine auch verwenden?

Ja.

Peter

von dtm (Gast)


Lesenswert?

Hallo zusammen!

Im ersten Post steht, dass der Timer durchlaufend sei, aber es wird doch 
nach jedem overflow das zählregister so gesetzt, dass nach zwei 
zählererhöhungen wieder ein overflow auftritt!?
Habe ich da etwas übersehen?
Bei einem "durchlaufenden" 8Bit timer hätte ich jetzt erwartet, dass der 
zähler auch die vollen 8 bit zählt.

gruß dtm

von Malte _. (malte) Benutzerseite


Lesenswert?

> Habe ich da etwas übersehen?
Nein.
Durchlaufen wohl eher in der Form, dass der Zähler durchgängig läuft, 
also nicht angehalten wird, wenn nichts zu empfangen ist.
Wenn du den Vorteiler kleiner setzt, kannst du den Timer aber problemlos 
über einen größeren Bereich laufen lassen.

von Peter D. (peda)


Lesenswert?

Malte __ schrieb:
> Wenn du den Vorteiler kleiner setzt, kannst du den Timer aber problemlos
> über einen größeren Bereich laufen lassen.

Neuere AVRs haben auch T0-Compare-Interrupts, damit kann man dann 
kleinere Intervalle erzeugen und weiterhin den Overflow erst nach 256 
Zyklen.


Peter

von dtm (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Neuere AVRs ...

Der Mega168 gehört nicht dazu, oder? Zumindest kann ich im Datenblatt 
nichts dazu finden.

von dtm (Gast)


Lesenswert?

Da kommt mir folgende Idee:

OC-Match Interrupt aktivieren, und das OC-Register bei jedem Aufruf der 
Interruptroutine um 2 (natürlich vom Prescaler abhängig) zu erhöhen.
Dann dort einfach die Flankenerkennung ablaufen lassen.

von Peter D. (peda)


Lesenswert?

dtm schrieb:
> Der Mega168 gehört nicht dazu, oder?

Doch: "Timer/Counter0 Compare Match A und B"


Peter

von Peter D. (peda)


Lesenswert?

dtm schrieb:
> OC-Match Interrupt aktivieren, und das OC-Register bei jedem Aufruf der
> Interruptroutine um 2 (natürlich vom Prescaler abhängig) zu erhöhen.

So war das gemeint.

Peter

von Kai E. (kai20)


Lesenswert?

Ich hätte eine Frage an Peter bzgl der Auswerteroutinean zu der Stelle,
wo eine 1 reingeschoben wird, die restlichen Anweisungen sind klar.

 if( !(rc5_bit & 1<<xRC5) ) tmp |= 1;  // inverted bit and insert new 
bit

Diese Abfrage wird doch nur ausgeführt, wenn eine lange Bitzeit erkannt 
wurde.
Wenn jetzt die fallende Flanke einer kommenden '1' erkannt wird und 
zuvor eine '0' kam, war es eine lange Bitzeit und eine '1' wird zu Recht
reingeschoben (rc5_bit hat doch dann den Wert 0x00).

Habe ich aber z.B. 3 aufeinanderfolgende Einsen, habe ich eine kurze 
Bitzeit vor der fallenden Flanke, also komme ich doch gar nicht zu 
dieser Abfrage,
aber wo schiebe ich dann für diesen Fall eine '1' rein ?

Ich sehe es einfach nicht,
Kai

von Ratlos (Gast)


Lesenswert?

Hallo,

erstmal Danke für den Code.

Will ihn anpassen damit er mit 3,686411 Mhz funktioniert. (myAvr)


Was ich nicht verstehe ist;
In deiner Erklärung schreibst du von 4 Mhz als Frequenz.
XTAL ist aber auf 11.0592e6 gesetzt.

Warum das?


Gruß

von Kai E. (kai20)


Lesenswert?

@Ratlos,

bin zwar auch nur Anwender, aber setze halt XTAL auf 3.68MHz,
dann bekommst du ca. alle 139us einen Timer IRQ.
Dann ergibt sich PULSE_MIN zu 5, PULSE_1_2 zu 10 und PULSE_MAX zu 15.
5*139us ist kleiner als die halbe Bitzeit und 10*139us waere
entweder eine kurze oder lange Bitzeit.

Sollte so klappen,
Kai

von Ratlos (Gast)


Lesenswert?

Guten Morgen,

danke erstmal für die rasche Antwort! ;)

XTAL habe ich soweit angepasst, leider funktioniert noch nichts. Dachte 
das ich die 512(Zyklen) bzw einen Vorteiler dementsprechend anpassen 
muss. Der Aufbau ist auch klar, leider bekomme ich an PortB, welcher die 
letzten 8 Bits ausgibt keinerlei Signal.


Lg Ratlos

von Di Pi (Gast)


Lesenswert?

code?

von Ratlos (Gast)


Lesenswert?

Guten Morgen nochmals :)

Danke vorab für die Mühe!


Zitat:
"Der Timerinerrupt wurde so eingestellt, daß er alle 512 Zyklen
aufgerufen wird. Damit ergeben sich bei 4MHz je Bitzeit 
4e6/512*1.778e-3=14 Aufrufe des Timerinterrupts."

Die Mhz des Quarzes wie auch die 1.778ms sind fixe Werte, also kann man 
theoretisch nur noch die "512" ampassen, um auf ~14 Aufrufe zu kommen.
Eine Idee wäre die besagten "512" variabel zu gestalten, sodass man eine 
Schleife generiert, welche den Wert in 10er Schritten von 300-700 
wandern lässt.

Denke ein großer Fehler kann es ja nicht sein, da am Orginalcode kaum 
etwas verändert wurde, dieser funktioniert und am PD7 ein sauberes 
Rc5-Signal anliegt.


Hier die Interrupt Routine:
(Muss man die 512 dementsprechend anpassen, sodass man auf ~14 kommt?)
1
#include "main.h"
2
3
#define RC5TIME   1.778e-3    // 1.778msec
4
#define PULSE_MIN  (uchar)(XTAL / 512 * RC5TIME * 0.4 + 0.5)
5
#define PULSE_1_2  (uchar)(XTAL / 512 * RC5TIME * 0.8 + 0.5)
6
#define PULSE_MAX  (uchar)(XTAL / 512 * RC5TIME * 1.2 + 0.5)
7
8
9
uchar  rc5_bit;        // bit value
10
uchar  rc5_time;        // count bit time
11
uint  rc5_tmp;        // shift bits in
12
uint  rc5_data;        // store result
13
14
15
SIGNAL (SIG_OVERFLOW0)
16
{
17
  uint tmp = rc5_tmp;        // for faster access
18
19
  TCNT0 = -2;          // 2 * 256 = 512 cycle
20
21
  if( ++rc5_time > PULSE_MAX ){      // count pulse time
22
    if( !(tmp & 0x4000) && tmp & 0x2000 )  // only if 14 bits received
23
      rc5_data = tmp;
24
    tmp = 0;
25
  }
26
27
  if( (rc5_bit ^ xRC5_IN) & 1<<xRC5 ){    // change detect
28
    rc5_bit = ~rc5_bit;        // 0x00 -> 0xFF -> 0x00
29
30
    if( rc5_time < PULSE_MIN )      // to short
31
      tmp = 0;
32
33
    if( !tmp || rc5_time > PULSE_1_2 ){    // start or long pulse time
34
      if( !(tmp & 0x4000) )      // not to many bits
35
        tmp <<= 1;        // shift
36
      if( !(rc5_bit & 1<<xRC5) )    // inverted bit
37
        tmp |= 1;        // insert new bit
38
      rc5_time = 0;        // count next pulse time
39
    }
40
  }
41
42
  rc5_tmp = tmp;
43
}


Und auch die Main:
(Unverändert)
1
#include "main.h"
2
3
4
void putchar( char c )
5
{
6
  while( (UCSRA & 1<<UDRE) == 0 );
7
  UDR = c;
8
}
9
10
11
void puts( char *s )
12
{
13
  while( *s )
14
    putchar( *s++ );
15
}
16
17
18
int main( void )
19
{
20
  uint i;
21
  char s[30];
22
23
  TCCR0 = 1<<CS02;      //divide by 256
24
  TIMSK = 1<<TOIE0;      //enable timer interrupt
25
26
  UBRRL = bauddivider;      //set baud rate
27
  UBRRH = bauddivider >> 8;
28
  UCSRA = 0;        //no U2X, MPCM
29
  UCSRC = 1<<URSEL^1<<UCSZ1^1<<UCSZ0;  //8 Bit
30
  UCSRB = 1<<RXEN^1<<TXEN;    //enable RX, TX
31
32
  sei();
33
  puts( "RC5-Dekoder:\n\r" );
34
  for(;;){        // main loop
35
    cli();
36
    i = rc5_data;      // read two bytes from interrupt !
37
    rc5_data = 0;
38
    sei();
39
    if( i ){
40
      DDRB = i;        // LED output
41
      putchar(( i >> 11 & 1) + '0');  // Toggle Bit
42
      putchar(' ');
43
      itoa( i >> 6 & 0x1F, s, 10);  // Device address
44
      puts( s );
45
      putchar(' ');
46
      itoa((i & 0x3F) | (~i >> 7 & 0x40), s, 10); // Key Code
47
      puts( s );
48
      puts( "\n\r" );
49
    }
50
  }
51
}

XTAL wurde der Quarzfrequenz (3.686Mhz) angepasst
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/signal.h>
4
#include <stdlib.h>
5
6
7
#define uchar unsigned char
8
#define uint unsigned int
9
10
#define  xRC5_IN    PIND
11
#define  xRC5    PD7      // IR input low active
12
13
#define  XTAL    3.686e6
14
15
#define  BAUD  19200
16
#define bauddivider (uint)(XTAL / BAUD / 16 - 0.5)
17
18
19
extern uint  rc5_data;        // store result




Lg Ratlos

von Di Pi (Gast)


Lesenswert?

Ratlos schrieb:
> DDRB = i;

Hier setzt du den Prot nicht, sondern definierst die Pins am PortB (in 
deinem fall vom rc5-signal gesteuert) als Ausgang.

Versuchs mal an gleicher Stelle mit
1
 PORTB = i;

und vor der main-loop mit:
1
 DDRB = 0xff;

von Kai E. (kai20)


Lesenswert?

Ich weiss nicht, ob WINAVR alle Pins auf Eingang initialisiert,
sonst setze mal PD7 auf input und aktiviere den internen Pullup
deines uC (der TSOP1736 hat 100kOhm pullup).
RC Filter an der Versorgung des TSOP1736 ist vorhanden ?

Sonst prüfe doch mal, ob die Timer IRQ überhaupt ausgeführt wird, zähle 
z.B. eine variable in der timer irq hoch und lasse sie im terminal 
ausgeben, oder auf den LEDs.

Ich habe einige FBs gehabt, von denen ich dachte, sie würden RC5 senden, 
haben sie aber nicht.

Grüße,
Kai

von Di P. (drpepper) Benutzerseite


Lesenswert?

bin nicht ganz sicher: aber vielleicht optimiert der compiler dein 
rc5_data auch weg, weil es nicht als volatile deklariert ist.

von Christian S. (Gast)


Lesenswert?

hey
finde den Code auch sehr gut und würde ihn gern verwenden.
Danke hier nochmal an Peter!

Ich verwende AVR Studio VER. 4.18 ich habe alle 3 Dateien in einem 
Projekt geöffnet allerdings nach drücken auf "build" kommt folgende 
Fehlermeldung:

c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr4/crt 
m8.o:(.init9+0x0):  undefined reference to `main'

Jemand ne Idee woran das liegen kann??

mfg Christian

von John Doe (Gast)


Angehängte Dateien:

Lesenswert?

Garnicht so einfach heutzutage eine FB mit RC5 Code zu finden.
Könnte mal jemand der sich damit auskennt überprüfen ob meine FB 
standardkonformes RC5 sendet?

Ich hoffe dass es RC5 ist, hab mal nacheinander die Tasten 1..9,0 
gedrückt und mit Audacity den Ausgang vom Empfänger IC (TSOP...) 
aufgezeichnet. Übrigens danke schonmal ans Forum für den genialen Tipp 
mit der Soundkarte.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

John Doe schrieb:
> Garnicht so einfach heutzutage eine FB mit RC5 Code zu finden.

Das stimmt allerdings. RC5 ist ziemlich tot.

Alternative wäre IRMP: http://www.mikrocontroller.net/articles/IRMP

Das erkennt so ziemlich jedes IR-Protokoll, was heutzutage so 
rumschwirrt.

> Könnte mal jemand der sich damit auskennt überprüfen ob meine FB
> standardkonformes RC5 sendet?

Das sieht wirklich wie RC5 aus, bei den meisten anderen FB-Protokollen 
sind die Startbits wesentlich länger als die Datenbits. Das ist hier 
nicht gegeben. Allerdings fehlen bei Deinem Bild Angaben zu den Timings. 
Wie breit sind die Pulse?

Gruß,

Frank

von John Doe (Gast)


Angehängte Dateien:

Lesenswert?

Danke für den Tipp mit dem IRMP, habe ich irgendwie über die 
Suchfunktion noch nicht entdeckt.

Scheint bei meiner FB aber tatsächlich RC5 zu sein, Start- und Toggle 
Bits sind vorhanden, der komplette Frame besteht aus 14 Bits und dauert 
etwa 24 ms (siehe Anhang.)
Leider hat sich auf der FB keinerlei Hersteller verewigt, einfach 
unbeschriftet. Ist aber ein interessantes Teil, da sie über ein 
Steuerkreuz und "Maustasten" mit deutlich höherer Updaterate als die 
anderen Tasten verfügt. Ich kann nachher mal Bilder davon machen.

von Norman (Gast)


Lesenswert?

Hallo,

habe im Mediamarkt von Vivanco eine Fernbedienung für 3,99E gekauft.
Siehe Link:
http://www.vivanco.de/cgi-bin/vivanco/de_DE/productDetail.html?productId=11158&catId=0

Diese produziert mit der Codeeinstellung: 035 einen RC-5 Code.
TV1 hat die Geräteadresse  0
Sat1 hat die Geräteadresse 8

MfG Norman

von Joshua (Gast)


Lesenswert?

Hallo erst mal,
habe den gesamten Thread jetzt mal. Es taucht immer wieder die Frage 
bzw. das Problem mit der Nutzung des internen Oszillators auf...
Ist das in irgendeiner Form ein Problem oder nicht bzw. kann jemand 
bestätigen die Routinen mit internem Oszillator lauffähig bekommen zu 
haben.
Ich selber kämpfe noch, arbeite allerdings mit ext. Quarz (9.8304Mhz), 
um glatte Baudraten einstellen zu können.
Plane aber später ne Version mit int. Oszillator, wo dann aber auch 
keine UART benötigt wird.

Gruß Josh

von Tom E. (hallo02)


Lesenswert?

Hallo!

Ich habe den original code von peter (erster beitrag) genommen. ich 
versuche ihn auf einem atmega32 mit 16Mhz zum laufen zu bringen. Leider 
bekomme ich keinen output :-(

ich habe die SIGNAL (SIG_OVERFLOW0) routine mit usart debug ausgaben 
bestueckt und herausgefunden, dass folgende if bedingung nicht erfuellt 
wird (siehe kommentar unten) - in allen anderen if bedingungen bekomme 
ich eine debug ausgabe

kann mir vielleicht jemand weiterhelfen?

SIGNAL (SIG_OVERFLOW0)
{
  uint tmp = rc5_tmp;

  TCNT0 = -2;
  if( ++rc5_time > PULSE_MAX ){
    if( !(tmp & 0x4000) && tmp & 0x2000 ) // <--- HIER KOMM ICH NICHT 
REIN
      rc5_data = tmp;                    // <--- HIER KOMM ICH NICHT 
REIN
    tmp = 0;
  }

  if( (rc5_bit ^ xRC5_IN) & 1<<xRC5 ){
    rc5_bit = ~rc5_bit;

    if( rc5_time < PULSE_MIN )
      tmp = 0;

    if( !tmp || rc5_time > PULSE_1_2 ){
      if( !(tmp & 0x4000) )
        tmp <<= 1;
      if( !(rc5_bit & 1<<xRC5) )
        tmp |= 1;
      rc5_time = 0;
    }
  }

  rc5_tmp = tmp;
}

von Tom E. (hallo02)


Lesenswert?

das problem hat sich geloest, ich habe einen fehler im code gehabt auf 
grund meiner vielen debug ausgaben - der oben gezeigte code funktioniert

das einzige was ich geandert habe, ist uint in uint16_t umzubenennen, 
bzw uchar nach uint8_t

von Christian S. (swoc)


Lesenswert?

Hallo zusammen

wieso wird bei

if( (rc5_bit ^ xRC5_IN) & 1<<xRC5 )

mit xRC5_IN der gesamte Port eingelesen und verknüpft?

von moo (Gast)


Lesenswert?

Hi Leute.

Sorry wenn ich den alten Threat wieder raus krame, aber ich bin jetzt 
auch dabei den RC5-Code von Peter auszuprobieren...
Leider klappt es nicht und ich such mich seit Wochen nach dem Fehler 
tot...bin total verzweifelt...hab alle Posts doppelt und dreifach 
gelesen...aber nix hilft.

Ich versuche den Code an einen ATMega128 mit 16MHz anzupassen. Das ganze 
ist ein AVRStudio4-Projekt.

Die relevanten Code-Stellen sehen folgender Maßen aus:
1
#define F_CPU 16000000UL
2
3
/* Zuweisungen PORT D */
4
#define PORT_D_CONFIGBYTE  0x48 //
5
  #define PD0x           PORTD0  // Input    -> 0  
6
  #define PD1x           PORTD1  // Input    -> 0 
7
  #define PD2x           PORTD2  // Input    -> 0  RX1
8
  #define PD3x           PORTD3  // Output   -> 1  TX1  
9
  #define PD4x           PORTD4  // Input    -> 0  switch
10
  #define PD5x           PORTD5  // Input    -> 0  switch
11
  #define PD6x           PORTD6  // Output   -> 1  led
12
  #define xRC5           PORTD7  // Input    -> 0  RC5-Signal
13
  
14
15
//RC5
16
#define  xRC5_IN    PIND
17
18
#define uchar unsigned char
19
#define uint unsigned int
20
#define  XTAL    16000000  
21
22
#define RC5TIME   1.778e-3    // 1.778msec
23
#define PULSE_MIN  (uint)(F_CPU / 2048 * RC5TIME * 0.4 + 0.5)
24
#define PULSE_1_2  (uint)(F_CPU / 2048 * RC5TIME * 0.8 + 0.5)
25
#define PULSE_MAX  (uint)(F_CPU / 2048 * RC5TIME * 1.2 + 0.5)

Ich benutze Timer2 (8-Bit).
1
TCCR2 |= (1<<CS22)| (1<<CS20);      //divide by 1024
2
TIMSK = (1<<TOIE2);      //enable timer interrupt

In der ISR(TIMER2_OVF_vect) habe ich
1
TCNT2 = -8;
 angepasst.

Der Rest ist eigentlich Original...

Kann mir jemand sagen warum das ganze nicht funktioniert?
In die ISR(TIMER2_OVF_vect) wird gesprungen, aber rc5_data wird nie 
gültig.
D.h.
1
if( !(tmp & 0x4000) && (tmp & 0x2000) ){  // only if 14 bits received
2
      rc5_data = tmp;
 wird nie erreicht.

Hat jemand eine Idee?

LG.
moo

von Hendrik X. (wolf77)


Lesenswert?

Guten Abend.
Ich versuche auch den RC5 Code von oben zu verwenden, doch ich weiß 
leider nicht wie ich das char_feld auslesen kann, wo code und adresse 
stehen, um die ausgänge meines ATMEGA8 mit 3 verschiedenen 
Fernbediehnungstasten zu steuern.

Ich hab das programm im atmelstudio kompiliert und übertragen, aber das 
einzige was ich erreiche sind komische 500mV flanken auf PB0 beim 
drücken einer taste.

Nun meine frage wie kann zb. beim drücken der PWR taste ( code 12) 
meiner Loewe fernbediehnung ( RC5) eine aktion auslösen?

von Malte _. (malte) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo,
ich habe mal die Version für einen XMEGA angepasst (getestet mit 
ATxmega64A1). Außerdem wird der Timer abgeschaltet, solange nichts 
empfangen wird. Der Pin ISR weckt den Timer dann wieder auf. Das erlaubt 
einen Betrieb auch während die CPU im Power Save Mode ist. Viel Spaß.

von Kim (Gast)


Lesenswert?

Hallo alle zusammen,
ich soll, von meinem Ausbilder, ein RC5-signal mit einem PIC16F84A 
auswerten und das Ergebnis von einem LCD anzeigen lassen
ich finde leider rein gar nichts dazu.
Kann mir da jemand helfen??

LG Kim

von Di P. (drpepper) Benutzerseite


Lesenswert?

IRMP hilft. Lesen bildet :)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Di Pi schrieb:
> IRMP hilft. Lesen bildet :)

Nunja, das Lesen des Artikels hilft bestimmt. Aber das IRMP-Paket als 
Software für diese Aufgabe anzuwenden dürfte wohl den gewünschten 
Lerneffekt unterlaufen ;-)

@Kim:

  http://www.mikrocontroller.net/articles/IRMP#RC5_.2B_RC5X

Hier findest Du weitere 4 Links als "Literatur-Hinweis":

  http://www.mikrocontroller.net/articles/IRMP#RC5-_und_RC5x-Protokoll

von Kim (Gast)


Lesenswert?

Danke =)
damit bin ich aber leider nicht viel weiter gekommen =/

LG Kim

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Kim schrieb:
> damit bin ich aber leider nicht viel weiter gekommen =/

Warum? Du weisst jetzt, wie das Signal aussieht. Jetzt musst Du das nur 
noch programmieren. Oder hapert es genau daran?

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.