Infrarot Burst Programmierung

Gast #3935304
Lesenswert?

Hallo,

ich möchte mit der IR-Led "LD271" ein IR-Empfänger Modul "TSOP31240" 
bestrahlen. Das 40kHz Signal kann ich als PWM mit meinem Atmega 32 
programmieren, aber wie überlagere ich das mit einem z.B. 7Hz Signal um 
diese Bursts zu bekommen? Mein Programm für die 40kHz sieht 
folgendermaßen aus.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdio.h>
4
#define F_CPU 3680000UL
5

6
int main()
7
{
8
DDRB =0xff;
9
ICR1=92;
10
OCR1A= 46;
11
TCCR1A = (1<<WGM11);
12
TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS10);
13
TIMSK = (1<<OCIE1A);
14

15
sei();
16

17
while(1)
18
    {}
19

20
ISR(TIMER1_COMPA_vect)  
21
{
22
  PORTB^=(1<<PB0);
23

24
}
Gast #3935324
Lesenswert?

Besucher schrieb:
> programmieren, aber wie überlagere ich das mit einem z.B. 7Hz Signal um
> diese Bursts zu bekommen? Mein Programm für die 40kHz sieht

Die ISR wird 40000 Mal/s angesprungen. Du könntest für 5714 Sprünge den 
PB0 toggeln lassen und für 5714 Sprünge nicht toggeln lassen.
Gast #3935342
Lesenswert?

Mein habe mein Programm deinem Vorschlag entsprechend geändert, 
allerdings sehe ich nicht das der Ausgang des Moduls auf Low geht (Habe 
eine Led daran angeschlossen).
1
int main()
2
{
3
DDRB =0xff;
4
ICR1=92;
5
OCR1A= 46;
6
TCCR1A = (1<<WGM11);
7
TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS10);
8
TIMSK = (1<<OCIE1A);
9

10
sei();
11

12
    while(1)
13
    {}
14
ISR(TIMER1_COMPA_vect)  
15
{
16
  a_b++;
17
  if (a_b<=2856)
18
  {
19
    PORTB^=(1<<PB0);
20
  }
21
  if (a_b>=5714)
22
  {
23
    a_b=0;
24
  }
25
}
Gast #3935815
Lesenswert?

Vorausgesetzt das Programm wie oben zu sehen ist korrekt, wie kann es 
dann sein dass das Empfänger-Modul nicht auf Low schaltet? Die IR-Led 
hat einen Vorwiderstand von 47 Ohm, der an PB0 angeschlossen ist. Das 
Modul hat den benötigten Kondensator mit 0,33uF und an VS einen 
Widerstand von 100 Ohm. Trotzdem liegt am Ausgang des Moduls immer eine 
"1" bzw 4V an.
(Firma: matzetronics) #3935828
Lesenswert?

Besucher schrieb:
> habe mein Programm deinem Vorschlag entsprechend geändert

Du hast allerdings die ISR in main() reingeschrieben. Ich habe das noch 
nie gemacht - was dabei passiert, sollte dir jemand sagen, der davon 
mehr Ahnung hat als ich. Ich schreibe Unterroutinen und auch ISR 
getrennt von main() und würde dir das gleiche empfehlen.

Der Code des Timers sieht erstmal gut aus bis auf einen unbedeutenden 
Rechenfehler. Die genaue Frequenz des STK500 ist zwar 3,6864 MHz, aber 
das spielt hier keine Rolle.
Das Toggeln geschieht allerdings mit 40kHz, so dass die resultierende 
Frequenz genau halb so gross ist. Der Compare Match geschieht ja pro 
Timerdurchlauf einmal und niemand toggelt in deinem Code den Pin, wenn 
der Timer bei OVF oder 0 ist.

Ein Dauersignal mit 40kHz wird übrigens die Regelung des TSOP lahmlegen 
und runterregeln, gepulste Signale sollten allerdings klappen. Es ist 
aber einfacher, einfach COM1A1 und COM1A0 zu setzen und den Rest der 
Hardware zu überlassen. An OC1A erscheint dann von alleine ein 40kHz 
Signal, ohne das ein extra toggeln in der ISR nötig wäre, und das würde 
mit deinem Code passieren, der dann recht genau 40kHz erzeugt.
Gast #3935851
Lesenswert?

Gut ich habe mein Programm erneut überarbeitet. PB7 testes den Ausgang 
des Moduls und setzt dementsprechend PB4 oder PB5. Müsste PB5 nicht so 
lange "1" sein wie der Burst ist also 1/7Hz = 142ms? Ich kann nämlich 
nur ein ganz kurzes Blinken sehen und wenn ich die Grenze a_b verdopple 
sehe gar kein Blinken mehr obwohl PB5 dann ja länger "1" sein sollte.
Gast #3935852
Lesenswert?

1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdio.h>
4
#define F_CPU 3680000UL
5

6
volatile uint32_t a_b;
7
int main()
8
{
9
DDRB=0x7f;
10
DDRD=0xff;
11
ICR1=92;
12
OCR1A= 46;
13
TCCR1A = (1<<WGM11)|(1<<COM1A1);
14
TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS10);
15
TIMSK = (1<<OCIE1A);
16
sei();
17
    while(1)
18
    {
19
    cli();
20
    if (PINB & (1<<PINB7))
21
    {
22
      PORTB|=(1<<PB4);
23
      PORTB&=~(1<<PB5);
24
    }
25
    else
26
    {
27
      PORTB|=(1<<PB5);
28
      PORTB&=~(1<<PB4);
29
    }
30
    sei();    
31
  }
