SSブログ

16x8マトリックスLED 第二弾 その4 [Arduino]

Arduino 1.0をそろそろ使ってみようかと思います。

arduino1_0.png

Arduino Wiki
http://www.musashinodenpa.com/wiki/

こちに Arduino 0023 からの変更点がいくつか記載してあります。
シリアル通信の関係他いくつか変更点があるようです。

また電光掲示板をつくってみました。
今回は、半角英数カナにも対応してみたいと思います。

以前つくったEEPROMのアドオンを使います。
eeprom_test_pic.jpg

(参照) 初めての I2C EEPROM
http://hello-world.blog.so-net.ne.jp/2011-05-22

・8x8ドット漢字フォントの恵梨沙フォントは下記のページから
ELISA Font Home Page by YAFO:
http://hp.vector.co.jp/authors/VA002310/

・4x8ドット半角フォントは、、
Mobile Computer Software Gallery
http://oohito.com/mcsg/archives/17
こちらのFontX2形式のファイルをそれぞれ使わせていただきました。

4x8ドット半角フォントには、JPNHN4X.FNT と 4DOT.FNT がありますが、4DOT.FNT がいいと思います。

前回と同じように、Tera Term から送信しますが、Arduino 1.0用のEEPROM書き込みスケッチは次のとおり。
// ★ Arduinoがシリアル受信したデータをI2C EEPROMに書き込むスケッチ
// ・8バイト毎にデータを書き込む (8で割り切れるデータサイズで)
// ・4800 baud まで (これを超えると書き込みが間に合わないと思われる)
// ・Arduino 1.0 用 (Wire.send → Wire.write)
#include <Wire.h> //I2C library

unsigned int addr=0; //first address
byte buf[8];

void setup() 
{
  Wire.begin(); // initialise the connection
  Serial.begin(4800);
  delay(10); //add a small delay
}

void loop() 
{
  if( Serial.available() >= 8 ){
    for(int i=0; i<8; i++) buf[i] = Serial.read();
    i2c_eeprom_write_page( 0x50, addr, buf, 8 );
    delay(10); //add a small delay
    addr += 8; 
  }
}

void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) {
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddresspage >> 8)); // MSB
  Wire.write((int)(eeaddresspage & 0xFF)); // LSB
  for (byte c = 0; c < length; c++)
    Wire.write(data[c]);
    Wire.endTransmission();
}

シリアルポートを 4800 baud で、バイナリーモードで
ELISA100.FNT、4DOT.FNT の順に続けて転送していきます。

スケッチは8byte ごとの書き込みなので、ファイルの最後の部分が書き込めませんが、データも入っていないし、使わないので気にしないことにします。
書き込み終わったら念のためライトプロテクトをしておきます。

続いて、シリアルからのデータを漢字イメージに変換し、マトリックスLEDに表示するスケッチ。
// シリアルからのテキストを電光掲示板
// ・Arduino 1.0用(0023以下では使えません)
// ・EEPROMに "ELISA100.FNT", "4DOT.FNT"
#include <Wire.h> //I2C library

void setup() {
  Wire.begin(); // initialise the connection
  Serial.begin(9600);
}

void loop() { 
  int elisa, i, j;
  unsigned int fontadrs;
  byte sjisH, scrollText[256], buf[8], txdata, chrwidth, col, row;
    // ■ LEDをクリアー ■
  for( i = 0; i < 16; i++ ) Serial.write( (byte) 0 );
    // ■ シリアルからテキスト取得 ■
  while( !Serial.available() );            // テキストが届くまで待機
  i = 0;
  do {
    if( i < sizeof(scrollText) - 5 )        // 配列に入りきるなら、、
      scrollText[i++] = Serial.read();     //   データを格納
    else  Serial.read();                   //   オーバーするなら破棄 (Arduino1.0前は .flush()でも )
    if( Serial.available() ) continue;     // データがあれば繰り返す
    delay(10);                              // 10msec待っても、
  } while( Serial.available() );           // データがなければ終了
  for( j = i; j < i+4; j++ ) scrollText[j] = ' ';      // スペース4個と
  scrollText[j] = '\0';                                // 終了コード追加
    // ■ 文字をイメージに変換しながらシリアル送信 ■
  for( i = 0; !Serial.available(); ) {     // シリアルから入力があるまで繰り返す
    sjisH = scrollText[ i++ ];              // 1byte 読み込む
    if((sjisH>=0x81 && sjisH<=0x9f) || (sjisH>=0xe0 && sjisH<=0xef)) {  // S-JISの上位1byteなら漢字
      elisa = sjisToElisa( ((unsigned int)sjisH << 8) + scrollText[ i++ ] );
      if( elisa == -1 ) elisa = 0;          // 対応コードがなければ全角スペース
      fontadrs = elisa * 8;                 // 1文字8byteなので、文字順に8をかける
      chrwidth = 8;                         // 全角は幅8ドット
    } else {		                    // 半角ANKなら、
      fontadrs = 55016 + 17 + sjisH * 8;    // Elisaサイズ+FontX2のヘッダ
      chrwidth = 4;                         // 半角は幅4ドット
    }
    i2c_eeprom_read_buffer( 0x50, fontadrs, buf, 8 );    // フォントデータ取得
    for( col = 0; col < chrwidth; col++ ) { // フォントを列ごとに取得
      for( row = 0; row < 8; row++ ) bitWrite( txdata, row , bitRead( buf[ row ], 7 - col ) );
      Serial.write( txdata );              // 文字パターンを1列ごと送信
      delay( 100 );                         // スクロールのスピード調節
    }
    Serial.write( (byte) 0 );              // 1文字毎に1列あける
    delay( 100 );                           // スクロールのスピード調節
    if( !scrollText[i] ) i = 0;             // 終わりまできたら始めに戻る
  }
}

