Arduino の工作で以前、加速度センサの情報をシリアル出力し、PC 側のソフトでセンサ情報を表示したり、MAX7219 という IC を使って、LED を制御したりしてみました。
今日は、加速度センサの情報を バー表示LED を使って表示するテストをしてみました。バー表示LED は 10個のLED が並んでいるだけのモノで、これを 2個(都合 LED 20 個)使います。
MAX7219 は LED を 8個単位で管理するので、Scan Limit レジスタの値は 「2」、つまり 3桁 (Display digits 0 1 2) になります。
さてさて、加速度センサの情報を LED 表示できるとなると、実際に車載して動きを確認したくなります。なので、車載前提で工作するため、2DIN に収まるサイズのブレッドボードを用意しました。EIC-108 というサイズのブレッドボードを一部バラして、2DIN のスケルトンシャシーに貼り付けたダケのものですが。
LED と MAX7219 との接続は、ブレッドボードに向かって、LED 左側から...
- DIG-0 の SEG_A、SEG_B、SEG_C...SEG_G、SEG_DP (LED 8個)
- DIG-1 の SEG_A、SEG_B、SEG_C...SEG_G、SEG_DP (LED 8個)
- DIG-2 の SEG_A、SEG_B、SEG_C、SEG_D (LED 4個)
一番左側の LED が、DIG-0 の SEG-A。一番右側が DIG-2 の SEG_D となってます。
今回のスケッチ。
analogRead() した値を、左右 512 に振り分け、10段階で LED 表示。
ニュートラル位置のキャリブレーションは未考慮で、512 決め打ちです。
//-----------------------------------------------------
//
// 加速度センサの左右 G の変化をバーLED で表示する。
//
// ・加速度センサ・シールド
// ・バー表示LED x2
// 2010-04-24
//-----------------------------------------------------
// 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 DATA
#define SEG_DP 0x80
#define SEG_A 0x40
#define SEG_B 0x20
#define SEG_C 0x10
#define SEG_D 0x08
#define SEG_E 0x04
#define SEG_F 0x02
#define SEG_G 0x01
// MAX7219 PIN at Arduino
int DIN = 2; // DATA IN
int LOAD = 3; // LATCH
int CLK = 4; // CLOCK
// LED Map(バー表示 LED 2個 (20 LED) を 8個単位で管理する)
typedef struct{
unsigned char ucLED_0; // 8 LED (左側)
unsigned char ucLED_1; // 8 LED
unsigned char ucLED_2; // 4 LED
}LEDMAP;
// 点灯させる LED のマップ
static LEDMAP s_LedMap;
//-----------------------------------------------------
// 初期化
//
//-----------------------------------------------------
void setup()
{
pinMode(DIN, OUTPUT);
pinMode(LOAD, OUTPUT);
pinMode(CLK, OUTPUT);
// Scan Limit
MAX7219_SendData(REG_SCANLIMIT, 2); // 2: Display digits 0 1 2
// 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.
// LED 0, 1, 2 -- OFF
MAX7219_SendData(REG_DIG_0, 0x0);
MAX7219_SendData(REG_DIG_1, 0x0);
MAX7219_SendData(REG_DIG_2, 0x0);
s_LedMap.ucLED_0 = 0;
s_LedMap.ucLED_1 = 0;
s_LedMap.ucLED_2 = 0;
}
//-----------------------------------------------------
// メイン
//
//-----------------------------------------------------
void loop()
{
int iValue;
int iDisplayValue;
#if 0
iValue = analogRead(0); // Analog 0 -- Accelerator
iValue = analogRead(1); // Analog 1 -- Brake
iValue = analogRead(4); // G-Force Z
#endif
//ユニットの設置都合により、G 検出センサを切り替える
if( 0 ){
iValue = analogRead(2); // G-Force X
}else{
iValue = analogRead(3); // G-Force Y
}
//表示する LED の個数 (1--10)
iDisplayValue = GetGForce(iValue);
//左右の表示 LED をセット
if(!GetGDirection(iValue)){
GForce_left(iDisplayValue);
GForce_Right(1);
}else{
GForce_left(1);
GForce_Right(iDisplayValue);
}
// LED 点灯
outLED();
delay(10);
}
//-----------------------------------------------------
// G の大きさを 10 段階の層値で返す
//戻り値:
// int G の大きさを表す層値 (1--10)
//
int GetGForce(int iNowForce)
{
int iNeutral = 512;
double dValue, dClass;
dValue = (double)(iNeutral < iNowForce) ? (iNowForce - iNeutral) : (iNeutral - iNowForce);
dClass = (dValue * 9.0L / 512.0L) + 1;
return (int)dClass;
}
//-----------------------------------------------------
// G の発生方向を返す
//
int GetGDirection(int iNowForce)
{
int iNeutral = 512;
return (iNeutral < iNowForce) ? 1 : 0;
}
//-----------------------------------------------------
// G-Force Left
// 点灯させるべき LED に対応する bit を ON する。
//
//引数:
// iLevel G レベル (1--10)
//
void GForce_left(int iLevel)
{
if(iLevel < 1){
s_LedMap.ucLED_0 = 0;
s_LedMap.ucLED_1 &= ~(SEG_A | SEG_B);
}else if(iLevel > 10){
s_LedMap.ucLED_0 = 0xFF;
s_LedMap.ucLED_1 |= (SEG_A | SEG_B);
}else{
s_LedMap.ucLED_0 = 0;
s_LedMap.ucLED_1 &= ~(SEG_A | SEG_B);
switch(iLevel){
case 10:
s_LedMap.ucLED_0 |= SEG_A;
case 9:
s_LedMap.ucLED_0 |= SEG_B;
case 8:
s_LedMap.ucLED_0 |= SEG_C;
case 7:
s_LedMap.ucLED_0 |= SEG_D;
case 6:
s_LedMap.ucLED_0 |= SEG_E;
case 5:
s_LedMap.ucLED_0 |= SEG_F;
case 4:
s_LedMap.ucLED_0 |= SEG_G;
case 3:
s_LedMap.ucLED_0 |= SEG_DP;
case 2:
s_LedMap.ucLED_1 |= SEG_A;
case 1:
s_LedMap.ucLED_1 |= SEG_B;
break;
}
}
}
//-----------------------------------------------------
// G-Force Right
// 点灯させるべき LED に対応する bit を ON する。
//
//引数:
// iLevel G レベル (1--10)
//
void GForce_Right(int iLevel)
{
if(iLevel < 1){
s_LedMap.ucLED_2 = 0;
s_LedMap.ucLED_1 &= ~(SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_DP);
}else if(iLevel > 10){
s_LedMap.ucLED_2 |= (SEG_A | SEG_B | SEG_C | SEG_D);
s_LedMap.ucLED_1 |= (SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_DP);
}else{
s_LedMap.ucLED_2 = 0;
s_LedMap.ucLED_1 &= ~(SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_DP);
switch(iLevel){
case 10:
s_LedMap.ucLED_2 |= SEG_D;
case 9:
s_LedMap.ucLED_2 |= SEG_C;
case 8:
s_LedMap.ucLED_2 |= SEG_B;
case 7:
s_LedMap.ucLED_2 |= SEG_A;
case 6:
s_LedMap.ucLED_1 |= SEG_DP;
case 5:
s_LedMap.ucLED_1 |= SEG_G;
case 4:
s_LedMap.ucLED_1 |= SEG_F;
case 3:
s_LedMap.ucLED_1 |= SEG_E;
case 2:
s_LedMap.ucLED_1 |= SEG_D;
case 1:
s_LedMap.ucLED_1 |= SEG_C;
break;
}
}
}
//-----------------------------------------------------
// LED 点灯
//
void outLED()
{
MAX7219_SendData(REG_DIG_0, s_LedMap.ucLED_0);
MAX7219_SendData(REG_DIG_1, s_LedMap.ucLED_1);
MAX7219_SendData(REG_DIG_2, s_LedMap.ucLED_2);
}
//-----------------------------------------------------
// 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);
}
