Jelenlét-érzékelés infravörös fény segítségével

Végre hosszú idő után előkerült a PICkit a fiókból. Az [intlink id=”559″ type=”post”]el%u0151z%u0151 PIC[/intlink]-es próbálkozásom után most egy kicsit bonyolultabb probléma megoldására vállalkoztam. Konkrétan arra, hogy a kütyü képes legyen érzékelni valakinek a jelenlétét. Erre a leggyakrabban alkalmazott módszer infravörös fényt vetít a vizsgált térrész felé, és méri a visszaverődött fény mennyiségét. Minél több fény verődik vissza, annál közelebb van a tárgy, amiről visszaverődött. Az elmélet egyszerű, és mint azt a továbbiakban olvashatjátok, a gyakorlat se sokkal bonyolultabb.

Az első probléma ami felmerült, az a jelentős háttérzaj kérdése. Az infravörös tartományban a nap és a legtöbb mesterséges fényforrás is sugároz, ráadásul sokkal erősebben, mint egy ilyen alkalmazásban szóba jöhető infra-led. A háttérzaj és az infra-led jelét szétválasztani csak úgy lehet, ha modulált jelet sugározunk a térbe, és ezt a modulált jelet keressük a mért értékekben is. Léteznek olyan infra-vevők, melyek hardveresen támogatják a modulált jel érzékelését (pl. TSOP), de hasonló alkatrészt tucatnyi boltot körbejárva sem találtam (ha tud valaki olyan boltot, ahol vásárolható ilyen, kérem írjon). Ilyen célezköz hiányában a modulációt szoftveresen oldottam meg.

A szoftveres moduláció miatt a hardver rendkívül egyszerű lett, a következő alkatrészekre volt szükségem:

  • Pic16F690
  • 1db infra led
  • 1db fotodióda
  • 1db npn tranzisztor
  • 4db 1kOhm ellenállás
  • 2db vörös led (egy a bekapcsolt állapotot jelzi – folyton világít, egy pedig a végeredményt adja meg, hogy érzékel-e jelenlétet az eszköz)

A munkát minimalizálandó felhasználtam a programozóhoz adott próbapanelt, amin beépített ledek állnak rendelkezésre, ezeket felhasználtam az állapotjelzések számára, így csak a fotódiódát és az infraledet kell hozzákötni, ami egy breadboard segítségével könnyedén kivitelezhető. Az infra-ledet a PIC rc0 kimenete fogja meghajtani, egy ellenállással bekötve ez a rész készen van. A kimenetet jelző led az rc1, a power-led az rc2-re van kötve hasonló módon. A fotódiódát a tranzisztorral erősítve kötjük a beépített A/D konverter bemenetére, hogy erősebb jelet kapjunk, ezzel megnövelve az érzékelés felbontását. A további félreértések rövidre zárásához felraktam egy kapcsolási rajzot:

pdetector.png

A szoftver ezzel a következő módon tud együttműködni: az alapötlet az, hogy kikapcsolt infra-leddel lemérjük a bejövő fény mennyiségét, majd bekapcsoljuk az infrát, és újra mérünk. A bekapcsolt illetve kikapcsolt infra-led melletti mérések különbsége adja meg az infra-led által leadott és visszavert fény mennyiségét. Ha ez a különbség több iteráció után is meghaladja a küszöbértéket, akkor a kimeneten jelezzük az érzékelt jelenlétet. Azaz két paraméter a küszöbérték (mekkora különbséget várunk el kikapcsolt és bekapcsolt infra-led melletti mérések között), és a kitartás (hány iteráción át kell tartani ezt a különbséget).

És íme, a kód. A dolog nehézségét jelzi, hogy a legtöbb időt két érték összehasonlítása vette el. A kódban szereplő makrót a Microchip MPasm leírásából vettem, én egy kétszer olyan hosszú megoldást csináltam elötte.


#include __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF &
_IESO_OFF & _FCMEN_OFF)

;presence detector code.
;assumed peripheres:
; infra-led on RC0
; photo-diode connected to AN0
; detected proximity output on RC1
; power led on RC2
;
;we measure input on photo diode, while infra-led is turned off.
;then we measure again with turned on infra-led.
;if the infra-ray is reflected from anything, the second measurement
;should return a higher value

;=================================================
;========VARIABLES================================
;=================================================

cblock 0x20
offmeasure ;stores measurement without infra led
onmeasure ;stores measurement with infra led
output ;output bits
waitcount ;wait count
surecount ;make sure that something is there and not moves
endc

OUT_ILED EQU H’0000′ ;bit for infra led
OUT_RES EQU H’0001′ ;bit for output
OUT_POWER EQU H’0002′ ;power led

THRESHOLD EQU H’0002′ ;threshold for measurment gain

SURENESS EQU H’000C’ ;number of measurements before we’re sure in the result

;===================================================
;==============macros for selecting banks
;====================================================
SELECT_BANK0 macro
bcf STATUS,RP0
bcf STATUS,RP1
endm

SELECT_BANK1 macro
bsf STATUS,RP0
bcf STATUS,RP1
endm

SELECT_BANK2 macro
bcf STATUS,RP0
bsf STATUS,RP1
endm

