Sonys IR-Code (SIRCS)

OP #965837
Lesenswert?

Hallo,
ich bin zur Zeit am Nachbilden des Sony SIRCS-Codes. Ich habe die IR-LED 
mit Timer0 per Hardware gepulst (40kHz). Das Signal erzeuge ich nun 
einfach durch ein- und ausschalten des Timers. Das klappt manuell auch 
wunderbar. Mit manuell meine ich folgendes:
1
IR_LED_ON(); _delay_ms(2.4); IR_LED_OFF(); _delay_ms(0.6);
2

3
IR_LED_ON(); _delay_ms(1.2); IR_LED_OFF(); _delay_ms(0.6);
4
IR_LED_ON(); _delay_ms(1.2); IR_LED_OFF(); _delay_ms(0.6);
5
IR_LED_ON(); _delay_ms(0.6); IR_LED_OFF(); _delay_ms(0.6);
6
IR_LED_ON(); _delay_ms(0.6); IR_LED_OFF(); _delay_ms(0.6);
7
IR_LED_ON(); _delay_ms(1.2); IR_LED_OFF(); _delay_ms(0.6);
8
IR_LED_ON(); _delay_ms(0.6); IR_LED_OFF(); _delay_ms(0.6);
9
IR_LED_ON(); _delay_ms(0.6); IR_LED_OFF(); _delay_ms(0.6);
10

11
IR_LED_ON(); _delay_ms(1.2); IR_LED_OFF(); _delay_ms(0.6);
12
IR_LED_ON(); _delay_ms(0.6); IR_LED_OFF(); _delay_ms(0.6);
13
IR_LED_ON(); _delay_ms(0.6); IR_LED_OFF(); _delay_ms(0.6);
14
IR_LED_ON(); _delay_ms(0.6); IR_LED_OFF(); _delay_ms(0.6);
15
IR_LED_ON(); _delay_ms(0.6); IR_LED_OFF(); _delay_ms(0.6);

Der Fernseher reagierte wie erwünscht mit dem verringern der Lautstärke. 
Der obige Abschnitt wurde mit Timer1 alle 45ms (=22,222Hz) wiederholt. 
Nun gibt es zwei Punkte, die mich zum erstellen einer Funktion bewegt 
haben:
1. Ich will nur einen Timer (0) verwenden
2. Ich möchte einfach Adresse und Kommando an die Funktion übergeben 
können, alles andere macht die Funktion

Hier mal die Funktion:
1
void SIRCS(uint8_t command, uint8_t address){
2
  float x = 0.0;
3
  
4
  for(uint8_t i=0; i<5; i++){
5
    //Start
6
    IR_LED_ON();
7
    _delay_ms(2.4);
8
    IR_LED_OFF();
9
    _delay_ms(0.6);
10
    
11
    //Command
12
    for(uint8_t j=0; j<7; j++){
13
      IR_LED_ON();
14
      _delay_ms(0.6);
15
      
16
      if(command & j){
17
        _delay_ms(0.6);
18
        x += 0.6;
19
      }
20
      
21
      IR_LED_OFF();
22
      _delay_ms(0.6);
23
    }
24
    
25
    //Address
26
    for(uint8_t j=0; j<5; j++){
27
      IR_LED_ON();
28
      _delay_ms(0.6);
29
      
30
      if(address & j){
31
        _delay_ms(0.6);
32
        x += 0.6;
33
      }
34
      
35
      IR_LED_OFF();
36
      _delay_ms(0.6);      
37
    }
38
    
39
    _delay_ms(27.6-x);
40
  }
41
}

