Arduino LED Matrix 中文 Running Text 迷你版

製作分享:
不久前已有自己嘗試實作的念頭, 在沒有專門做 LED Driving IC 及手頭上有限的零件條件下, 初步總算完成了.
最初設定的目標:
1. 螢幕能顯示中文字或中文句子.
2. 螢幕上文字能簡單移動.
3. 電腦那邊, 利用簡單界面輸入欲顯示的文字和設定Font的Family, Size, Style 和文字移動速度, 之後即時更新.

最初設計及掣作中問題, 自問自答:
Q1: 為甚麼要做 16x16 的 LED Dot Matrix, 只用一個 8x8 的不可以嗎?
A1: 因為目標是能顯示中文字, 而一般中文字型最少也要 10x10 的解像點數才看得清楚(可用小畫家測試), 因此決定要用4個 8x8 組成 16x16, 及後觀察巿面上大部份的中文 LED Display 最少也有10多點的高度. 若只須顯示英文字, 一個 8x8 已足夠, 而且線路會比較簡單了.

Q2: 中文字型的編碼字庫儲存在那裡?
A2: 中文字型的編碼是有須要顯示出來是才會從電腦那邊傳送到Arduino 的記憶體上.
現在的設計是每個字都係 fixed 16x16 dot, 即係要每個字要 32 bytes (因為16x16=256 點 LED, 每Byte 8個Bits 能儲存8點, 所以256/8=32)
字樣有用到先send 過去 arduino
冇選擇在arduino建立字庫係因為我覺得:
1. ATmega328 上的Flash or EEPROM 都應該唔係幾夠位, 但可能可以只儲存某些常用字,
2. 不計理由1, 若果字庫在arduino 那邊, 輸入中文後我要考慮send 碼過去時要用正常的big5 or utf-8 的話 , arduino 要有一個mapping table 小弟覺得較困難.
若重新跟據字型在記憶上的地址做編碼, pc 那邊又要有一個table,

其他的問題:
關於字型的儲蓄, 編碼
待修

使用硬件:
1. Arduino Duemilanove
2. 8x8 LED Dot Matrix x 4
    四個組成16x16 LED Dot Matrix
3. 74LS138 x 2
    74LS138 是 1-of-8 Demultiplexer, 兩個便組成 1-of-16 Demultiplexer, 用在逐行LED column scan
4. MCP23017 IO Port Expander
    Arduino 用 I2C Interface (Wire Library) 與它連接擴充16 個Digitial Out. LED row 的控掣
5. KSP2907A PNP Transistor x 16
    用作整行 (垂直) LED Switch On/Off
6. Resistor
    用在LED限流及 Transistor
7. Breadboard

PC 軟件:
1. Arduino IDE
2. Eclipse IDE for Java

套用的有關技術: (可上網搜查更詳細資料)
PNP Transistor Switch LED
LED Multiplexing
利用 IC 74LS138 做 1-of-8 Demultiplexer (與LED Multiplexing 有關)

影片一
http://www.youtube.com/watch?v=3mzN5QnAiSE

影片二
http://www.youtube.com/watch?v=8cHiBezWQTM

其他資料整理後再放上來...

[ 本帖最後由 sscm 於 2009-6-24 09:49 編輯 ]
附件: 您需要登錄才可以下載或查看附件。沒有帳號?註冊

Arduino Source Code
如果有足夠腳位如Arduino Mega, 根本可以不用Wire Library 控掣外加的 IO Port Expander,
直接改為控掣Arduino 的Port 就可以了.

#include <Wire.h>

int colIdx = 0;           
int dataLen = 0;      // 共多少byte作儲存 字型,  =msgLen x32 (每個字佔32byte)
int mode = 0;          // mode 0 與PC連拉作接收文字資料, mode 1 作顯示文字
int msgLen = 0;      //   共多少個字位
int msgSpeed = 6;   // 文字移動速度

int inByte;
byte data[640];    // 每個字佔32byte, 分配最多20個字位

int pause = 400;

void setup() {
    DDRB = B11111111;
    Serial.begin(9600);
    Wire.begin();
}