32
}
33
ISR(TIMER1_COMPA_vect)  
34
{
35
  a_b++;
36
  if (a_b<=2857)
37
  {
38
    PORTB^=(1<<PB0);
39
  }
40
  if (a_b>=5714)
41
  {
42
    a_b=0;
43
  }
44
}
(Firma: matzetronics) #3935909
Lesenswert?

Besucher schrieb:
> Wie mach ich das am geschicktesten?

Ich hatte dir weiter oben schon mal geschrieben, das du zum Unterdrücken 
des Signals einfach den OC1A Ausgang auf Eingang schalten kannst, der 
Timer läuft dann weiter, aber es kommen keine Pulse mehr an OC1A. Wenn 
du wieder 40kHz am Ausgang haben willst, einfach wieder OC1A (PD5) als 
Ausgang konfigurieren. Du kannst aber auch an dem COM1A1 Bit ein- und 
ausschalten.
Also:
1
// OC1A abschalten
2
DDRD &= ~(1<<PD5);
3
// OC1A einschalten
4
DDRD |= (1<<PD5);
5
// oder die COM1A1 Methode
6
// OC1A abschalten
7
TCCR1A &= ~(1<<COM1A1);
8
// OC1A einschalten
9
TCCR1A |= (1<<COM1A1);
Gast #3935984
Lesenswert?

Erstmal danke für die Hilfe bis hier hin, dennoch funktioniert es immer 
noch nicht.
1
ISR(TIMER1_COMPA_vect)  
2
{
3
  a_b++;
4
  if (a_b<=2857)
5
  {
6
    DDRD &= ~(1<<PD5);
7
  }
8
  else
9
  {
10
    DDRD |= (1<<PD5);
11
  }
12
  if (a_b>=5714)
13
  {
14
    a_b=0;
15
  }
16
}
Den Rest habe ich so gelassen wie er war. Sobald a_b zwischen 2857 und 
5714 ist sollte PD5 also mit 40kHz toggeln. Schließe ich eine Led mit 
Vorwiderstand an PD5 an bleibt die aber dunkel. Das heißt für mich PD5 
funktioniert nicht wie gewollt.
Gast #3936142
Lesenswert?

1
ISR(TIMER1_COMPA_vect)  
2
{
3
  a_b++;            //a_b erhöhen
4
  if (a_b<=2857)        //ISR wird 40000/sec aufgerufen
5
  {              //2857 entspricht off-Phase eines 7Hz Signal
6
    DDRD &= ~(1<<PD5);    //An OC1A soll in der Zeit kein 40kHz Puls liegen
7
  }
8
  else                        //Zwischen 2857 und 5714 On-Phase des 7Hz Signals
9
  {              //In der Zeit soll das 40kHz Signal an OC1A liegen
10
    DDRD |= (1<<PD5);    
11
  }
12
  if (a_b>=5714)        
13
  {
14
    a_b=0;
15
  }
16
}
#3936154
Lesenswert?

Besucher schrieb:

> Schließe ich eine Led mit
> Vorwiderstand an PD5 an bleibt die aber dunkel.

Dann würde ich an deiner Stelle erst mal das ganze gekünstel sein lassen 
und zusehen, dass ich den Timer zum Laufen kriege. Das und nur das.
1
int main()
2
{
3
  Portpin auf Ausgang
4
  Timer konfigurieren
5

6
  sei();
7

8
  while( 1 )
9
    ;
10
}
11

12
ISR( ... )
13
{
14
  Portpin umschalten
15
}

Und erst dann, wenn das funktioniert und ich an der LED sehe, dass die 
ISR aufgerufen wird und der Pin toggelt, erst dann gehe ich weiter und 
kümmere ich mich um die Bursts.

Wenn die nicht funktionieren, dann hab ich mich in der letzten 
Erweiterung vertan und ich geh nochmal einen Schritt zurück zur letzten 
funktionierenden Version und seh zu, dass ich rauskriege, wo da das 
Problem liegt.


Edit: Seh gerade, dass du ja genau so angefangen hast. ALso nochmal 
zurück auf Anfang und die erste von dir gepostete MOdifikation gemacht. 
(PS: ein uint32_t ist bei deinen Zahlen wirklich nicht notwendig)
Gast #3936229
Lesenswert?

Mittlerweile bin ich echt verwirrt...
Ich habe das Programm auf ein Minimum reduziert einfach um zu gucken ob 
der Timer läuft und das ISR anspricht. Dafür habe ich einen Prescaler 
eingebaut damit das ganze entwas langsamer läuft und ich ein mögliches 
Blinken auch sehen kann.
1
volatile uint32_t a_b=0;
2
int main()
3
{
4
DDRB=0x7f;
5
DDRD=0xff;
6
ICR1=92;
7
OCR1A= 46;
8
TCCR1A = (1<<COM1A1)|(1<<WGM11);
9
TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS12);
10
TIMSK = (1<<OCIE1A);
11
sei();
12
    while(1)
13
    {}
14
}
15
ISR(TIMER1_COMPA_vect)  
16
{
17
        a_b++;            
18
  if (a_b<=22)        
19
  {              
20
    PORTB^=(1<<PB0);
21
  }
22
  if (a_b>=44)        
23
  {
24
    a_b=0;
25
  }
26
}
PB0 toggelt, kann man an der angeschlossenen Led sehen, also wird der 
Interrupt aufgerufen. PD5, der hardware mäßig toggeln sollte tut es 
nicht. Ich blick echt nicht mehr durch

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