フォト
2025年4月
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30      
無料ブログはココログ

« 無線LANルータ TP-Link TL-WR703NでWebカメラを利用する | トップページ | Aliexpressで購入したシフトレジスタ(74HC595)が到着 »

2013年12月16日 (月)

arduinoで4桁7セグメントLEDの表示 の続き

前回arduinoで作成した4桁7セグメントLED表示を汎用的に利用するためにモジュール化しました。

まずはハードウェアのモジュール化
ユニバーサル基板上に実装し直しました。arduinoとは6線接続となります。



裏はこんな感じです。0.26mmのポリウレタン銅線(UEW)を使っています。
この線は被膜がハンダごての熱で溶けるので、はんだ付けが楽です。

作成した回路図を見ながら一本一本接続を間違わないようにはんだ付けしました。
はんだ付け後、テスターで通電チェックをしたら問題無し。
奇跡的に一発で正常動作してくれました。

接続端子の詳細
(2013/12/28 追記)

Bord

GND    : ArduinoのGNDに接続
Vcc(5V)
Arduinoの5Vに接続
DATA    : シリアルデータ入力端子
(サンプルではarduinoの5ピンに接続)
CLK      : クロック信号入力端子(サンプルではarduinoの4ピンに接続)
STB      : ストローブ信号入力端子
(サンプルではarduinoの3ピンに接続)
CLR      : クリア信号入力端子
(サンプルではarduinoの2ピンに接続)

ソフトウェアのモジュール化


この表示器用のライブラリも作成しました。
前回作成したプログラムをクラスライブラリ化しました。

arduinoのライブラリは他のライブラリのソースをまねて作成しました。
もしかしたら、正規の作り方でないかもしれませんが、まあ動いたのでよしとします。
ライブラリを使ったプログラムはかなりシンプルになりました。

(2013/12/28 修正)
ソースを見直し大幅修正しました。
汎用的に使うLED用フォントクラスを追加しました。


サンプルプログラム(SEG4.ino)

#include <stdlib.h>
#include <led7segfont.h>
#include <mstimer2.h>
#include <Dinamic7Seg.h>

// ダイナミック点灯用 インスタンスの作成
// 利用ピン: CLR:2、STB:3、CLK:4、DATA:5
Dinamic7Seg seg(2, 3, 4, 5);

// タイマー割り込みから呼び出される表示用関数
void disp() {
   seg.show();
}

void setup() {
  // タイマー割り込み開始
  MsTimer2::set(20, disp);
  MsTimer2::start(); 
}

void loop() {
   // デモプログラム
   // フォントは見た目に近いものを強引に表示している
   // mwxz はもう無理、なんだか分からんフォントで表示
   char* t="0123456789abcdefghijklmnopqrstuvwxyz -,_~^([)]<>/=\\\?#+:\"012";
   int n;
   char*p;
   int i;
   p=t;
   n = strlen(t);
   
   // 桁表示確認を確認する
   seg.print("");  delay(1000);  // 0文字はクリアに相当する   
   seg.print("1");  delay(1000); // 左詰めから表示となる。
   seg.print("12");  delay(1000);
   seg.print("345");  delay(1000);
   seg.print("1234");  delay(1000);
   seg.print("3.141");  delay(1000); // 数字の後ろのドットは数字に付く
   seg.print("   1");  delay(1000);  // 空白文字は何も表示しない
   seg.print("  12");  delay(1000);
   seg.print(" 123");  delay(1000);
   seg.print("1234");  delay(1000);

   // フラッシュ表示(1234が点滅する)
   seg.print("");  delay(200);
   seg.print("1234");  delay(200);
   seg.print("");  delay(200);
   seg.print("1234");  delay(200);
   seg.print("");  delay(200);
   seg.print("1234");  delay(2000);

  // フォント確認
  //   プログラムは表示開始位置をずらしてスクロール表示する
  //   print文では4文字以上の指定が可能だが、表示できない分は無視する。
  for(;;) {
    seg.print(p);
    p++;
    if (*(p+3) == '\0') {
      p = t;
    }
   delay(500);
 }
}

ライブラリはarduino-1.0.5\libraries\の下に格納するとIDEから利用可能になります。