void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8)); // MSB       (Arduino1.0前は .send() )
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,length);
  for (int c = 0; c < length; c++ ) if (Wire.available()) buffer[c] = Wire.read();
}

signed int sjisToElisa(unsigned int sjiscode) {    // シフトJISからELISAフォント上の位置に
  byte jisH, jisL;
  int sp, jiscode;
    // まず、シフトJISをJISに変換
  jisH = sjiscode / 256;    // 上位バイト
  jisL = sjiscode % 256;    // 下位バイト
  jisH = (jisH - ((jisH <= 0x9F) ? 0x71:0xB1)) * 2 + 1;
  if( jisL > 0x7F ) jisL--;
  if( jisL >= 0x9E ) jisH++;
  jisL -= ((jisL >= 0x9E) ? 0x7D:0x1F);
  jiscode = (jisH << 8) + jisL;
    // JISから ELISAフォントでの文字位置を計算
  if     (jiscode>=0x2121 && jiscode<=0x222e) sp =   0;  // 一般記号
  else if(jiscode>=0x223a && jiscode<=0x2241) sp =  11;  // 集合記号
  else if(jiscode>=0x224a && jiscode<=0x2250) sp =  19;  // 論理記号
  else if(jiscode>=0x225c && jiscode<=0x226a) sp =  30;  // 幾何記号
  else if(jiscode>=0x2272 && jiscode<=0x2279) sp =  37;  // 音楽記号
  else if(jiscode==0x227e)                    sp =  41;  // 丸記号
  else if(jiscode>=0x2330 && jiscode<=0x2339) sp =  56;  // 数字
  else if(jiscode>=0x2341 && jiscode<=0x235a) sp =  63;  // 英大文字
  else if(jiscode>=0x2361 && jiscode<=0x237a) sp =  69;  // 英小文字 
  else if(jiscode>=0x2421 && jiscode<=0x2473) sp =  73;  // ひらがな
  else if(jiscode>=0x2521 && jiscode<=0x2576) sp =  84;  // カタカナ
  else if(jiscode>=0x2621 && jiscode<=0x2638) sp =  92;  // ギリシャ大文字
  else if(jiscode>=0x2641 && jiscode<=0x2658) sp = 100;  // ギリシャ小文字
  else if(jiscode>=0x2721 && jiscode<=0x2741) sp = 138;  // キリル大文字
  else if(jiscode>=0x2751 && jiscode<=0x2771) sp = 153;  // キリル小文字
  else if(jiscode>=0x2821 && jiscode<=0x2840) sp = 166;  // 罫線
  else if(jiscode>=0x3021 && jiscode<=0x4f53) sp = 886;  // 第一水準漢字
  else if(jiscode>=0x5021 && jiscode<=0x7426) sp = 929;  // 第二水準漢字
  else return -1;              // 対応文字コードがなければ -1
  return (jiscode / 256 - 0x21) * 94 + (jiscode % 256) - 0x21 - sp;
}

テキストデータは随時イメージに変換することにして、RAMをあんまり使わないようにしてみました。

eleboard2.jpg
ジャンパピンは、Arduinoからのシリアル出力(TX)を、マトリックスLEDのTiny2313の入力側につなぐようにします。
EEPROMのアドオンが載っていると不格好ですが、、。

シリアルモニターを9600baudにして、文字列を入力すると、LEDマトリックスに電光掲示板のように表示されます。

半角英数カナと全角漢字も全部OK!
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。