SSブログ

日本語対応の電光掲示板ができました [Arduino]

いままでの成果

・I2C EEPROM
・日本語処理
・16x8 マトリックスLED

これらをまとめたものが完成しました。


シリアルで入力した文字列を、スクロール表示するスケッチです。
ふと思ったのは、LinuxやMac OSだとシフトJISでないかもしれないことです。
しかし確認のしようがないのでごめんなさい。

あと、アナログピンソケットの接触不良は、ピンをすこし曲げることで応急処置が可能でした。

スケッチはビギナーらしく、きれいとは言えませんが、
 i2c_eeprom_read_buffer()
 sjisToElisa()
 asciiToElisa()
 matrixClear()
 matrixRefresh()
これらの以前使ったものを再利用して、
さらに、シリアルからのテキストを受信/テキストをドットイメージに変換/スクロール表示部分を追加しました。

お恥ずかしながら、スケッチを載せます。
#include <Wire.h> //I2C library

byte buf[8];
byte scrollText[64], scrollImage[256];
int scrollSpeed = 10;  // 1行スクロールあたりのリフレッシュ回数(多いとゆっくり)
boolean scrollHorizontal = true;    // true 横、false 縦

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

void loop() 
{ 
  unsigned int sjisH, sjisL;
  signed int elisa;
  int i, col, row, p = 0, len = 16;

  // テキストが届くまで待機
  while( !getTextFromSerial( scrollText ) );
  // テキストをイメージに展開
  for( i = 0; i < 256; i++ )  scrollImage[ i ] = 0;  // イメージ初期化
  for( i = 0; i < 64; ) {
    sjisH = scrollText[ i++ ];       // 1byte 読み込む
    if( sjisH == 0 ) break;
    elisa = asciiToElisa ( sjisH );  // ASCII文字 → ELISAでの位置
    if( elisa == -1 ) {              // シフトJIS上位1バイトなら漢字を表示
      sjisL = scrollText[ i++ ];
      elisa = sjisToElisa( (sjisH << 8) + sjisL );
      if( elisa == -1 ) continue;      // 対応文字コードがなければ終了
    } else if( elisa < -1 ) continue;  // 制御コード、半角カナなどなら終了
    i2c_eeprom_read_buffer( 0x50, elisa * 8, buf, 8 );
    if( scrollHorizontal ) {         // 横スクロールの場合
      for( row = 0; row < 8; row++ ) {
        for( col = 0; col < 8; col++ ) {
          bitWrite( scrollImage[ len + col ], row , bitRead( buf[ row ], 7 - col ) );
        }
      }
    } else {                         // 縦スクロールの場合
      for( row = 0; row < 8; row++ )  scrollImage[ len + row  ] = buf[ row ];
    }
    len += 8;
    scrollImage[ len++ ] = 0;        // 1文字毎に1行あける
    if( len >= 256 - 16 ) break;
  }
  // テキストをLED表示
  while( !Serial.available() ) {
    for( i = 0; i < scrollSpeed; i++ )  matrixRefresh( &scrollImage[0] + p );
    if( p > len ) p = 0; else p++; 
  }
}

int getTextFromSerial( byte textdata[] ) {
  int i;
  if( !Serial.available() ) return 0;
  for( i = 0; i < 64; i++ ) {
    textdata[i] = Serial.read();
    if( Serial.available() ) continue;
    delay(10);                              // 10msec待ってもデータがこなければ終了
    if( Serial.available() ) continue;
    textdata[i + 1] = 0;
    break;
  }
  return i + 1;  // 読み込んだ文字数を返す
}

  // maybe let's not read more than 30 or 32 bytes at a time!
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8)); // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,length);
  int c = 0;
  for ( c = 0; c < length; c++ )
    if (Wire.available()) buffer[c] = Wire.receive();
}

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

signed int asciiToElisa(unsigned int code) {  // 半角を全角ELISAに変換 (半角カナはごめんなさい)
  static byte ElisaMark[] = {  0,  9, 40, 83, 79, 82, 84, 38, 41, 42, 85, 59,
                               3, 60,  4, 30,  6,  7, 66, 64, 67,  8, 86, 45,
                              78, 46, 15, 17, 13, 47, 34, 48, 16};
  if((code>=0x81 && code<=0x9f) || (code>=0xe0 && code<=0xef))
                  return -1;                    // ★ シフトJIS上位1バイトは -1 ★
  if(code  <  32) return -2;                    // 制御文字
  if(code <=  47) return ElisaMark[code-32];    // 記号 SP ! " # $ % & ' ( ) * + , - . /
  if(code <=  57) return code + 99;             // 数字
  if(code <=  64) return ElisaMark[code-42];    // 記号 : ; < = > ?
  if(code <=  90) return code + 92;             // 英大文字
  if(code <=  96) return ElisaMark[code-68];    // 記号 [ \ ] ^ _
  if(code <= 122) return code + 86;             // 英小文字
  if(code <= 126) return ElisaMark[code-94];    // 記号 { | } ~
  if(code == 127) return -2;                    // 制御文字 DEL
  if(code >= 0xa1 && code <= 0x9f) return -4;   // 半角カタカナで
  return -3;                                    // 未使用またはシフトJIS下位1バイト
}

void matrixClear() {
  for(int i = 0; i < 16; i++ )  pinMode( i + 2, INPUT );
}

void matrixRefresh( byte bitmap[] ) {
  for(int x = 0; x < 16; x++ ){
    matrixClear();
    pinMode( x + 2, OUTPUT );      // 点灯する列を指定
    digitalWrite( x + 2, LOW );
    for(int y = 0; y < 8; y++ ) {  // 指定列のデータを表示
      if( bitRead( bitmap[x], y ) ) {
        pinMode( y + ( ( x < 8) ? 10 : 2 ) , OUTPUT );
        digitalWrite( y + ( ( x < 8) ? 10 : 2 ) , HIGH );
      }
    }
    delay(1);
  }
}

nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

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

トラックバック 0

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