Sida 1 av 2

IR-diod

Postat: 17 mars 2007, 15:42:45
av Luckan
Hej!
Jag ska koppla in en ir-diod (http://www.elfa.se/elfa-bin/inforuta.pl ... ld=7522519) på ett breadboard tillsammans med ett ATMega 16 eller Tiny 13. Min fråga är hur ir-dioden skall kopplas in, vilka motstånd behövs? Krävs en kondensator? osv....

Postat: 17 mars 2007, 15:47:19
av strombom
Enligt databladet klarar den max 100mA, dock klarar inte pinnarna på en AVR mer än 40mA. Så säg 20mA ?

Spänningen över ir-dioden är enligt databladet ca 1.3 volt. Jag gissar att du driver AVR med 5 volt. Då blir det 3.7 volt över motståndet.

3.7 volt / 0.020 ampere = 185 ohm

Standardmotstånd är på 180 ohm och 220 ohm, så något i den trakten borde duga.

[b]Ny fråga[/b]

Postat: 18 mars 2007, 21:31:46
av Luckan
Jag har nu kopplat in dioden och har suttit ett tag med att försöka skriva ett program som skickar en signal till min stereo. Det funkar tyvärr inte alls. Vad kan det vara för fel??
Jag vill skicka en signal med 38kHz bärvåg med hjälp av timer1. Om nån kan hitta något i koden som verkar vara fel får denne gärna hojta till:) Eller är det nåt som är otydligt i koden är det oxå bara att fråga...

Kod: Markera allt

#include <avr/io.h>
 int main(void){
	TCCR1A=0x00;
	TCCR1B=0x09; 
	OCR1A=13; 
                DDRD=0x20;
	unsigned int i,j;
	unsigned char switch_zero;
	unsigned char one_or_zero;
	unsigned int volume_down=0x50AF;

	void send_one(void){
		for(j=0;j<500;j++){
			TCCR1A=0x40; 
			}
		for(j=0;j<1800;j++){
			TCCR1A=0x00;
			}	
		}

	void send_zero(void){
		for(j=0;j<500;j++){
			TCCR1A=0x40;
			}
		for(j=0;j<600;j++){
			TCCR1A=0x00;
			}
		}

	void send_startbit(void){
		for(i=0;i<9000;i++){
			TCCR1A=0x40; 
			}
		for(i=0;i<4600;i++){
			TCCR1A=0x00;
			}
		for(i=0;i<8;i++){
			send_zero();
			}
		for(i=0;i<8;i++){
			send_one();
			}
		}

	void check_one_or_zero(unsigned int one_or_zero){
		if(one_or_zero==1){
			send_one();
			}
		else{
			send_zero();
			}
		}

             while(1){
	switch_zero = PINB & 0x01; //0000 0001
	if(switch_zero==0){
		send_startbit();
		for(i=15;i>0;i--){
			one_or_zero=volume_down>>i;
			one_or_zero &= 0x0001;
			check_one_or_zero(one_or_zero);
			}
		one_or_zero = volume_down & 0x0001;
		check_one_or_zero(one_or_zero);
		for(i=0;i<10000;i++){
			}
		}
	}
}

Postat: 18 mars 2007, 22:25:46
av vfr
Använd "CODE"-taggarna när du skriver in kod så det blir läsbart!

Postat: 19 mars 2007, 07:25:57
av Luckan
Fixat! Kanske lite lättare att läsa nu :D

Postat: 19 mars 2007, 12:13:50
av mke
Jag ser inte hur du har tänkt att utnyttja timer1. Du har inte ha någon interruptrutin som tar hand om räknaravbrott.

Sen är jag inte riktigt med på dina for-loopar typ:

Kod: Markera allt

void send_zero(void){
      for(j=0;j<500;j++){
         TCCR1A=0x40;
         }
      for(j=0;j<600;j++){
         TCCR1A=0x00;
         }
      } 
Vad har du tänkt att göra här?

Sen så har du inte kommenterat något av koden vilket gör det mycket svårare att följa.

Postat: 19 mars 2007, 12:23:08
av sodjan
Att försöka fixa det med for-loopar för att få rätt "timing" är dömt att misslyckas.
Varför inte använda en timer som du föreslog !?

Postat: 19 mars 2007, 13:14:19
av MicaelKarlsson
"Att försöka fixa det med for-loopar för att få rätt "timing" är dömt att misslyckas. "

Håller med!
I detta fall så är det säkert lättare att använda en delayfunktion, om det nu är så att pulserna skall vara 600μs. Då ser jag två alternativ:
- Använda delayfunktion. För WinAVR: _delay_us(delay_time);
- Använda t.ex. timer2