SELECT_BANK3 macro
bsf STATUS,RP0
bsf STATUS,RP1
endm

;==============================================
;=====MACRO TO WAIT=============================
;==============================================

WAIT macro us
local a = 0
while a < us
nop
a += 1
endw
endm

;============================================
;========EXECUTE A MEASUREMENT===============
;============================================

MEASURE macro
WAIT 5
bsf ADCON0,GO ; start conversion
btfsc ADCON0,GO ; this bit will change to zero when the conversion is complete
goto $-1

movf ADRESH,w

btfsc output,OUT_ILED
goto $+3
movwf onmeasure
goto $+2
movwf offmeasure
nop
endm

;========================================
;=======SWITCH output led================
;========================================

SWITCH_ILED macro
movlw 0x01
xorwf output,F
endm

;========================================
;========REFRESH OUTPUT==================
;========================================

REFRESH_OUTPUT macro
movfw output
movwf PORTC
endm

;======================================================
; compare file to constant and jump if file
; >= constant.
;======================================================
cfl_jge macro file, con, jump_to
movlw con & 0xff
subwf file, w
btfsc STATUS, C
goto jump_to
endm

;===============================================
;==============MAIN PROGRAM=====================
;===============================================
org 0
Init:
;set variables to zero
movlw 0x00
movwf output
movwf onmeasure
movwf offmeasure

;set powerled on
bsf output,OUT_POWER

;initialize devices
SELECT_BANK1
movlw 0xFF
movwf TRISA ; Make PortA all input
clrf TRISC ; Make PortC all output
movlw 0x10 ; A2D Clock Fosc/8
movwf ADCON1
SELECT_BANK2
movlw 0xFF ; we want all Port A pins Analoge
movwf ANSEL
SELECT_BANK0
movlw 0x01
movwf ADCON0 ; configure A2D for Channel 0 (RA0), Left justified, and turn on the A2D module

Loop:
MEASURE ;measure with light off
SWITCH_ILED ;turn light on
REFRESH_OUTPUT
call SubWait ;wait a bit

MEASURE ;measure with light on
SWITCH_ILED ;turn light off
call DecideOutput ;decide output
REFRESH_OUTPUT
call SubWait ;wait a bit
goto Loop

;==============================================
;=====Decide output============================
;==============================================
DecideOutput:
;onmeasure-offmeasure >= threshold
movfw offmeasure
subwf onmeasure,F
cfl_jge onmeasure,THRESHOLD,DecideYes
goto DecideNo
DecideYes:
;bsf output,OUT_RES
incf surecount,F
goto DecideOutputReturn
DecideNo:
clrf surecount
bcf output,OUT_RES
DecideOutputReturn:
cfl_jge surecount,SURENESS, SwitchOn
goto SwitchOff
SwitchOn:
bsf output, OUT_RES
return
SwitchOff:
bcf output, OUT_RES
return

;===========================================
;===========Subroutine for long wait========
;===========================================
SubWait:
movlw 0xFF
movwf waitcount
StartWait:
WAIT 100
decfsz waitcount,F
goto StartWait
return

;===============================================
;=====PROGRAM END===============================
;===============================================
end

A kütyüt felprogramoztam, a perifériákat megépítettem, és pár iteratív hibajavítás/paraméterfinomítás után eljutottam arra az állapotra, amit elégségesnek neveztem a koncepció működésének a bizonyítására.

dscf1957_small.jpeg

A fenti köntörfalas megfogalmazás nem költői önkifejezés, és nem is véletlen. Az eszköz működik, de épp hogy. A környezet által kifejtett fényerő fehérzajként adódik a rendszerhez, és csak magas “kitartás” és “küszöbérték” paraméter mellett lehet kiszűrni a téves jelzéseket. Ennek az az eredménye, hogy kb. két másodperc után jelzi ha 5cm-nél közelebb teszem a kezemet az infra-led+fotódióda pároshoz. 10cm-nél már bizonytalan a mérés, és akkor is előfordul egy-egy téves jelzés, ha nincs semmi a közelben.

Ezen problémák orvoslására több ötletem is van, egy részük azonnal megoldódna, ha találnék egy rendes infra adó-vevőt. Persze ötleteket, javaslatokat, hasonló problémákban szerzett tapasztalatokat szívesen fogadok.

http://ww1.microchip.com/downloads/en/DeviceDoc/33014g.pdf

Színbeállítások Eclipse-ben – javított megoldás

Ahogy tegnap is írtam, [intlink id=”623″ type=”post”]Eclipse-hez beállító ablakokat[/intlink] könnyen lehet készíteni. De ez még mindig bonyolultabb, mint az optimum, ha csak színeket (és esetleg betűtípusokat) akar az ember beállíthatóvá tenni.

Hogy miért is mondom ezt? Azért, mert így teljesen úgy beállításlapot kell csinálni, amikor az Eclipse már tartalmaz egy színbeállítással foglalkozó oldalt (General/Appearance/Colors and Fonts). És ha az ember jobban megnézi, akkor itt bizony jó néhány olyan beállítás is szerepel, ami semmilyen hivatalos Eclipse csomagban nincs benne, innen kezdve adódik a következtetés: kiterjeszthető. 🙂