void loop() {
    Wire.beginTransmission(B100000);
    Wire.send(0x00);
    Wire.send(0x00);
    Wire.send(0x00);
    Wire.endTransmission();
   
    Wire.beginTransmission(B100000);
    Wire.send(0x12);
    Wire.send(0xFF);
    Wire.send(0xFF);
    Wire.endTransmission();
   
    while (true) {
        while (mode == 0) {
            digitalWrite(13, HIGH);
            if (Serial.available() > 0) {
                inByte = Serial.read();
                switch (inByte) {
                   case 255:
                       mode = 1;
                       digitalWrite(13, LOW);
                       break;
                   case 0:
                       while (true) {
                           if (Serial.available() > 0) {
                               msgSpeed = Serial.read();
                               break;
                           }
                       }
                       break;
                   case 1:
                       int i = 0;
                       while (i < 32) {
                           if (Serial.available() > 0)
                             data[msgLen * 32 + i++] = Serial.read();
                       }
                       msgLen++;
                       dataLen = msgLen * 32;
                       break;
               }
            }
        }
        
        int i, j, k, l;
        unsigned long t = millis();
        while (true) {
            for (i = 0; i < 16; i++) {
                PORTB = i;
               
                j = (colIdx*2)+ (i*2);
                if (j < dataLen) {
                    k = data[j];
                    l = data[j + 1];
                } else {
                    k = data[j-dataLen];
                    l = data[j + 1-dataLen];
                    if (i == 0 && j - dataLen == 0) {
                        colIdx = 0;
                    }
                }
               
                // Turn on row LED
                Wire.beginTransmission(B100000);
                Wire.send(0x12);
                Wire.send(k);
                Wire.send(l);
                Wire.endTransmission();
               
                delayMicroseconds(pause);
               
                // Turn off all row LED
                Wire.beginTransmission(B100000);
                Wire.send(0x12);
                Wire.send(0xFF);
                Wire.send(0xFF);
                Wire.endTransmission();
               
                if (millis() - t > (msgSpeed*50)) {
                    t = millis();
                    colIdx++;
                }
            }
        }
    }
}

[ 本帖最後由 sscm 於 2009-6-18 23:26 編輯 ]
附件: 您需要登錄才可以下載或查看附件。沒有帳號?註冊

TOP

測試中文顯示

[ 本帖最後由 sscm 於 2009-6-17 00:05 編輯 ]
附件: 您需要登錄才可以下載或查看附件。沒有帳號?註冊

TOP

好正喎!PC用乜野造界面呀?

TOP

原帖由 zonebaby 於 2009-6-17 00:23 發表
好正喎!PC用乜野造界面呀?


用 Eclipse 寫 Java, 界面係輸入文字後編番 code, serial send 去 Arduino.

TOP

原帖由 sscm 於 2009-6-17 00:33 發表


用 Eclipse 寫 Java, 界面係輸入文字後編番 code, serial send 去 Arduino.


中文字要唔要逐隻字編定有字庫用呀?

TOP

原帖由 zonebaby 於 2009-6-17 00:41 發表


中文字要唔要逐隻字編定有字庫用呀?


開始時我也想過這個問題, 最後選擇係逐隻字編,
現在的設計是每個字都係 fixed 16x16 dot, 即係要每個字要 32 bytes
字樣有用到先send 過去 arduino

冇選擇字庫係因為我覺得:
1. ATmega328 上的Flash or EEPROM 都應該唔係幾夠位, 但可能可以只儲存某些常用字,
2. 不計理由1, 若果字庫在arduino 那邊, 輸入中文後我要考慮send 碼過去時要用正常的big5 or utf-8 的話 , arduino 要有一個mapping table 小弟覺得較困難.
若重新跟據字型在記憶上的地址做編碼, pc 那邊又要有一個table,
所以最後都係用了較簡單的方法來實作

其實我不清楚巿面上那些怎様做, 若果其他師兄知道請指教

TOP

多謝指教。

另外請問咁大塊Breadboard係邊處買架?

TOP

原帖由 zonebaby 於 2009-6-17 01:19 發表
多謝指教。

另外請問咁大塊Breadboard係邊處買架?

華輝有,幾塊Breadboard可以構起一齊
留意下邊位 有凸有凹

[ 本帖最後由 rutellor 於 2009-6-17 01:55 編輯 ]

TOP

呢件 breadboard 晌華輝買相當貴...過百蚊...

TOP