Beberapa waktu lalu, ia berpartisipasi dalam diskusi tentang proyek DIY dari arloji LED matriks.
Dan yang mengejutkan saya - matriks LED monokromatik 8x8 kuno dengan langkah 5 milimeter digunakan sebagai perangkat tampilan. Terlebih lagi, papan sirkuit tercetak yang kompleks dibuat untuknya, indikasi dinamis yang lembut dibuat. Dan ini adalah saat ketika panel LED 64x32 penuh warna yang siap pakai dengan pitch 3 mm telah lama tersedia dengan harga $ 10-20. Dan bermacam-macam panel seperti itu sangat besar dan memiliki pitch pixel 2 hingga 10 mm dan hampir semua ukuran.
Pada saat yang sama, menggunakan panel seperti itu dalam desain DIY cukup sulit - pengontrol siap pakai harganya cukup mahal dan tidak memiliki API normal. Sangat sulit untuk melakukan pemindaian panel yang cukup cepat pada mikrokontroler yang biasa digunakan di DIY. Selain itu, interval waktu harus dijaga dengan akurasi tinggi - jika tidak, ketidakrataan kecerahan yang terlihat dimulai.
Ada solusi bagus di
Adafruit , tetapi semuanya cukup mahal dan kompleks.
Setelah beberapa pemikiran, muncul pemikiran - mengapa tidak membuat papan yang sangat murah yang akan menjadi jembatan antara papan sen biasa seperti arduino dan panel LED? Setelah beberapa bulan ribut-ribut, sesuatu yang berhasil lahir.
Artikel ini menjelaskan versi kedua dari pengontrol yang ditingkatkan.
Tantangan
Sebagai tugas dasar, saya ingin dapat mengontrol panel dengan ukuran total setidaknya 64x64, sementara memiliki kemampuan untuk bekerja setidaknya di Highcolor (RGB565) sambil mempertahankan kecepatan refresh layar yang dapat diterima (setidaknya 50Hz). Dalam versi pertama dari pengontrol, tugas dasar sepenuhnya dilaksanakan, tetapi muncul ide untuk mengimplementasikan tugas dengan metode lain yang sangat menjanjikan, dari mana versi kedua lahir.
Penjelasan dasar tentang desain panel LED yang khas
Input antarmuka HUB75:
Pada setiap input warna ada rantai register tipe HC595 (tetapi versi khusus 16-channel untuk LED). Ada begitu banyak register yang cukup untuk lebar panel. Rusak, boot paralel, dan izin output umum untuk semua register. Input ABCDE - ini adalah pilihan seri - pergi ke dekoder konvensional.
Prinsip kerja:
- atur data ke input RGB, klik tombol CLK. Ulangi sampai kami memuat seluruh baris
- matikan output OE = 1 (sehingga tidak ada gangguan)
- berikan kepada decoder nomor baris yang dimuat
- klik paralel load LAT - data garis ditransfer ke register keluaran
aktifkan keluaran OE = 0 - ulangi untuk baris berikutnya
Itu adalah indikasi dinamis klasik. Jelas bahwa dengan metode ini dalam satu siklus seperti itu kita hanya dapat menghidupkan / mematikan setiap LED tertentu.
Untuk mendapatkan gradasi kecerahan dengan PWM klasik, siklus seperti itu harus diulang N-1 kali, di mana N adalah jumlah gradasi kecerahan (256 untuk RGB888). Dan mengingat bahwa pada saat yang sama masih berkedip - semua ini harus dilakukan dengan sangat, sangat cepat.
Ada solusi - Bit Angle Modulation (BAM). Dalam hal ini, waktu cahaya dalam setiap siklus sebanding dengan bobot bit yang ditampilkan. Artinya, untuk RGB888 Anda hanya perlu 8 siklus tampilan. Sedikit lebih rinci di sini .
Versi pertama dari pengontrol menggunakan PWM klasik, yang menerapkan batasan ketat pada jumlah siklus pemindaian. Dalam versi kedua, BAM diimplementasikan, yang memberi keuntungan besar dalam kecepatan.
Implementasi
Cukup jelas bahwa mikrokontroler konvensional hanya menarik panel kecil - yang besar tidak memiliki kecepatan yang cukup. Oleh karena itu, CPLD atau FPGA sangat diperlukan di sini - secara fisik tidak mungkin untuk menghasilkan puluhan MB / s pada mikrokontroler berbiaya rendah.
Sebagai memori, saya direkomendasikan di forum IXBT oleh FIFO memory Averlogic AL422B yang sangat menarik, yang memiliki sekitar 400kbytes memori dan dapat beroperasi pada frekuensi hingga 50MHz.
Mempertimbangkan bahwa persyaratan utama saya adalah biaya rendah maksimum dari komponen, sehingga syal jadi dapat diakses oleh produsen buatan sendiri, Altera EPM3064 - CPLD dengan 64 macrocell dipilih. Pada saat yang sama, sejumlah kecil sel makro tidak memungkinkan membuat papan yang dapat dikonfigurasi secara dinamis - konfigurasi harus dikompilasi langsung ke dalam CPLD.
β Sirkuit yang dihasilkan terletak di sini
Detail:
- CPLD EPM3064ATC44-10 - harga Ali adalah sekitar $ 13-15 untuk selusin
- FIFO RAM AL422B - harga Ali adalah sekitar $ 15 per lusin
- Osilator kristal 50MHz. Papan menyediakan untuk instalasi dalam kasus DIP14 / DIP8 / 7050. Harga Ali adalah sekitar $ 6-7 per lusin
- Stabilizer 3.3V dalam paket SOT223. Harga dalam bentuk Chip dan Dip - 40r
- Konektor IDC-10MS. Harga dalam Chip & Dip - 3 p / potong
- Konektor IDC-16MS. Harga dalam Chip & Dip - 8 r / potong
- Konektor IDC-14MS. Harga dalam Chip & Dip - 7 r / potong
- Kapasitor 1 mikrofarad 0805 - 8 buah sekitar 1 r / potong
- Kapasitor 0,1 uF 0805 - sekitar 1 r / potong
- Resistor 10k 0805 - satu sen
Total detail diperoleh 1,5 + 1,5 + 0,7 = $ 3,7 dan 40 + 3 + 8 + 7 + 8 * 1 + 1 = 67 p. Semuanya dalam $ 5 - satu sen.
β Gambar papan asli ada di sini
β File gerber yang disiapkan untuk pemesanan
Papan disiapkan untuk versi pertama, di mana tidak ada kontrol RE. Untuk menggunakannya dengan versi kedua, Anda harus memotong jumper antara terminal 23 dan 24 dari AL422B dan membuang kabel dari terminal 28 EPM3064 (dibawa ke blok terminal) ke terminal 24 dari AL422B.
Saat menyolder papan, jangan lupa untuk menyolder jumper listrik di bagian belakang papan.