És valóban: az [cci]org.eclipse.ui.themes[/cci] kiterjesztési pont az, amit mi keresünk. Ami lényeges előrelépés az általános beállításpanelhez képest, hogy itt a beállításokat mindössze a plugin.xml megfelelő kitöltésével megoldhatjuk, és ez rögtön legenerálja a megfelelő felhasználói felületet. Lustaság fél egészség.:D

De a lényeg az egészben, hogy ez oda kerül, ahol a többi hasonló beállítás van, ezért talán a felhasználó is könnyebben megtalálhatja (nem szabad elfelejteni, hogy az Eclipse környezetnek a célközönsége nem a mezei felhasználó, hanem annál hozzáértőbbek, legalább poweruser-ek, de egyelőre még inkább programozók, így megengedhető, hogy az összes beállítás így jelenjen meg).

A kiterjesztéshez definiálhatok különböző paramétereket: ami az én esetemben lényeges volt, az a [cci]themeElementCategory[/cci] és a [cci]colorDefinition[/cci] attribútumok: az előbbivel egy kategóriát definiálhatok, míg a másodikkal színeket (a betűtípusok definiálásához a [cci]fontDefinition[/cci] attribútumot lehet használni, hasonlóan a colorDefinitionhöz).

A színekhez meg lehet adni egy alapértelmezett színt (nem kódban, hanem az XML-ben), ezt a value elemhez érdemes tenni, egy színazonosítót (a későbbi hivatkozáshoz), valamint egy categoryId-t (itt lehet megadni a korábban definiált kategóriát). A plugin.xml grafikus szerkesztőjén teljesen magától értetődő a kezelés.

A kategóriának meg egy Id-t és egy feliratot kell megadni.

Ha ezeket az elemeket megadtuk, akkor már késznek is tekinthető a beállítási felület, és nincs más hátra, minthogy a kódból elérjük a színeket. Ez hasonló bonyolultsággal, de kicsit eltérő kóddal kezelhető, mint a beállítások esetén. Kicsit konkrétabban:
[cc_java]IThemeManager themeManager = PlatformUI.getWorkbench()
.getThemeManager();
ITheme theme = themeManager.getCurrentTheme();
ColorRegistry colorRegistry = theme.getColorRegistry();
ENTITY_BG = colorRegistry
.get(“org.eclipse.viatra2.visualisation.entity.background”);[/cc_java]

Betűtípus lekéréséhez pedig a getFontRegistry hívással kell a témától elkérni a betűtípus-tárat, és annak a get metódusával a betűtípusokat lehet megkapni. Az így megkapott Color, ill. Font objektumokat nem kell felszabadítani, ezt a rendszer elvégzi helyettünk.

Ennyi munkával már össze lehet rakni egy jól működő beállításablakot, ezt képekkel illusztrálva a következő oldalon is lehet látni (angol nyelven): http://blog.eclipse-tips.com/2008/08/adding-color-and-font-preferences.html. Így ennyit se nagyon kellett volna írni, de egy aprósággal ezt is kiegészítettem még: a kiterjesztés megengedi, hogy egy előnézetet hozzak létre az így elkészült beállítási ablakhoz. Hogy megmutassam, ezzel mire gondolok, megmutatom az elkészült panelt.

Az elkészült színbeállítóablak grafikus képe
Az elkészült színbeállítóablak grafikus képe

Röviden: összerakhatok egy tetszőleges SWT formot, ami megjeleníti a beállítások eredményét. Ehhez a kategória class nevű attribútumát kell beállítani egy általunk létrehozott osztályra. Az interfész két metódus megvalósítását követeli meg: egy [cci]createControl[/cci] és egy [cci]dispose[/cci] metódust. A megvalósítás magától értetődő(nek tűnik): a createControl mindig meghívódna, amikor a beállítások módosulnak.

De sajnos nem. Az csak egyszer hívódik meg. Ezért a [cci]createControl[/cci] futása során fel kell iratkoznunk a téma változásaira az [cci]addPropertyChangeListener[/cci] metódus segítségével, és amikor ott befut az eredmény, akkor frissíteni kell az előnézetet.

Az előnézetet tényleg tetszőleges módon meg lehet valósítani, én például simán hozzácsaptam egy Zest Graph Viewert, és azt paramétereztem fel némi “dummy” adattal, és az eredmény a fenti képen látható (és a gyakorlatban tényleg azonnal frissül 🙂 ).

Ez az kiterjesztés láthatóan arra van kihegyezve, hogy egységes módon lehessen színbeállításokat tenni, és ennek a legjobb módja, hogy ne adjuk ki a kódot a kiterjesztő kezébe, hanem csak lehetőséget adjunk a felparaméterezésre. Ugyanakkor ez kellően rugalmasan sikerült megoldani, és a dokumentáció alapján tényleg magától értetődő a kitöltés. De nem szabad elfelejteni, hogy ez nem egy teljes körű megoldás, például vonalvastagságot vagy vonaltípust itt beállítani nem lehet, noha grafikus pluginek témabeállításaihoz ez is hozzátartozik.

Eclipse Preference Page készítésről röviden