ファイル構成
   \libraries\
    LED7SEGFont\ ・・・・・ LED7セグ用表示パターンフォントクラス
        led7segfont.h
        led7segfont.cpp
  Dinamic7Seg\ ・・・・ LED7セグ4桁ダイナミック点灯表示クラス

        Dinamic7Seg.h   
        Dinamic7Seg.cpp
        examples\
              SEG4\
                SEG4.ino

汎用的に利用するLED7セグ用表示パターンフォントもクラス化して、簡単に利用できる
ようにしました。

ライブラリのソース
led7segfont.h

/**
 ** 7セグメントLEDスタティックフォントクラス
 ** 2013/12/27 Tamakichi
 **
 **/
 
#ifndef led7segfont_h
 #define led7segfont_h

#include <arduino.h>

// キャラクターコード
#define SEG_CHAR_0 0
#define SEG_CHAR_1 1
#define SEG_CHAR_2 2
#define SEG_CHAR_3 3
#define SEG_CHAR_4 4
#define SEG_CHAR_5 5
#define SEG_CHAR_6 6
#define SEG_CHAR_7 7
#define SEG_CHAR_8 8
#define SEG_CHAR_9 9
#define SEG_CHAR_A 10
#define SEG_CHAR_B 11
#define SEG_CHAR_C 12
#define SEG_CHAR_D 13
#define SEG_CHAR_E 14
#define SEG_CHAR_F 15
#define SEG_CHAR_G 16
#define SEG_CHAR_H 17
#define SEG_CHAR_I 18
#define SEG_CHAR_J 19
#define SEG_CHAR_K 20
#define SEG_CHAR_L 21
#define SEG_CHAR_M 22
#define SEG_CHAR_N 23
#define SEG_CHAR_O 24
#define SEG_CHAR_P 25
#define SEG_CHAR_Q 26
#define SEG_CHAR_R 27
#define SEG_CHAR_S 28
#define SEG_CHAR_T 29
#define SEG_CHAR_Y 30
#define SEG_CHAR_V 31
#define SEG_CHAR_W 32
#define SEG_CHAR_X 33
#define SEG_CHAR_Y 34
#define SEG_CHAR_Z 35
#define SEG_CHAR_SPACE 36
#define SEG_CHAR_BAR 37
#define SEG_CHAR_DOT 38
#define SEG_CHAR_UBAR 39
#define SEG_CHAR_TILD 40
#define SEG_CHAR_HAT 41

class LED7SEGFont {
 public:
  static byte asc2font(char c);    // アスキーキャラクタコードをフォントデータに変更
  static byte code2font(char c);   // LED7SEGフォントコードに対応するフォントを取得 
};
#endif 

led7segfont.cpp

#include <led7segfont.h>
//7SEGフォント
static const byte font[] = {
   // abcdefgp 
    0b11111100, //0 :0
    0b01100000, //1 :1
    0b11011010, //2 :2
    0b11110010, //3 :3
    0b01100110, //4 :4
    0b10110110, //5 :5
    0b10111110, //6 :6
    0b11100000, //7 :7
    0b11111110, //8 :8
    0b11110110, //9 :9
    0b11101110, //A :10
    0b00111110, //B :11
    0b10011100, //C :12
    0b01111010, //D :13
    0b10011110, //E :14
    0b10001110, //F :15    
    0b10111100, //G :16    
    0b01101110, //H :17    
    0b00001100, //I :18    
    0b01110000, //J :19    
    0b10101110, //K :20    
    0b00011100, //L :21    
    0b11101101, //M :22    
    0b11101100, //N :23    
    0b00111010, //O :24    
    0b11001110, //P :25    
    0b11100110, //Q :26    
    0b00001010, //R :27    
    0b10110111, //S :28    
    0b10001100, //T :29    
    0b01111100, //U :30    
    0b00111000, //V :31    
    0b01111110, //W :32    
    0b01101111, //X :33    
    0b01110110, //Y :34    
    0b11011011, //Z :35    
    0b00000000, //  :36   
    0b00000010, //- :37    
    0b00000001, //. :38     
    0b00010000, //_ :39     
    0b10000000, //~ :40     
    0b11000100, //^ :41
    0b11110000, //] :42
    0b01001010, ///':43
    0b00011010, //< :44
    0b00110010, //> :45
    0b00010010, //= :46
    0b00100110, //\ :47
    0b11001010, //? :48
    0b01101100, //# :49
    0b01100010, //+ :50
    0b10010000, //: :51
    0b01000100  //" :52
};

