Prostorový LED displej ˇr´ızený Arduinem
Transkript
Gymnázium, Brno, třı́da Kapitána Jaroše 14 Prostorový LED displej řı́zený Arduinem Three-dimensional LED Display Controlled by Arduino Středoškolská odborná činnost Obor 10 – Elektrotechnika, elektronika a telekomunikace Vedoucı́ práce: Mgr. Marek Blaha Jiřı́ Papoušek Brno 2016 Jihomoravský kraj Děkuji Mgr. Tomáši Nečasovi a Mgr. Vojtěchovi Procházkovi za rady ohledně realizace elektronické části této práce. Dále bych rád poděkoval svým přátelům a spolužákům za věcné připomı́nky, zejména pak Aleši Kramlovi, Vlastimilu Blažkovi a Janu Šabackému. Prohlašuji, že jsem svou práci SOČ vypracoval samostatně a použil jsem pouze podklady (literaturu, projekty, SW atd.) uvedené v seznamu vloženém v práci SOČ. Prohlašuji, že tištěná verze a elektronická verze soutěžnı́ práce SOČ jsou shodné. Nemám závažný důvod proti zpřı́stupňovánı́ této práce v souladu se zákonem č. 121/2000 Sb., o právu autorském, o právech souvisejı́cı́ch s právem autorským a o změně některých zákonů (autorský zákon) v platném zněnı́. V Brně dne 15. února 2016 .................................................... 4 Abstrakt Tato práce popisuje konstrukci jednobarevného prostorového LED displeje o rozlišenı́ 8 × 8 × 8, tedy zařı́zenı́, které je schopné zobrazovat prostorové objekty v pohybu. Pro kontrolu displeje je použito Arduino spolu s pro tento účel vytvořeným rozšiřujı́cı́m obvodem. Práce také zahrnuje aplikaci pro tvorbu vstupu pro toto zařı́zenı́ vytvořenou v programovacı́m jazyku Python, přičemž jsou jejı́ funkce podrobně popsány v dokumentu. Klı́čová slova: 3D LED displej, Arduino, Python, sériová komunikace, posuvný registr Abstract This paper describes the construction of a monochromatic three-dimensional display with a 8 × 8 × 8 resolution, a device that is capable of displaying objects in motion. Arduino and expanding circuit, which is made for this purpose, are used to control the display. This paper also includes work on an application, created in the programming language Python, that allows a change of input. The functions of this application are described in the document. Keywords: 3D LED display, Arduino, Python, serial communication, shift register 5 OBSAH Obsah 1 Úvod a cı́l práce 1.1 Úvod do problematiky . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Cı́le práce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Elektronická část a jejı́ realizace 2.1 Použitı́ Arduina . . . . . . . . . 2.2 Počet výstupů . . . . . . . . . . 2.3 Posuvné registry . . . . . . . . 2.4 Rezistory . . . . . . . . . . . . 2.5 Tranzistory . . . . . . . . . . . 6 6 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 8 8 9 10 11 3 Použitý sofware 3.1 Rozvrženı́ uživatelského prostředı́ . . 3.2 Práce s daty v uživatelském prostředı́ 3.3 Ukládánı́ a otevı́ranı́ dat . . . . . . . 3.4 Náhled modelu . . . . . . . . . . . . 3.5 Řı́dı́cı́ software . . . . . . . . . . . . 3.6 Sériová komunikace . . . . . . . . . . 3.7 Vytvořenı́ spustitelného souboru . . . 3.8 Omezenı́ a požadavky . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 12 13 15 17 20 21 24 24 4 Závěr . . . . . . . . . . 25 1 ÚVOD A CÍL PRÁCE 1 1.1 6 Úvod a cı́l práce Úvod do problematiky Obrázek 1: Foto displeje (vlevo) a zobrazeného modelu (vpravo) [1] Prostorový displej je zařı́zenı́ plnı́cı́ hlavně estetickou funkci a dı́ky své konstrukci umožňuje jiné efekty a využitı́, než jiné typy uživatelských výstupů. Vzhledem k tomu, že se jedná o trojrozměrnou variantu klasického LED displeje, může se zdát, že bude plnit i podobnou funkci, pouze budou zobrazené modely obohaceny o prostorový prvek. Bohužel tomu tak nenı́ – mezi diodami v prostorovém displeji musı́ být volný prostor, aby byly vidět i svı́tivé diody za nimi. To pak představuje problém při zobrazovánı́ složitějšı́ch modelů, ve kterých je i vı́ce samostatných objektů zároveň, protože při zakrytı́ jednoho objektu druhým bude zakrytý objekt skrz tyto mezery svı́tit. A to je samozřejmě nežádoucı́. Proto by měl tento displej zobrazovat co možná nejjednoduššı́ modely. Aplikace, při kterých by tento nedostatek nevadil, jsou napřı́klad hra Snake, vizualizace hudebnı́ch souborů či prosté grafické efekty. Displej se sestává z pěti set dvanácti svı́tivých diod uspořádaných do tvaru krychle, což by při nejjednoduššı́m možném zapojenı́ znamenalo přı́liš velké množstvı́ výstupů. Přestože nenı́ tak obtı́žné rozšı́řit počet výstupů Arduina (a také to je nutné), je potřeba celý obvod zefektivnit, protože by zapojenı́ každé z diod zvlášt’ přinášelo komplikace. Mimo jiné by vývody těchto diod narušovaly praktickou použitelnost displeje, jelikož by se jednalo o přı́liš mnoho vodičů v prostoru, který by měl být transparentnı́. Nehledě na to, že by tyto vodiče musely být izolované, protože je v praxi nemožné zajistit, aby nějaké z vodičů v tomto prostoru nevytvořily nežádoucı́ spoj a nenarušovaly celý obvod. 1.2 Cı́le práce 7 Při řešenı́ tohoto problému jsem se z velké části inspiroval v návodu [1], který se snažı́m upravit tak, aby vyhovoval parametrům tohoto displeje, a vzı́t v úvahu použitı́ Arduina. 1.2 Cı́le práce Cı́lem je popsat konstrukci displeje, řı́dı́cı́ho obvodu a také nastı́nit postup při odlišných parametrech displeje. Na toto je pak navázáno vytvořenı́m uživatelsky přı́větivé aplikace jakožto nástroje, dı́ky němuž lze měnit výstup displeje. Tato aplikace také představuje ukázku jedné z možnostı́ využitı́ a má být v této práci podrobně popsána. 2 ELEKTRONICKÁ ČÁST A JEJÍ REALIZACE 2 2.1 8 Elektronická část a jejı́ realizace Použitı́ Arduina Arduino je open-source platforma, která je schopná ovládat jednoduchá elektronická zařı́zenı́ (např. motory, senzory nebo displeje). Na desce se mimo řı́dı́cı́ prvky nacházı́ USB konektor, napájecı́ konektor a piny, do kterých lze posı́lat napětı́ v rozmezı́ 0–5 V (digitalnı́ piny pouze 0 nebo 5 V, analogové pokrývajı́ celou škálu). Dále jsou zde různé specializované piny, které lze využı́vat napřı́klad k napájenı́ nebo k sériové komunikaci. Dı́ky použitı́ Arduina v této konstrukci je umožněno mnohem snadnějšı́ zapojenı́ dodatečných prvků k zařı́zenı́ (např. jednoduché ovládánı́). Také je snazšı́ pozměnit program a komunikovat s displejem skrz klasický počı́tač. To vše by samozřejmě bylo možné udělat i bez toho, ale bylo by to komplikovanějšı́ a řešenı́ takových problémů nenı́ účelem této práce. 2.2 Počet výstupů Jednı́m z největšı́ch úskalı́ při realizaci tohoto zařı́zenı́ je počet výstupů. Kdyby měla být každá ze svı́tivých diod v displeji zapojená zvlášt’, bylo by potřeba celkem pět set dvanáct výstupů, skrz displej by vedlo velké množstvı́ vodičů a bylo by problematické celou krychli ovládat a vytvořit v nı́ nějaký přehledný systém. Arduino MEGA použité při konstrukci displeje má celkem padesát čtyři výstupů, které sice lze navýšit za pomocı́ posuvných registrů (viz nı́že), přesto lze a je žádoucı́ práci s krychlı́ ještě zefektivnit. Dı́ky setrvačnosti lidského oka [2], tedy meznı́ frekvenci, při které splývajı́ dva po sobě následujı́cı́ obrazy v jeden, nemusı́ displej zobrazovat celý obraz, ale v daný okamžik může být zobrazována pouze dı́lčı́ část obrazu. Touto částı́ byla z praktických důvodů určena jedna vrstva krychle, tedy jedna dvourozměrná mřı́žka svı́tivých diod o rozlišenı́ 8 × 8. Obrázek 2: Uspořádánı́ anod (modře) a katod (červeně) svı́tivých diod v displeji [1] 2.3 Posuvné registry 9 Pokud je zajištěno, že v daný okamžik budou zobrazovány pouze body v právě jedné vrstvě krychle, je problém zjednodušený na 8 × 8 výstupů – je třeba ovládat jen jednotlivé sloupce. Ve finálnı́m návrhu jsou tedy spojeny anody svı́tivých diod ve sloupcı́ch a jejich katody ve vrstvách (obr. 2). Každá vrstva je pak připojena katodou na kolektor NPN tranzistoru a na bázi je připojen výstup, jehož účelem je kontrolovat průchod proudu tranzistorem na emitor a ovládat tak celou vrstvu. Dı́ky tomuto opatřenı́ je nakonec potřeba pouze šedesát čtyři výstupů na ovládánı́ sloupců a osm na ovládánı́ vrstev, celkem tedy sedmdesát dva na ovládánı́ celého displeje. 2.3 Posuvné registry Obrázek 3: Výsledné zapojenı́ posuvných registrů ovládajı́cı́ch sloupce displeje [1] (vytvořeno pomocı́ programu Fritzing) I přes zredukovánı́ nutných výstupů pro displej je třeba navýšit jejich počet, což je provedeno pomocı́ posuvných registrů 74HC595 [3]. Ty navyšujı́ tři výstupy 2.4 10 Rezistory (nepočı́tám-li zdroj napětı́) na osm, což je v přı́padě rozlišenı́ 8 × 8 × 8 ideálnı́ počet. Tak je totiž potřeba právě jeden posuvný registr na jeden řádek sloupců. Na ovládánı́ všech sloupců je tedy potřeba celkem osm posuvných registrů. Obrázek 4: Rozloženı́ pinů na 74HC595 [3] 74HC595 má šestnáct pinů a osm z nich může být využı́váno jako kontrolovatelné výstupy (Q0 – Q7). Dva piny sloužı́ k napájenı́ (VCC a GND) a dalšı́ dva je nutné k nim připojit pro správnou funkci registru (OE a MR). Pin data (DS) poskytuje informaci v bitech o tom, jaké z osmi výstupů registru majı́ napájet svı́tivé diody (např. signál 01110001 rozsvı́tı́ čtyři svı́tivé diody). Ve schématu je u prvnı́ho registru připojen k digitálnı́mu pinu 11 u Arduina. Pin clock (ST CP) poskytuje pravidelný přerušovaný signál, tedy interval, podle kterého se čtou informace z pinu data. Je připojen k digitálnı́mu pinu 12 u Arduina. Ve chvı́li, kdy je pin latch (SH CP) aktivnı́, je naráz přepsán signál na všech výstupech registru podle aktuálnı́ch dat. Tento pin je připojen k digitálnı́mu pinu 13 u Arduina. Posuvné registry lze navı́c řetězit za sebou pomocı́ pinu overflow, jehož výstupem jsou přebytečná data. Registry se chovajı́ jako zásobnı́ky, pin overflow tedy posı́lá vždy nejstaršı́ data, zatı́mco registr sám si uchovává informaci o poslednı́ch osmi přijatých bitech. Ve zdrojovém kódu jsou registry ovládány pomocı́ přı́kazu ShiftOut(), jehož funkce je blı́že popsána v sekci ”Řı́dı́cı́ program”v kapitole ”Použitý software”. 2.4 Rezistory Pro tento displej byly použity modré nerozptýlené svı́tivé diody. Hodnota úbytku napětı́ u takové diody bývá udávána mezi 3,3 a 3,5 V, přičemž doporučený proud je 2.5 Tranzistory 11 20 mA [4, 5]. Odpor použitých ochranných rezistorů by se tedy při zdrojovém napětı́ 5 V měl pohybovat mezi 75 a 85 Ω, přesto byly v reálu použity rezistory o odporu 1000 Ω. Svı́tivými diodami by tedy měl protékat proud 1,7–1,5 mA. Tato hodnota byla použita z několika důvodů: Pokud by svı́tivými diodami protékal proud 20 mA, maximálnı́ možný dodávaný proud by musel vı́ce než 1280 mA (proud odebı́raný v přı́padě, že jsou rozsvı́ceny všechny diody ve vrstvě1 ). Samotné Arduino MEGA je schopné dodávat nejvýše 500 mA, takže by by bylo nutné zapojenı́ externı́ho zdroje. Jelikož jsou svı́tivé diody nerozptýlené, je vhodné zeslabit jejich jas. Bez tohoto opatřenı́ se kvůli intenzivnı́mu směrovému světlu při rozsvı́cenı́ jedné svı́tivé diody zdá, že je rozsvı́cená i dioda nad nı́, což je nežádoucı́. Použité posuvné registry nejsou stavěné na vyššı́ dodávaný proud, než 70 mA [2]. Jelikož každý registr řı́dı́ osm svı́tivých diod, muselo by skrz registr při optimálnı́m proudu protékat 160 mA a registr by se zničil. 2.5 Tranzistory Obrázek 5: Schéma zapojenı́ tranzistorů k pinům Arduina [1] (vytvořeno pomocı́ programu Fritzing) Tranzistory musı́ na kolektoru pojmout od 0 do 320 mA. Ve výsledném obvodu byly pro řı́zenı́ vrstev vybrány tranzistory BC337-40 (typ NPN) s 15Ω rezistorem regulujı́cı́m proud protékajı́cı́ bázı́. 1 Nenı́ započı́tán proud nutný k napájenı́ tranzistoru ovládajı́cı́ho vrstvu. 3 POUŽITÝ SOFWARE 3 12 Použitý sofware Software se skládá ze dvou samostatně fungujı́cı́ch celků – desktopové aplikace sloužı́cı́ k tvorbě animacı́ a odesı́lánı́ zdrojových dat Arduinu a programu pro Arduino sloužı́cı́mu k přı́jmu zdrojových dat a jejich zpracovánı́ na výsledný signál. Desktopová aplikace je psána v programovacı́m jazyku Python ve verzi 2.7.6. Pro tvorbu uživatelského rozhranı́ byla použita knihovna Tkinter, pro dialogová okna při ukládánı́ a otevı́ránı́ souboru knihovna tkFileDialog. 3.1 Rozvrženı́ uživatelského prostředı́ Obrázek 6: Základnı́ uspořádánı́ widgetů v aplikaci [1] 3.2 Práce s daty v uživatelském prostředı́ 13 Knihovna Tkinter pro tvorbu uživatelského prostředı́ v programovacı́m jazyku Python umožňuje použitı́ dvou správců rozvrženı́ – rozvrženı́ pomocı́ metody grid(), nebo pomocı́ metody pack(). Jelikož je metoda pack() užitečnějšı́ spı́še pro programy s méně prvky a je použı́vána zejména tam, kde je potřeba velikost a umı́stěnı́ prvků přizpůsobovat např. změně velikosti okna, rozhodl jsem se pro použitı́ metody grid(). K orámovánı́ všech prvků aplikace a vytvořenı́ mezer mezi nimi jsem využil třı́dy Frame obsažené v knihovně Tkinter. Všechny prvky aplikace jsou pak zahrnuty do instance této třı́dy jménem app, jejı́mž rodičem je samotná aplikace (root). Potomci tohoto widgetu jsou pak nahledFrame, menuFrame, poleFrame a několik dalšı́ch instancı́ třı́dy Frame, které sloužı́ pouze jako rozdělovače mezi těmito hlavnı́mi widgety. Potomci menuFrame jsou pak volitkaFrame a tlacitkaFrame. Ve widgetu nahledFrame byl použit správce Pack kvůli použitı́ widgetů xbar a ybar v souvislosti s widgetem nahled. Jelikož většinou nelze mezerám mezi těmito hlavnı́mi widgety a uvnitř nich přiřadit nějaký smysluplný název, jsou všechny mezery prvky seznamu mezera. Celé prostředı́ aplikace by samozřejmě šlo navrhnout i bez tohoto postupného členěnı́ na menšı́ celky, takový postup by ale byl značně nepřehledný a přidánı́ nového prvku by tak bylo daleko obtı́žnějšı́. 3.2 Práce s daty v uživatelském prostředı́ Samotná data jsou reprezentována pětirozměrným seznamem data[cas][a][x][y] [z], kde proměnná cas vyjadřuje čı́slo modelu v animaci, proměnná a může nabývat hodnoty 0 nebo 1, přičemž při hodnotě 0 určuje přı́stup k souřadnicı́m a při hodnotě 1 obahuje pouze jeden prvek, a to časový interval, po který má model svı́tit. Proměnné x, y, z pak určujı́ souřadnice svı́tivé diody. Třı́da Pole() 1 class Pole () : 2 def __init__ ( self ,x ,y , z ) : 3 global cas 4 self . x = x 5 self . y = y 6 self . z = z 7 self . pole = Checkbutton ( poleFrame , indicatoron = 0 , image = cervenyctverec , width = 14 , height = 14 , command = self . klikNaPole , variable = data [ int ( cas . get () ) ][0][ self . x ][ self . y ][ self . z ]) 8 self . souradnicex = levokraj + self . z * int ( rozestup . get () ) +(7 - self . y ) * cos ( radians ( int ( uhel . get () ) ) ) * int ( rozestup . get () ) /2 9 self . souradnicey = spodokraj + x * int ( rozestupvrstva . get () ) -(7 - y ) * sin ( radians ( int ( uhel . get () ) ) ) * int ( rozestup . get () ) /2 10 self . prekryvajici = [] 11 3.2 Práce s daty v uživatelském prostředı́ 12 13 14 15 16 17 14 def klikNaPole ( self ) : if data [ int ( cas . get () ) ][0][ self . x ][ self . y ][ self . z ]. get () == True : self . pole . config ( image = zelenyctverec ) else : self . pole . config ( image = cervenyctverec ) nakresliKruh ( self .x , self .y , self . z ) Každá svı́tivá dioda v displeji je v aplikaci reprezentována jednou instancı́ třı́dy Pole, jejı́ž součástı́ je třı́da Checkbutton z knihovny Tkinter. Dále jsou to také informace, zdali má být dioda rozsvı́cena a na jakých souřadnicı́ch v náhledu (instance třı́dy Canvas z knihovny Tkinter) se má vykreslit kruh reprezentujı́cı́ danou svı́tivou diodu, přı́padně s jakými svı́tivými diodami se v náhledu překrývá. Významnou součástı́ třı́dy je pak funkce klikNaPole(), která vyhodnocuje kliknutı́ uživatele na Checkbutton včetně překreslenı́ přı́slušného kruhu v náhledu pomocı́ funkce nakresliKruh(). Instancı́ třı́dy Pole je v aplikaci celkem pět set dvanáct, což stačı́ pro reprezentaci jednoho modelu pro displej. Pomocı́ widgetu delaySpinbox lze nastavit, jak dlouho má být model zobrazený na displeji, než se přejde k dalšı́mu modelu v pořadı́. Funkce datareset() 1 def datareset () : 2 for x in range (8) : 3 for y in range (8) : 4 for z in range (8) : 5 pole [ x ][ y ][ z ]. pole . config ( variable = data [ int ( cas . get () ) ][0][ x ][ y ][ z ]) 6 pole [ x ][ y ][ z ]. klikNaPole () 7 delaySpinbox . config ( textvariable = data [ int ( cas . get () ) ][1]) Tato funkce je volána pokaždé, když uživatel změnı́ čı́slo modelu pomocı́ widgetu casSpinbox. Jsou změněny vlastnosti všech widgetů reprezentujı́cı́ LED diody a je změněna zobrazená časová prodleva widgetem delaySpinbox. Funkce createNewModel() 1 def createNewModel () : 2 global maxcas 3 global cas 4 maxcas = maxcas + 1 5 casSpinbox . config ( state = NORMAL ) 6 delObjectButton . config ( state = NORMAL ) 7 cas . set ( str ( maxcas ) ) 8 casSpinbox . config ( to = maxcas ) 9 data . append ([[[[ BooleanVar () for x in range (8) ] for x in range (8) ] for x in range (8) ] , StringVar () ]) 10 data [ int ( cas . get () ) ][1]. set ( " 1000 " ) 11 datareset () 3.3 Ukládánı́ a otevı́ranı́ dat 15 Funkce createModel() je volána po zmáčknutı́ tlačı́tka createNewModel. Sloužı́ k vytvořenı́ nového modelu, což se projevı́ přidánı́m nového prvku v poli data na řádku (9). Na řádcı́ch (5) a (6) je změněn atribut state u widgetů casSpinbox (pomocı́ kterého lze přepı́nat mezi modely) a delModelButton (tlačı́tka, které po kliknutı́ smaže zobrazený model). Zároveň se zvýšı́ hornı́ hranice čı́selného rozpětı́ widgetu casSpinBox na řádku (8). Také jsou atributy veškerých widgetů aplikace přenastaveny podle dat nově vytvořeného modelu, což je provedeno na řádcı́ch (7), (10) a (11). Funkce deleteModel() 1 def deleteModel () : 2 global maxcas 3 global data 4 data = data [: int ( cas . get () ) ]+ data [ int ( cas . get () ) +1:] 5 maxcas = maxcas - 1 6 if maxcas == 0: 7 casSpinbox . config ( state = DISABLED ) 8 delModelButton . config ( state = DISABLED ) 9 if int ( cas . get () ) != 0: 10 cas . set ( str ( int ( cas . get () ) -1) ) 11 casSpinbox . config ( to = maxcas ) 12 datareset () Funkce deleteModel je volána po zmáčknutı́ tlačı́tka delModelButton. Je podobná předchozı́ funkci a jejı́m účelem je smazánı́ zobrazeného modelu, což je provedeno řádkem (4). Všechny widgety a proměnné jsou poté nastaveny na data předchozı́ho modelu, za předpokladu, že nebyl smazán prvnı́ model. V takovém přı́padě jsou nastaveny na data modelu následujı́cı́ho. 3.3 Ukládánı́ a otevı́ranı́ dat K ukládánı́ dat do souboru sloužı́ tlačı́tko saveButton. K otevı́ránı́ je to pak openButton. Každé z nich po kliknutı́ volá přı́slušnou funkci. Funkce saveFile() 1 def saveFile () : 2 saveDialog = tkFileDialog . asksaveasfile ( mode = ’w ’ , defaultextension = " . txt " ) 3 text2save = " " 4 if saveDialog == None : 5 return 6 for i in range ( maxcas +1) : 7 for x in range (8) : 8 for y in range (8) : 9 for z in range (8) : 10 if data [ i ][0][ x ][ y ][ z ]. get () == False : 11 text2save = text2save + " 0 " 12 else : 3.3 13 14 15 16 Ukládánı́ a otevı́ranı́ dat 16 text2save = text2save + " 1 " text2save = text2save + str ( data [ i ][1]. get () ) + " / " saveDialog . write ( text2save ) saveDialog . close Tlačı́tko saveButton volá funkci saveFile(), která nejprve na řádku (2) pomocı́ dialogu z knihovny tkFileDialog otevře soubor daný uživatelem k zápisu. Poté na řádku (3) vytvořı́ proměnnou text2save, která má být naplněna daty v podobě textu. Následně na řádku (4) zjistı́, jestli byl uživatelem skutečně vybrán nějaký soubor, a v přı́padě, že soubor vybrán nebyl (tedy v přı́padě, že uživatel zavřel dialogové okno), řádek (5) ukončı́ program. Jinak na řádcı́ch (6) až (9) proběhne několikanásobný vnořený cyklus, který projde celý seznam data a uložı́ jeho hodnoty za sebou do proměnné text2save. Kromě toho také na řádku (9) zapı́še znak lomı́tka za časový rozestup, protože na rozdı́l od ostatnı́ch hodnot v seznamu data u časového rozestupu nevı́me, kolik znaků bude jeho hodnota zabı́rat, což je důležité při zpětném čtenı́ hodnot ze souboru. Jakmile tento cyklus skončı́, je na řádku (10) zapsána hodnota proměnné text2save do souboru a soubor je následně uzavřen. Funkce openFile() 1 def openFile () : 2 global maxcas 3 soubor = tkFileDialog . askopenfile ( mode = " r " , defaultextension = " . txt " ) 4 if soubor == None : 5 return 6 soubordata = soubor . read () 7 soubordata = soubordata . split ( " / " ) 8 del data [:] 9 for i in range ( len ( soubordata ) -1) : 10 data . append ([[[[ BooleanVar () for x in range (8) ] for x in range (8) ] for x in range (8) ] , StringVar () ]) 11 for x in range (8) : 12 for y in range (8) : 13 for z in range (8) : 14 data [ i ][0][ x ][ y ][ z ] = BooleanVar () 15 data [ i ][0][ x ][ y ][ z ]. set ( soubordata [ i ][ x *64+ y *8+ z ]) 16 data [ i ][1] = StringVar () 17 data [ i ][1]. set ( soubordata [ i ][512:]) 18 cas . set ( " 0 " ) 19 maxcas = len ( soubordata ) -2 20 if maxcas >0: 21 casSpinbox . config ( to = maxcas , state = NORMAL ) 22 else : 23 casSpinbox . config ( to = maxcas , state = DISABLED ) 24 datareset () 25 soubor . close () Tlačı́tko openButton volá funkci openFile(). Ta má za úkol zpětně zpracovat data z vybraného souboru a upravit proměnné a parametry widgetů v aplikaci tak, aby odpovı́daly původnı́mu nastavenı́ při uloženı́ otevı́raného souboru. 3.4 17 Náhled modelu Na řádku (3) je opět vybrán soubor pomocı́ dialogového okna z knihovny tkFileDialog, poté je na řádku (4) zkontrolováno, zda byl soubor vybrán a na řádku (6) je soubor otevřen. Řádek (7) nahraná data rozděluje a ukládá do seznamu soubordata s tı́m, že jako rozdělovnı́k je použit znak lomı́tka, a řádek (8) z původnı́ho seznamu data použitého v aplikaci vymaže veškeré prvky. Na řádcı́ch (8) až (17) je pak několikanásobný vnořený cyklus, který seznam data plnı́ novými prvky a do těchto prvků zapisuje hodnoty ze seznamu soubordata. Na řádku (18) je proměnná cas nastavena na hodnotu 0, aby byla aplikace nastavena podle dat prvnı́ho modelu v seznamu data. Řádek (19) nastavı́ hodnotu proměnné maxcas podle délky seznamu soubordata, ale od této délky se musı́ odečı́st 2. To je nutné kvůli tomu, že indexovánı́ seznamu data začı́ná od 0, a také kvůli tomu, že při rozdělovánı́ textu z otevı́raného souboru podle lomı́tka je poslednı́m prvkem seznamu prázdný prvek, protože text v souboru končı́ lomı́tkem. Hodnota této proměnné je pak dána jako parametr widgetu casSpinbox a parametr state je na řádku (21) nastaven na NORMAL (aby bylo ovládánı́ widgetu zpřı́stupněno uživateli), za předpokladu, že hodnota proměnné maxcas nenı́ 0, v tom přı́padě by byl widget na řádku (23) znepřı́stupněn (parametr state by byl nastaven na DISABLED). Nakonec je provedena funkce datareset(), aby byly nastaveny parametry všech widgetů v okně podle aktuálnı́ch dat, a také je zavřen soubor. 3.4 Náhled modelu Obrázek 7: Náhled modelu v aplikaci [1] 3.4 Náhled modelu 18 Při tvorbě modelu je vhodné mı́t přehled o rozloženı́ rozsvı́cených diod v displeji, proto je v aplikaci také náhled displeje pomocı́ widgetu Canvas z knihovny Tkinter. Jedná se o obyčejný grafický widget, ve kterém je pomocı́ souřadnicového systému dosaženo tvaru krychle. V této krychli jsou pak zobrazovány jednotlivé svı́tivé diody jako kruhy. Je možné měnit rozestup mezi kruhy ve vrstvě pomocı́ widgetu rozestupvrstvaSpinbox, rozestup mezi vrstvami pomocı́ widgetu rozestupSpinbox a úhel nadhledu pomocı́ uhelSpinbox. Funkce nakresliKruh(x,y,z) 1 def nakresliKruh (x ,y , z ) : 2 if data [ int ( cas . get () ) ][0][ x ][ y ][ z ]. get () == True : 3 nahled . create_oval ([ pole [ x ][ y ][ z ]. souradnicex , pole [ x ][ y ][ z ]. souradnicey , pole [ x ][ y ][ z ]. souradnicex + prumer , pole [ x ][ y ][ z ]. souradnicey + prumer ] , fill = " green " ) 4 else : 5 jeLEDrozsvicena = False 6 for i in pole [ x ][ y ][ z ]. prekryvajici : 7 if data [ int ( cas . get () ) ][0][ i [0]][ i [1]][ i [2]]. get () == True : 8 jeLEDrozsvicena = True 9 break 10 if jeLEDrozsvicena == False : 11 nahled . create_oval ([ pole [ x ][ y ][ z ]. souradnicex , pole [ x ][ y ][ z ]. souradnicey , pole [ x ][ y ][ z ]. souradnicex + prumer , pole [ x ][ y ][ z ]. souradnicey + prumer ] , fill = " red " ) Tato funkce je volána pokaždé, když proběhne nějaká změna v náhledu displeje. Parametry x, y a z udávajı́ souřadnice svı́tivé diody v displeji, jejı́ž kruh se má přebarvit v náhledu. Na řádku (2) je podmı́nka, která podle toho, jakou hodnotu má přı́slušný prvek v seznamu data, přebarvı́ kruh na zelenou (když je dioda rozsvı́cená), nebo na červenou (když je dioda zhasnutá). Pokud má být zhasnutá, zkontroluje všechny diody, které se s nı́ překrývajı́, pomocı́ cyklu na řádcı́ch (6) až (9). Pokud je mezi nimi nějaká rozsvı́cená, je hodnota proměnné jeLEDrozsvicena na řádku (8) nastavena na True. Poté řádek (9) cyklus přerušı́ a nenı́ provedeno přebarvenı́ kruhu na červenou na řádku (11), takže kruh zůstane zelený. Jinak se ale kruh bud’ na řádku (3), nebo na řádku (11) přebarvı́, tedy je vykreslen kruh pomocı́ přı́kazu create_oval. Funkce reset() 1 def reset () : 2 global rozestup , rozestupvrstva , uhel 3 nahled . delete ( " all " ) 4 for x in range (8) : 5 for y in range (8) : 6 for z in range (8) : 7 pole [ x ][ y ][ z ]. souradnicex = levokraj + z * int ( rozestup . get () ) +(7 - y ) * cos ( radians ( uhel ) ) * int ( rozestup . get () ) /2 3.4 Náhled modelu 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 19 pole [ x ][ y ][ z ]. souradnicey = spodokraj + x * int ( rozestupvrstva . get () ) -(7 - y ) * sin ( radians ( uhel ) ) * int ( rozestup . get () ) /2 for x in range (8) : for y in range (8) : for z in range (8) : pole [ x ][ y ][ z ]. prekryvajici =[] for a in range (8) : for b in range (8) : for c in range (8) : if ( pole [ x ][ y ][ z ]. souradnicex == pole [ a ][ b ][ c ]. souradnicex ) and ( pole [ x ][ y ][ z ]. souradnicey == pole [ a ][ b ][ c ]. souradnicey ) and (( a ,b , c ) !=( x ,y ,z)): pole [ x ][ y ][ z ]. prekryvajici . append (( a ,b , c ) ) for x in range (8) : for y in range (8) : for z in range (8) : nakresliKruh (x ,y , z ) Účelem funkce reset() je přenastavit parametry souřadnic každé instance třı́dy Pole() v trojrozměrném seznamu pole na základě proměnných uhel, rozestup a rozestupvrstva, a poté podle těchto nových parametrů překreslit náhled. Proměnná uhel určuje úhel, pod kterým má být zobrazována krychle (ten je standartně nastaven na 45°). Proměnná rozestup udává velikost mezery ve vrstvě mezi jednotlivými kruhy v náhledu. Proměnná rozestupvrstva pak určuje mezeru mezi vrstvami. Na řádku (3) je model vymazán z náhledu. Na řádcı́ch (4) až (8) je pak vnořený cyklus, který na řádcı́ch (7) a (8) měnı́ souřadnice na osách x a y v náhledu podle daných vzorců. K proměnné levokraj, která vyjadřuje počet pixelů od levého okraje widgetu, je přičtena hodnota označujı́cı́ mezeru mezi kruhy ve vrstvě krát souřadnice z daného prvku pole. K tomu je také přičten počet pixelů v závislosti na rozestupu mezi kruhy ve vrstvě a úhlu, pod kterým je krychle znázorněna. Tento člen je ještě spolu s jednı́m členem na následujı́cı́m řádku dělen dvěma, protože se jedná o délku odvěsen pravoúhlého trojúhelnı́ku, jehož přepona je kolmá na průmětnu, kvůli čemuž by měla mı́t polovičnı́ délku, než kdyby byla rovnoběžná s průmětnou. Přesto se též jedná o parametr, který by po drobné úpravě šlo v uživatelském rozhranı́ měnit. Obdobný výpočet je při změně patřičných parametrů a goniometrické funkce použit pro výpočet souřadnice y. Dalšı́ cyklus na řádcı́ch (10) až (18) pak projde na řádcı́ch (14) až (16) všechny prvky pole. Poté jsou jejich souřednice porovnány s prvkem, který byl určen prvnı́mi třemi průchody cyklu (indexy tohoto prvku v seznamu jsou dány proměnnými x,y,z). Pokud se shodujı́ a zároveň to nejsou souřadnice totožných prvků, jsou indexy tohoto prvku přiřazeny na řádku (18) jako parametry do seznamu prekryvajici (prvku určeného prvnı́mi třemi průchody cyklu). Poslednı́ cyklus pouze vykresluje kruhy na přı́slušných souřadnicı́ch v náhledu pomocı́ funkce nakresliKruh() (popsána v předchozı́ podsekci). 3.5 Řı́dı́cı́ software 3.5 20 Řı́dı́cı́ software Program na Arduinu je vždy rozdělen na dvě hlavnı́ funkce – funkci setup() a loop(). Prvnı́ z nich je provedena vždy, když je Arduino resetováno, např. když je připojeno k napájecı́mu zdroji, je s nı́m zahájena nebo ukončena sériová komunikace, nebo je ručně resetováno pomocı́ tlačı́tka umı́stěného na samotném Arduinu. Jsou zde předevšı́m inicializovány všechny piny, které jsou v programu použity, pomocı́ přı́kazu pinMode(cislopinu,OUTPUT/INPUT). Funkce loop() se pak opakuje ve smyčce dokud je Arduino napájeno. Reprezentace dat Data animace jsou reprezentována dvěma poli data typu byte a prodlevy typu unsigned int2 . Pole data obsahuje veškerá data o modelech, určuje tedy, jaké LED majı́ být v modelu rozsvı́cené. Každý prvek v tomto poli reprezentuje jeden řádek v displeji. Prvky v poli prodlevy určujı́, jak dlouho má být daný model zobrazen. Dále je zde také proměnná topindex, jejı́ž hodnota určuje počet prvků v obou polı́ch. Cyklus procházejı́cı́ modely 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int x ,y , z ; unsigned long cas ; for ( x =0; x <=( topindex -1) ; x = x +65) { cas = millis () + data [ x +64]; while ( cas > millis () ) { for ( y =0; y <8; y ++) { digitalWrite ( latch , LOW ) ; for ( z =0; z <8; z ++) { shiftOut ( dat , clock , MSBFIRST , data [ x +8* y + z ]) ; } if ( y ==0) { digitalWrite (24 , LOW ) ; } else { digitalWrite (38 -2*( y -1) , LOW ) ; } digitalWrite ( latch , HIGH ) ; digitalWrite (38 -2* y , HIGH ) ; } } } Na řádku (1) a (2) jsou deklarovány proměnné, se kterými cyklus pracuje. Proměnná x představuje čı́slo modelu, y vrstvu a z řádek. Vzhledem k tomu, že je model zobrazován pomocı́ cyklu, nemůže být program pozastaven pomocı́ delay(), aby model zůstal na displeji po daný čas. Proto je zde deklarována proměnná cas 2 Unsigned int na Arduinu zabı́rá 16 bitů, jeho rozsah je tedy od 0 do 65 635. 3.6 Sériová komunikace 21 typu unsigned long. Do té je pro každý model uložen aktuálnı́ čas pomocı́ funkce millis()3 , ke kterému je přičten čas v milisekundách, po který má model zůstat zobrazený na displeji. Tento čas je pak v každém kroku cyklu na řádku (5) porovnán s aktuálnı́m časem a pokud je menšı́, cyklus skončı́ a je zobrazen dalšı́ model4 . V cyklu, který ověřuje čas, po který je model zobrazen, je na řádku (6) vnořen dalšı́ cyklus, který procházı́ vrstvy, a v něm poslednı́ na řádku (8), který procházı́ řádky v displeji. Ten do všech posuvných registrů pošle data pro aktuálnı́ vrstvu. Poté je na řádcı́ch (11) až (16) vypnuta vrstva, která svı́tila v předchozı́m kroku cyklu. Dále je na řádku (17) aktualizován výstup posuvných registrů a na následujı́cı́m řádku je vyslán signál na bázi tranzistoru ovládajı́cı́ho aktuálnı́ vrstvu. Celé projitı́ cyklu, který ovládá vrstvy, trvá několik milisekund. 3.6 Sériová komunikace Vzhledem k použitému systému ukládánı́ dat na Arduinu je třeba data z aplikace nějakým způsobem upravit. Kvůli výpočetnı́m parametrům Arduina a počı́tače je výhodnějšı́ tato data upravit ještě před odeslánı́m přes sériovou komunikaci. V tomto přı́padě musı́ být obě části softwaru odladěné do té podoby, aby jedna část odesı́lala data přesně v takovém tvaru, ve kterém je druhá část očekává. Funkce sendToArduino() 1 def sendToArduino () : 2 port = " " 3 ports = list ( serial . tools . list_ports . comports () ) 4 for p in ports : 5 if " Arduino Mega 2560 " in p [1]: 6 port = p [0] 7 if port != " " : 8 ser = serial . Serial ( port ,38400 , timeout = 5) 9 time . sleep (1) 10 ser . write ( " ! " ) 11 for i in range ( maxcas +1) : 12 for x in range (8) : 13 for y in range (8) : 14 shoda = False 15 while shoda == False : 16 radek = 0 17 for z in range (8) : 18 if data [ i ][0][ x ][ y ][ z ]. get () == True : 19 radek = radek + mocnina (7 - z ) 20 ser . write ( " * " + str ( radek ) + " / " ) 21 prijem = ser . readline () 22 if int ( prijem ) == int ( radek ) : 3 Přesněji řečeno je výstupem této funkce uplynulý čas v milisekundách od poslednı́ho resetu Arduina. 4 Unsigned long zabı́rá v paměti 32 bitů, takže jeho rozsah je od 0 do 4 294 967 296. To znamená, že asi po padesáti dnech čas přeteče a animace v Arduinu se zastavı́. 3.6 Sériová komunikace 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 22 shoda = True else : ser . write ( " -" ) shoda = False while shoda == False : ser . write ( " * " + data [ i ][1]. get () + " / " ) prijem = ser . readline () if int ( prijem ) == int ( data [ i ][1]. get () ) : shoda = True else : ser . write ( " -" ) ser . write ( " ! " ) ser . close () else : tkMessageBox . showerror ( " 3 D displej nenalezen " , " Pros ı́m , zkontrolujte , jestli je displej skute č n ě p ř ipojen . " ) Funkce sendToArduino() je volána po zmáčknutı́ tlačı́tka sendButton. Prvnı́, co se musı́ provést při jejı́m zavolánı́, je pokus o otevřenı́ sériové komunikace mezi Arduinem a PC. Nejdřı́ve jsou na řádku (3) do seznamu ports uloženy všechny otevřené sériové porty, a pokud je mezi nimi detekováno připojené Arduino, je na řádku (8) otevřena sériová komunikace. V přı́padě, že nenı́ Arduino nalezeno, je na řádku (37) zobrazeno dialogové okno ohlašujı́cı́ chybu a funkce je následně ukončena. Nejdřı́ve funkce na řádku (9) počká, než Arduino otevře sériovou komunikaci. Poté je Arduinu poslán znak "!", který zajistı́, že Arduino přestane zobrazovat aktuálnı́ animaci a začne čı́st data z USB. Každá informace o stavu diod v jednom řádku nebo o časové prodlevě, po kterou má být model zobrazen, je Arduinu posı́lána ve tvaru "*...odeslaná data.../", kde znak "*" určuje začátek a znak "/" konec sekvence. Jelikož jsou data displeje uložena v seznamu, kde je každý řádek displeje popsán jednı́m osmiciferným binárnı́m čı́slem (přesněji seznamem osmi prvků, které mohou nabývat dvou hodnot), je třeba tato čı́sla převést před odeslánı́m Arduinu do decimálnı́ soustavy. To je provedeno na řádcı́ch (17) až (19). Jakmile je tato sekvence odeslána, je Arduinem zaslána zpět k ověřenı́. Pokud se přijatá data shodujı́ s odeslanými, funkce pokračuje v odesı́lánı́ dalšı́ch dat. V přı́padě neshody je odeslán znak "-" značı́cı́, že odeslaná data nejsou v pořádku a majı́ být ignorována. Funkce se pak snažı́ odesı́lat stejnou sekvenci do té doby, dokud data nesouhlası́. Tato pojistka je bohužel nutná kvůli občasné chybě v sériové komunikaci. Jakmile jsou veškerá data odeslána, je Arduinu vydán pokyn ke spuštěnı́ animace pomocı́ znaku "!" a sériová komunikace je ukončena. Přı́jem dat na Arduinu 1 if ( Serial . available () ) { 2 input = Serial . read () ; 3 if ( input == 33) { 4 topindex = 0; 3.6 Sériová komunikace 23 5 input = Serial . read () ; 6 while ( input !=33) { 7 if ( input ==42) { 8 zapisRadek () ; 9 } 10 if ( input ==45) { 11 topindex - -; 12 } 13 input = Serial . read () ; 14 } 15 } 16 } Jelikož jedinou věcı́ s proměnlivou potřebnou pamětı́ v řı́dı́cı́m programu jsou samotná data animace, zabı́rajı́ tato pole maximálnı́ možnou velikost bez ohledu na to, kolik mı́sta je skutečně využı́váno. To, kolik prvků je z těchto polı́ skutečně čteno, je dáno hodnotou proměnné topindex, která určuje jejich součet. Funkce Serial.read() přečte v otevřené sériové komunikaci právě jeden znak. V přı́padě, že je smyčkou loop() v Arduinu přečten znak "!" (jehož kód v tabulce ASCII je 33), je nastavena hodnota proměnné topindex na 0, což znamená, že program bude ingnorovat veškerá předešlá nahraná data. Poté proběhne cyklus, který bude čı́st z USB portu data do té doby, dokud nenı́ znovu přečten znak "!". 1 void zapisRadek () { 2 int vysledek = 0; 3 int input ; 4 while ( input !=47) { 5 if ( Serial . available () ) { 6 input = Serial . read () ; 7 if (( input >47) &&( input <58) ) { 8 vysledek = vysledek *10+ input -48; 9 } 10 } 11 } 12 if ((( topindex +1) %65) ==0) { 13 prodlevy [( topindex +1) /65 -1] = vysledek ; 14 } 15 else { 16 data [ topindex -( topindex +1) /65] = vysledek ; 17 } 18 Serial . println ( vysledek ) ; 19 topindex ++; 20 } Jakmile je přečten znak "*" (kód 42 v ASCII tabulce), je zavolána funkce zapisRadek(), která čte jednotlivé cifry odesı́laného čı́sla. Z těch pak vytvářı́ výsledek tak dlouho, dokud nenı́ přečten znak "/" (kód 47 v ASCII tabulce). Tento výsledek je pak uložen bud’ do pole data, nebo prodlevy, přičemž záležı́ na zbytku po dělenı́ proměnné topindex (každý šedesátý pátý prvek je časová prodleva). Kromě toho je také zvyšena hodnota této proměnné o jedna. 3.7 Vytvořenı́ spustitelného souboru 24 Pokud je přečten znak "-" (kód 45 v ASCII tabulce), je snı́žena hodnota proměnné topindex o jedna, dı́ky čemuž jsou ingnorována data nahraná v předešlém kroku. 3.7 Vytvořenı́ spustitelného souboru Vzhledem k tomu, že má být aplikace pro uživatele co nejpřı́větivějšı́, je žádoucı́ vytvořit spustitelný soubor (.exe), aby uživatel nemusel instalovat Python s přı́davnými moduly. Pro tento účel jsem použil balı́k cx Freeze a upravil vzor skriptu pro vytvořenı́ spustitelného souboru, který byl uvedený v dokumentaci [6]. 3.8 Omezenı́ a požadavky Aplikace je určena pro operačnı́ systém Windows. Aby mohla detekovat připojené Arduino, je také nutné instalovat patřičný ovladač. Po vı́ce jak čtyřiceti devı́ti dnech od poslednı́ho zapnutı́ displeje se displej sekne na aktuálnı́m snı́mku (viz str. 20). Pokud je zařı́zenı́ vypnuto, je smazána na něj nahraná animace. Je to způsobeno resetovánı́m Arduina při jeho opětovném zapnutı́5 . Bylo by možné využı́t možnostı́ EEPROM [8], která nabı́zı́ ukládánı́ dat s možnostı́ obnovy po opětovném zapnutı́ Arduina. Bohužel má toto úložiště kapacitu pouhých 512 bytů, což by stačilo na uloženı́ animace o maximálně sedmi modelech. Dalšı́ alternativou by mohlo být využitı́ shieldu se slotem pro SD kartu [9]. 5 Arduino se resetuje i při vypnutı́ či zapnutı́ sériové komunikace, to však bylo znemožněno pomocı́ přivedenı́ trvalého napětı́ na pin RESET u Arduina [7]. 4 4 ZÁVĚR 25 Závěr Byly splněny všechny vytyčené cı́le – byl sestaven displej a jeho řı́dı́cı́ obvod, dále byl také sespsán řı́dı́cı́ program pro Arduino a aplikace pro Windows. Ty spolu dokážı́ komunikovat skrze sériovou komunikaci. V práci je pak popsáno, jak fungujı́ veškeré důležité částı́ použitého zdrojového kódu a řı́dı́cı́ obvod displeje. Některé prvky práce lze dále rozvinout a vylepšit, přı́padně lze navázat dalšı́mi projekty, např.: Vylepšenı́ grafického rozhranı́ aplikace, předevšı́m pak náhledu displeje. Přidánı́ možnosti kopı́rovat dı́lčı́ části animace pro usnadněnı́ práce uživatele. Vytvořenı́ verzı́ aplikace pro dalšı́ operačnı́ systémy. Přidánı́ shieldu se slotem pro SD kartu kvůli vytvořenı́ trvalého úložiště dat na Arduinu. Přidánı́ Bluetooth/WiFi shieldu a vytvořenı́ bezdrátové komunikace. Přidánı́ ovládacı́ho zařı́zenı́ spolu s malým displejem na Arduino pro možnost nahrát vı́ce různých modelů a přepı́nat mezi nimi. SEZNAM LITERATURY 26 Seznam literatury [1] LED Cube 8 × 8 × 8. In: Instructables [online]. [cit. 2016-02-11]. Dostupné z: http://www.in structables.com/id/Led-Cube-8x8x8/ [2] Věda a technika v pozadı́. KRÁLOVÁ, Magda. Eduportál [online]. [cit. 2016-02-11]. Dostupné z: http://edu.techmania.cz/cs/veda-v-pozadi/798 [3] MAW, Carlyn a Tom IGOE. Serial to Parallel Shifting-Out with a 74HC595. Arduino Website [online]. [cit. 2016-02-11]. Dostupné z: https://www.arduino.cc/en/Tutorial/ShiftOut [4] OLEJÁR, Martin. LED diody: parametry, základnı́ údaje.. [online]. [cit. 2016-02-11]. Dostupné z: http://www.elweb.cz/clanky.php?clanek=34 [5] LENORE, Edman. Basics: Picking Resistors for LEDs. Evil Mad Scientist [online]. 2012 [cit. 2016-02-11]. Dostupné z: http://www.evilmadscientist.com/2012/resistors-for-leds/ [6] TUININGA, Anthony. Distutils setup script [online]. [cit. 2016-02-11]. Dostupné z: http://cx -freeze.readthedocs.org/en/latest/distutils.html#distutils [7] DisablingAutoResetOnSerialConnection. Arduino Website [online]. [cit. 2016-02-11]. Dostupné z: http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection [8] EEPROM Write. Arduino Website [online]. [cit. 2016-02-11]. Dostupné z: https://www.ardu ino.cc/en/Tutorial/EEPROMWrite [9] EARL, Bill. Using the SD Card. Adafruit [online]. [cit. 2016-02-11]. Dostupné z: https://le arn.adafruit.com/adafruit-data-logger-shield/using-the-real-time-clock-1 ZDROJE OBRÁZKŮ 27 Zdroje obrázků [1] Archiv autora. [2] 74HC595; 74HCT595: Product data sheet [online]. 2015 [cit. 2016-02-11]. Dostupné z: http: //www.nxp.com/documents/data_sheet/74HC_HCT595.pdf
Podobné dokumenty
CZ - O SMT-info
produktového portfolia. Jednou z nich je systém „OPTILIGN“ pro sítotiskové zařízení EKRA
(EKRA je součástí ASYS Group od r. 2005).
OPTILIGN je synonymum odvozené z anglických slov Optical and Optim...
Text magisterská práce - Katedra geoinformatiky
aplikace, kolik stránek bude obsahovat a jaký na nich bude obsah. Bylo nutno definovat
funkce, které byly rozděleny do skupin na uživatelské, mapové a ostatní. Taktéž
Využití moderních metod pro tvorbu map pro orientaˇcní bˇeh
V rámci bakalářské práce bylo prováděno měření v konfiguraci PDA Fujitsu Siemens
s nainstalovaným operačním systémem Windows CE a software ArcPad 7.0 spojeného přes
bluethooth s mobilním při...
2005 / 3 únor
budeme kupovat „intel vív“, to netuším.
n Firma Sony se přiznala, že v oblasti
digitální zábavy udělala „chyby ve strategii“. Tento pocit měla většina jejích
příznivců už dlouho. Na minidisky
připo...
List1 Stránka 1 - First
List1
Upozornění: tento seznam není úplný!
Celý naleznete na http://www.seznamkatalogu.cz (nejúplnější seznam CZ katalogů,
podle něho registrujeme)
http://123zoznam.info/
http://citycenter.over.cz/...