GR KURUMI + LEDマトリクス (その2)

id:currygyu:20130528

前回↑が消化不良だったので、改良してみました。


修正点

トランジスタアレイを使ってLED用の電源を別に確保
・上記に関連して、電源を3.3Vから5Vに変更
(3.3Vで始めたらトランジスタアレイの電圧降下でLEDが点灯しなくなりました)
・74HC595(x2)でインタフェースをSPI化

はんだ付けを1箇所ずれたまま進めてしまい、半日悩んだりしましたが、どうにか完成しました。

次はフルカラーのLEDマトリクスをいじってみようかと思います。

SPI化したので、GR KURUMIのスケッチもシンプルになりました。

/*GR-KURUMI Sketch Template Version: V1.00*/
#include <RLduino78.h>
#include <spi.h>

byte leddat[8] = { 0x18, 0x24, 0x42, 0x81, 0x81, 0x42, 0x24, 0x18 };
void disp_update(unsigned long u32ms);

// the setup routine runs once when you press reset:
void setup() {

  // initialize the digital pin as an output.
  pinMode(9, OUTPUT);        // SS(STCP)
  digitalWrite(9, HIGH);

  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV128);
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);

  delay(50);
  
  attachCyclicHandler(1, disp_update, 1000);
}

// the loop routine runs over and over again forever:
void loop() {
  byte i=0;

  for(i=0; i<8; i++){
    SPI.transfer((byte)(0x01<<i));
    SPI.transfer(leddat[i]);
    digitalWrite(9, HIGH);
    digitalWrite(9, LOW);

    delay(1);
  }
}

void disp_update( unsigned long u32ms )
{
    int y, x;
    int num = 0;
    int alive = 0;
    byte work[8];
    
    for(y=0; y<8; y++){
        work[y] = leddat[y];
    }

    for(y=0; y<8; y++){
        for(x=0; x<8; x++){
            num = 0;
            
            /* count around */
            if( x != 0 ){
                if( ( ( leddat[y] >> ( 8-x ) ) & 0x01 ) != 0 ){
                    num ++;
                }
            }
            
            if( x != 7 ){
                if( ( ( leddat[y] >> ( 6-x ) ) & 0x01 ) != 0 ){
                    num ++;
                }                    
            }
            
            if( y != 0 ){
                if( ( ( leddat[y-1] >> ( 7-x ) ) & 0x01 ) != 0 ){
                     num ++;
                }
                if( x != 0 ){
                    if( ( ( leddat[y-1] >> ( 8-x ) ) & 0x01 ) != 0 ){
                        num ++;
                    }
                }
                if( x != 7 ){
                    if( ( ( leddat[y-1] >> ( 6-x ) ) & 0x01 ) != 0 ){
                        num ++;
                    }
                }
            }                    

            if( y != 7 ){
                if( ( ( leddat[y+1] >> ( 7-x ) ) & 0x01 ) != 0 ){
                    num ++;
                }
                if( x != 0 ){
                    if( ( ( leddat[y+1] >> ( 8-x ) ) & 0x01 ) != 0 ){
                        num ++;
                    }
                }
                if( x != 7 ){
                    if( ( ( leddat[y+1] >> ( 6-x ) ) & 0x01 ) != 0 ){
                        num ++;
                    }
                }
            }                    

            /* decide */
            if( ( ( leddat[y] >> ( 7-x ) ) & 0x01 ) == 0 ){
                if( num == 3 ){
                    work[y] |= ( 0x80 >> x );
                }
            }
            else{        
                if( ( num != 2 ) && ( num != 3 ) ){
                    work[y] &= ~( 0x80 >> x );
                }
            }
        }
    }

    for( y=0; y<8; y++ ){
        leddat[y] = work[y];
    }
}

表示内容は前回と同じライフゲームです。

1秒ごとにタイマで呼ばれるdisp_update関数の中で、表示内容を設定するleddat配列を書き換えています。その辺りをいじれば好きな表示内容に変更も可能かと。

※leddat配列は、ドットを8ビットで表現したものを1行目から順に8行分入れたたものです。

SPIで16ビット送信していますが、最初の8ビットは行指定、次の8ビットは点灯内容となっていて、送信後に74HC595にラッチの信号(KURUMIの9ピン)を入れて表示内容を反映させています。

よくあるやりかたなので、検索すればたくさんでてきます。僕もマネしました。

回路図

https://docs.google.com/file/d/0B9mpDLlbvvN8Wi04eVk1VGpBSkk/edit?usp=sharing

※7/5 配線ミス修正&PDFの窓を出すのやめました