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: 28927, Oldal olvasási idő: kb. 4 perc
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.
Mindkét program egyben letölthető a cikk végén. LoggerA 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(;
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 ParserAz 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!
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!
Értékeléshez bejelentkezés szükséges! |
Bejelentkezés
Hirdetés |



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

