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.
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.
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.
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.
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.
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).
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.
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.
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.
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.
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?
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:
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.
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.
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
intmain()
2
{
3
PortpinaufAusgang
4
Timerkonfigurieren
5
6
sei();
7
8
while(1)
9
;
10
}
11
12
ISR(...)
13
{
14
Portpinumschalten
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)
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
volatileuint32_ta_b=0;
2
intmain()
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