// アスキーキャラクタコードをフォントデータに変更
byte LED7SEGFont::code2font(char c) {
  return font[c];
}

// キャラクタコードをフォントデータに変更
byte LED7SEGFont::asc2font(char c) {
  if ( isdigit((int)c) ) {
    // 数字
    return font[c-'0'];
  }   
  if ( isalpha((int)c) ) {
    // アルファベット
    if (c >='a' && c <= 'z') {
      return font[c-'a' + SEG_CHAR_A];
    } else if (c >= 'A' && c <= 'Z') {
      return font[c-'A' + SEG_CHAR_A];
    }
  }
  
  switch(c) {
    case ' ':return font[SEG_CHAR_SPACE];
    case '-':return font[SEG_CHAR_BAR];
    case ',':return font[SEG_CHAR_DOT];
    case '_':return font[SEG_CHAR_UBAR];
    case '~':return font[SEG_CHAR_TILD];
    case '^':return font[SEG_CHAR_HAT];
    case '(':
    case '[':return font[SEG_CHAR_C];
    case ')':
    case ']':return font[42];
    case '<':return font[44];
    case '>':return font[45];
    case '/':return font[43];
    case '=':return font[46];
    case '\\':return font[47];
    case '?':return font[48];
    case '#':return font[49];
    case '+':return font[50];
    case ':':return font[51];
    case '"':return font[52];
  }
  return font[SEG_CHAR_SPACE];	
}

Dinamic7Seg.h

/**
 ** 4ケタ7セグメントLEDダイナミック表示クラス
 ** 2013/12/27 Tamakichi 
 **
 **/

#ifndef Dinamic7Seg_h
 #define Dinamic7Seg_h

#include <Arduino.h>
#include <led7segfont.h>
 
class Dinamic7Seg {
  private:

	// 利用ピン
	int	pin_clr;
	int	pin_stb;
	int	pin_clk;
	int pin_data;

	//表示データ
	byte bcd[4];
		
  public:
  	Dinamic7Seg();
  	Dinamic7Seg(int pin_clr, int pin_stb, int pin_clk, int pin_data); // 利用ピン指定

	void init(void);
  	void attach(int pin_clr, int pin_stb, int pin_clk, int pin_data); // 利用ピン指定

	void clear();					// 7セグLEDのクリア
	void print(char* str);			// 7セグLEDへの表示
	void show(); 					// 7セグLED4桁表示
	void segout(int no, byte c);	// 指定桁の表示
};
#endif

Dinamic7Seg.cpp
/**
 ** 4ケタ7セグメントLEDダイナミック表示クラス
 ** 2013/12/27 Tamakichi
 **
 **/

#include <Arduino.h>
#include <Dinamic7Seg.h>
 
// 桁表示パターン
static const boolean __DIG[4][4] = {
	  {0,0,0,1},
	  {0,0,1,0},
	  {0,1,0,0},
	  {1,0,0,0}
};

// コンストラクタ
Dinamic7Seg::Dinamic7Seg() {
	clear();
}

Dinamic7Seg::Dinamic7Seg(int _pin_clr, int _pin_stb, int _pin_clk, int _pin_data) {
	clear();
	attach(_pin_clr, _pin_stb, _pin_clk, _pin_data);
}

// ビンの初期化	
void Dinamic7Seg::init() {
  digitalWrite(pin_clr, HIGH); 
  digitalWrite(pin_stb, HIGH);
  digitalWrite(pin_clk, LOW);
  digitalWrite(pin_data, LOW);
}

// 利用ピンの指定
void Dinamic7Seg::attach(int _pin_clr, int _pin_stb, int _pin_clk, int _pin_data) {
	pin_clr = _pin_clr;
	pin_stb = _pin_stb;
	pin_clk = _pin_clk;
	pin_data = _pin_data;
	
	pinMode(pin_clr, OUTPUT);
	pinMode(pin_stb, OUTPUT);
	pinMode(pin_clk, OUTPUT);
	pinMode(pin_data, OUTPUT);
	init();
}

