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); }