Perhitungan
Perhitungan parameter yang diperlukan cukup rumit.
Faktanya adalah bahwa dalam pengontrol dua proses dilakukan secara paralel - memuat data dari baris berikutnya / menunjukkan jalur yang sudah dimuat.
Proses dimulai secara bersamaan, tetapi berakhir pada waktu yang berbeda, sehingga proses yang lebih cepat menunggu selesainya proses yang lebih lama.
β Tablet Excel dibuat untuk perhitungan
Sumber data:
- CRYSTAL_FRQ (MHz) - frekuensi generator (50 MHz)
- PIXEL_COUNT - jumlah piksel di bilah unduhan. Lebih detail di bagian switching.
- RGB_INPUTS - jumlah input RGB yang digunakan dalam antarmuka HUB75E dari panel yang digunakan. 1 atau 2
- BYTES_PER_PIXEL - byte per piksel. Dalam kasus kami, selalu 3 - RGB888
- SCAN_LINES - jumlah garis pindai di panel yang digunakan. 8/16/32
Parameter yang dipilih:
- PRE_DELAY - tunda dari sinyal LAT sampai OE dihidupkan, atur ticks
- PRESCALER - prescaler untuk penghitung utama. Yaitu, jika daftar harga adalah 8 dan berat bit saat ini adalah 4, maka OE akan dihidupkan selama 8 * 4 = 32 siklus
- POST_DELAY - jeda minimum dari mematikan OE ke sinyal LAT berikutnya, atur ticks
Misalnya, kami memiliki panel 32x32 yang memiliki 8 garis pindai dan 2 input RGB. Panel semacam itu memiliki dua konektor HUB75E, yaitu, secara fisik ini adalah dua panel 32x16. Kami menghubungkan panel-panel ini secara seri, yaitu, secara logis panel ini akan terlihat seperti 64x16.
PRE_DELAY dan POST_DELAY mengosongkan interval sebelum dan sesudah output diaktifkan (OE) sehingga multiplexer dapat mengalihkan output dan kunci membuka / menutup. Tanpa mereka, akan ada "trik" dari membakar piksel ke garis yang berdekatan. Nilai dipilih secara eksperimental untuk panel tertentu. Biasanya 15 langkah sudah cukup (diatur dalam langkah-langkah).
Ini menimbulkan pertanyaan memilih prescaler - bagaimana memilihnya.
Nilai prescaler rendah memberikan waktu tampilan bingkai pendek, tetapi mengurangi kecerahan keseluruhan. Nilai tinggi dari prescaler meningkatkan waktu tampilan frame, yaitu, ketika menghitung, itu berkedip layar.
Mari kita coba PRESCALER = 1
Kami mendapatkan:
OE_EFFICIENCY - 8,3%, mis. Panel hanya akan bekerja 8,3% dari kemungkinan kecerahan maksimum
FRAMES_PER_SECOND - 2034 fps - tetapi kecepatan refresh gambar akan sangat besar - lebih dari 2000 fps.
Hilangnya kecerahan sudah sangat besar.
Mari kita coba PRESCALER = 16
Kami mendapatkan:
OE_EFFICIENCY - 72,9% artinya, panel akan bekerja pada 72,9% dari kemungkinan kecerahan maksimum
FRAMES_PER_SECOND - 1117 - dan kecepatan refresh gambar sangat baik - lebih dari 1000 fps.
Yah, itu cukup normal - efisiensi lebih dari 50% cukup normal dan frame rate sangat baik.
Aturan umum praktis adalah PRESCALER sekitar 8 kali lebih kecil dari produk PIXEL_COUNT * RGB_INPUTS
Baiklah, terus menghitung dan memeriksa.
Berpindah panel LED
Semua panel terhubung secara seri. Diagram koneksi: pertama dari kanan ke kiri, lalu dari bawah ke atas. Artinya, pertama kita hubungkan horizontal secara seri, kemudian output dari baris bawah ke pintu masuk baris kedua dari bawah, dll. ke baris paling atas.
Kontroler menempel di panel kanan bawah.
Ada panel yang memiliki dua input dan dua konektor output. Panel semacam itu pada dasarnya hanyalah rakitan mekanis dua panel secara vertikal. Diganti sebagai dua panel independen.
Setelah perakitan, kita perlu menghitung panjang total rantai dalam piksel - untuk ini kita lihat - berapa banyak total panel dalam rantai dan kalikan angka ini dengan lebar panel dalam piksel. Jumlah ini kemudian perlu didorong ke nilai PIXEL_COUNT selama konfigurasi CPLD dan ke dalam kalkulator waktu.
Firmware FPGA
Semua file yang diperlukan ada di github . Anda perlu mengunduh langsung dengan folder tersebut.
Setelah mendaftar, Anda harus mengunduh dan menginstal Quartus II 13.0sp1 dari situs web Altera. Anda perlu mengunduh PERSIS versi INI - versi yang lebih baru tidak lagi mendukung seri MAX3000. Tidak perlu untuk memecahkannya - versi edisi Web (gratis) sudah cukup. Saat mengunduh, pastikan untuk mencentang kotak untuk MAX3000 dan dukungan Programmer. Untuk jaga-jaga, saya memperingatkan Anda - paket besar, sekitar dua pertunjukan. Anda juga membutuhkan Altera USB Blaster - harga yang biasa untuk ali adalah sekitar $ 3.
Buka proyek al422_bam.qpf. Di sebelah kiri, buka tab file dan buka file al422_bam.v - ini adalah file proyek utama. Di dalamnya Anda perlu mengkonfigurasi parameter:
Berapa banyak input RGB pada panel - pada panel dengan input HUB75 mungkin ada 1 atau 2 input RGB. Untuk mengetahui dengan tepat berapa banyak input yang mungkin dengan cara ini - kami mengambil jumlah piksel dalam panel secara vertikal. Membaginya dengan jumlah garis pindai (ditunjukkan dalam penunjukan panel sebagai 8S, misalnya). Dibagi dengan jumlah konektor input (1 atau 2). Misalnya - Saya memiliki panel 32x32, pemindaian 8S, dan dua konektor input - 32/8/2 = 2 - yang berarti dua input RGB.
`define RGB_outs 2
Berapa banyak garis pindai pada panel - karena standar HUB75E didukung, dapat mencapai 32x. Jumlah garis pindai biasanya dalam nama panel masing-masing dalam bentuk 8S / 16S / 32S.
Hanya satu baris yang harus dihapus komentar:
`define SCAN_x8 1 //`define SCAN_x16 1 //`define SCAN_x32 1
Jumlah total piksel horizontal dalam rantai. Piksel dipertimbangkan dalam seluruh rantai panel - lihat bagian di atas βMengalihkan panel LEDβ
`define PIXEL_COUNT 64
Fase-fase sinyal keluaran. Konfigurasi yang paling umum adalah ini: OE aktif pada level rendah (komentar dihapus), CLK berjalan di depan (komentar aktif), LAT aktif pada level tinggi (komentar aktif). Segala macam opsi aneh mungkin terjadi. Cari tahu yang mana yang Anda miliki hanya secara eksperimen atau dengan menghapus sirkuit dan mencari lembar data untuk chip yang digunakan).
//`define LED_LAT_ACTIVE_LOW 1 `define LED_OE_ACTIVE_LOW 1 //`define LED_CLK_ON_FALL 1
Pra dan pasca tunda sinyal OE relatif terhadap LAT dan prescaler untuk penghitung utama. Lihat di atas.
`define OE_PRESCALER 16 `define OE_PREDELAY 31 `define OE_POSTDELAY 31
Semua, tekan ctrl-L - proyek dikompilasi. Jika Anda tidak mengacaukannya di mana saja, akan ada beberapa peringatan, tetapi seharusnya tidak ada kesalahan. Selanjutnya, kita kaitkan papan solder ke USB Blaster, berikan daya ke papan. Di Quartus, buka tools - programmer. Pilih USB-blaster di pengaturan Perangkat Keras, klik Mulai. Itu dia, CPLD diprogram.
Bagian mikrokontroler
Output data ke controller, secara umum, sangat sederhana - kami mereset alamat tulis dan kemudian secara berurutan mengeluarkan byte data, membelai mereka dengan sinyal WCLK. Dan tampaknya arduinka dangkal pun cukup untuk bekerja. Tetapi ada dua masalah:
a) Membutuhkan banyak memori. Bahkan panel 32x32 kecil dalam mode RGB888 membutuhkan 3kBytes memori untuk buffer layar. Atmega328 berbasis Arduino biasa hanya mengandung 2kbytes RAM. Anda dapat, tentu saja, menggunakan papan Mega berdasarkan Atmega2560, yang mengandung RAM sebanyak 8 kB, tetapi bahkan ini tidak cukup untuk panel berukuran normal - panel 128x64 dalam mode RGB565 membutuhkan memori 16kB.
b) Dalam proses bekerja dengan AL422B, kesalahan yang tidak didokumentasikan keluar - ketika menulis data dengan kecepatan kurang dari 2MB / s, penghitung alamat tidak berfungsi dengan benar dan menulis data "tidak ada". Mungkin ini adalah kesalahan pesta saya. Mungkin tidak. Tapi kesalahan ini harus dielakkan. Mengingat bahwa AVR8 beroperasi pada 16 MHz, hampir mustahil untuk memperoleh data darinya pada kecepatan yang diinginkan.
Solusi yang diusulkan adalah menggunakan syal murah berdasarkan pengontrol STM32F103C8T6 32-bit. Syal semacam itu berharga Ali sekitar $ 2,5 per potong, atau sekitar $ 1,7 ketika membeli selusin, yaitu, bahkan lebih murah daripada Arduino Nano. Pada saat yang sama, kami mendapatkan mikrokontroler 32-bit penuh yang beroperasi pada 72 MHz dan memiliki 20 kB RAM dan 64 kB flash (bandingkan dengan Atmega328 2kB / 8kB, yang ada di Nano).
Pada saat yang sama, papan semacam itu cukup berhasil diprogram di lingkungan Arduino. Tentang ini ada artikel bagus di jam , jadi saya tidak akan menduplikatnya. Secara umum, lakukan semuanya seperti yang dijelaskan dalam artikel.
Di lingkungan Arduino, pilih Generic STM32F103C, varian STM32F103C8 board. Data melewati DMA, sehingga Anda dapat menggunakan opsi pengoptimalan apa pun.
Perpindahan terjadi sebagai berikut:
Dipaku dengan kuat di perpustakaan:
A0..A7 β DI0..DI7 AL422B
B0 β WCLK AL422B
B1 β WRST AL422B
Ditetapkan dalam sketsa ke controller:
B10 β KAMI AL422B
Kawat biasa:
G β GND
Nah, jangan lupa untuk memasok daya 5V / GND dari panel ke pin pengontrol yang sesuai.
Ambil pinout konektor pada pengontrol dari sirkuit .

Bagian perangkat lunak
Karena tugasnya adalah membuat semuanya sesederhana dan semurah mungkin, semua perangkat lunak dibuat untuk lingkungan Arduino dan dirancang sebagai perpustakaan LED_PANEL .
Perpustakaan LED-PANEL aktif menggunakan perpustakaan Adafruit GFX , sehingga perlu diinstal.
Saya sangat merekomendasikan untuk tidak meletakkan pustaka LED_PANEL di direktori pustaka, tetapi meninggalkannya di folder sketsa. Faktanya adalah bahwa ada banyak parameter terikat-besi, dan jika Anda ingin mentransfer pekerjaan ke mikrokontroler yang lebih "gemuk", Anda harus mengubah banyak hal dalam kode itu sendiri.
Inisialisasi kira-kira dalam bentuk berikut:
#include "LED_PANEL.h" #define width 32 #define height 32 #define bpp 3 #define scan_lines 8 #define RGB_inputs 2 #define we_out_pin PB10 LED_PANEL led_panel = LED_PANEL(width, height, bpp, scan_lines, RGB_inputs, we_out_pin);
yaitu, kita membuat turunan dari kelas LED_PANEL, yang kami tentukan parameternya:
width - total lebar panel dalam piksel (total)
tinggi - tinggi total panel dalam piksel (total)
bpp - byte per pixel, 3 untuk RGB888. Versi BAM hanya berfungsi di RGB888
scan_lines - jumlah garis pindai adalah 8/16/32. Itu harus sesuai dengan mode flash ke controller.
RGB_inputs - jumlah input RGB pada konektor HUB75 adalah 1/2. Itu harus sesuai dengan mode flash ke controller.
we_out_pin - pin yang terhubung dengan output WE
Harap dicatat bahwa selama inisialisasi, hanya pin WE yang ditentukan. Semua pin lainnya terdaftar secara kaku dalam kode, karena mereka terikat pada timer dan saluran DMA yang digunakan dan perubahan mereka akan memerlukan perubahan signifikan dalam kode.
Memulai dan membersihkan layar di bagian pengaturan:
led_panel.begin(); led_panel.clear();
mulai inisialisasi pin yang diperlukan untuk output, menghubungkan timer dan DMA
hapus membersihkan buffer
Untuk menggambar, Anda dapat menggunakan semua prosedur standar perpustakaan Adafruit GFX - dari drawPixel yang paling sederhana hingga keluaran teks. Untuk menampilkan ditarik ke prosedur buffer digunakan:
led_panel.show();
Dalam bentuk ini, tunjukkan memulai transfer data ke controller melalui DMA dan segera mengembalikan kontrol. Cari tahu apakah transfer telah berakhir dengan bantuan fungsi led_panel.OutIsFree () - jika dikatakan benar, maka transfer telah berakhir. Ada fitur - jika Anda memanggil acara saat transfer belum selesai - itu hanya akan diabaikan.
led_panel.show(false);
analog dari show (), tetapi jika Anda memanggil show (false), dan transfer belum selesai, prosedur akan menunggu transfer selesai, kemudian mulai transfer baru dan kontrol kembali:
led_panel.show(true);
analog dengan show (false), tetapi jika Anda memanggil show (true), maka setelah dimulainya transfer baru, prosedur tidak akan mengembalikan kontrol sampai transfer selesai.
Secara umum, itu saja.

Beberapa catatan pada perangkat lunak:
a) Koreksi Gamma diperkenalkan saat menghitung ulang warna dari RGB565 (yang digunakan perpustakaan) dengan fungsi ExpandColor. Dalam semua kasus lain, fungsi transfer linier digunakan, yaitu, kecerahan berbanding lurus dengan nilai.
b) Perangkat lunak memungkinkan Anda untuk menghubungkan beberapa pengendali LED ke satu papan mikrokontroler. Untuk melakukan ini, kirim jalur data bus, RST, dan CLK ke pengontrol secara paralel. Pengontrol yang diinginkan dipilih melalui jalur WE. Dalam perangkat lunak, Anda perlu membuat instance terpisah dari kelas LED_PANEL untuk setiap pengontrol, dan setiap instance harus memiliki baris WE yang berbeda (parameter terakhir) selama inisialisasi.
HARUS DILAKUKAN
- Berurusan dengan "pickup" bunga di baris tetangga. Sepertinya kabel yang buruk dari panel itu sendiri (tombolnya berserakan), tetapi Anda perlu memeriksa. Baru saja tiba panel baru - saya akan periksa;
- Buat versi baru papan - dengan RE yang sudah bercerai dan penambahan konverter level output dalam 5V;
- Buat kelas META_LED_PANEL, yang akan memungkinkan menggabungkan beberapa LED_PANEL menjadi satu layar virtual - ini akan memungkinkan untuk membuat layar yang sangat besar dengan beberapa pengontrol;
- Di masa mendatang, buka seri CPLD yang lebih kuat, misalnya CycloneIV. Ini akan secara signifikan memperluas kemampuan sambil mempertahankan biaya rendah (EP4CE6E22 biaya sekitar $ 5 untuk Cina, sementara ada macrocell 100 kali lebih banyak dan sekitar 32 kB memori internal). Tapi saya akan melakukan ini suatu hari nanti. Jika saya mau. Karena perkembangan seperti itu terlalu banyak waktu.