2010-01-16

MAX7219 動作テスト

以前、加速度センサや曲げセンサからの情報を Arduino から UART 経由で PC へ送り、PC 上でセンサ情報を表示させるソフトを作成しました。

これを使ってサーキット走行した際に、ロガーとしての効果を期待するなら...

  1. PC をクルマに搭載し、車載カメラにセンサ表示を映り込ませる
  2. 後から、車載映像を加工してセンサ情報をオーバレイ表示させる
といった手法を取らないといけません。手法1 は、たぶん光量的に問題あって、車載カメラの映像内のPC画面を読み取るのは難しいかと。はたまた手法2 は、データ時間あわせ(映像のスタートと、センサデータのスタートの同期)が面倒。
お手軽かつ、安価なのはやっぱり、LED による表示機を作成する事でしょうか。

・・・という前置きを経て本題。
センサ情報を LED 表示したい場合...スロットルポジション10段階(LED10個)、ブレーキ10段階、加速度が、前方向10段階、後ろ方向10段階、右方向も10、左も10...最低でも合計60個のLEDを制御しなければなりません。Arduino から 60個の LED を個別制御するために、MAX7219 を試してみました。

◆MAX7219 について
MAX7219 は、計64個の LED をシリアル制御で個別駆動可能なディスプレイドライバICです。Arduino との接続は、5V、GND、DIN、CLK、LOAD の5本。DIN、CLK、LOAD の3本は DIGITAL ピンに接続。DIN に 16bit のデータを shiftOut() 関数を使って送ることで、64個のLED を個別に制御できます。
2個の IC をカスケード接続することもでき、使用ピン数はそのままで、128個のLED制御も可能です。

◆送信するシリアルデータについて
Arduino のデジタルピンと、MAX7219 の DIN 端子を接続します。送信するデータのフォーマットですが、基本、7セグLEDでの利用を前提に考えられているので...16bitのウチ上位8bit に桁の指定(8桁まで対応)、下位8bitに7セグLED(DP含む)のそれぞれのセグメントが対応しています。(BCDモードもありますが今回は使いません)

D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
× × × × ADDRESS(各桁) DATA(各セグメント)

1回のデータ送信(16bit)で、点灯の指定が可能なのは、8個のLED(D0-D7)ですが、このICは、V+が 2V を上回っている限り、各桁の値を保持しますので、続けて個々の桁を更新可能です。
別に、7セグLED を接続しなきゃイケナイ訳では無く、マトリックスLED でも、単体の LED 64個でも良くて、LED を8個のづつのグループに分けて管理すれば OK です。

ADDRESS に指定する値ですが、表示したい桁の指定などのほかに、MAX7219 内のレジスタを指定できます。使用する桁数や、動作モードなどを初期設定します。

◆MAX7219 と LED の接続
カソードコモンの7セグLED が前提です。アノードの A~G、DP の8本と、カソード側が1本...8桁まで対応なので8本。計16本を接続します。1桁(単体LEDが8個以下)しか使わない場合は、カソードの接続は1本のみ。
接続が3桁以下の場合、電流が流れすぎて輝度に影響が出るそうなので、I_SET 端子に接続する抵抗値で調整します。
※ MAX7219 で検索してデータシートを見てください。

◆実験
配線が面倒なので、今回は7セグLED を1つだけ使いました。初期設定周りのソースコードを固めるのが目的なので。

輝度ですが、I_SET 端子には、100kΩ を接続しました。INTENSITY レジスタのデューティーは 15/32 です。
続きに今回のスケッチ。


//-----------------------------------------------------
// MAX7219 のテスト
//
//-----------------------------------------------------


// MAX7219 REGISTER ADDRESS MAP
#define  REG_NO-OP   0x00
#define  REG_DIG_0   0x01
#define  REG_DIG_1   0x02
#define  REG_DIG_2   0x03
#define  REG_DIG_3   0x04
#define  REG_DIG_4   0x05
#define  REG_DIG_5   0x06
#define  REG_DIG_6   0x07
#define  REG_DIG_7   0x08
#define  REG_DECODEMODE  0x09
#define  REG_INTENSITY  0x0A
#define  REG_SCANLIMIT  0x0B
#define  REG_SHUTDOWN  0x0C
#define  REG_DISPLAYTEST  0x0F


// MAX7219 PIN at Arduino
int  DIN  = 2;   // DATA IN
int  LOAD = 3;   // LATCH
int  CLK  = 4;   // CLOCK


//-----------------------------------------------------
// 初期化
//
//-----------------------------------------------------
void setup()
{
 pinMode(DIN,  OUTPUT);
 pinMode(LOAD, OUTPUT);
 pinMode(CLK,  OUTPUT);

 // Scan Limit
 MAX7219_SendData(REG_SCANLIMIT, 0);   // 0: Display digit-0 only.

 // Decode Mode
 MAX7219_SendData(REG_DECODEMODE, 0);  // 0: No decode for digits 7–0

 // Intensity
 MAX7219_SendData(REG_INTENSITY, 0x07);  // 7: Duty Cycle 15/32

 // Shutdown Mode
 MAX7219_SendData(REG_SHUTDOWN, 1);   // 1: Normal Operation.

 // Display Test
 MAX7219_SendData(REG_DISPLAYTEST, 0);  // 0: Normal Operation.
}

//-----------------------------------------------------
// メイン
//
//-----------------------------------------------------
void loop()
{
 MAX7219_SendData(REG_DIG_0, 0x0);   // LED off
 delay(1000);

 MAX7219_SendData(REG_DIG_0, 0x01);   // G
 delay(1000);

 MAX7219_SendData(REG_DIG_0, 0x02);   // F
 delay(1000);

 MAX7219_SendData(REG_DIG_0, 0x04);   // E
 delay(1000);

 MAX7219_SendData(REG_DIG_0, 0x08);   // D
 delay(1000);

 MAX7219_SendData(REG_DIG_0, 0x10);   // C
 delay(1000);

 MAX7219_SendData(REG_DIG_0, 0x20);   // B
 delay(1000);

 MAX7219_SendData(REG_DIG_0, 0x40);   // A
 delay(1000);

 MAX7219_SendData(REG_DIG_0, 0x80);   // DP
 delay(1000);

 MAX7219_SendData(REG_DIG_0, 0x30);   // 1 (B+C)
 delay(500);
 MAX7219_SendData(REG_DIG_0, 0x6D);   // 2 (A+B+D+E+G)
 delay(500);
 MAX7219_SendData(REG_DIG_0, 0x79);   // 3 (A+B+C+D+G)
 delay(500);
 MAX7219_SendData(REG_DIG_0, 0x33);   // 4 (B+C+F+G)
 delay(500);
 MAX7219_SendData(REG_DIG_0, 0x5B);   // 5 (A+C+D+F+G)
 delay(1000);
}

//-----------------------------------------------------
// MAX7219 の DIN へデータ (16bit) を送る
//
void MAX7219_SendData(unsigned char regAddress, unsigned char data)
{
 digitalWrite(LOAD, LOW);

 regAddress &= 0x0F;
 shiftOut(DIN, CLK, MSBFIRST, regAddress);
 shiftOut(DIN, CLK, MSBFIRST, data);

 digitalWrite(LOAD, HIGH);
}