2012年11月26日月曜日

8ドットLED POVを作ってみる


(縦8ドットでも日本語がなんとか)

LED POVとは、LEDを点滅させその残像で文字等を表示させる装置です。

参考:残像表示装置“POV”をプログラムしよう!

上記サイトのスケッチだけでも遊べますが、このスケッチのままだと点滅が連続でループしてしまいます。手の振りに合わせて点滅を開始させるために、マーキュロスイッチ(水銀スイッチ)を使います。

D13をプルアップ、そこにマーキュロスイッチを写真の方向で取り付けます。
POVを右から左に振って止まった時にD13がLOWになり、100ms後からLEDの点滅が始まります。

マーキュロスイッチを反対側にもう1個使い、右から左へ振っている時に逆から点滅させてみましたが、手の振りでは往復でLEDの点滅が重ならないため読みづらくなるので片道だけの点滅です。ワイパーのようにモーター+ギア等で正確に往復運動出来れば、往復両方で表示させてもきちんと読めるかも。

振り方によって、復路で裏向きに表示されることがありますが、マーキュロスイッチ内で水銀がバウンドしてるせいかと思います。スイッチの角度や、振り方、スケッチを工夫してください。

ビットマップデータを2次元配列の変数に格納することにより、振るごとにPOVパターンを切り替えできるようにしました。
また、1つのパターンを指定回数リピートさせるループも入れてます。

ここで表示させる文字のデータの編集がめんどくさくなるわけですが、便利なものが公開されてます。

【Py】8ドット美咲フォントをJapanino POV用にコンバート
http://boxheadroom.com/2010/06/16/pov_misaki_font
pythonで書かれています。
pythonスクリプトをどこかに保存。
リンク先の美咲フォント(truetypeフォント)をダウンロードし、misaki_gothic.ttf を misaki.ttf にリネームして、スクリプトを置いた場所に移動。
pythonのPython Imaging Library (PIL)が必要なのでこちらもインストール。
win7、python2.7、PIL1.1.7の環境でpythonスクリプトを実行したところ
The _imagingft C module is not installed
というエラーが出ましたが

参考:Step.5 – PILを書き換える
http://99blues.dyndns.org/blog/2011/01/blockdiag_for_win/
に書いてあるように、_imageft.pyd をバイナリエディタで書き換えると動きました。
生成されたデータをスケッチにコピペして使えます。

3mmのLEDを使いました。
LEDの傾き具合や輝度ムラのせいか正面から見ると読みづらい場合もあります。
光の拡散のために半透明のセロハンテープ(鉛筆で上から書けるやつ)でLEDにかぶせています。

flashでpovデータを生成するページ、スクリプト
参考:テキストからPOV用データを作成する(FLASH)

こちらではライブラリ化されており、スクロールも可能
参考:大人の科学マガジン vol.27 「ジャパニーノ」(その4)P.O.Vライブラリ

flashメモリは大きいので、表示させたいデータが固定されているなら、スケッチ内にデータを置いてもいいでしょうが、ちょっとスマートじゃないような。
SDカードに保存したビットマップデータを表示させるのが現実的かな。

部品:
周辺部品はLED8個、抵抗220Ωx8と、腕のふりを検出するマーキュロスイッチ1個。
8個のLEDはD2~D9に接続。マーキュロスイッチはD13に。
arduinoを振り回すのは重そうなので、生328Pにブートローダーを書き込み、リセット端子のプルアップ抵抗10KΩ、電源は100円ショップDCDCコンバータ。
すべての部品を長めのブレッドボードに配置しました。
振った時に飛び散らないように気をつけてください。

最後のスケッチにはこの4パターンが入っています。
HELLO WORLD!  (D!が切れてますが)
こんにちは世界
地球●日本
市松模様

スケッチ:
ひとまず4パターンのビットマップデータをスケッチにおいたので長くなってます。

// 8ドットLED POV by cranberry
// http://cranberrytree.blogspot.jp/
//                           2012/11/25

#define LEN 56         // 1パターンの長さ(表示時横ドット数)

byte ledpin = 2;       // どのピンから使ったか(今回は2から9 連番で)
int pat_num = 4;       // パターンの数
int rep_num = 3;       // リピートの回数
int delay_ms = 1;       // 点滅間隔(ミリ秒で指定)
byte sw=13;            //マーキュロスイッチを接続
byte delay_start = 100;  //点滅はじめ前のウェイト
int pos = 0;