Tänk på:
The maximal possible delay is 768 us / F_CPU in MHz.

The maximal possible delay is 262.14 ms / F_CPU in MHz.
Detta är hämtat från delay.h

EDIT:
"Jag har nu kopplat in dioden och har suttit ett tag med att försöka skriva ett program som skickar en signal till min stereo."

Har du kopplat den direkt till din AVR? Om du drar mer ström än vad din AVR klarar så kan ju det ställa till det för dig.

Har du kollat att du får ut det du vill?

Postat: 19 mars 2007, 18:00:29
av Luckan
Tack för alla svar! Har insett nu efter mätning med flukemetern att mina for-loopar var helt uppe på läktaren och införskaffade korv med mos... :shock:

Men om jag då istället använder tex TIMER2, hur ska den användas? För att t.ex. skicka en logisk etta vill jag sända en 38kHz våg i cirka 500us, vilket sedan skall följas av "ingenting" i cirka 600us. Kan jag göra det genom att helt enkelt först nollställa TIMER2 och sedan låta den räkna upp till 500 och sedan nollställa igen och räkna upp till 600?

Postat: 19 mars 2007, 18:09:19
av sodjan
När jag har gjort IR-sändere (i och för sig med en PIC, men det är
ingen principiell skillnad), så har jag konfigurerat PWM modulen
för att generera bärvågen (t.ex 38 Khz). Sedan genererade jag
signalen (d.v.s *moduleringen* av bärvågen) genom att helt enkelt
stänga av/på PWM modulen. På en PIC är det en enda bit som
ska sättas/clearas, borde vara något liknande på en AVR...

Timingen av signalen (d.v.s de 600 us pulserna) fixade jag via en
*annan* timer (än den som styr PWM modulen).

Postat: 19 mars 2007, 18:12:49
av mke
du använder t.ex. timer0 för att skapa interrupts (CTC-mode) med en frekvens på 38kHz. Vid varje interrupt så flippar du utsignal så du får 1-0-1-0-1-.... För att bestämma när du ska flippa utsignalen och när du ska ha den låg använder du timer1.

Hoppas du blir något klokare utav mitt försök till förklaring

Postat: 19 mars 2007, 18:17:29
av MicaelKarlsson
Luckan: for-lopen glömde väl inte senapen? :lol:

Skämt åsido!!

Kod: Markera allt

	
// Setup timer0 and timer2
TIMSK |= (1 << TOIE0)|(1 << TOIE2);  // Enable timer0 & 2  overflow  nterupt.
TCCR0 |= (1 << CS00); //  timer0 CLK = internal clock
TCCR2 |= (1 << CS22)|(1 << COM20); // timer2 CLK  = internal clock/64
Sedan kan du köra timer0 som "togglar" en pinne

Kod: Markera allt

	
#define bit_flip(p,m) ((p) ^= (m))

ISR(TIMER0_OVF_vect)
{
  bit_flip(PORTB,1); 
}
Om du inte får rätt frekvens kan du använda:
TCNTx för att sätta ett startvärde för räknaren så du får 38kHz.


Edit: mke, tycker det var en bra förklaring! :)

Postat: 19 mars 2007, 20:12:10
av Luckan
Har skrivit lite ny kod men det vill fortfarande inte fungera...
Nedan följer en liten del av programmet. Nån som ser något som inte borde vara där eller något som borde vara där :D

Kod: Markera allt

void send_one(void){ //metod som sänder etta
		TCCR0|=(1 << COM00); //Toggle OC0 on compare match
		TCNT1=0x00; //Nollställ timer1
		while(TCNT1<=540){ //delay 540us
			}
		TCNT1=0x00; //Nollställ timer1
		TCCR0 &= 0xEF; // OC0 disconnected
		while(TCNT1<=1800){ //delay 1800us
			}
		}

Postat: 19 mars 2007, 22:22:51
av sodjan
> Har skrivit lite ny kod.....

Någon speciell anledning att du dels gör exakt som alla har sagt att
du *INTE* ska göra samt inte gör på något av de sätt som du har
blivit rekomendera *ATT* göra ??

> Nån som ser något som inte borde vara där...

Ja.

Postat: 20 mars 2007, 10:25:10
av MicaelKarlsson
Luckan: Vad vill du att koden skall göra? Jag tror att du bör sätta dig och skriva ner lite pseudokod eller möjligen ett detaljerat flödesschema och sedan när det är klart skriva koden.

"Någon speciell anledning att du dels gör exakt som alla har sagt att
du *INTE* ska göra samt inte gör på något av de sätt som du har
blivit rekomendera *ATT* göra ?? "

Skulle jag också vilja ha svar på.