A héten egy „egyszerű” problémát kellett megoldanom: egy Eclipse-pluginhoz konfigurációs lehetőségként kellett lehetővé tennem színek kiválasztását. Elhangzott ötletnek, hogy csináljak akár Java properties fájlokat vagy valami hasonlót (értsd: kódold le kézzel), de ha már Eclipse házinak készül a dolog, inkább úgy döntöttem, nézzük meg, hogy az Eclipse mit kínál.

Egyik természetes megoldásnak tűnik egy saját Property page létrehozása, amin be lehet állítani a megfelelő színeket. Ehhez kiderült (némi keresgélés után, ez tényleg gyorsan megvan), hogy az org.eclipse.ui.PreferencePages kiterjesztési ponthoz kell kapcsolódni. És még további próbálkozás után kiderül, hogy érdemes legeneráltatni a mintát az Eclipse-ből, mert lényegesen okosabb kódot rak össze, mint ami az interfész naiv implementációjából kijönne. De erről egy kicsit később.

Az extension point igényli, hogy megadjuk, milyen névvel illetve milyen másik Page alá szeretnénk betenni az új lapunkat, ami lehetővé teszi a kényelmes hierarchikus beállításszervezés összeállítását. Nice.

Ami meglepően egyszerűvé teszi az oldal tervezését, hogy a JFace API tartalmaz beépített FieldEditor osztályokat, így a beállítások lap tervezéséhez egyszerűen annyira van szükség, hogy ezeket (esetleges SWT konténerekkel együtt) kidobálok egy API-tól kapott konténerre. Triviális. És ami még fontosabb, egy percig sem kell azzal szórakoznom, hogy mikor/hogyan mentsem ki az adatokat a háttértárra, hogyan olvassam ki a mezőkből, mert ezt automatikusan elvégzi a rendszer. Nekem csak minden egyes mezőhöz egy azonosítót kell rendelnem, és a többi már gyorsan megy. Ha valami speciális feltételek vannak a kitöltéshez, ahhoz pedig a legtöbb komponens validator hozzátételével működik – ezzel az egyszerű struktúrával a legtöbb gyakorlatban előforduló eset kezelhető (szerintem).

A FieldEditor osztályok nagyon könnyen kezelhetőek: van köztük színválasztó, fontválasztó, egyszerű szöveges beviteli mező, checkbox, könyvtárválasztó és még sok minden más, egyszóval a gyakorlatban előkerülő legtöbb igényt le lehet fedni velük. És ami igazán fontos: ezek a megfelelő natív dialógusokat hívják be (pl. OSX-en a natív színválasztót, nem valami Javaból összetákolt valamit…).

A generált mintakód igazából három fájlból áll: a PreferenceConstants.java fájlban konstansokat lehet felvenni, amellyel később azonosíthatjuk az elmentett adatokat, a PreferenceInitializer.java fájlban a kezdőértékeket, míg az általunk választott nevű harmadik fájlban lehet összerakni a tényleges adatokat. Ezeket a fájlokat tovább nem is elemezném, ha valakit jobban érdekel, nézze meg, ennyi ismerettel könnyen érthető és módosítható igény szerint. Vagy meg lehet nézni a http://www.eclipsepluginsite.com/preference-pages.html oldalon a részletesebb kifejtést.

Inkább csak azt írom le, hogy ebbe hogyan lehet betenni a színkezelést (amit nem ír le az eredeti forrás). A form összerakásakor egyszerűen ColorFieldEditor-t kell létrehozni, hasonló paraméterezéssel, mint a mintában, míg az inicializálásnál a következő módon lehet gondolkodni:
PreferenceConverter.setDefault(store, PreferenceConstants.P_ENTITY_BG_COLOR, new RGB(216,226,248));

Azaz egy RGB értéket példányosítok, és ezt töltöm be alapértelmezésként. Ettől a pillanattól kezdve van egy kész színbeállító komponensem, menti is az adatait. Zsír. Akkor már csak egyszerűen be kell tudni olvasni. Szerencsére ez sem túl bonyolult. Ha egyszerűen Stringként akarom beolvasni a beállítást, és a stringet átadni a Color konstruktornak, akkor a következő kód jöhet számításba:
IPreferenceStore store = RmpPlugin.getDefault()
.getPreferenceStore();
String colorCode = store.getString(PreferenceConstants.P_ENTITY_BG_COLOR);

De lehet egyszerűbben is: a JFace tartalmaz egy PreferenceConvertert, aminek segítségével ez még egyszerűbben elintézhető.
RGB color = PreferenceConverter.getColor(store, PreferenceConstants.P_ENTITY_BG_COLOR);

Röviden összefoglalva ez is egy kényelmesen használható API, jól illeszkedik az Eclipse filozófiájába, aminek az az előnye, hogy gyorsan megtanulható, ráadásul kellően rugalmas is. Az előre megírt FieldEditorok pedig tényleg egyszerűvé teszik az egységes (ráadásul ugyanakkor platformfüggő!) kinézet összerakását a beállítópanelen is.

Ugyanakkor a végleges megoldásom nem ezt a menetet követi, helyette egy másik beépített megoldást használtam, de arról majd inkább legközelebb írok egy kicsit.

Kiéltem természetfotós hajlamaimat

A hátsó kertben. Ahhoz képest jók lettek. Minden érdeklődő megtekintheti az újonnan készült [[http://flickr.com|Flickr]] fotógyűjteményemben: [[http://www.flickr.com/photos/gbalage/]]. A flickr gyűjtemény elkészítése azonban nehezebbnek bizonyult, mint a fotózás..

A hátsó kertben. Ahhoz képest jók lettek. Minden érdeklődő megtekintheti az újonnan készült [[http://flickr.com|Flickr]] fotógyűjteményemben: [[http://www.flickr.com/photos/gbalage/]]. A flickr gyűjtemény elkészítése azonban nehezebbnek bizonyult, mint a fotózás..

Alapvetően két [[http://en.wikipedia.org/wiki/Photo_sharing|képmegosztó]] szolgáltatást vizsgáltam meg: [[http://picasa.google.com|Picasa]] és [[http://flickr.com|Flickr]]. Ezek közül egyik se fogad el regisztráció helyett [[http://openid.net|OpenID]]-t, ami killer feature lett volna. A Picasa-t már próbáltam korábban, a kliens alkalmazásuk csak windows-ra van, a linuxos verzió egyszerűen egy [[http://www.winehq.org|Wine]]-osított változat. Ráadásul szerény véleményem szerint pocsék. Kvázi ömlesztve szembesít a 2004 óta készített, kb hatezer fotómmal és várja, hogy egyenként felcimkézzem őket. A Flickr, amellett, hogy csak havi feltöltési korlátot szabott meg, az általam használt [[http://www.digikam.org|digiKam]] program képes rá képeket exportálni. A gond ezzel csak annyi volt, hogy a Flickr használatához Yahoo ID kell.

Egyel több id/jelszó nem számít, rászántam magam a registrációra. Miután sikerült elfogadtatnom vele egy értelmes felhasználói nevet is (balage, gbalage, balageg, balagehun, hunbalage, stb.. és még egy pár próbálkozásom foglaltnak bizonyult) és minden szükséges adatot megadtam, szembesültem a minden regisztrációnál szokásos [[http://hu.wikipedia.org/wiki/Captcha|Captcha]] teszttel. Persze, alapesetben ez nem okoz gondot. Kivéve, ha a várt “zajos” betűk helyett egy fehér, üres részt találok:

[[http://cubussapiens.hu/node/620|]]

Csak átmeneti elmezavar, gondolnánk, ha újrapróbálkozáskor nem szembesülök ugyanazzal:

[[http://cubussapiens.hu/node/621|]]

Eltartott egy darabig, míg rájöttem, hogy az [[http://tinyurl.com/2b9sow|Adblock Plus]] vidáman kiszűrte a yahoo-s javascripteket. Kiváncsi volnék ki rakta bele az adatbázisban ezeket. Alapvetően a yahoo agyonscriptelt felhasználói felületeit ismerve nem ítélném el azonnal a tettét, de most kis gondot okozott. A probléma felfedezése után persze egyetlen kattintással fel lehet oldani a szűrést, és így minden probléma nélkül létrehozhattam a fotógyűjteményt. Tehát: [[http://www.flickr.com/photos/gbalage/|mindent]] a szemnek!

Technikai írásokról néhány pontban

Most olyan kedvem támadt (illetve olyan ingerek értek a közelmúltban), hogy úgy gondoltam, érdemes foglalkozni egy keveset írástechnikával is. Túlságosan nem értek a kérdéshez, éppen ezért, ha valaki úgy gondolja, valamivel nem ért egyet, esetleg kiegészítené az elhangzottakat, szépen megkérem, tegye meg!

Hihetetlen módon még a mi informatikusi életünkben is előfordul, hogy írnunk kell (méghozzá valamilyen emberi nyelven, nem számítógépnek). Sokszor kell bemutatni valaki másnak, hogy mit csináltunk, esetleg új fejlesztő jön a csapatban, és nem baj, ha nem kell sokáig mellette ülni, hogy felfogja, mivel dolgozik. Esetleg csak a főnökünknek/marketingeseknek/stb. kell elmondani, leírni, hogy mivel is foglalkozunk.

Most olyan kedvem támadt (illetve olyan ingerek értek a közelmúltban), hogy úgy gondoltam, érdemes foglalkozni egy keveset írástechnikával is. Túlságosan nem értek a kérdéshez, éppen ezért, ha valaki úgy gondolja, valamivel nem ért egyet, esetleg kiegészítené az elhangzottakat, szépen megkérem, tegye meg!

Hihetetlen módon még a mi informatikusi életünkben is előfordul, hogy írnunk kell (méghozzá valamilyen emberi nyelven, nem számítógépnek). Sokszor kell bemutatni valaki másnak, hogy mit csináltunk, esetleg új fejlesztő jön a csapatban, és nem baj, ha nem kell sokáig mellette ülni, hogy felfogja, mivel dolgozik. Esetleg csak a főnökünknek/marketingeseknek/stb. kell elmondani, leírni, hogy mivel is foglalkozunk.

És sokaknál ezen a ponton eljött az Armageddon. Elvégre a mi a fenének szórakozzunk mi menet közben a dokumentálással, hiszen a kód úgyis magától értetődő, tisztább, mint az emberi nyelvek (elvégre a fordítók elég igényes állatfajt alkotnak, csak azt érti meg, amit tökéletesen mondunk neki, és esetleg félre is érthetik).

De az emberek jelentős része egyáltalán nem érti a programkódot, és a maradék számottevő része is szívesebben látja egy mondatban összefoglalva, hogy mit csinál az a kód (ami lehet, hogy akár csak öt sor). Azaz egyéb formában is le kell tudni írni, mit csinálunk. Amit hatékonyan csak az tud megcsinálni, aki ismeri is a rendszert (pl. aki írta). És utólag összeszedni, hogy miért pont egy adott megvalósítás mellett döntöttünk, kicsit nehéz megállapítani.

Aki még mindig kételkedik benne, hogy ez valóban probléma, annak javaslom megtekinteni a következő képet [[http://www.linuxkungfu.org/images/fun/geek/project.jpg|a kommunikációs félreértésekről]] szoftverfejlesztés kapcsán.

További probléma (még tiszta programkód esetén is!), hogy az, aki megpróbálja megérteni a programot, annak csak egy kis részét láthatja egyszerre. Tegye fel a kezét, akinek sikerült mondjuk az Eclipse jobban megírt részeit ránézésre megérteni: többszálú alkalmazás (hogy debug módban nehezebb legyen végigléptetni), tervezési minták (aminek általában az egyik fele valahol az API belsejében van, neked meg a túloldali interfészt kell csak megvalósítani), és több-kevesebb elérhető dokumentáció (Javadoc többnyire van, de az egy efféle rendszerben édeskevés).

Az egyedüli dolog, ami segíthet, az egy jól felkommentezett mintapélda (ha lehetséges megfelelően kis méretben megoldani), vagy még inkább megfelelő részletezettségű programozói dokumentáció (ezen azt értem, hogy ne kelljen 500 oldal dokumentációt áttanulmányozni a egy nézet írásához, de azért kellően részletes ahhoz, hogy az ötleteket megértsem, és tudjam, mikor melyik osztályhoz kell fordulni).

Igen, ez nehéz. Nem kicsit, nagyon.

Röviden összeszedve, bizony előfordul, hogy emberi nyelven kell írni, hosszabb-rövidebb szöveget. És ezt lassan ideje megtanulni is. Elméletileg az általános és középiskolában a magyarórákon a fogalmazástanításnak ez lenne az egyik célja: megtanuljunk írni.

És itt és most lezárnám ezt az első szakaszt, és átváltanék egy másikra: szeretnék néhány trükköt leírni, amik segítenek egy jobb minőségű írott szöveget összehozni.

Alapötlet: ismételhetőség

A tanszéken azt az ökölszabályt szokták mondani laborjegyzőkönyvekre, hogy szükség esetén abból egy alapfogalmakkal tisztában levő ember reprodukálni tudja a laborfeladatokat. Ezt jó ökölszabálynak tartom majdnem minden (technikai jellegű) dokumentációhoz, leíráshoz. Nem technikai leírásnál meg talán az lehetne a lényeg, hogy az olvasót valamilyen gondolatmeneten végigvezesse az író (esetleg adott érzetet keltsen benne).

Persze egy kicsit általánosítani kell ehhez a szabályt: legyen benne minden lényeges elem a reprodukáláshoz/felhasználáshoz, lehetőség szerint megfelelően struktúrálva.

Másik alapötlet: döntsd el, kinek írsz!

Természetesen nem döntheted el, ki fog elolvasni, amit írtál, de azért van egy célközönség. A célközönségről feltehetsz bizonyos ismereti szintet, de nem érdemes ezt túl magasra tenni a lécet, mert akkor kevesen tudják átugrani.

Érdemes egy nem túl magas szintet választani, és ehhez következetesen tartani magad az írás során.

Szenteljünk egy fejezetet a terület bemutatásának!

Egy átmeneti terület a strukturálás és a közönség megismerése között egy területbemutató fejezet írása. Ez a fejezet felhasználható arra, hogy a különböző előismeretű olvasók számára biztosítsuk azt a tudásszintet, amire szükségünk van a saját eredményeink bemutatásához.

Még akkor is hasznos, ha feltehető, hogy minden olvasó ért a területhez, ugyanis nagyon gyakran nem egységes a terminológia, különböző megközelítések léteznek. Ebben a fejezetben erre is ki lehet térni, ki lehet választani a terminológiát, és lehet hivatkozni egyéb művekre, amik a megértést segítik.

Legyen az írásnak eleje és vége!

Az írást lehetőleg a kontextus megadásával kell kezdeni. Ide tartozik az, hogy mi a motiváció a munkára, milyen problémát oldunk meg, esetleg egyéb megoldások miért nem alkalmazhatóak. Egyetemi házi feladatok, laborjegyzőkönyvek esetén ez többnyire nehézkes, hiszen a kontextust maga a feladat adja, és gyakran nem látszik, hogy miért pont így, de már önálló laboratórium, diplomamunka vagy TDK dolgozat esetén ez nagyon lényeges pont. Nagyon nehéz feladat bevezetést írni, hiszen egyfelől nem arról beszélsz, hogy mivel foglalkozol, hanem arról, hogy miért ezzel – és amikor már az ember olyan fázisba jut, hogy ír róla, ez gyakran triviálisnak tűnik, holott egyáltalán nem az.

További nehézség ennél a pontnál, hogy a célközönség előképzettsége ismeretlen. Így nem szabad túlságosan technikai módon bevezetni, mert akkor nem fogják elolvasni (mondván, túl bonyolult), nem fognak figyelni rá (nem érdekes), de a másik oldalra sem szabad átesni: a semmimondó bullshitre egy hozzáértő esetleg kicsit érzékenyen reagál.

Szintén nehéz kérdés a befejezés. Itt jön a második pont, ahol meg lehet próbálni eladni, ami készült. Értékelni kell, hogy mit tud, ami elkészült, legalább szőr mentén emlegetni, hogy mi az, nem, mások eszközei mit tudnak, esetleg írni azokról az írásokról, amit alapötletnek használunk.

A fejezetek önállóak – de csak részben

Az előbb említett bevezetésen és befejezésen kívül lehet beszélni még a lényegről is: nem mindegy, hogy milyen struktúrában kerül sor az eredmények részletezésére. A szomszédos fejezetek között megengedhető, hogy nagyobb logikai ugrás legyen, hiszen ezek önmagukban is értelmes, zárt elemek.

Amire viszont érdemes figyelni, hogy milyen utalásokat teszünk a fejezetek között. Visszautalni szabad, sőt célszerű is, hiszen itt lehet egyrészt a fontos elemeket újra hangsúlyozni (elvégre a korábbi fejezeteket már olvasták), az ismétlés pedig a hangsúlyozás egyik fontos eszköze. Nyilván itt is csínján kell bánni a dologgal, hiszen ha túl sokszor utalunk vissza, azzal pont a hangsúly megy el…

Az előreutalás nehezebb eset: mivel ezt még feltehetőleg nem olvasták, ezért a teljes gondolatot össze kell foglalni a hivatkozáshoz, előrehivatkozni csak azt lehet, hogy ezzel ott foglalkozunk részletesebben. Elvégre ez nem az internet, ahol össze-vissza lehet hivatkozgatni.

Ábrák, képek

Az ábrák, képek nagyon fontosak lehetnek: noha alapvetően szöveges tartalomról beszélek, egy-egy jól megválasztott ábra a megértést nagyban könnyítheti. Nyugodtan használjunk akár színes ábrákat is, de ne felejtsük el, hogy esetleg az olvasó csak fekete-fehér képet fog látni; és hasznos, ha a munkában szereplő képek, ábrák nagyjából egységes formátumúak – ha nagyon különböző stílusú ábrákat használunk (és látszólag ok nélkül), az amatőr benyomást kelt.

Felsorolások, táblázatok

Ez nagyon hasonló az előző lépéshez: bizonyos adatok szemléletesebbek felsorolásként vagy táblázatként. Ez az egyik gyenge pontom nekem is, ha visszanézi valaki a korábbi írásaimat itt az oldalon, látható, hogy hajlamos vagyok rosszul strukturált szösszeneteket összeszedni, címsorok is ritkán, de felsorolások, táblázatok szinte sohasem. Pedig az ilyesmi segíti az olvasót, hogy akár ugorjon is a szövegben, ne sorról sorra kelljen neki végigolvasnia, hogy mit tartalmaz a szöveg.

A [[Modelltranszformációk statikus analízise – TDK dolgozat|TDK dolgozatom]] érthetőségén sokat segített (nem mellesleg a terjedelmet is megdobta egy kissé :D), amikor a háromoldalas egybefüggő szöveget széttördeltem felsorolások segítségével. Rögtön jobban olvashatóvá vált a szöveg (már nem tudok példát mondani, az írás utolsó egy hete egy kissé összemosódik :)).

Példák

Hasonlóan fontos kérdés a példák használata. A jó példa egyszerű, hogy ne azzal menjen az idő, hogy a példa kontextusát megértsük, hanem azzal, hogy felfogjuk, ez hogyan kapcsolódik a máshol elhangzottakhoz. Ugyanakkor határozottan nem árt az sem, ha a példák kontextusa az írás során nagyjából ugyanaz marad.

A TDK dolgozatomban például a modelltranszformációkat Petri-hálók segítségével mutattam be, és később Petri-hálós példa segítségével lehetett volna teljesítmény-tesztelést végezni (ez eddig elmaradt, de legalább van mit írnom a diplomamunkámba 🙂 ). Természetesen hasznos lehet egyéb példák alkalmazása (például a kényszerkielégítési probléma bemutatásánál viszonylag kevéssé használható megközelítés a Petri-hálók használata), de lehetőség szerint érdemes minél inkább egy kontextusra hagyatkozni.

Írjuk meg előre a tartalomjegyzéket!

Legalább nagyjából. Nem kell kőbe vésni, amit leírunk, de azért tartsuk magunkat hozzá. Miért is jó ez? Mert ekkor végiggondoljuk, hogy miről fogunk írni, és milyen sorrendben. Itt lehet figyelembe venni a “függőségeket”, hiszen van olyan fejezet, aminek a megértéséhez egy másik fejezet elolvasása szükséges – ekkor nyilván ezt előrébb kell venni.

A fejezet címe nélkül is legyen érthető a fejezet tartalma!

Nagyon tipikus hibának tekinthető, hogy ami a fejezetcímben leírtak, azt a szövegben nem írják le még egyszer. Pedig érdemes. A fejezetcím valahogy nem a szöveg része, ezért amikor rájövök, hogy esetleg azt is el kell olvasnom (mármint még egyszer), kizökkentenek a szokásos olvasási ciklusaimból.Ezt a problémát nyomtatott szövegnél egyelőre relatíve ritkán látom, annál többször blogokban vagy levelezőlistákon. Ott más tényezők miatt még fontosabb lenne e szabály betartása. Gyűlölöm, amikor e-maileknél megkérdezi valaki, hogy a “Subject”-ben megjelölt tantárggyal kapcsolatban tud-e valaki valami információval szolgálni. Ennél még eggyel rosszabb, ha ezt programozási makróként $subject-tel jelöli. De ez most nem tartozik az írásom fő témájához, ezért be is fejezem.

Bekezdések

A kisebb részek megírásánál is oda kell figyelni. Az egyes bekezdések nagyjából egy-egy gondolatnak felelnek meg, így elég szerencsétlen a helyzet, ha ezek között nem megfelelő a kötés. Arra utal, hogy az egész témakör nincs rendesen körüljárva, illetve nem állt össze valami egységes rendszerbe az író fejében. Határozottan nem árt, ha egy bekezdésnek szerves folytatása az utána következő.

A jól összekötött bekezdések emiatt megfelelő irányba terelhetik az olvasó gondolatait olvasás közben, hiszen egy logikai láncot tükrözhet. Az összekötések kiválasztásában segítségünkre lehet a (akár matematikai) logika: ellentmondhatunk a korábbi bekezdésnek, következtethetünk belőle, esetleg kiegészíthetjük, és még sok minden egyebet tehetünk. Ha nagyon új gondolat következik, amit nem lehet a korábbiakhoz kapcsolni, akkor kell új fejezetet/szakaszt kezdeni, vagy a gondolatot máshova helyezni.

Alkalmazkodj a médium és a közönség stílusához!

Itt is bejön, hogy ismerd meg a közönséged, és kiegészül azzal, hogy tudd, hogy az adott médiumon mit szabad és mit nem. Egy blog például egy relatíve kötetlen műfaj: ott a legtöbb szabályt nem szükséges betartani, és a stílus is teljesen szabadon választott: ami neked tetszik, azt lehet.

Ugyanakkor egy házi feladat, dokumentáció vagy diplomamunka esetén a forma és a stílus nagyon kötött: nem engedheted meg magadnak a laza stílust vagy a poénkodást, és ezt rossz néven is veszik.

Ne ragaszkodj feltétlenül a szabályokhoz!

Természetesen előfordulhat olyan eset, amikor valamely szervezési szabály nem alkalmazható. Például házi feladatok esetén többnyire értelmetlen egy hosszú fejezetben bemutatni a területet, hiszen az értékelő tudja – ugyanakkor hasznos lehet leírni az eredeti feladatot, és az esetleges nem egyértelmű részek választott értelemzését (ami többé-kevésbé megfeleltethető a kontextus megadásának). Rövid írások esetén nem feltétlen érdemes a tartalomjegyzéket előre megírni, mert ilyenkor a tartalomjegyzék is gyakran felesleges lehet.

Ilyen esetekben nyugodtan hagyjuk figyelmen kívül a vonatkozó szabályt – de tudatosan! Tudjuk, hogy melyik szabályt szegjük meg, valamint azt is, hogy miért!

Egyéb apróságok

A legtöbb esetben valamilyen szinten kötött a forma (pl. oldalméret, betűméret, terjedelem), de ha mégsem, akkor is ésszel kell meghatározni az írás kinézetét. A túl széles sorok nehezen olvashatóak, de például monitoron a több hasáb is… A legtöbb normának megvannak a maguk okai, csak ezeket sehol sem oktatják, hogy mit érdemes, ill. hogyan. Érdemes utánanézni.

És a végére hagytam az adu ászt: helyesírás. Semmi nem képes úgy elrontani egy írott szöveget, mint a helyesírás. Az elgépelések, vesszőhibák, esetleg a súlyosabb nyelvtani hibák egytől egyig rontják a munka színvonalát. És a helyesírásellenőrzőkben nem szabad megbízni (és erre nem vonatkozik a szabály figyelmen kívül hagyásának lehetősége 🙂 ). Annak érdekében, hogy ez megfelelő legyen, lehetőleg többször el kell olvasni a szöveget, és az sem baj, ha más is elolvassa beadás előtt. Természetesen így is benn maradhatnak hibák, de nem mindegy, hogy mennyi. Ajánlom mindenki figyelmébe [[http://tompika.symbion.hu/2007/01/19/helyesiras/|Tompika vonatkozó blogbejegyzését]], illetve egész hasznos ötleteket szedtek össze az [[http://hu.opensuse.org/Seg%C3%ADts%C3%A9g:Ford%C3%ADt%C3%A1s#Helyes.C3.ADr.C3.A1s|OpenSuse honosítási]] oldalán.

Remélem, ez a lista hasznos így összeszedve, de ha bárki bármivel ki tudja egészíteni, esetleg azt mondja, hogy nincs igazam, szívesen meghallgatom. Mindenesetre ez most belőlem kikívánkozott.