// 7セグLEDのクリア
void Dinamic7Seg::clear() {
  bcd[0]= 0;
  bcd[1]= 0;
  bcd[2]= 0;
  bcd[3]= 0;	
}	

// 7セグLEDへの表示
void Dinamic7Seg::print(char* str) {
  clear();
  int n = strlen(str);
  int p = 0;
  byte c;
  boolean pre = 0;
  
  for (int i=0; i <n && p < 4 ; i++) {
    if (str[i] == '.') {
      // ドットの処理
      if (pre) {
        bcd[p-1] |= LED7SEGFont::code2font(SEG_CHAR_DOT);
        pre=0;
      } else {
        bcd[p] = LED7SEGFont::code2font(SEG_CHAR_DOT);
        p++;
        pre=1;
      }
    } else {
      // それ以外の文字  
      bcd[p] = LED7SEGFont::asc2font(str[i]);
      p++; 
      pre = 1;
    }
  }
}

// 7セグLED4桁表示
void Dinamic7Seg::show() {
  for (int i = 0; i < 4; i++) {
    segout(i, bcd[3-i]);
  }
  digitalWrite(pin_clr, LOW);
  digitalWrite(pin_clr, HIGH);  
}

// 指定桁の表示
void Dinamic7Seg::segout(int no, byte c) {
  // 12 ビットデータ転送

  // 表示する桁のセット
  for (int i=0; i< 4; i++) {
    digitalWrite(pin_data, __DIG[no][i]);
    digitalWrite(pin_clk, HIGH);  
    digitalWrite(pin_clk, LOW);  
  }  
  
  // フォントデータのセット
  shiftOut(pin_data, pin_clk, LSBFIRST, c);
  
  digitalWrite(pin_stb, LOW); 
  digitalWrite(pin_stb, HIGH);
  delay(2);
}
C++でプログラムを組んだのは数年ぶりでした。
JavaやPHPの感覚でクラスを定義したらコンパイルエラーが続出。
クラス定義とメンバー関数実装が別ファイルとなるのは非常に違和感があります。
クラス定義内に配列データを定義するのがJavaのように出来ないしちょっと不便。

まあ、これでセンサー類を使って簡単に数値が表示できるようになったと思われます。

このダイナミック点灯だと、タイマー割り込み等で随時表示処理を実行しないと
いけないのでちょっと無駄にCPU負荷がかかりますねぇ。
表示くらいハードウェアで全てやりたいなぁ。

« 無線LANルータ TP-Link TL-WR703NでWebカメラを利用する | トップページ | Aliexpressで購入したシフトレジスタ(74HC595)が到着 »

arduino」カテゴリの記事

AVR」カテゴリの記事

表示器制御関連」カテゴリの記事

コメント

赤外線LEDとフォトトランジスタで物を感知したら、4桁7セグメントLEDでカウントされるようなプログラムを教えてください。お願いします。

> 赤外線LEDとフォトトランジスタで物を感知したら、4桁7セグメントLEDでカウントされるようなプログラムを教えてください。お願いします。

状況・回路構成等が分からないので、具合的なプログラムソースの提示は難しいですね。

物の感知は、物が赤外線を反射して
その反射光をフォトトランジスタで受信することで感知する感じでしょうか?

フォトトランジスタからの入力をデジタル入力または、
アナログ入力(物までの距離により閾値を決めて判定)で感知すれば良い思います。

物を感知していない状態から、物を感知した状態に変化したときにカウントすれば良いです。
場合により誤カウント対策を考慮する必要があるかもしれません。
例えば、アナログ入力での判定で閾値付近の値での短時間での状態変化はフィルタリング(除外)するなど

物の感知はおっしゃる通りの方法です。
今、SN74HC595NのICを使ってアルディーノUNOと4桁7セグメントをつないでいます。
7セグメントで1.2.3.4と順番に表示するようなプログラムを書いています。

フォトトランジスタをどこに繋いだらいいのかもよくわからない状況です。すいません。

コメントを書く

(ウェブ上には掲載しません)

トラックバック


この記事へのトラックバック一覧です: arduinoで4桁7セグメントLEDの表示 の続き:

« 無線LANルータ TP-Link TL-WR703NでWebカメラを利用する | トップページ | Aliexpressで購入したシフトレジスタ(74HC595)が到着 »