byte bitmap[][LEN] = {
  {
    0b11111111,
    0b00010000,
    0b11111111,
    0b00000000,
    0b11111111,
    0b10010001,
    0b10010001,
    0b00000000,
    0b11111111,
    0b10000000,
    0b10000000,
    0b00000000,
    0b11111111,
    0b10000000,
    0b10000000,
    0b00000000,
    0b01111110,
    0b10000001,
    0b01111110,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b11111111,
    0b01110000,
    0b11111111,
    0b00000000,
    0b01111110,
    0b10000001,
    0b01111110,
    0b00000000,
    0b11111111,
    0b00010001,
    0b11101110,
    0b00000000,
    0b11111111,
    0b10000000,
    0b10000000,
    0b00000000,
    0b11111111,
    0b10000001,
    0b01111110,
    0b00000000,
    0b00000000,
    0b10011111,
    0b00000000,
    0b00000000,
    0b00000000, 
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000
  }
  ,{
    0b00000000,
    0b00100000,
    0b01010010,
    0b01000010,
    0b01000010,
    0b01000010,
    0b01000000,
    0b00000000,
    0b01000000,
    0b00110000,
    0b00001100,
    0b00110011,
    0b01000000,
    0b01000000,
    0b00100000,
    0b00000000,
    0b01111111,
    0b00000000,
    0b00100000,
    0b01010010,
    0b01000010,
    0b01000010,
    0b01000000,
    0b00000000,
    0b00000000,
    0b00000010,
    0b00010010,
    0b01001110,
    0b01001011,
    0b01001010,
    0b00110010,
    0b00000000,
    0b01111111,
    0b00000000,
    0b00100100,
    0b01010100,
    0b01010100,
    0b00111111,
    0b01000100,
    0b00000000,
    0b00000100,
    0b01111111,
    0b01000100,
    0b01011111,
    0b01010100,
    0b01011111,
    0b01000100,
    0b00000000,
    0b00100000,
    0b01011111,
    0b00110101,
    0b00011111,
    0b01110101,
    0b00011111,
    0b00100000,
    0b00000000,
  }
  ,{
    0b00100100,
    0b00111111,
    0b00001000,
    0b01111110,
    0b01000100,
    0b01011111,
    0b01101100,
    0b00000000,
    0b00101001,
    0b00111111,
    0b00101010,
    0b01010010,
    0b01111111,
    0b00010010,
    0b00101011,
    0b00000000,
    0b00011100,
    0b00111110,
    0b01111111,
    0b01111111,
    0b01111111,
    0b00111110,
    0b00011100,
    0b00000000,
    0b00000000,
    0b01111111,
    0b01001001,
    0b01001001,
    0b01001001,
    0b01001001,
    0b01111111,
    0b00000000,
    0b00100010,
    0b00010010,
    0b00101010,
    0b01111111,
    0b00101010,
    0b00010010,
    0b00100010,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000
  }
  ,{
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010,
    0b01010101,
    0b10101010
  }
};

void setup() {
  for(byte pin=ledpin; pin<ledpin + 8; pin++) {  //指定したピンから連続8本を使用
    pinMode(pin, OUTPUT);
  }
  pinMode(sw,INPUT);
  digitalWrite(sw,HIGH);     //プルアップ
}

void loop() {
  for(byte cnt = 0; cnt<pat_num; cnt++){           //POVパターンを切り替える
    for(byte repeat=0; repeat<rep_num; repeat++){  //パターンを繰り返す
      delay(delay_start);
      while(pos != LEN){                     //1パターン1回描画
        for(byte i=0; i<8; i++) {                       //縦1行描画
          digitalWrite(ledpin + i, (bitmap[cnt][pos] >> i) & 0b00000001);
        }
        pos += 1;
        delay(delay_ms);
      }
      pos = 0;
      for(byte j=0; j<8; j++) {                   //全LED消灯
        digitalWrite(ledpin + j, LOW);
      }
      while(digitalRead(sw)==HIGH){}
    }
  }
}




環境:ArduinoUnoR3、Arduino1.0.2、win7、python2.7、PIL1.1.7(改)






0 件のコメント:

コメントを投稿