2014年1月18日土曜日

秋月電子のSPI(3線式)LED Module 8 Digital を使う

こんにちは.
今日は研究室に転がっていた秋月電子のSPI(3線式)LED Module 8 Digital を使ってみました.
商品URL:http://akizukidenshi.com/catalog/g/gM-06681/

 使い方とサンプルプログラムがhttp://www.dfrobot.com/wiki/index.php?title=SPI_LED_Module_(SKU:DFR0090)#Pinout_Diagram に示されています.どうやらbyte配列を送信することで表示が可能となるようです.
 サンプルプログラムではシリアル通信を使うことが前提となっています.ですが時計を作ったり,Arduinoに付いているセンサの値を表示する時には数値データをそのまま表示したいですね.ですので今回は,8桁(負数は7桁)までの数値をこのモジュールで表示するサンプルプログラムを書きました.

以下ソースコード

//Pin connected to latch pin (ST_CP) of 74HC595
const int latchPin = 8;
//Pin connected to clock pin (SH_CP) of 74HC595
const int clockPin = 3;
//Pin connected to Data in (DS) of 74HC595
const int dataPin = 9;
//7SegLEDの数
const int ledArray = 8;

byte byteData[ledArray] = {0};
char strData[ledArray] = {0};

//表示させたい数字ledArrayの桁数以内
//8桁の場合-9999999から99999999
long number = 20140119;

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
}

void loop() {
 sprintf(strData, "%ld", number);
 //char型文字をbyte配列に置き換え、右揃えで表示できる形に整形
 setDataFormat(strData, byteData);
 
 digitalWrite(latchPin, LOW);
 for(int i=ledArray-1; i>=0; i--){
     shiftOut(dataPin, clockPin, MSBFIRST, byteData[i]);
 }
 digitalWrite(latchPin, HIGH);
 
}

void setDataFormat(char* strData,byte *byteData){
  int numofNull=0;
  // char型数字をbyteコードに置き換えはじめ
  for(int i=0; i<ledArray; i++){
    switch(strData[i]){
      case '\0':
        byteData[i]=0xff;
        numofNull++;
        break;
      case '0': 
        byteData[i]=0xc0;
        break;
      case '1':
        byteData[i]=0xf9;
        break;
      case '2':
        byteData[i]=0xa4;
        break;
      case '3':
        byteData[i]=0xb0;
        break;
      case '4':
        byteData[i]=0x99;
        break;
      case '5':
        byteData[i]=0x92;
        break;
      case '6':
        byteData[i]=0x82;
        break;
      case '7':
        byteData[i]=0xf8;
        break;
      case '8':
        byteData[i]=0x80;
        break;
      case '9':
        byteData[i]=0x90;
        break;
      case '-':
        byteData[i]=0xbf;
        break;
    }
  }
  // char型数字をbyteコードに置き換えおわり
  //配列の入れ替えはじめ
  for(int i=0; i<numofNull; i++){
    byte tmp[ledArray];
    int j;
    for(int i =0; i<ledArray; i++){
      tmp[i]=byteData[i];
    }
    for(int i =0; i<ledArray; i++){
      if(i==0){
        j = ledArray-1;
      }else{
        j = i-1;
      }
      byteData[i] = tmp[j];
    }
  }
  //配列の入れ替えおわり
}


今回のポイント
  1. 送信するbyte配列:byteDataを読み込ませる順番
  2. 表示の右揃え
  3. マイナスを表示
送信するbyte配列:byteDataを読み込ませる順番
 このモジュールでは読み込んだbyteデータを右から順番に並べていきます.例えば,20140119を配列の0番目から7番目まで読み込ませた場合,91104102と表示されます.これを解消するには配列の7番目から0番目に向かって読み込ませていけば大丈夫です.つまり,配列を右から読んで右から詰めるということです.整理整頓!(?)

表示の右揃え
 このプログラムでは数値データをsprintfという関数をつかって文字型数字配列に変換しています.ここでもしも,桁数が7桁の数値1234567を変換すると'1','2','3','4','5','6','7','\0'というようになります.これを表示すると
というようになります.数字データなのに右端が開くのは違和感があります.そこで,送信前に配列を入れ替えてすべての'\0'を左端に持ってくることで表示を右揃えにします.
具体的には82行目から94行目の部分です.まず,配列の複製を行います.そして入れ替えを行います.入れ替えでは,入れ替えれる側(元の配列)の先頭に\0を入れたいので,0番目の要素の時だけ,複製された配列の最後の要素つまり,7番目の要素を代入します.残りは一つづつ右にずらしていきます.これを\0の数だけ繰り返すとどんなに桁数が減っても右揃えして表示できるようになります.

マイナスを表示
 数字以外のアルファベットやハイフン、ピリオドなどを表示したくなった時どうしたらよいかです.サンプルプログラムでは文字型数字からバイトコードへの変換を40行目から79行目で行っています.処理は単純なswitch-case文です.このモジュールの場合,LEDの各セグメントと8ビットの関係は次の様になっています.例えば,ハイフンを表示したいときには10111111となります.
次に,得た10111111を16進数にします.自分で計算してもいいのですが,めんどくさい人は,http://www.binary-code.org/ のサイトを使いましょう.

主なポイントは以上です.
もっとよく知りたい方はこのモジュールを実現しているシフトレジスタ74HC595について調べたり,小数表示を実装してみたりするといいと思います.


1 件のコメント:

  1. 参考になりました。ありがとうございました。

    返信削除