Ukázkový projekt do MMIA: LED CUBE 8x8x8
Autoři: Petr Lecián, Ivan Macháček
Garant předmětu: Zbyněk Fedra UREL, FEEC, VUT Brno fedraz
feec.vutbr.cz
Obsah:
- Úvod
- Realizace
- Závěr
- Literatura
- Ke stažení
V projektu byla realizována z LED krychle, jedna strana sestávala z osmi LED,
celkem tedy krychle obsahuje 8³ = 512 LED.
Pomocí multiplexování vždy osmice LED lze vyrobit jakýkoliv prostorový "obrázek"
ze svítících LED. Kostka může být
využita pro estetické účely, prezentace, hry (např. 3D Snake), atd.
Pro výrobu krychle bylo potřeba celkem 512 LED diod. Z cenových důvodů byly
použity červené difuzní (1Kč/ks). Pro buzení dané osmice
bylo dále potřeba 72 tranzistorů PNP (typ BC640) a 8 tranzistorů NPN (typ BC338). Principiální zapojení
je uvedeno na obr. 1. Pro jednoduchost je zapojení pouze pro část kostky 3x3x3.

Obr. 1: Princip zapojení krychle
Pomocí portu C se nízkou úrovní napětí vybere jedna řada LED, tedy celkem 64 LED.
Dále se pomocí portu B nízkou úrovní aktivuje daná osmice LED.
Portem A se vysoukou úrovní spínají konkrétní diody. Proud LED diodou je omezen
rezistory 10Ω, které jsou zapojeny v kolektoru NPN tranzistorů v portu A.
Proud procházející použitou LED diodou je 50mA. Zapojení umožňuje použít napájení 5VDC.
Pro zobrazení obecného obrázku je tedy nutné udělat celkem 8x8 = 64 taktů.
Obnovovací frekvence postačuje 60Hz, při které není patrné blikání diod.
Kostka byla po mechanické stránce vyrobena podle návodu [1], [2] a [3].
Vrstvy byly vyrobeny na překližkové šabloně, jednotlivé vrstvy pak drží pohromadě pomocí plošného spoje
a drátků připájených po stranách krychle. Celá krychle je dostatečně tuhá.
Plošný spoje bylo nutné realizovat jako oboustranný.
Tranzistory byly použity v plastovém pouzdru s drátovými vývody (TO92).
Pomocí drátových vývodů byly realizovány i propoje mezi vrstvami DPS.
NPN tranzistory byly vybrány BC338, PNP jsou BC640.
Propojení s řídicím obvodem je provedeno trojicí plochých kabelů.
Podklady pro výrobu lze stáhnout zde.

Obr. 2: Provedení desky plošného spoje
Ovládání kostky je zajištěno mikrokontrolérem AVR Atmel ATMEGA16.
Hodinový signál 16MHz je z krystalového oscilátoru. Kostka zabírá celkem 3 porty mikrokontroléru.
Pomocí dvojice multiplexorů by bylo možné porty kostky B a C řídit jen jedním portem mikrokontroléru.
Obr. 3: Fotodokumentace (kliknutím na obrázek se otevře v novém okně obrázek ve větším rozlišení)
Programové vybavení se skládá ze 3 částí:
- Programová paměť: Uložení obrázků do paměti mikrokontroléru.
- Periferie: 8 bitový čítač/časovač 0 pro zobrazování obrázku a jejich přepínání.
- Přepínání mezi vizualizacemi: Obslužný program pro kontrolu trojice tlačítek.
Uložení obrázků do paměti mikrokontroléru
Vzhledem k velikosti obrázků 64B je nutné vše uložit do programové paměti mikroprocesoru, která má v
případě ATMEGA16 velikost 16kB.
Základním prvkem je vizualizace, což je skupina libovolného počtu po sobě jdoucích obrázků.
Obsah jedné vizualizace je uložen v třírozměrném poli Cube1 v programové paměti:
#define CUBE_ORDER 8 /*Řád krychle*/
/*Uložení obrázků vizualizace*/
char Cube1[/*Počet obrázků*/][CUBE_ORDER][CUBE_ORDER] = {...};
Datový typ char
má velikost 8bitů, což pro použitou kostku dostačuje.
Každý bit pak slouží pro jednu LED diodu.
Pokud je bit nastaven na 1, dioda svítí, pokud je nastaven na 0, dioda nesvítí.
Dále k tomuto poli musí existovat další pole Time1,
ve kterém jsou uloženy doby trvání jednotlivých obrázku.
Obrázek pak zůstane vidět po dobu určenou jako násobek doby trvání obnovovací periody
F_REFRESH.
/*Uložení dob trvání jednotlivých obrázků*/
char Time1[/*Počet obrázků*/] = {...};
Aby bylo možné k těmto polím snadno přistupovat,
bylo vytvořeno ještě jedno pole Data,
které obsahuje počty obrázků ve vizualizacích, dále adresu prvního prvku pole s obrázky
a adresu prvního prvku pole s časy.
Délka adresy je 2B, je tedy nutné použit 16-ti bitový typ integer (u překladače AVR-GCC).
#define NUM_COUNT 5 /*Počet úvodních vizualizací (číslic, ...)*/
#define VIZ_COUNT 4 /*Počet skutečných vizualizací*/
/*Pole s ukazateli na jednotlivé vizualizace*/
const int Data[NUM_COUNT + VIZ_COUNT][3] = {
{1, (int) &sCube1[0][0][0], (int) &sTime1[0]}, /*Zobrazení číslice jedna*/
{1, (int) &sCube2[0][0][0], (int) &sTime2[0]}, /*Zobrazení číslice dva*/
{1, (int) &sCube3[0][0][0], (int) &sTime3[0]}, /*Zobrazení číslice tři*/
{1, (int) &sCube4[0][0][0], (int) &sTime4[0]}, /*Zobrazení číslice čtyři*/
{1, (int) &sCube5[0][0][0], (int) &sTime5[0]}, /*Zobrazení číslice pět*/
{65, (int) &Cube1[0][0][0], (int) &Time1[0]}, /*Vizualizace 1: Skládání kostek*/
{24, (int) &Cube2[0][0][0], (int) &Time2[0]}, /*Vizualizace 2: Pohybující se kostky*/
{8, (int) &Cube3[0][0][0], (int) &Time3[0]}, /*Vizualizace 3: Tři čáry*/
{8, (int) &Cube4[0][0][0], (int) &Time4[0]} /*Vizualizace 4: "šachovnice"*/
};
V případě přidání/odebrání vizualizace je nutné aktualizovat pole
Data.
Pokud se změní počet obrázku ve vizualizaci, stačí jen aktualizovat aktualizovat
první prvek v poli Data.
8 bitový čítač/časovač 0
Čítač pracuje v režimu CTC (Clear Timer on Compare), využívá se vektor přerušení
TIMER0_COMP.
Po vyvolání přerušení dojde k nastavení osmice LED.
Aktuální pozice osmice LED je určena globálními proměnnými
currentX a currentY,
které mohou nabývat hodnot 0, 1, 2, ..., 7. V dvourozměrné poli
Img o velikosti 8x8 je uložen konkrétní obrázek.
Z pole se však vybírají hodnoty pomocí ukazatele *pImg = &Img[0][0].
Mezi změnami výstupních portů jsou vloženy časové prodlevy
10μs pomocí funkcí delay_us(time) [6].
Protože celkový počet osmic LED je 64 a obnovovací
frekvence by měla být minimálně 60Hz, je potřeba nastavit registry
čítače/časovače tak, aby k přerušení docházelo s frekvencí 64*60Hz = 3840Hz.
Pro dosažení této frekvence byla nastavena předdělička
čítače na 256 a následně dopočítána hodnota porovnávacího registru
OCR0 podle [4].
/* definice kmitočtů */
#define F_OSC 12000000 /*Frekvence hodinovéhu kmitočtu MCU [Hz]*/
#define F_REFRESH 60 /*Frekvence obnovení obrázku [Hz]*/
#define REG_OCR0(x) ((char)((uint32_t)F_OSC/((uint32_t)x*F_REFRESH*CUBE_ORDER*CUBE_ORDER))) /*Registr OCR0*/
/* definice směru registrů */
#define KOSTKA_DDR_A DDRC
#define KOSTKA_DDR_B DDRB
#define KOSTKA_DDR_C DDRA
/* definice výstupních registrů */
#define KOSTKA_PORT_A PORTC
#define KOSTKA_PORT_B PORTB
#define KOSTKA_PORT_C PORTA
/*Nastavení refistrů čítače/časovače 0*/
TIMSK |= (1 << OCIE0);
TCCR0 = (1 << WGM01)|(1<< WGM01)|(1 << CS02)|(0 << CS01)|(0 << CS00);
OCR0 = REG_OCR0(256); //256 je hodnota předdělička čítače/časovače 0
/*refresh obrázku*/
ISR(TIMER0_COMP_vect) {
KOSTKA_PORT_A = 0x00;
delay_us(10); //čekej 10us
KOSTKA_PORT_B = ~(1 << currentY);
delay_us(10); //čekej 10us
KOSTKA_PORT_C = ~(1 << currentX);
delay_us(10); //čekej 10us
KOSTKA_PORT_A = Img[currentY][currentX];
/*výběr další osmice LED
if (++currentX > 7) {
currentX = 0;
if (++currentY > 7) {
currentY = 0;
zmena = 1;
}
}
}
Čítač/časovač 0 rovněž zajišťuje změnu obrázků.
Základní perioda je dána (přibližně) hodnotou F_REFRESH.
Skutečná doba trvání obrázku je pak dána součinem této periody a
délkou trvání jednoho obrázku. Přepínání mezi obrázky je realizovano funkcí
void changeImg(char refresh).
Funkce se stará o přepis hodnot z
programové paměti do globálního pole Img.
Protože čas potřebný pro vykonání funkce trvá delší dobu než
je prodleva mezi přerušeními čítače/časovače 0, je nutné ji volat z hlavní funkce int main(void)
(když není mikroprocesor v obsluze přerušení).
Proto byla přidána proměnná zmena.
Pokud je její hodnota různá od 0, dojde k zavolání funkce changeImg(0).
V případě, že by se funkce void changeImg(char refresh volala v přerušení
docházelo by k problikávání určitých LED diod.
Pokud je parametr refresh) různý od 0,
dojde vždy k přepsání pole Img.
/*Změna obrázku*/
void changeImg(char refresh) {
char i;
char *pImg = &Img[0][0];
while (1) {
if (time == 0 || refresh) {
/*nacteni obrazku z Flash do RAM*/
time = pgm_read_byte((char*) (Data[currentViz][2] + currentImg));
if (time != 0) {
for (i = 0; i < 64; i++) {
*pImg = pgm_read_byte(Data[currentViz][1] + 64*currentImg + i);
pImg++;
}
}
if (currentImg > Data[currentViz][0] - 2) {
currentImg = 0;
} else {
currentImg++;
}
}
if (time != 0) {
time --;
return;
}
}
}
Ovládání kostky
Kostka je ovládána trojicí tlačítek: Start/Stop, Další (NEXT) a Předchozí (PREV).
Tlačítkem Start/Stop se přepíná mezi úvodní vizualizací (např. číslo vizualizace) a skutečnou vizualizací.
Tlačítky Další a Předchozí se vybírá příslušná vizualizace.
Kontrola stavu tlačítek je zahrnuta do nekonečné smyčky v hlavní části programu.
Zákmity kontaktů tlačítek jsou ošetřeny softwarově.
Stisknutím tlačítka se změní úroveň napětí na daném pinu z vysoké úrovně na nízkou úroveň.
Vytvořená kostka je plně funkční, použitý mikrokontrolér je výkonově zcela postačující,
programová paměť umožňuje nahrání asi 200 obrázků. S obnovování obrázku není problém, blikání LED diod není patrné.
Bohužel použité LED diody nevynikají vysokou svítivostí a nejsou čiré.
Při přímém denním světle je těžko rozeznatelné, zda LED svítí nebo nikoli,
za šera je 3D obrázek již dobře vidět.
Dalším pokračováním projektu by mohlo být připojení kostky k PC,
využití paměti EEPROM pro uložení vlastních animací, jednoduché hry, např. 3D Snake, apod.
[1] 5³ LED CUBE Controller : for PIC16F688 [online]. 2009 [cit. 2009-05-10]. Dostupný z WWW: <http://picprojects.org.uk/projects/lc/index.htm>
[2] The 3D LED Cube [online]. 2009 [cit. 2009-05-10]. Dostupný z WWW: <http://www.lomont.org/Projects/LEDCube/LEDCube.php>
[3] bit-tech.net: Help with LED cube wiring [online]. 2009 [cit. 2009-05-10]. Dostupný z WWW: <http://forums.bit-tech.net/showthread.php?t=76578>
[4] Datasheet ATMEGA16 [online]. 2009 [cit. 2009-05-10]. Dostupný z WWW: <http://www.atmel.com/dyn/resources/prod_documents/doc2466.pdf>
[5] Manuál AVR-libc-1.6.5 [online]. 2009 [cit. 2009-05-10]. Dostupný z WWW: <http://www.nongnu.org/avr-libc/>
[6] Precise Delay Functions [online]. 2009 [cit. 2009-05-10]. Dostupný z WWW: <http://motivecvs.tux-project.de/cgi-bin/viewcvs.cgi/doc/Source_Bsp/CAN_AVR_TESTPRJ/>
[7] MANN, B. C pro mikrokontroléry. BEN technická literatura, 2003. ISBN 80-7300-077-6