Forum: Mikrocontroller und Digitale Elektronik Infrarot Burst Programmierung


von Besucher (Gast)


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
}

von STK500-Besitzer (Gast)


Lesenswert?

Besucher schrieb:
> aber wie überlagere ich das mit einem z.B. 7Hz Signal um
> diese Bursts zu bekommen?

mit Hilfe eines weitern Portpins, der mit einem weiteren Timer oder der 
seriellen Schnittstelle verbunden ist.

von Besucher (Gast)


Lesenswert?

Ist das Ausgangssignal des Moduls für die komplette Dauer des 7Hz Burst 
Signals Low oder blinkt es in der Zeit mit 40kHz?

von Rutger (Gast)


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.

von Rutger (Gast)


Lesenswert?

Rutger schrieb:
> 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.

Sorry, die Hälfte davon.

von Rutger (Gast)


Lesenswert?

Eigentlich werden normalerweise die 40kHz über einen der HW-Ausgänge 
eines Timers ausgegeben zB OC1A. Über die COM1Ax Bits wird dann im 
gewünschten Takt der HW-Ausgang ein- und ausgeschaltet.

von Besucher (Gast)


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
}

von Besucher (Gast)


Lesenswert?

volatile uint32_t a_b;
int main()...

von Rutger (Gast)


Lesenswert?

Besucher schrieb:
> allerdings sehe ich nicht das der Ausgang des Moduls auf Low geht (Habe
> eine Led daran angeschlossen).

Kann verschiedene Ursachen haben. Mach dir klar, was da genau passiert - 
zur Not händisch auf low schalten.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Es ist auch legitim, den OC Ausgang zum Sperren auf Eingang 
umzuschalten, z.B.:
1
DDRB &= ~(1<<PB0);

Sobald er wieder Ausgang ist, erscheint dann wieder das OC Signal am 
Pin.

: Bearbeitet durch User
von Besucher (Gast)


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.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


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.

: Bearbeitet durch User
von Besucher (Gast)


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.

von Besucher (Gast)


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
}

von Besucher (Gast)


Lesenswert?

Ok den Fehler habe ich gerade selber erkannt, ich muss OC1A ja noch mit 
PB0 Und-Verknüpfen sonst habe ich gar keinen richtigen Burst^^
Wie mach ich das am geschicktesten?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


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);

: Bearbeitet durch User
von Besucher (Gast)


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.

von Besucher (Gast)


Lesenswert?

Niemand eine Idee weshalb es nicht funktioniert?

von STK500-Besitzer (Gast)


Lesenswert?

Besucher schrieb:
> Niemand eine Idee weshalb es nicht funktioniert?

Was willst du mit dem Code in der ISR anstellen?
Kommentier das bitte mal, damit man sieht, wo du Verständnisprobleme 
hast.
Ich vermute, dass du willenlos rumstocherst.

von Besucher (Gast)


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
}

von Karl H. (kbuchegg)


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)

: Bearbeitet durch User
von Besucher (Gast)


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

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.