Hier eine kleine Funktionsbeschreibng:
Da der Code je nach Anzahl der 0en und 1en unterschiedlich lang ist, 
wird die 45ms Wiederholzeit mit der Variable x dynamisch errechnet.
Die erste for-Schleife wiederholt den Code 5mal. In ihr wird erst der 
Startblock gesendet, dann das Kommando und die Adresse. Unsicher bin ich 
mir bei den Abschnitten "if(command & j)" bzw. "if(address & j)", kann 
man so überprüfen, ob das j'te Bit gesetzt ist? Naja der Rest sollte 
klar sein. Mein Problem ist jetzt, dass das Ganze nicht funktioniert. 
Kann es sein, dass durch die ifs und fors das Timing durcheinander 
gerät? Wo könnte noch der Fehler liegen?

Hier die Infos über das Protokoll: 
http://www.sbprojects.com/knowledge/ir/sirc.htm

Ich hoffe ihr könnt mir weiterhelfen. mfG, Sven
OP #966322
Lesenswert?

Hallo Christian,
wie viele CPU-Takte brauchen denn diese Fließkommaoperationen?

Wenn ich das ganze mit nur einem Timer machen wollte, müsste dieser ja 
mit 40kHz aufgerufen werden. In jeder ISR müsste dann überprüft werden, 
ob bereits 600µs vergangen sind, usw. Ich stelle mir das Ganze 
wesentlich komplizierter vor...
Gast #966433
Lesenswert?

Hi,

selbst wenn du es mit der Delayfunktion machen möchtest, dann sollte das 
auch ohne weiteres ohne Float klappen. Musst halt das Delay ein wenig 
anders aufrufen

bsp.:
1
void warte(uint16_t zeit)
2
{
3
  for(; zeit>0; zeit--) _delay_us(100);
4
}
5

6
int main( void )
7
{
8
.
9
.
10
.
11
warte(6);
12
warte(12);
13
.
14
.
15
.
16
}

oder hier mal nachsehen:

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#avr-libc_Versionen_kleiner_1.6

mfg
Persönliche Seite #966484
Lesenswert?

"In order for these functions to work as intended, compiler 
optimizations must be enabled, and the delay time must be an expression 
that is a known constant at compile-time. If these requirements are not 
met, the resulting delay will be much longer (and basically 
unpredictable), and applications that otherwise do not use 
floating-point calculations will experience severe code bloat by the 
floating-point library routines linked into the application."

  http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html
OP #966778
Lesenswert?

Hallo, ich habe versucht eure Tips umzusetzen. Es läuft allerdings 
immernoch nicht. Ich verschwende wahrscheinlich zu viel Zeit mit den 
if-Abfragen usw. Mir wird wohl nichts anderes übrig bleiben, als das 
alles mit Timern zu lösen. Habt ihr einen Ansatz, wie man das mit nur 
einem Timer lösen könnte?
Gast #966946
Lesenswert?

> Unsicher bin ich
> mir bei den Abschnitten "if(command & j)" bzw. "if(address & j)", kann
> man so überprüfen, ob das j'te Bit gesetzt ist?
Nein. Besser so.
1
if(command & (1<<j))

Oder das ganze evtl. so.
1
for(uint8_t j=1; j<=(1<<5); j<<=1){
2
  ...blabla...
3
  if(command & j){
4
  ...
OP #967116
Lesenswert?

Halli-Hallo,
eine Frage habe ich noch: Ich schalte ja die gepulste IR-LED mit 
folgenden Makros an und aus:
1
#define IR_LED_ON()  TCCR2 |= (1<<CS20)
2
#define IR_LED_OFF()  TCCR2 &= ~(1<<CS20)

Das klappt auch wunderbar, aber bei "ausgeschalteter" IR-LED ist das 
Potential dennoch HIGH am OC2-Pin. Das bedeutet, dass die IR-LED 
ungepulst leuchtet. Das beeinträchtigt die Funktion zwar nicht, aber da 
ich die IR-LED später mit wesentlich höherem Strom betreiben werde, wird 
diese das nicht ungepulst vertragen. Wie muss ich also meine Makros 
modifizieren, damit das Potential bei ausgeschalteter IR-LED LOW ist?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren