5x5x5 LED Cube

download 5x5x5 LED Cube

of 31

Transcript of 5x5x5 LED Cube

5x5x5 LED Cube - Orientasi Independen 3D Display

Proyek kami, dalam satu kalimat, Orientasi adalah tampilan 3D LED independen. Kami terinspirasi oleh berbagai video di youtube batu Serupa tetapi juga oleh gagasan interaktif Menciptakan tampilan 3-dimensi. Kami membangun sebuah Kubus 5x5x5 LED layar dan papan pengendali yang dihubungkan ke sebuah Kubus Mega32 Mikrokontroler. Kita dapat Menampilkan berbagai gambar 3D atau Animasi resolusi rendah Kubus kami dan kami Menggunakan accelerometer untuk Mendeteksi Orientasi Kubus horisontal dan vertikal atau menyesuaikan tampilan agar tetap tegak Bahkan Kubus Jika kita mengubah ke samping. Kubus itu Digunakan untuk Menampilkan pesan dan Menampilkan Pertunjukan cahaya sedikit animasi.

High Level Design

Kami menerima inspirasi untuk desain kami Ketika kami Melihat salah satu dari sekian banyak video di youtube Kubus 3D LED. Kami pikir gagasan tentang tampilan 3D yang menarik tapi menantang dan Anggaran Mengingat kendala waktu dan kami juga Berpikir ide kita bisa banteng satu langkah lebih lanjut (langkah ekstra Penyesuaian ini berakhir dengan Menggunakan Orientasi accelerometer). Salah satu utama Pertimbangan Ketika pertama kali itu kami merancang Kubus Memutuskan berapa besar untuk membuatnya. Jelas lebih lampu LED akan Memberikan resolusi yang lebih baik dan memungkinkan kita untuk Menampilkan Beberapa gambar yang lebih menarik tetapi pada saat yang sama kami dibatasi oleh seberapa besar sebuah Kubus kita bisa Mengarang dalam waktu Tertentu dan Bahkan lebih lagi oleh berapa banyak lampu LED yang bisa kami Mengendalikan diberikan cukup terbatasnya jumlah pin port pengolahan dan terbatasnya Kekuatan Mega32. Kami akhirnya menetap di sebuah Kubus 5x5x5 Sebagai trade off yang wajar antara ukuran dan kepraktisan, namun, kami mengundang kelompok-kelompok di masa depan, dan orang lain yang tertarik, untuk mencoba membangun sebuah Kubus yang lebih besar diberikan waktu dan Anggaran Serupa kendala (kami Memberikan sarankan Anda 8x8x8 karena bulat 512 lampu LED yang bagus).

Pertimbangan utama adalah bagaimana kita berikutnya akan Mengendalikan semua lampu LED. Sebuah Kubus 5x5x5 dibuat untuk 125 lampu LED yang jauh lebih lampu LED dari pelabuhan-pelabuhan di Mega32. Kami awalnya dikembangkan sebuah metode untuk Mengendalikan individu setiap LED yang jauh seperti metode yang Digunakan dalam driver common LED. Metode pengiriman Terlibat serial sedikit sungai yang mewakili negara masing-masing memiliki sedikit 125 LED serial-in paralel-out register geser. Setelah pergeseran di negara masing-masing lampu LED 125 maka kita akan kait nilai setiap bit Menggunakan sandal jepit dan 125 mobil setiap LED off Keluaran dari flip flop. Metode ini hanya Memerlukan port 3 pin (satu untuk arus bit serial, satu register geser ke jam, dan satu jam ke sandal jepit) dan sangat cepat karena kita bisa mendaftar geser jam di atas 1 MHz dan secara Teoritis memperbarui semua LED dalam beberapa ratus mikrodetik . Secara Teoritis metode ini tampak sangat cepat, namun, metode praktis ini sangat tidak efisien.

Masalah utama Mengendalikan dengan setiap LED Bahwa secara individu adalah untuk Melakukan hal itu setidaknya kita harus Menjalankan kawat 1 untuk masing-masing dan setiap LED. Masalah ini dengan cepat keluar dari tangan; di bagian bawah Kubus kita akan memiliki sekurang-kurangnya 6 kabel melarikan diri dari masing-masing dari 25 kolom. Semua kabel ini akan membuat untuk aethstetically Kubus tidak menyenangkan dan sekarang pertanyaan tentang bagaimana rute kabel akan kami jual bersama-sama dan cocok mereka ke Kubus dasar. Bahwa kami menyadari kami akan perlu kabel LED bersama-sama dengan cara yang kami bisa alamat mereka tanpa harus secara individu Menjalankan kawat terpisah untuk masing-masing. Ini adalah masalah rumit sejak skema pengalamatan yang khas seperti memilih kolom, lalu berturut-turut, tingkat maka akan memiliki efek samping yang tidak diinginkan lampu dari lampu LED yang lebih dari yang kita Inginkan. Setelah Beberapa pemikiran dan pencarian, akhirnya kami Menemukan situs ini yang memberi kami sebuah besar metode bagaimana melakukannya. Tutorial menunjukkan kepada kita Bahwa kita sebenarnya bisa alamat satu lampu LED pada satu waktu tanpa harus Menjalankan satu ton kabel. Untuk melakukannya kita akan Menghubungkan semua kolom atas dan bawah dari lampu LED yang sama terminal positif (25 kolom total, dengan 5 lampu LED masing-masing) dan hubungkan Kemudian semua tingkat horisontal yang sama 'tanah' (5 tingkat dengan 25 lampu LED masing-masing ). Untuk memilih satu LED kami akan berlaku 5V ke kolom di mana LED Terletak Kemudian tanah dan tingkat yang aktif. Dengan cara ini Menggunakan kontrol hanya 25 baris untuk kolom dan 5 baris kontrol dasar untuk kita bisa memilih setiap LED secara individu. Namun, hasil ini masih dalam masalah sebelumnya kilat LED's sengaja ekstra Jika kita mencoba untuk menyalakan LED lebih dari 1 sekaligus. Seperti diilustrasikan dalam Gambar 3, Jika kita ingin menyalakan LED pertama hanya di tingkat atas (sudut kiri belakang) dan yang terakhir LED di tingkat bawah (sudut kanan depan) kita akan Menetapkan tanggal 1 dan 25 kolom Kemudian tinggi dan tanah yang tingkat atas dan bawah . Namun, Jika kita Melakukan ini, bukan hanya memiliki 2 LED yang menyala kita akan memiliki 4 (atas dan bawah dari belakang dan sudut atas dan bawah dari sudut depan). Untuk menyiasati hal ini kita hanya mencoba untuk menyalakan lampu LED pada kolom dalam satu Suatu waktu. Untuk Menampilkan gambar yang memiliki lampu LED yang menyala dari berbagai kolom Siklus kita melalui setiap kolom dengan kecepatan lebih tinggi (sekitar 62.5Hz) untuk membuatnya tampak seolah-olah lebih dari satu kolom dari lampu LED adalah pada pada waktu yang sama.

Program / Hardware Design

Hardware Deskripsi Ada banyak sirkuit yang harus dibangun untuk mewujudkan proyek ini. Pertama, kami harus membangun LED kubus itu sendiri yang sebenarnya ternyata jauh lebih sulit maka kita pertama diantisipasi karena jumlah geser lampu LED. Kami membangun 5x5 masingmasing bidang horisontal secara individual dengan meletakkan flat LED di atas kawat dan pematrian semua terminal negatif lampu LED ke kawat dan meninggalkan terminal positif menggantung. Dasarnya ini terhubung semua terminal negatif lampu LED di tingkat yang sama tanah yang sama pesawat. Kami kemudian harus hati-hati solder 5 horisontal pesawat bersama-sama dengan terlebih dahulu me-mount mereka di sisi sebuah kotak kardus dan rekaman itu ke tempatnya dalam posisi tegak dan kemudian solder 1 kabel untuk menghubungkan semua lampu LED di kolom vertikal bersama-sama untuk masing-masing 25 kolom. Selain membangun LED kubus itu sendiri kami juga harus merancang dan membangun kebiasaan kita sendiri rangkaian driver LED. Sirkuit ini harus mengambil masukan dari sejumlah pin mikrokontroler dan decode mereka menjadi sesuatu yang bisa mengontrol kubus. Jika kami hanya mengambil masukan dari setiap kolom dan setiap permukaan tanah langsung dari pin mikrokontroler ini akan diambil 30 pin yang akan telah mengambil sebagian besar dari 32 pelabuhan Mega32 pin dari mikrokontroler. Ini pasti akan baik-baik saja untuk aplikasi terakhir kami (yang hanya membutuhkan dua pin tambahan untuk input accelerometer) tetapi akan membuat sulit bagi proyek-proyek masa depan untuk memanfaatkan desain kami. Sebaliknya, kami memutuskan untuk datang dengan cara cerdas untuk mengurangi ukuran bus dan menyederhanakan antarmuka antara sopir dan decoding microcontroller.We menciptakan rangkaian (Gambar 1) yang dapat mengontrol 24 kolom menggunakan hanya 5 pin. 25 kolom yang tersisa dan 5 level tanah yang dikuasai langsung dari mikrokontroler; mengakibatkan ini menggunakan total hanya 11 pin untuk mengontrol seluruh kubus.

Dua bit pertama dari 5 garis kendali disisipkan kedalam decoder pertama (inst37). Decoder ini berfungsi sebagai sebuah kontrol yang dapat memilih untuk mengaktifkan salah satu, dan hanya satu, dari 3 decoders lain. Ada juga opsi keempat di mana tidak ada keluaran diaktifkan decoders yang kita gunakan sebagai cara untuk mematikan semua lampu LED dalam kubus. 3 sisanya garis kendali disisipkan kedalam output 3 decoders (inst34, inst35, dan inst36). Output dari pakan decoders ini langsung ke kolom; karena hanya satu output dari decoder tertentu tinggi pada satu waktu, dan hanya 1 dari output decoders diaktifkan pada waktu tertentu, itu hanya mungkin untuk menghidupkan 1 kolom pada suatu waktu. Hal ini sangat menguntungkan karena, seperti ditunjukkan dalam Gambar 3, berusaha untuk mengemudi lebih dari satu kolom pada satu waktu tinggi menghasilkan pencahayaan yang tidak diinginkan lampu LED tambahan. Pada dasarnya menggunakan skema decoding ini kita dapat memilih salah satu dari 24 kolom pertama hanya dengan mengirimkan nomor biner kolom (puncak dua bit menjadi master DNS untuk decoder dan bagian bawah tiga menjadi input decoder yang dipilih). Setelah menyelesaikan desain sirkuit digital kami siap untuk menghubungkannya ke kubus LED kami, Namun, sebelum kami lakukan, kami menyadari masalah yang mencolok. Output dari masing-masing pin dari masing-masing decoder adalah untuk menggerakkan sebuah kolom seluruh lampu LED. Ini berarti mengemudi sebanyak 5 lampu LED secara paralel, masing-masing gambar sekitar 40 mA saat ini (Gambar 4), dengan total 200 mA

saat ini, bagaimanapun, arus maksimum output dari decoder chip dinilai di hanya 25 mA yang akan tidak cukup untuk mengusir bahkan 1 LED, apalagi semua 5. Selain itu, pelabuhan pin dari mikrokontroler pada awalnya akan berfungsi sebagai pesawat tanah untuk semua lampu LED tetapi kami menyadari bahwa mereka dapat sama sekali tidak tenggelam jumlah arus yang kami perlu tenggelam. Untuk menjelaskan hal ini, kita harus merancang sebuah rangkaian driver LED yang masih menggunakan keluaran dari Decoder dan mikrokontroler untuk mengontrol setiap kolom dan tanah mengemudikan pesawat tapi lampu LED melalui kekuatan eksternal dan tanah.

Untuk mengontrol LED yang menggunakan output dari decoders kami menggunakan 25 PMOS transistor sebagai saklar sisi tinggi dan 5 NMOS transistor sebagai saklar sisi rendah (Gambar 2). The PMOS transistor menggunakan output dari rangkaian dekoder sebagai semacam mengaktifkan dan pasokan LED's dengan 5V ketika mereka dihidupkan. Namun, karena PMOS transistor menghidupkan dengan gerbang rendah untuk sumber tegangan, dan Decoder yang kami digunakan adalah aktif tinggi, kami harus memberi makan output decoders melalui inverter sebelum kami menghubungkan mereka ke transistor. Dalam cara yang sama port MCU digunakan untuk mengendalikan transistor NMOS yang menghubungkan ke ground lampu LED Namun, karena kontrol datang langsung dari pin pelabuhan tidak perlu untuk inverter di sini. Masalah lain yang kami temui melibatkan jumlah arus yang kita bisa mengemudi. Kekuatan sekarang datang langsung dari 5V regulator yang diberi untuk memasok sekurang-kurangnya satu amp saat ini, yang lebih dari cukup, tapi PMOS transistor yang kami gunakan hanya diberi nilai untuk memasok 160 mA yang berkesinambungan saat ini. Ini berarti bahwa kami akan tetap mengalami kesulitan mengemudi semua 5 dari lampu LED pada waktu yang sama

karena masing-masing dari 5 lampu LED akan mencoba untuk menarik arus 40 mA untuk total 200 mA. Dalam rangka untuk mendapatkan sekitar ini kita menerapkan trik dalam perangkat lunak itu, bukannya semua 5 menyalakan lampu LED pada saat yang sama, akan mengaktifkan bagian bawah 3 lampu LED yang pertama dan kemudian menghidupkan lampu LED atas 2.

Kekhawatiran lain, yang merupakan konsekuensi langsung dari skema pencahayaan kita, adalah waktu. Karena kita perlu strobo melalui serangkaian lampu LED untuk membuatnya tampak seolah-olah lebih dari satu LED pada pada saat yang sama kita harus berhati-hati tentang jumlah waktu yang dibutuhkan untuk siklus melalui semua LED's (refresh rate) dan waktu yang kita pegang masing-masing LED selama (duty cycle). Kami ingin mencoba untuk menjaga setiap LED pada selama mungkin karena siklus yang lebih panjang akan membuat lampu LED untuk lebih cerah. Namun, setiap LED memegang lebih lama akan berarti bahwa dibutuhkan lebih banyak waktu untuk menggilir semua LED dan jika refresh rate terlalu lambat maka Anda bisa melihat terlihat berkedip. Setelah beberapa pengujian kami memutuskan bahwa kami ingin menggilir semua LED's setiap 16 ms memberi kami kira-kira 62,5 Hz refresh rate dan menghapuskan setiap terlihat berkedip. Ini berarti bahwa dalam 16 ms kita harus menggilir semua kolom 25 dari kami dan untuk setiap kolom, pegang bawah tiga lampu LED yang dinyalakan pada saat ini untuk sementara waktu, mematikannya, dan kemudian terus atas dua. Kami menemukan bahwa kami bisa terus masing-masing dari 50 set lampu LED (atas dan bawah dari masing-masing dari 25 kolom) pada 200 S dan masih memenuhi persyaratan refresh rate; masing-masing "frame" akan mengambil 10 ms untuk membuat meninggalkan kami dengan 6 ms rahmat waktu untuk melakukan perhitungan yang diperlukan untuk frame berikutnya. Software Description Kontrol perangkat lunak untuk LED kubus memiliki struktur yang sangat sederhana.

Pertama kita dua flash array diinisialisasi dengan pra-kolom yang diberikan untuk semua kemungkinan angka dan huruf sehingga kita bisa melihat ini dengan mudah untuk string ditampilkan pada kubus. Dalam kasus kami, kami bisa saja dikodekan keras string karena kita hanya memiliki satu intro string, tapi kami memutuskan untuk melakukan hal ini dan menggunakan rutin inisialisasi sehingga ini mungkin dapat dimanfaatkan dalam proyekproyek masa depan yang mencoba LED kubus dan ingin menampilkan teks . Ini juga tersimpan beberapa ruang memori. Kami membuat sebuah rutin inisialisasi yang kita sebut di awal fungsi utama untuk mendirikan directionality pelabuhan yang kita digunakan untuk mengontrol kubus. Kami pada dasarnya hanya membutuhkan dua bit bagian bawah dari PORTA untuk analog ke digital kita konversi untuk menjadi masukan bagi dua baris accelerometer, semua pelabuhan pin dari PORTC dan bagian bawah port 3 pin PORTB untuk menjadi output untuk mengontrol pencahayaan kubus . Tata letak yang sebenarnya pin dijelaskan secara rinci dalam komentar-komentar dari kode pada rutin inisialisasi. Kami mengatur timer 0 untuk dijalankan pada pertandingan membandingkan dengan prescaler dari 64, mengatur OCR mendaftar ke 249, dan memungkinkan membandingkan pertandingan menyela. Ini memberi kami interupsi yang memicu sekali per milidetik. Dengan basis waktu milidetik ini, kita bisa menjadwalkan tugas tepat. Kami juga menginisialisasi sebuah counter untuk penjadwalan tugas kita. Kami menginisialisasi analog-ke-digital untuk dijalankan pada 125KHz, untuk pertama-tama mengubah saluran ketika 0 konversi dimulai, dan mengganggu konversi dilakukan sehingga kita bisa melakukan dua konversi berturut-turut dengan mudah. Kami kemudian memanggil kami sensor rutin inisialisasi untuk menginisialisasi nilai-nilai bias accelerometers kami dan kemudian kami intro rutin inisialisasi untuk menginisialisasi sebuah array nilai kolom untuk digunakan dalam menampilkan string pengantar kami. Akhirnya, kita menginisialisasi variabel negara kita dan mulai konversi dari nilai-nilai accelerometer. Mengkalibrasi sensor yang rutin melakukan hanya apa dengan namanya. Mengasumsikan bahwa kubus mulai berdiri pada dasar (atas dan bawah orientasi), kami mencari tahu bias nol kedua dari sensor. Kami hanya melakukan tiga konversi dari masing-masing dari kedua nilai accelerometer dan dibagi dengan tiga untuk mendapatkan nilai rata-rata. Kami menyimpan nilai-nilai ini sebagai x dan y kita accelerometer konversi bias (akan dikurangkan dari membaca masa depan ketika kita melakukan konversi). Analog ke digital dilakukan konversi rutin layanan interupsi digunakan untuk melakukan konversi dua kali berturut-turut (dari x dan y accelerometer nilai-nilai) dengan cepat tanpa memperlambat program lain atau melakukan pengkodean lain yang lebih rumit trik. Kami menginginkan dua nilai konversi harus dilakukan pada waktu yang sangat mirip dan tersedia bersama-sama. Kami menggunakan variabel keadaan untuk melacak saluran yang kami mengubah, dan memeriksa dalam rutin ini. Jika itu adalah yang pertama dari kedua, kita ambil nilai konversi, mengubah analog ke digital multipleks multiplekser ke saluran berikutnya, mengubah variabel keadaan untuk mencerminkan bahwa kita mengkonversi nilai berikutnya, dan menginisialisasi konversi berikutnya. Saat ini konversi berikutnya akan kembali ke ISR, kami menyimpan nilai konversi dan menetapkan bendera global yang menandakan bahwa data konversi siap sehingga program lain dapat menggunakan nilai

konversi. Kita hanya memiliki satu tugas dalam perangkat lunak yang merupakan tugas layar kita. Hal ini dijadwalkan sekali setiap 16 mS menggunakan counter yang menghitung mundur dari 16 milidetik kami menyela tanda centang (dan sederhana jika pernyataan dalam lingkaran utama yang memeriksa saat counter menjadi nol). Keterlambatan ini menimbulkan panggilan 62.5Hz tingkat yang jauh di atas refresh rate tampilan bahwa mata manusia dapat melihat. Jadi, kami tidak dapat mendeteksi setiap berkelap-kelip di lampu LED. Walaupun namanya, yang sebenarnya beberapa hal lain juga. Pada awal tugas layar, kami memeriksa animasi kami / demo negara dan memperbarui frame buffer dengan frame dari animasi. Frame buffer yang terdiri dari sebuah array dari 25 byte. Setiap byte dalam frame buffer berkaitan dengan suatu kolom dalam tampilan LED. Nomor indeks dalam array sesuai dengan jumlah kolom. Kolom dari kubus yang disusun dengan asumsi sebagai berikut kita melihat kubus dari atas dengan bagian depan kubus di bagian bawah layar: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Bagian bawah lima bit dari setiap byte dalam frame buffer yang mewakili dari lima LED dalam kolom yang saat ini sedang dinyalakan. Yang paling significant bit dari byte LED di bagian bawah kolom dan ke-5 bit paling signifikan atas LED. A 1 mewakili pada 0 mewakili sedangkan off. Selanjutnya, tugas layar cek apakah ada percepatan konversi siap, mengubahnya ke nilai floating point dan mengurangi bias bahwa kita menghitung ketika kita menginisialisasi sistem, dan akhirnya mulai konversi baru (menempatkan konversi dalam keadaan pertama mengkonversi y percepatan). Ini memberi kita nilai skala percepatan pada sumbu x dan y. Kami benar-benar berakhir hanya dengan menggunakan x percepatan, tapi meninggalkan kode untuk bagaimana melakukan dua konversi berturut-turut sebagai contoh untuk bagaimana siswa di masa depan mungkin bisa mencapai hal ini. Data tambahan bahkan bisa digunakan dalam perpanjangan proyek ini bersama dengan mesin negara untuk memberikan informasi negara yang lebih kompleks untuk bagaimana berorientasi kubus. Dengan sedikit debug menggunakan USART dari Mega32, kami menemukan bahwa 1g gravitasi sekitar + -74 unit ADC konversi sumbu accelerometer (setelah bias). Kami menggunakan ini untuk mendeteksi apakah kubus berujung pada sisinya. Kami pada dasarnya mengatakan ini adalah berujung pada sisi x positif jika nilai percepatan pada sumbu x lebih besar dari 65 dan ini berujung pada hal yang negatif x sisi jika percepatan dalam sumbu kurang dari -65. Ini memberi kami performa yang cukup bagus ketika kita mengujinya. Dalam kasus bahwa papan tip, kami harus menyalin frame buffer ke buffer sementara dan kemudian "flip buffer" 90 derajat ke sisi yang benar. Ini ternyata menjadi non-sepele perhitungan dan dapat dilihat dalam bagian ini tampilan kode tugas dalam lampiran. Ide dasarnya adalah sebagai berikut:

Melihat bagian depan kubus, kita bisa memikirkan masalah dalam konteks tampilan 2D karena semua irisan kubus harus diputar dengan cara yang sama dan kita bisa membangun sebuah loop yang mengulangi melalui 5 iris belakang ke depan melakukan hal yang sama hanya dengan offset sederhana. Hal ini diilustrasikan pada Gambar 5.

Dengan sedikit mengutak-atik, itu adalah sepele (walaupun sedikit membosankan) untuk flip frame 90 derajat dalam arah yang sesuai. Setelah semua ini, satu-satunya yang tersisa untuk dilakukan dalam fungsi layar, sebenarnya adalah menyalakan lampu LED yang ditunjukkan seperti di dalam frame buffer. Pada dasarnya, kami menggunakan untuk loop untuk berjalan melalui kolom satu per satu waktu, menyalakan lampu LED yang sesuai untuk 200uS dan kemudian pergi lagi. Ini nyala dari lampu LED adalah begitu cepat sehingga tidak dapat dimengerti oleh mata manusia (satu urutan dari nyala memakan waktu sekitar 10 ms = 25 * 2 * 200uS). Untuk setiap kolom, sebenarnya kita menyalakan bawah 3 lampu LED yang ditandai sebagai menyalakan dan kemudian atas 2. Membatasi arus ini menarik dari kami gating LED power transistor (yang tidak diberi nilai untuk arus yang cukup tinggi untuk menyalakan lampu LED di 5 seri pada saat ini kami menempatkan melalui masing-masing) dan juga memperpanjang waktu hidup baterai kita tanpa menimbulkan konsekuensi negatif apapun selain mungkin kerugian kecil dalam kecerahan (jika ada). Jadi, mengingat kolom yang kami ingin menghidupkan, pertama-tama kita menginisialisasi karakter sementara dengan tiga bit bagian bawah sama dengan arus bawah kolom tiga bit. Kami kemudian menetapkan PORTB.0 ke paling atas dari tiga bit (yang alasan lapisan 3 jika tinggi) dan untuk menetapkan atas 2 bit paling signifikan dari PORTC dengan dua bit berikutnya. Port ini tanah lapisan 2 dan 1 masing-masing. Kami kemudian menetapkan 6 bit yang lebih rendah dari PORTC dengan nilai yang sesuai pilih yang kolom kita saat ini pencahayaan. Jika kolom ini 0-23, kita bisa mengatur ke-6 dari PORTC bit ke 0 dan lima yang rendah PORTC bit dengan jumlah kolom sejak kami mendirikan encoder kita memilih perangkat keras dan mikrokontroler baris ke kolom alamat dengan benar diberi jumlah kolom. Namun, jika kolom adalah sangat terakhir (nomor 24 atau 25 kolom) kita perlu menonaktifkan Decoder dan memungkinkan keenam kita pilih garis yang memungkinkan hanya 25 kolom. Kami menonaktifkan decoders dengan menetapkan lima bit bagian bawah

dari PORTC ke 11.000. Ini akan mengirim 11 sampai master encoder yang memilih yang tidak ada decoder, membuat semua decoders gerbang itu kekuasaan untuk kolom yang lain cacat. Akhirnya, kami sekarang memiliki dasar yang tepat 3 lampu LED menyala dan kami menunda untuk memungkinkan 200uS LED untuk cahaya dan terang bagi pemirsa dirasakan oleh mata, dan kemudian kami menonaktifkan lapisan dan kolom dengan menetapkan semua garis dasar rendah, mematikan listrik untuk 25 dan menetapkan garisgaris decoder untuk yang lagi-lagi 11.000 Menonaktifkan semua jalur diaktifkan oleh decoders. Kami kemudian melakukan top 2 lampu LED pada kolom di mode yang sama kecuali bahwa kita mengaktifkan lapisan, bukan menggunakan garis-garis yang sesuai pada PORTC.

HasilKubus mampu menampilkan pesan dan gambar dengan jelas belum terlihat berkedip atau keterlambatan. Walaupun pencahayaan maksimum 3 lampu LED pada suatu waktu kami masih mampu menghasilkan gambar yang memerlukan lebih dari 3 lampu LED akan menyala dengan nyala melalui beberapa lampu LED pada tingkat tinggi. Struktur juga mengejutkan kaku dan dapat menahan gemetar ringan dan berputar. Ini pada mulanya merupakan keprihatinan karena seluruh kubus ini diselenggarakan bersama oleh solder, kawat tembaga, dan papan busa. Namun, lampu LED tidak cerah seperti yang kami harapkan dan dalam ruangan yang cukup terang atau pada hari yang sangat cerah dapat sulit untuk melihat apa yang kubus berusaha untuk ditampilkan. Masalah ini dapat diperbaiki di masa depan dengan menggunakan transistor yang berbeda yang dinilai lebih tinggi saat ini dan dengan menggunakan resistor yang lebih kecil. Suatu transistor yang mampu memasok arus ke semua 5 lampu LED pada saat yang sama akan memungkinkan Anda untuk menyimpan setiap rangkaian lampu LED lebih lama (peningkatan siklus) dan resistor yang lebih kecil akan meningkatkan arus yang melalui LED; kedua hal ini akan memberikan kontribusi positif yang dirasakan kecerahan LED. Juga, mengingat lebih banyak waktu kita ingin datang dengan aplikasi yang lebih rumit dari kubus, mungkin menggunakannya untuk model dinamika fluida atau mungkin membuatnya menjadi permainan 3D pong. Produk terakhir kita baik digunakan dan aman. Kubus adalah baterai bertenaga dan semua komponen yang diperlukan yang terkandung dalam basis sehingga perangkat portabel baik dan aman. Kubus juga menghasilkan gangguan minimal dengan proyek lain karena satusatunya hal yang kita benar-benar 'memancarkan' adalah lampu merah. Untuk proyek kami demo, kami diprogram sebuah string yang pengantar gulungan di kubus dari kanan ke kiri yang berbunyi "FINAL ECE476 PROYEK DEMO" dan animasi singkat yang mengikuti string. Animasi terdiri dari beberapa pesawat horisontal bolak-balik yang kemudian berubah menjadi bidang horizontal di bidang pertengahan kubus. Hal ini kemudian menjadi morphs garis horizontal dari tengah depan kubus tengah ke belakang. Morphs ini ke bidang vertikal di tengah kubus yang kemudian meluas ke seluruh kubus dinyalakan. Akhirnya, LED spiral off dari kolom pertama di belakang kiri sampai ke tengah kolom (kolom 12). Sebuah video ini dapat dilihat di bawah ini bersama dengan contoh dari perubahan orientasi kemampuan kubus. MP4 video - res tinggi MOV video

Kami menggunakan ini sebagai demo untuk menunjukkan beberapa hal. Pertama-tama, teks bergulir menunjukkan bahwa itu mampu untuk menampilkan teks yang dapat dibaca pada LED 3D kubus dengan resolusi rendah 5x5 di sisi. Hal ini penting untuk setiap layar. Selanjutnya, teks bergulir adalah cara yang baik untuk menunjukkan bahwa perubahan orientasi pada kenyataannya benar dan dibedakan memutar kubus pada kedua sisi yang berbeda. Teks selalu gulungan di arah yang benar. Selanjutnya, animasi adalah cara untuk menunjukkan kemampuan layar. Ini menunjukkan hanya bagian kecil dari apa yang dapat ditampilkan pada kubus (apa saja yang dapat ditampilkan dalam grid 5x5x5 piksel) termasuk semua LED dihidupkan, pesawat, dan garis. Kita juga dapat menyalakan LED individu yang tidak ditampilkan dalam demo. Jelas bahwa hal ini mungkin didasarkan pada skema pencahayaan. Demo menunjukkan baik horisontal dan vertikal pesawat. Bidang vertikal adalah seluruh kolom diaktifkan tetapi horisontal pesawat secara individual LED dihidupkan dalam satu kolom (strobed satu pada satu waktu). Karena animasi ini tidak kembali ke depan simetris seperti teks, hal itu juga menunjukkan bahwa peralihan orientasi sebenarnya bekerja dengan benar (membalik semua pixel ke posisi yang benar) bila kubus itu berpaling pada sisinya.

KesimpulanKubus kami tampil cukup baik, kami mampu menampilkan pesan pada kubus yang dapat dibaca jika ruangan yang relatif gelap dan kamu sedang melihat pada sumbu. Menunjukkan terang kita juga bekerja sesuai dengan yang diharapkan dan baik pesan dan pertunjukan cahaya disesuaikan sendiri ketika Anda menoleh ke kubus ke samping. Jika kita mengulagi proyek kami telah merancang kita akan sedikit berbeda rangkaian driver LED yang akan dapat mensuplai arus listrik semua 5 lampu LED sekaligus dan juga membuat setiap LED cerah. Kita mungkin juga mempertimbangkan untuk membuat semacam kasus plexiglass untuk membuat struktur visual lebih kuat dan lebih menyenangkan. Selain itu kita akan melihat ke dalam menampilkan beberapa hal menarik lainnya di kubus kami. Pertimbangan Kekayaan Intelektual Kami kubus dibangun di atas ide awalnya dibuat dan dipatenkan oleh James Clar (www.JamesClar.com) USPTO paten # 7.190.328. Selain itu, kubus kita sedang digunakan hanya untuk tujuan pendidikan dan kami tidak punya maksud keuntungan dari James Clar desain asli dengan cara apapun. Pertimbangan etis Sepanjang proyek kami berpegang pada Kode Etik IEEE setiap saat. Kami telah secara konsisten mengambil keputusan yang menjamin kesehatan dan keselamatan publik dan orang-orang di sekitar kita dan menerima tanggung jawab atas keputusan ini. Kami juga menghindari konflik kepentingan seluruh proyek tetapi jika kita telah bertemu mereka, kita akan diperlihatkan kepada semua pihak yang terlibat. Selain itu kita telah realistis dan jujur dalam melaporkan hasil proyek kami dan telah mendukung klaim dan perkiraan kami yang sesuai dengan angka-angka dan gambar. Ketika bekerja pada proyek kami kami tidak menemui bentuk penyuapan tetapi jika kita sudah kita akan segera menolaknya. Kami juga telah diupayakan untuk meningkatkan pemahaman terhadap teknologi yang digunakan dan aplikasi potensi mereka dan telah berbagi pengetahuan kita dengan publik dalam bentuk website ini. Kami juga memastikan bahwa tindakan kita tidak akan menyebabkan kerugian atau cedera kepada orang lain dengan cara apapun dengan memastikan bahwa sirkuit kita

itu aman dan bahwa kami berbelok pasokan listrik dari sementara tanpa pengawasan dan tidak meninggalkan kabel terpapar dengan cara yang dapat membahayakan seseorang. Lebih penting lagi kita harus aktif mencari pekerjaan kita kritik dari TA dan dari Profesor Tanah dan telah membetulkan kesalahan bahwa mereka telah menunjuk keluar. Kami juga telah mencoba yang terbaik untuk membantu rekan-rekan kami dalam proyek-proyek mereka sendiri dan berbagi segala pengetahuan yang kita miliki dengan mereka yang tertarik. Dalam melakukan semua yang kami sebutkan di atas, kita percaya kita telah mengikuti Kode Etik IEEE secara keseluruhan.

Lampiran A - Program Kode# include / / termasuk instruksi perpustakaan bagi ATMega32 MCU # include //includes instruction library for time delays/pauses //Flash array to store how to make characters on our cube (3x5) //Each character is 3 bytes - first column, second column, third column flash unsigned char letters[78] = { //A 0b00001111, 0b00010100, 0b00001111, //B 0b00011111, 0b00010101, 0b00001111, //C 0b00011111, 0b00010001, 0b00010001, //D 0b00011111, 0b00010001, 0b00001111, //E 0b00011111, 0b00010101, 0b00010101, //F 0b00011111, 0b00010100, 0b00010100, //G 0b00011111, 0b00010011, 0b00011011, //H 0b00011111, 0b00000100, 0b00011111, //I 0b00010001, 0b00011111, 0b00010001, //J

0b00010001, 0b00011111, 0b00010000, //K 0b00011111, 0b00000100, 0b00011011, //L 0b00011111, 0b00000001, 0b00000001, //M 0b00011111, 0b00001000, 0b00011111, //N 0b00011111, 0b00001110, 0b00011111, //O 0b00011111, 0b00010001, 0b00011111, //P 0b00011111, 0b00010100, 0b00011100, //Q 0b00011111, 0b00010011, 0b00011111, //R 0b00011111, 0b00010110, 0b00011101, //S 0b00011101, 0b00010101, 0b00010111, //T 0b00010000, 0b00011111, 0b00010000, //U 0b00011111, 0b00000001, 0b00011111, //V 0b00011110, 0b00000001, 0b00011110, //W 0b00011111, 0b00000010, 0b00011111, //X 0b00011011,

0b00000100, 0b00011011, //Y 0b00011000, 0b00000111, 0b00011000, //Z 0b00011001, 0b00010101, 0b00010011 }; //Flash array to store how to make numbers on our cube (3x5) //Each character is 3 bytes - first column, second column, third column flash unsigned char numbers[30] = { //0 0b00011111, 0b00010001, 0b00011111, //1 0b00010001, 0b00011111, 0b00000001, //2 0b00010011, 0b00010101, 0b00011101, //3 0b00010101, 0b00010101, 0b00011111, //4 0b00011100, 0b00000100, 0b00011111, //5 0b00011101, 0b00010101, 0b00010111, //6 0b00011111, 0b00010101, 0b00010111, //7 0b00010001, 0b00010010, 0b00011100, //8 0b00011111, 0b00010101, 0b00011111, //9 0b00011101, 0b00010101, 0b00011111 };

//Current frame info, and acceleration data float a_x, a_y; //Current converted accelerations float bias_a_x, bias_a_y; //Calculated biases of x and y axis accelerometers unsigned char data_ready; //Flag indicating acceleration conversions ready unsigned char intro_pos; //Current position in the introduction string (scrolled) unsigned char intro_string[133]; //Buffer to hold all columns representing intro string unsigned char cur_frame[25]; //Buffer for current frame (25 columns - each bytes //5 least significant bits represent the five LEDs in a //column which are on if bit is 1, and off if bit is 0 unsigned char temp_convert[25]; //Buffer for a frame to use as temporary storage //Animation states #define INTRO_STRING #define ALTERNATING_HORIZONTAL_PLANES #define PLANE_TRANSITION #define CENTER_LINE_TO_VERTICAL_PLANE #define VERTICAL_PLANE_TO_ALL #define ALL_TO_NONE unsigned char animation_state; animation state unsigned char animation_count; variable for use with updating unsigned char animation_temp; useful variable to use animating, temporary state unsigned char plane_sequence[4] = {0x11,0x0a,0x04,0x0a}; of column values for use alternating planes animation unsigned char temp_frame[25]; frame buffer to keep frame between animation updates //A/D Conversion #define IDLE 0 #define CONVERTING_X 1 #define CONVERTING_Y 2 unsigned char conversion_stage; unsigned char ADC_accel_x; acceleration unsigned char ADC_accel_y; acceleration 0 1 2 3 4 5 //Current //Count //animation //Another //when //Sequence //in the //Temporary //state

//Conversion state variable //Reading from the ADC converter for X //Reading from the ADC converter for Y

//Temp variables (made global for faster allocation in method) unsigned char i, temp;

unsigned int count; //Scheduling timer variables #define DISPLAY_TIME 16 unsigned char display_count; task //Method prototypes void display_task(void); void initialize(void); void calibrate_sensors(void); void init_intro(flash char* str); takes a string and display

//Scheduling variable for display //Scheduled at ~ 60Hz (62.5Hz) //Display task //Initialization routine //Sensor calibration routine //Intro string initialization //converts it to column values for

/** * Timer interrupt code running at 1000 Hz (ms tick). **/ interrupt [TIM0_COMP] disp_int(void) { //Decrement display count each millisecond (used to schedule display task) if (display_count > 0) display_count--; } /** * ADC done interrupt, allows us to do one conversion after the other (accel_x,accel_y) **/ interrupt [ADC_INT] adc_int(void) { if (conversion_stage == CONVERTING_Y) { ADC_accel_y = ADCH; //Grab the converted value of Y_Accel conversion_stage = CONVERTING_X; //Update conversion stage ADMUX |= 0x01; //Switch conversion channel to A1 (x-accel) ADCSR &= 0xef; //Clear interrupt flag (just to be safe) ADCSR |= 0x40; //Start a new conversion } else if (conversion_stage == CONVERTING_X) { ADC_accel_x = ADCH; //Grab the converted value of X_Accel conversion_stage = IDLE; //Update conversion stage ADMUX &= 0xf8; //Clear conversion channel back to A0 (y-accel) ADCSR &= 0xef; //Clear interrupt flag (just to be safe) data_ready = 1; //Now we have both converted values, data is ready } }

/** * Main loop. **/ void main(void) { initialize(); //Main loop while(1) { //Schedule tasks if (display_count == 0) display_task(); } } /** * All the functionality is in this display task. It keeps animation/demo state and fills in * a frame buffer with the current LEDs to be lit in this frame (this is called once every 16mS * for a refresh rate of about 62.5Hz). The method also grabs acceleration values if they are * ready from the conversion task (which converts both x and y acceration channels and then sets * a flag) and then checks whether the acceration values are near +gravity whose values were * found with experimentation. If so, we flip the frame on its side left or right to keep the * same orientation of the frame with respect to the ground. **/ void display_task(void) { display_count = DISPLAY_TIME; //Reschedule this task //We are displaying the demo opening string if (animation_state == INTRO_STRING) { //Render appropriate frame right side up (current 5 columns for all //rows) offset by our current position in this prerendered string for (i = 0; i < 5; i++) { cur_frame[i] = intro_string[intro_pos+i]; cur_frame[i+5] = intro_string[intro_pos+i]; cur_frame[i+10] = intro_string[intro_pos+i]; cur_frame[i+15] = intro_string[intro_pos+i]; cur_frame[i+20] = intro_string[intro_pos+i]; } count++; //Use count to slow update (12*16mS = 192mS between scrolling updates) if (count > 12) { count = 0; intro_pos += 1;

//If we are at the end of the string, set animation_temp with its next value and //switch to first animation state "ALTERNATING_HORIZONTAL_PLANES" if (intro_pos > 128) { animation_temp = 0x11; animation_state = ALTERNATING_HORIZONTAL_PLANES; } } } //We are displaying two horizontal planes moving up and down opposite each other else if (animation_state == ALTERNATING_HORIZONTAL_PLANES) { //Render frame right side up (all columns get same value) for (i = 0; i < 25; i++) { cur_frame[i] = animation_temp; } count++; //Count slows update (again 192mS between updates) if (count > 12) { count = 0; animation_count++; //Use this count to clock through the animation sequence animation_temp = plane_sequence[animation_count & 0x03]; //Once we have done the animation a few times (and get to just a middle plane) if (animation_count == 0x1f) { animation_temp = 0; animation_count = 0; animation_state = PLANE_TRANSITION; } } } else if (animation_state == PLANE_TRANSITION) //Horizontal plane to front to back (middle) line { //Render frame right side up //First clear the frame for (i = 0; i < 25; i++) { cur_frame[i] = 0x00; } //Then turn on the appropriate middle LEDs (out *animation_count* turned off) for (i = animation_temp; i < 5-animation_temp; i++) { cur_frame[i] = 0x04; cur_frame[i+5] = 0x04; cur_frame[i+10] = 0x04; cur_frame[i+15] = 0x04; cur_frame[i+20] = 0x04;

} count++; //Count slows update (192mS between updates) if (count > 12) { count = 0; animation_count++; //Clock through animation sequence //Once the plane has turned to front to back line, switch animation states //Want to then turn front to back line into a vertical plane on the middle //LEDs from front to back if (animation_count == 3) { animation_temp = 0x04; //First value for the plane animation_count = 0; animation_state = CENTER_LINE_TO_VERTICAL_PLANE; } else { animation_temp = animation_count; } } } else if (animation_state == CENTER_LINE_TO_VERTICAL_PLANE) //Front to back line to vertical plane { //Render frame right side up for (i = 0; i < 25; i++) { cur_frame[i] = 0x00; } cur_frame[2] = animation_temp; cur_frame[7] = animation_temp; cur_frame[12] = animation_temp; cur_frame[17] = animation_temp; cur_frame[22] = animation_temp; count++; //Count slows update (192mS between updates) if (count > 12) { count = 0; animation_count++; //Clock through animation sequence //Update the next value to use for the center columns switch (animation_count) { case 1 : animation_temp = 0x0e; break; case 2 : animation_temp = 0x1f; break; case 3 : animation_temp = 2; animation_count = 0; animation_state = VERTICAL_PLANE_TO_ALL; //Next animation state break;

}

}

} else if (animation_state == VERTICAL_PLANE_TO_ALL) //Transition from vertical plane to all lit { //Render frame right side up for (i = 0; i < 25; i++) { cur_frame[i] = 0x00; } //Turn all LEDs on for all columns front to back for inner 1+2*animation_temp LEDs for (i = animation_temp; i < 5-animation_temp; i++) { cur_frame[i] = 0x1f; cur_frame[i+5] = 0x1f; cur_frame[i+10] = 0x1f; cur_frame[i+15] = 0x1f; cur_frame[i+20] = 0x1f; } count++; //Count slows update (15*16mS = 240mS between updates) if (count > 15) { count = 0; animation_count++; //Clock through the animation (set animation_temp //appropriately for next display frame) switch (animation_count) { case 1 : animation_temp = 1; break; case 2 : animation_temp = 0; break; case 3 : animation_temp = 0; animation_count = 0; animation_state = ALL_TO_NONE; //Initialize the temporary frame with the current one (all on) for (i = 0; i < 25; i++) temp_frame[i] = cur_frame[i]; break; } } } else if (animation_state == ALL_TO_NONE) //Spiral to none lit { //Render frame right side up for (i = 0; i < 25; i++) cur_frame[i] = temp_frame[i]; count++; //Count slows update (192mS between updates) if (count > 12) { count = 0; animation_count++; //Clock animation //This is the update seqence for the all lit cube spiralling

inwards to //none, turning off columns as we spiral, given the following column //orientation looking at the cube from above: // 0 1 2 3 4 // 5 6 7 8 9 // 10 11 12 13 14 // 15 16 17 18 19 // 20 21 22 23 24 //The sequence of columns to turn off is: // {0,1,2,3,4,9,14,19,24,23,22,21,20,15,10,5,6,7,8,13,18,17,16,11,12} //First 5 we count from 0 if (animation_count < 6) { temp_frame[animation_count-1] = 0x00; } //Next four we count by fives from 9 (simplified below) else if (animation_count < 10) { temp_frame[animation_count*5 - 21] = 0x00; } //Next four we count down by ones from 23 else if (animation_count < 14) { temp_frame[33-animation_count] = 0x00; } //Next 3 we count down by fives from 15 else if (animation_count < 17) { temp_frame[(17-animation_count)*5] = 0x00; } //Next 3 we count up by ones from 6 else if (animation_count < 20) { temp_frame[animation_count - 11] = 0x00; } //Next 2 we count up by fives from 13 else if (animation_count < 22) { temp_frame[(animation_count - 20) * 5 + 13] = 0x00; } //Next 2 we count down by ones from 17 else if (animation_count < 24) { temp_frame[39 - animation_count] = 0x00; } //For the final two we count up by ones from 11 else { temp_frame[animation_count - 13] = 0x00; } //Once we have gone through all the columns, go to next state if (animation_count == 25) {

animation_temp = 0; animation_count = 0; animation_state = INTRO_STRING; intro_pos = 0; position } } }

//Back to intro string //Make sure we are at first

//If conversion data is ready, clear flag, get accelerations, start next conversion if (data_ready) { data_ready = 0; //Clear data ready bit //Convert the sampled 8-bit values to accelerations +/- 74/g (x) and 77/g (y) a_x = -((float)ADC_accel_x - bias_a_x); a_y = -((float)ADC_accel_y - bias_a_y); //Start a new conversion conversion_stage = CONVERTING_Y; ADCSR |= 0x40;

}

//Now flip frame sideways as necessary if (a_x > 65.0) //We are on +x side, scroll up, come up with frame { //Convert this frame to left is bottom (zero bits of all become last column, etc) //First columns bit is first bit etc for (i = 0; i < 5; i++) { temp = 5*i; //Last column (all first bits in order) temp_convert[temp+4] = (cur_frame[temp+0] & 0x01) | ((cur_frame[temp+1] 1) > 1) > 1) > 1) > 2) & 0x01) | (((cur_frame[temp+1] >> 2) > 2) > 2) > 2) > 3) & 0x01) |

(((cur_frame[temp+1] >> 3) > 3) > 3) > 3) > 4) & 0x01) | (((cur_frame[temp+1] >> 4) > 4) > 4) > 4) 1) > 1) > 1) > 2) & 0x01) | (((cur_frame[temp+3] >> 2) > 2) > 2) > 2) > 3) & 0x01) | (((cur_frame[temp+3] >> 3) > 3) > 3) > 3) > 4) & 0x01) | (((cur_frame[temp+3] >> 4) > 4) > 4) > 4) > 2; if (i < 24) { PORTC = i | (temp 2; if (i < 24) { PORTC = i | (temp