View Single Post
Tenkte jeg skulle dele dette i tilfellet noen var interessert. Har fullført del 1 av et todelt prosjekt jeg holder litt på med i jula og har dekket det meste på bloggen min Henrik.SandakerPalm.no, men tenkte å oversette til norsk her.


Etter å ha kjøpt meg et fjernstyrt lekehelikopter på teknikmagasinet ble jeg overrasket over hvor godt man kan styre en noe tidskritisk applikasjon med infrarødt lys.

Først litt basisinfo om de få og enkle komponentene som utgjør hoveddelen av kretsen. Det er viktig å vite hvordan mottakeren fungerer før man lager fjernkontrollen! Du trenger en eller fler LEDs som lyser med infrarødt lys, forkortet IR LED. Jeg brukte en TSOP4838 fra Tayda Electronics, produsert av Vishay, som er en IR mottaker modul. Hva "48" står for vet jeg ikke, men tallet 38 er mottakerens carrier frequency, som er 38KHz, oversetter her til bærefrekvens uten å vite om det er korrekt oversatt.

Bærefrekvensen er den frekvensen som IR LEDen må lyse med ("blinke") for at mottaker modulen skal oppfatte lyse. Når infrarødt lys lyser med denne frekvensen vil mottakeren oppfatte dette som et korrekt signal. Inni mottakermodulen finnes det bl.a. et båndpassfilter som jobber for å filtrere ut alt annet enn IR lys på bærefrekvensen, så alt annet infrarødt lys blir behandlet som søppel, f.eks vil lysstoffrør emmittere en viss mengde IR lys. Det er noe forhåndsregler som må tas hensyn til med slike mottakermoduler for å unngå tap av data. For eksempel må et lyssignal (på 38KHz) være på mellom 10 og 70 perioder (2,63e-4 til 1.8 ms med lys), og må bli etterfulgt av en pause på minst 14 perioder uten lys. Hvis et IR lyssignal overskrider dette antall perioder (10-70) gjelder andre regler. Fra databladet
For each burst which is longer than 1.8ms a
corresponding gap time is necessary at some time in
the data stream. This gap time should be at least 4
times longer than the burst.

Altså må hvert lyssignal som overstiger 1.8 millisekunder etterfølges av en pause på minst fire ganger lengden på lyssignalet.

Mottakermodulen har tre pinner. Den skal kobles til jord og strøm (foretrekker 5 volt), og har en Vut pinne hvor utgangssignalet oppstår. Utgangssignalet er aktivt lavt, det betyr at utgangen ligger på 5 volt helt til den oppdager et korrekt lyssignal og da går pinnen til 0v helt til lyssignalet opphører.

http://sandakerpalm.no/blog/wp-content/uploads/2010/12/burstsoflight.jpg

For å kontrollere lyssignalets periodetider og hvordan data skulle overføres brukte jeg en Atmega8. Det finnes proprietære funksjoner i mikrokontrollere og egne mikrokontrollere til å ta seg av IR kommunikasjon, men min metode funket veldig bra til mitt lavnivå formål! Fjernkontrollen min består av en Atmega8, en IR led og fire taktile knapper. De fire knappene er koblet til hver sin pinne på PORTB, fra pinne 0 til 3, men alle er også koblet til ekstern interrupt pinne PORTD PIN2 (INT0). Når en bryter trykkes så trekkes interrupt pinnen lav, og i interruptrutinen i programmet leser jeg av verdien på PORTB for å se hvilken knapp som ble trykket. Jeg bruker Timer 2 i CTC modus for å lage en output på OC2 pinnen med riktig frekvens, som avbrytes i sekvenser for å tilsvare forskjellige datasignaler avhengig av hvilken knapp som ble trykt. Jeg deler opp utgangssignalet i datapakker på 4 bit ved å skru av og på muligheten for utgangssignaler på porten, dette gjøres ved å skrive til DDR registeret (Data Direksjons Registreret) til den gjeldende porten.

En ting du bør ta hensyn til som ikke jeg gjorde, er å ikke drive IR LEDen direkte fra mikrokontrollerens utgang. En pinne på en mikrokontroller kan levere rundt 20mA, som er tilstrekkelig for en normal LED ved normal bruk. Men siden du skrur LED av og på med en viss frekvens så vil LED faktisk se en gjennomsnittsspenning avhengig av hvor lenge en periodetid er høy. Du kan dermed øke spenningen og strømmen slik at LEDen lyser kraftigere for hver høye puls på bærefrekvensen. Du må nå ta hensyn til LEDens maksimale peak current, i stedet for continuous current. LED bør derfor styres fra samme utgangsport, men via en transistor og en strømbegrensende motstand i passende størrelse.

http://sandakerpalm.no/blog/wp-content/uploads/2010/12/fjernkontroll.jpg
Diodene er satt feil vei i koblingsskjemaet! De er for å forhindre at en bryter vil trekke alle fire pinnene på PORTB til jord.

Dette er koden som ligger på mikrokontrolleren


Kode

#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 8000000UL
#include <util/delay.h>

int main(void)
{
	//timer 2
	TCCR2 |= (1<<WGM21) | (1<<COM20) | (1<<CS20);
	OCR2 = 48;	

	DDRC = 0x00;
	PORTC= 0xF; //Pullup
	PORTD=0xFF;

	//INT0
	MCUCR |= /*(1<<ISC00)*/ (1<<ISC01);
	GICR |= (1<<INT0);

	sei();

	while(1)
	{
	}
	
	return 0;
}

//Dette er interruptrutinen som utføres hver gang en bryter trykkes
//Datasignalet vises som kommentar over hver if-setning
ISR(INT0_vect)
{
	// -__----
	if ((PINC & (1<<PIN0)) == 0)
	{
		DDRB |= (1<<PIN3);
		_delay_us(2000);
		DDRB &= ~(1<<PIN3);
		
	}

	// -_-_--
	if ((PINC & (1<<PIN1)) == 0)
	{
		DDRB |= (1<<PIN3);
		_delay_us(1000);
		DDRB &= ~(1<<PIN3);
		_delay_us(1000);
		DDRB |= (1<<PIN3);
		_delay_us(1000);
		DDRB &= ~(1<<PIN3);
	}

	// -___--
	if ((PINC & (1<<PIN2)) == 0)
	{
		DDRB |= (1<<PIN3);
		_delay_us(3000);
		DDRB &= ~(1<<PIN3);
	}

	// -_--_-
	if ((PINC & (1<<PIN3)) == 0)
	{
		DDRB |= (1<<PIN3);
		_delay_us(1000);
		DDRB &= ~(1<<PIN3);
		_delay_us(2000);
		DDRB |= (1<<PIN3);
		_delay_us(1000);
		DDRB &= ~(1<<PIN3);
	}
}
Her er en video som demonstrerer bruken av fjernkontrollen. De fire nederste bitene på STK500 brettet forteller hvilken datapakke den mottok, nr 1, 2, 3 eller 4. Se på oscilloskopet for en eksakt måling av utgangssignalet på Vut pinnen på mottakeren! Denne kretsen som mottar signalene vil jeg ta for meg ved en senere anledning
http://www.youtube.com/v/BlZQTbCztkY?fs=1&amp;hl=nb_NO
Sist endret av wanna-b; 21. desember 2010 kl. 13:55.