Fórum témák

» Több friss téma
Cikkek » Építsünk be utólag távirányítót!
Építsünk be utólag távirányítót!
Szerző: sargarigo, idő: Júl 31, 2012, Olvasva: 28104, Oldal olvasási idő: kb. 4 perc
Lapozás: OK   4 / 4

Miután meggyőződtem róla hogy az elmélet és a gyakorlat szerencsésen fedi egymást, írtam egy programot, ami a fentiek alapján dekódolja a vett infra adást, és soros porton kiírja a címet, és a parancskódot is.  A noteszembe kíváncsiságból felirkáltam a távirányítón található összes gomb kódjait, majd kiválasztottam azokat, amiket fel kívánok használni.

A deszkamodell

Mindkét program egyben letölthető a cikk végén.

Logger

A logger főprogram az alábbi:

 int main(void)
{
	PORTB	= 0x00;
	DDRB &= ~(1<<PB3);	// PB3(2) bemenet lett
	PORTB &= ~(1<<PB3);	// nem kell felhuzo ellenallas
	DDRB |= (1<<PB4);	// PB4(3) kimeneti led

	TCCR0A |= (1<<WGM01);	// ctc mode 
	OCR0A	= 255;		// ... csak szepen lassan..
	TIMSK0 |= 1<<OCIE0A;
	sei();
			
	_delay_ms(5000);
	PutString("nrnrnr");
	LED_OFF();

	for(;
	{
		wait_for_sync();	// varjuk a startbitet
		receive();		// vesszuk az adatot
		send_pattern();		// kiirjuk a terminalra
	}

	return 0;
}

Mint látható a főprogram nem lett elbonyolítva. Egy bemenet az infrának, egy-egy kimenet a LED-nek és a soros kommunikációnak. Beállítjuk a timert hogy ctc módban dolgozzon, ezáltal szép, szabályos időközönként veszi a mintákat. Megjegyzem, meg lehetett volna oldani timer nélkül is, de már ezért nem akartam újra átírni az egészet. A kódméretet illetően el kell mondanom, hogy egy nyomorult copyright szöveg sem fért már bele! Ezért itt mondom, hogy szabadon felhasználható, átírható terjeszthető, de kérlek legalább említésként a nevem szerepeljen ott valahol... creativecommons.org/licenses/by-nc-nd/2.5/hu/

A wait_for_sync addig várakozik, amíg a vonal nyugalmi állapotba nem kerül, majd megérkezik az első startbit. A GET_IR makró már tartalmazza a fentebb említett invertálást, tehát standard logikai jelként értelmezhető  a kimenete. A startbit detektálását követően már nem foglalkozunk a második startbittel, elhisszük neki hogy az is jön. Ennyi egyszerűsítés már igazán belefér.

void wait_for_sync(void )
{
	unsigned int counter;
start:
	counter = 0;
	LED_OFF();
	// Ha most magas, akkor varni kell, amig alacsony nem lesz
	while (GET_IR);
	// most mar biztosan alacsony

	// Most varni kell amig magasba nem megy, de kozben szamolunk
	while (!GET_IR)
	{
		if (counter < 0xffff) counter ++;	// nincs tulcsordulas
		_delay_ms(1);

	}
	// most mar magasban van
	if (counter < 500)	// ha meg nem eleg hosszu ideig volt alacsony
		goto start;	// akkor elolrol az egesz
	// Eleg sokaig volt alacsony, jelzest adunk
	if (counter >1100) LED_ON();
	_delay_ms(10);
	LED_OFF();
}

Miután biztosan megérkezett a startbit, következik a tényleges vétel.

void receive(void)
{
	LED_ON();		// Jelezzuk a startot
	TCNT0 = 0;		// Nullarol szamolunk
	received_word = 0;	// Ez lesz a vett adat
	TCCR0B |= (1<<CS01) | (1<<CS00);	// clk/16
	_delay_ms(300);
	TCCR0B &= ~(1<<CS01) & ~(1<<CS00);	// stop
	received_word >>= 1;	// egyel tulleptettuk, korrigalunk
}

Ez annyiból áll, hogy elindítja a timer-t, ami összeszedi az érkező biteket, majd leállítja azt, és egy korrekciót végez. Az ISR kóddal együtt lesz értelmes egész, így az itt következik.

ISR(TIM0_COMPA_vect)
{
		// Jelezzuk a mintavetel helyet
		PORTB ^= 1<<PB4;
		// majd eltaroljuk az aktualis erteket
		if (GET_IR)
		{
			received_word |= 1;
		}
		// leptetunk egy bitet es kesz is vagyunk egyenlore
		received_word <<= 1;
}

A LED-et átkapcsolja (ha ki volt kapcsolva akkor bekapcsolja, ha be volt akkor meg ki), amivel jelzi, hogy hol történik a mintavétel. Beolvassa a vonal aktuális állapotát, tárolja, majd végezetül ellépteti a tárolót, hogy jöhessen a következő bit. A receive eljárás határozza meg hogy mennyi ideig fusson a timer, tehát hogy hány bitet várjon.

Végezetül a sendpattern megjeleníti vett adatot a soros terminálon. Ezt az alábbi formában teszi (a cím, és a parancs is hexa szám):

11 0 10000 010000 RCV: 1A10 ADDR: 10 CMD:10

Parser

Az előbbi program már megvalósított szinte minden funkciót amire szükségem volt, mindössze át kellett egy kicsit faragni, hogy az alkalmazáshoz jó legyen. Kivettem belőle a soros port kezelését, és betettem helyette egy "szótárazó" kódot, ami egy táblázatból kikeresi a vett kódot, és ha megtalálja, akkor hozzárendel egy kimenetet. A főprogram teljesen ugyanaz mint az előbbi, csak az eljárások változtak meg.

char funcs[4] = { PB0, PB1, PB4, PB2};
char addrs[4] = {0x10, 0x10, 0x10, 0x10};
char cmds[4] = { 0x10, 0x11, 0x0f, 0x06};
//		{Vol+, Vol-, DSC (mode), DBB (input)}

Bevezettünk három új tömböt, ami majd a szótárazáshoz fog kelleni. Itt jegyzem meg, hogy ugyan csak négy gomb kezelésére van a program felkészítve, de tetszőleges számút lehet használni a fenti tömbök bővítésével!
A tömböket egymáshoz képest függőlegesen kell nézni. Tehát a PB0 kimenet van hozzárendelve a 0x10 című 0x10 parancshoz.

void parser(void)
{
	unsigned char addr = ((received_word & 0x07c0) >> 6);
	unsigned char cmd = (received_word & 0x003f);
	unsigned char repeat = ((received_word & 0x0800) >> 11);
	
//	if ((old_addr != addr) || (old_cmd != cmd) || (old_repeat != repeat))
        // Ha cim, parancs, vagy ismetles elter
	// Kikeressuk a hozza tartozo funkciot
	for (char i=0; i<4; i++)
	{
		if ((addrs[i] == addr) && (cmds[i] == cmd))
		{
		// Ha egyezik a kod, akkor aktivaljuk (alacsony szinten aktiv
			PORTB &= ~(1<< funcs[i]);	
			_delay_ms(1000);
		// majd kikapcsoljuk			
			PORTB |= (1<< funcs[i]);	
			
		}
			
	}	
	old_repeat = repeat;
	old_addr = addr;
	old_cmd = cmd;
}

Az eljárás motorja ugyanaz maradt, mint az előbb, szétdarabolja a bitsorozatot cím, és parancs részekre. Miután ezzel végzett, kikeresi a szótárból, hogy van-e ilyen tárolt cím:parancs kombináció. Ha van, akkor a hozzá tartozó kimenetet aktívvá teszi. Vár egy kicsit, majd visszatér a fő ciklusba. Ugyan itt nem használjuk ki, de a kódban benne van a gombismétlés tiltása. Erre szolgál az old_repeat (ami valójában a toggle-bit), az old_addr, és az old_cmd. Összehasonlítja az értéküket az előzővel, és ha egyezik, akkor eldobja. A funkció aktiválásához a megjegyzést vegyük ki a hetedik sor elől!

Ezzel a programmal már sikerült elérni, hogy a próbapanelon csak a kijelölt gombok megnyomásakor villant a hozzá tartozó LED. Mivel az erősítő előlapján lévő gombok felhúzott állapotban vannak, ezért fordított logikát kell a kimenethez alkalmazni. Alapból magas, gombnyomásra alacsony szintet vesz fel az adott kimenet, így az AVR közvetlenül le tudja húzni, vagyis megnyomja a gombot. Az IC-t a foglalatba rakva rögtön működőképes volt szépen lehet irányítani az Elta erősítőt a Philips távirányítóval. Kívülről pedig semmi sem látszik. Muris mi?

A működésről egy videó: youtu.be/IUEm-foVKB8

Itt tudod a programokat letölteni: 876/taviranyito.zip

Remélem hasznos volt a cikket végigolvasni!

És mindennek az eredménye!

Következő: »»   4 / 4
Értékeléshez bejelentkezés szükséges!
Bejelentkezés

Belépés

Hirdetés
XDT.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem