Volt már olyan, hogy egy csomó kontroll alatti panelen szerettetek volna MouseEnter / leave / hoover stb eventet használni? Ugye a panelen levő kontrollokra húzva ezek az evenetek megszakadnak/ellövődnek.
Ha olyan szerencsés helyzetben vagy, mint én, hogy a kontrollok csak kijeleznek, akkor megtehetnéd, hogy egy átlátszó panelt teszel legfelülre! De persze nincs átlátszó panel :D
De szerencsére találtam megoldást, hogy hogyan tegyem átlátszóvá!
http://bytes.com/topic/c-sharp/answers/234245-transparent-panel
Tényleg jó, működik.
Ha szerinted valami nem fedi a valóságot, kérlek írd meg, hogy javítani tudjam. Ha kérdésed van, fordulj hozzám bizalommal!
2012. március 7., szerda
C# átlátszó panel
2010. február 22., hétfő
Advanetch CAN - Implementálás II rész
Több tapasztalat is összegyűlt :)
Az első nem is advantech, se nem implementálás jellegű, de megszívlelendő: mindig tartsd be az előírásokat. Ez úgy jött, hogy miután a kártya 1-es portja simán elbeszélgetett a 2-essel, a beckhoff CANopen fejegységgel sehogy sem akart. Ez a fejegység auto baud rate-s és ahogy elindult az üzi, kiállt hibára. Addig addig vakargattam a fejem, amig a leírásában megtaláltam, hogy ez bizony busz jellegű hiba. Keressünk szakadást, rövidzárt, ellenőrrizzük a lezáró ellenállásokat. Na, ekkor elhatároztam magam és ráforraszottam őket. Rögtön ment minden, mint a doxa óra.
Az implementálás maga jó hosszan és nehezen kezdődött. Először is meggyűlt a bajom a port írás/olvasásával. Ha asszinkron módon nyitunk meg egy fájlt/perifériát (CreateFile), akkor az írás-olvasás függvények (ReadFile, WriteFile) mindig várnak egy OVERLAPPED paramétert, amit általában előre nullázni kell. Ha ezt nem kapják meg, mindenféle hibaüziket küldenek, amikből csak az nem derül ki, hogy ez hiányzik nekik :). Az advantech függvény könyvtárakban az acCanOpen() függvény foglalja magába a port helyes megnyitását (CreateFile hívását a megfelelő paraméterekkel).
[code]Az acCanWrite és acCanRead függvények az írás-olvasást teszik meg. Általáabn az advantechtől kapott header (.h) fájlban levő függvények és deklarációk érthetőek. Ez alól talán az üzenet szerkezet volt a kivétel.
[..] //Deklarációs résznél
OVERLAPPED ov;
HANDLE hDevice;
[..]
hDevice= acCanOpen("can2", 1); // Az 1 azt jelenti, hogy asszinkron módon
ZeroMemory( &ov, sizeof(OVERLAPPED) );
ov.hEvent = CreateEvent( NULL,FALSE, FALSE, NULL );
ret=acCanWrite(hDevice, &pbyData, 1, &write_time, &ov);
ulErr= GetLastError();
if(ret!=0) printf("Writing can failed %d, %lu, wt %u\n",ret, ulErr, write_time);
[/code]
typedef struct {Míg sima can esetében ez nem igazán volt probléma, elsőre nem tudtam, hogy a CANopen COB+ID-jét hova tenni. Rövid próbálkozások után (miután már működött a rendszer, és a lezáró ellenállások is a helyükön voltak;)) lokalizálódott: a COB+ID-et egyértelműen az ID mezőbe kell tenni. A többi tényleg egyértelmű és a commanetezés jól magyaráz. Megy minden, mint a karika csapás :).
int flags; /* Flags, indicating or controlling special message properties */
int cob; /* CAN object number, used in Full CAN */
ULONG id; /* CAN message ID, 4 bytes */
short int length; /* Number of bytes in the CAN message */
UCHAR data[DATALENGTH]; /* Data, 0...8 bytes */
} canmsg_t;
A SetBaud és hasonló beállításokat a kártyán levő chip reset módba lökése után lehetett elvégezni, így legyen itt egy minta erre:
[CODE]Advantech C + LabView
int SetBaud(HANDLE ref, int nBaud)
{
int flag;
flag = acEnterResetMode(ref);
flag |= acSetBaud(ref, nBaud);
flag |= acEnterWorkMode(ref);
return flag;
}
[/CODE]
A labviewes wrapper fileoknál sem volt igazi probléma. Elsődlegesen a HANDLE típus passzolása nem akart rögtön menni, így ha nem is biztos, hogy gyönyörű, de jól működö megoldás az volt, hogy a LabView híváskor átadott egy int32 mutatót (32bites OS), a függvényem elkészítette a handlert és átadtad intnek castolva:
[CODE]A többi függvény értékként kapja meg a referenciát és a C fv. deklarációjában HANDLE-ként várjuk.
int CreateCanRef(unsigned int *ref, char *portName)
{
HANDLE r;
if (!ref) return -2;
r= acCanOpen(portName, 1);
if( r== INVALID_HANDLE_VALUE )
return -1;
*ref=(unsigned int)r;
return 0; // Lehetne a visszaadott érték is, akkor ez lenne itt: (unsigned int)r;
}
[/CODE]
A különböző struktúrák átadásába nem mentem most bele, nem is azért, mert sok rossz tapasztalatom van, de inább azért, mert itt nem tűnt szükségesnek.
Nagy negatívum viszont, hogy a wrapperek használatával valamiért nagyon lassú a labview, és szinte azonnal el kezd laggolni. Gondolom memória kezelés, vagy hasonló miatt. Ezért át kell dolgoznom az egészet valahogy úgy, hogy a busz olvasás egy külön C-s thread intézi a busz forgalmat, de legalábbis az olvasást, és a labviewnek egy struct mutatót adok, amit pl íráskor felfűzök egy láncolt listára és az olvasó thread fogadott üzenetkor onnan kikeresi.
2010. február 1., hétfő
Labview Load VI
Ha Labview standalone (EXE-be fordított) programba be akarunk hívni egy VI-t problémánk akadhat. Az LU azt jelzi, hogy a VI nem futtatható (Error 1003 occurred at Open VI Reference - The VI is not executable). De ezt el lehet kerülni!
Kétféle megoldás van:
- A kívánt VI-ket fordítás előtt hozzá kell adni a projekthez. De ennek az a hátránya, hogy újra kell fordítani az egész programot.
- Az igazi megoldás viszont az, hogy a később behívni kívánt VI-ket llb-be rakjuk, majd onnan "Save As"-zel kimentjük. A kimentett fájlokat a standalone exe be fogja tudni hívni fejlesztő környezet nélküli számítógépen is!
2009. október 18., vasárnap
RS-232-n programozható termosztát
Egy régebbi projektem végére raktam ma pontot. Ennek örömére, gondoltam, mostmár fel is teszem ide a javított verziót.
Ez a termosztát már a V2 kialakítás. Az elsőnek az lett volna a feladata, hogy egy kenyérpirító hőmérsékletét szabályozza (ezért is van betervezve a KTY84/130 hőmérő ellenállás), de az a projekt átmenetileg befagyott.
A második körben a marató folyadék hőmérsékletének a szabályozására készült el. Ezt osztom meg itt. A szoftver még nem tart sehol, valójában többre mentem volna vele, ha ráteszek egy potit.... A soros interface is még az előző alkalmazásból maradt meg. A kezdeteknél jó volt, mert a segítségével lehet kalibrálni a hőelemet.A feladat méretéhez mérten nem akartam transzformátort tenni a panelre (és a V1-nél TRIAC került az áramkörbe, ott érzékelni kellett a hálózati feszültség 0 átmenetét). A transzformátor nélküli tápegység ötletét még a Microchip egyik adatlapján találtam. Csúcs ez az öltet de kéretik óvatosan bánni vele, hiszen a nyákon ezután mindenfelé 230V szaladgál! Akkoriban tettem próbát a rezisztív kialakításra is, de az önmagát a nyákból kiolvasztó munkaellenállás meggyőzött róla, hogy a kapacitív megközelítés, bár jobban terheli a hálózatot, mégiscsak kényelmesebb :D.
A hőmérsékelt mérést a KTY84/130 végzi. A KTY szobahőmérsékleten kb 0.6KOhm és 100°C-n kb 1kOhm. Szerintem nagyon jó kis cucc, alacsony áron hihetetlen hőmérséklet átfogással.
A hőmérséklet mérés tehát ellenállás változáson alapszik. Ebből rögtön jön, hogy az ellenállást konstans árammal kell meghajtani és akkor a mi kis PICünk simán méri a feszültséget rajta. A konstans áramot egy LM317 állítja nekünk elő. Az adatlapban is megtalálható áramkör kimeneti áramát az Iki = Vref / R adja, ahol Vref = 1,25V. Így a 2K2-es ellenállásunkkal 0,5mA-t engedünk át a mérőellenálláson. Így akár 300°C-ig is mérhetnénk vele :).
A táp méretezése:
A táp kimenti áramát a bemeneti impedanciájával tudjuk kiszámolni a jó öreg I=U/R képlettel.
A kondenzátor impedanciája:Ezen esik az egy utasan egyenirányított hálózati feszültség:
, ahol Vz a Zener dióda nyitó feszültsége, Vcsucs a hálózate feszültség csúcs értéke, ami a négyzetes közép értéknek (itthon 230V) a gyök kétszerese.
Ezekből a táp bemenő árama (ami egy picivel nagyobb, mint a kivehető max):Az áramkörnek kb 110-120mA-ra van szüksége a tekercs nagy áramával együtt. Ehhez C1-nek 3uF-nek kell lennie, ami igen ritka méret az ilyen kondiknál... Amikor a legutóbb nem kaptam 3uF-et a boltban, szigetelő szalaggal oldottam meg a problémát. Úgy értem, hogy hozzáragasztottam még 2-t :) Mondjuk a 3.3uF kondi akkora, hogy úgysem fér el :), ezért lengőben kell bekötni.
Az ilyen tápegység méretezésekor fontos figyelembe venni az alkatrészek szórását és a worst case-ra méretezni. Tehát, ha van egy 3.3uF 20%-os kondink, akkor a legrosszabb esetben csak 2.64uF!
Így a projektből tisztán látszódik, hogy ezek a trafó nélküli megoldások nem az ilyen esetekre vannak, hanem olyanra, amikor pár 10nF kapacitás elég a bemenetre. Ugyanis a 3.3uF kondenzátor simán akkora, vagy nagyobb helyet foglal, mint a nyákra ültethető transzformátorok és árban is hasonlók.
Soros kommunikáció:
Igen, azt eddig kihagytam, hogy csak az IC TX/RX pinjei vannak kivezetve. Ez nekem azért jó, mert csináltam egy kis önálló nyákot a híres neves MAX232-vel és a 4 1uF kondival, + két kábel, egyik D-Sub9 a másik meg a 3 pines hüvely. Így azt tudom használni a tesztelésekkor, tervezés alatt és az ilyen esetekben, amikor egy nyák nem igényel üzemszerűen soros kapcsolatot. Ezt a kis nyákot is fel fogom valamikor tenni.
A firmware:
A firmware nem nagyon tart még sehol, mert a marató folyadék hőfokszabályozáshoz nem kellett itthonra túl bonyolítani. Később beleírom, hogy legalább sorosról fogadja az új értéket. Úgyhogy érdemes lesz majd figyelni!
A jövö: az áramkörnek van jövője. Először is át fogom alakítani úgy, hogy egy kisebb, olcsóbb PIC elvigye az egészet, hiszen termosztát lévén nincs nagy szükség RS232 kommunikációra. Tehát rá kerül a nyákra egy poti is. Csinálok belőle kis trafós megoldást is.
A többi meg már csak a mese, beszéljenek inkább a fájlok :D
Letölthető fájlok:
És akkor mégegyszer:
FELELŐSSÉG KIZÁRÁS / DISCLAIMER
VIGYÁZZ! A nyák 230V-os betápot használ! Ne kösd ész nélkül rá a programozót és MINDIG SÜSD KI A KONDIKAT!
A balesetekért, károkért semmilyen felelősséget nem vállalok és nem is vagyok felelősségre vonható!
Mindenki kizárólag a saját felelősségére építheti meg.
Ez a blogon megjelent összes projektre igaz!
2008. november 7., péntek
Ruby on Rails
Kezdeti próbálkozások a RoR-el. Persze, rögtön hibába futottam: hiányolta az sqlite3 libraryt. Ez először furcsa volt, hiszen fel volt telepítve, de szükség volt a ruby sqlite3 csatolóra. Ezt feltelepthetjük a ruby saját installerével (gem), de én inkább az portage-t használtam:
# emerge sqlite3-ruby
A RadRailssal való rövid ismerkedés után visszaváltottam a jól megszokott és kiváló JOE szerkesztőre. Hírtelen hátrányának éreztem, hogy nem ismerte a szintaxis kiemelője a RoR-t. De rövid google keresgélés után egy blogon találtam hozzá megfelelőt: itt. Ezúton is köszönöm!
Kis apróság a Rubihoz. Az ismerkedést az Agile Web Developmnet with Rails 3rd edition-nel kezdtem meg és az Ajax résznél hiányoltam valamit: megoldottuk, hogy az Add to Cart-ra kattintva szépen, AJAX módra frissüljön a kosár, de a form_remote_tag -et nem sikerült a képekre is alkamaznom. A megoldást a link_to_remote adta:
<%= link_to_remote (image_tag(product.image_url),
:url => {:action => :add_to_cart, :id => product} ) %>
Ez még bárkinek hasznos lehet akár :D.
2008. október 23., csütörtök
Omron PLC programozás
Van szerencsém, hogy az egyik új munkához Omron PLC-t kell használnom. Valójában nem örülök neki, kezd elég lenni a ismerd_meg_két_hét_allatt csinálj_kitűnő_programot és működjön_is felállású munkákból. És a PLC-k soha nem is voltak a szívem csücske. Viszont a program elvi változata már kész, muszáj implementálni, azt meg nehéz az új ismeretek nélkül.
Nnna, elég a nyafogásból. Hál istennek az Omron cég a fennállásának a 70%-át dokumentálással töltötte, ezt abból gondolom, hogy ritka az 1000 oldal alatti pdf-ük :), de 500 alá már tényleg csak a legritkább esetbe silányodnak.
Elég sok az új információ, ezért egy picit muszáj jegyzetelnem közülük, mert van, amit más másodszor olvasok át és a teljes újdonság hatásával él.
Szóval a Programming Manualból szemezgetek elsőként. Hagyjuk inkább a régen-tekercs, de ma-már-kártya jellegű program szerkezet megközelítést, ez röhej és szánalom és nem program struktúra.
Az interlock és a jump:
Erősen nem értem az Interlock koncepciót. Ennek az lenne a lényege, hogy kikapcsol programrészleteket. Egy nem túl bonyi kis programmal próbáltam megérteni a két megoldás lényegét: az interlock kikapcsolja a közbezárt programkódban definiált kimeneteket, ha azok aktívak, függetlenül az őket aktiváló parancs állapotától és ha megszűnik az interlock, akkor a parancsnak megfelelő állapotba térnek vissza. Emellett reseteli az időzítőket is. A Jump (JMP) parancs viszont, 100%-ban a nevének megfelelően működik: átugorja a közbezárt parancsokat (JME-hez ugrik), NOP-ot futtat helyettük. Ezáltal hangyányit gyorsabb lehet a program futása is. Így egyáltalán nem foglalkozik a közbezárt kimenetekkel, időzítőkkel stb...
Címzések
Na de mindegy is. Térjünk át inkább a címzés konvenciókra:
Bit szerinti címzésnél a WWWW . BB (W- word, B- bit) formáció a használatos, a WWWW nem csak szám lehet, hanem a PLC különböző memória területeinek valamelyike. Értelemszerűen wordre a .BB elhagyásával hivatkozhatunk.
Az '@' jel egy szám előtt azt jelzi, hogy Hexa értéket írtunk oda, míg a '*' használata BCD kódolású számot jelez.
Lehetőség van indirekt címzések használatára az IR tároló regiszter alkalmazásával, de ebbe nem mennék bele (és remélem nem is lesz most szükségem hasonlóra).
Konstansok beadása:
Ha egy szám elé '#'-et teszünk, a fordító előjel nélküli hexa számként fogja értelmezni, ha előjelet írunk elé, akkor előjeles decimális számnak, míg az '&' karakter előjel nélküli decimális számnak tünteti fel. BCD számot itt is a hexával megegyező módon jelölünk.
Vannak sztringek is, ezeknek a lezárása 00, vagy 0000-al történik.
Futtatási feltételek:
Számomra az első újdonság az a Differentiated jelző és jelentése volt. Egy differenciált művelet csak a bementi változó (felfele, jelölése '@') 0->1, vagy (lefele, jelölése '%') 1->0 változásakor egyszer fut le! Azért, ez még hasznos lehet. Ez lehet egy parancs előtt is, pl: @MOV, de lehet a kontaktusba építve is, amit a kontaktusba rajzolt fel/le nyíl.
2008. szeptember 22., hétfő
MPLAB C30 & Linker és a dsPic30F2020
A mai napnak igen nagy tapasztalata van: sose hidd el a fordítónak egyszerűen azt, hogy nincs watchdog fuse define-olva.
Tehát: a dsPic30F2020 include file-ja állítja az utolsó sorok környékén, hogy a watchdog a
_FWDT(WDT_OFF);
kódsorral kapcsolható ki. De ha ezt használod, a fordító sír, hogy nincs WDR_OFF definiálva. Kis keresgélés után megtalálod, hogy az FWDTEN_OFF valójában. Semmi gond, csak 2 napja optimalizálom a kódot, mert stack OV-tól tartottam a folyamatos, oknélküli resetek miatt. Mostmár beleférne egy F690-esb is :D
Még egy dolog: a disassembly listing. Ez egy annyira kényelmes és kellemes funkció, hogy akik a windows alatti MPLAB-ba integrált C30-at használják, nem is érzik át mennyire hiányzott linux alól. Annyira, hogy arra vetemendtem, hogy átnézzem a C30-as doksikat és a linker beállítások között megtaláljam a megoldást:
# wine /path/a/C30/bin/pic30-objdump.exe -S -d main.o > main.asm
A -S kapcsoló kapcsolja, hogy ne csak sima disassembly legyen, hanem a forráskódot is mixelje bele. Remélem segít másoknak is!
(UI ha nem működik a pic30-objdump.exe, akkor nekem a pic30-coff-objdump.exe-t kellet használni.)
2008. július 6., vasárnap
Neurális hálózatok II.
Küszöbszintes hálózatok: Perceptron és Adaline




A Perceptron tanulási folyamta:
Bemenő minták: X vector.
Kimenet: d(X), ami osztályozó feladat esetén általában +1 és -1.
Ilyen esetekben a perceptron tanulási szabálya egyszerű:
- Véletlenszerűen kiválasztott súlyokkal kezdjük.
- Az oktató csoportból kiveszünk egy X vektort.
- Ha y != d(X) akkor a súlyokat d wi= d(X) * xi értékkel megváltoztatjuk.
- Vissza a 2. pontba.
2008. június 16., hétfő
CCS és a #locate
A CCS PICC nagy előnyének látom azt, hogy bármely változót, így akár struct-ot is, egyben kirakhatunk egy PORT-ra, sőt, akár köthetjük is a porthoz. Így bármilyen bit változik a változóban, az megjelenik a Pic kimenetén. Ez struct-ok esetében kényelmes és nagyon jól olvasható kódot ad.
A legutóbbi esetben a kimeneti portnak csak egy részét szerettem volna a következő kód segítségével uralni.
#byte portc = GETENV("sfr:portc")
/*Ez teljességgel azonos a régebbi verziókban használt változattal, amit most is lehet használni
int portc;
#locate portc= GETENV("sfr:portc")
*/
Ehhez a megoldáshoz elengedhetetlen volt a byte maszkolások segítségével történő manipulálása. De bármit tettem, az előzőleg kirakott adatot mindig felülírta a következő. Legalábbis úgy tűnt és csak a sokadik próbálkozásra tűnt fel, hogy nem felülírta, hanem elveszett minden lépésnél az adat. Így már eljutottam oda, hogy a #locattel elhelyezett változókon keresztül valamiért nem lehet visszaolvasni a kimeneti port aktuális állapotát. A megoldáshoz jelenleg egy átmeneti változót vezettem be és a változásokat ennek segítségével helyezem át a portra.
Egyenlőre nem tudom, hogy ez a hiba miért jelentkezik így, de több ötletem is van rá:
- A PICC az olvasás hatására bemenetté konfigurálja a portot és így az nincs hajtva és az üres portot olvassa be.
- A PICC nem veszi figyelembe, hogy a 16F690-es sfr memóriaterülete bankokra van osztva a változón keresztüli olvasáskor és nem választja ki a megfelelő bankot.
2008. február 27., szerda
Projekt kezdés
Egy ellenőrző lista a projekt kezdésekhez:
- Van specifikációs dokumentum?
- Benne vannak a felhasználó által végzendő feladatok?
- Egyértelműek, tiszták a bejegyzések?
- Leírja-e tisztán a dokumentum a technikai igényeit a projektnek?
- Van benne ellentmondás?
- Minden specifikáció benne van?
- Tisztázva van-e benne a költségek és időigények?
- Implementálni lehet-e az összes specifikációt?
- Nem tartalmaz tervezési részleteket?
- Tesztelve lett-e az összes specifikált változó?
Kommunikáció a megrendelővel:
- Tudja-e, hogy miért van szükség a specifikációk implementálására?
- Definiálva vannak-e az adatkezelési és reprezentálási módszerek?
- Definiáltak-e a felhasználói kezelőfelület igények?
- Ki van-e választva céleszköz?
- Definiáltak-e a szoftver által végrehajtandó funkciók?
- Kezelőfelület kiderítése.
- Felhasználó és program interakciók kiderítése (hogy fogja a felhasználó használni).
2008. február 18., hétfő
LabView Projekt kezelés: Project Library
Egy új projektbe kezdtem, és tapasztalva az előző (monumentális) projekt hordozhatósági nehézségeit, úgy döntöttem, hogy az újat már ilyen szemléletben fogom készíteni.
Sok próbálgatás után a Project Library létrehozása adta a megfelelő eredményt. Ez a megoldás bár csak logikai kapcsolatokat eredményez (referenciákkal mutat a projektlib filejaira) mégis magával tudja vinni az Application Builder őket. Az elérési utak is használhatóak maradnak .exe-vé fordítás után.
A létrehozásáról csak ennyit: File-> New, itt válaszd ki a Library-t. Pakolj bele mindent ami kellhet, legyen akár vi, akár egyébb fájl (nekem pl .dll-ek miatt lett rá szükségem).
Eredmény: az App. Builderhez hozzáadva (always included) az egyéb fájlok a (defaultban) data könyvtárba kerülnek, maga a projektlib viszont bele az exébe, de megfelő útvonal feloldással könnyen és fixen visszaszerezhető. Fontos még, hogy a "Remove unused members of project libraries" ki legyen kattintva az "Additional Exclusions" fülön.