先日のArduino STM32用タイマー割り込みライブラリを使って、
BluePillボードを使って、4桁7セグLEDをダイナミック点灯にて制御してみました。
動いている様子
以前、秋月電子で入手して放置していた 4桁7セグLEDはOSL40562-IG を利用しました。
このOSL40562-IG、アノードコモンでVFが3.3Vと高く 少々使いにくです。
ダイナミック接続4桁高輝度緑色7セグメントLED表示器 アノードコモン アノード共通接続 OSL40562-IG
とりあえず、次のような回路で駆動させてみました。
BluePillボードの5Vトレラント対応のピンを使って駆動させます。
各LEDに流れる電流は5mA程度にしています。
I = (5[V] - Vf[V] ) / 330[Ω] = (5 - 3.3) /330 = 0.00515[A] ≒ 5[mA]
各桁セグメントDIG1 ~ DIG4は、LED8個分の40mAが流れます。
BluePillボードでは20mAまでしか流せないため、PNPトランジスタ 2SA1015を使って
駆動させるようにしました。
スケッチ
//
// 4桁高輝度緑色7セグメントLED表示器(アノードコモン) OSL40562-IG の制御
// 2019/03/17 たま吉さん
// 利用パーツ
// BluePillボード
// 4桁7セグメントLED OSL40562-IG x 1
// 桁制御用トランジスタ 2SA1015L-GR x 4
// LED電流制御用抵抗 330Ω x 8
// トランジスタベース抵抗 10kΩ x 4
//
#include "TimerEvent.h"
// タイマー割り込み管理
TimerEvent ticker;
#define REFTIME 4
// デジタルピンの定義
#define DIG1 PB12
#define DIG2 PB13
#define DIG3 PB14
#define DIG4 PB15
#define SEGA PB3
#define SEGB PB4
#define SEGC PB6
#define SEGD PB7
#define SEGE PB8
#define SEGF PB9
#define SEGG PB10
#define SEGP PB11
// 桁表示ON・OFF
#define DIG_ON 0
#define DIG_OFF 1
// セグメント表示ON・OFF
#define SEG_ON 0
#define SEG_OFF 1
// セグメントビット定義
#define BIT_A 0b10000000
#define BIT_B 0b01000000
#define BIT_C 0b00100000
#define BIT_D 0b00010000
#define BIT_E 0b00001000
#define BIT_F 0b00000100
#define BIT_G 0b00000010
#define BIT_P 0b00000001
// フォントの定義
const uint8_t font[12] = {
BIT_A|BIT_B|BIT_C|BIT_D|BIT_E|BIT_F, // 0
BIT_B|BIT_C, // 1
BIT_A|BIT_B|BIT_G|BIT_E|BIT_D, // 2
BIT_A|BIT_B|BIT_G|BIT_C|BIT_D, // 3
BIT_F|BIT_B|BIT_G|BIT_C, // 4
BIT_A|BIT_F|BIT_G|BIT_C|BIT_D, // 5
BIT_A|BIT_F|BIT_E|BIT_D|BIT_C|BIT_G, // 6
BIT_A|BIT_B|BIT_C, // 7
BIT_A|BIT_B|BIT_C|BIT_D|BIT_E|BIT_F|BIT_G, // 8
BIT_A|BIT_B|BIT_C|BIT_D|BIT_F|BIT_G, // 9
0, // ブランク
BIT_G, // -
};
// 桁制御ピン
const uint8_t pin_dig[4] = {
DIG1, DIG2, DIG3, DIG4,
};
// セグメント制御ピン
const uint8_t pin_seg[8] = {
SEGA, SEGB, SEGC, SEGD, SEGE, SEGF, SEGG, SEGP,
};
// 表示用データ
volatile uint8_t digit[4];
// タイマー割り込み呼び出し関数
void dinamic_update() {
static uint8_t cnt = 0;
for (uint8_t i = 0; i < 4; i++)
digitalWrite(pin_dig[i], DIG_OFF);
for (uint8_t i = 0; i < 8; i++)
digitalWrite(pin_seg[i], digit[cnt] & (0x80>>i) ? SEG_ON:SEG_OFF);
digitalWrite(pin_dig[cnt], DIG_ON);
cnt++; if (cnt == 4) cnt = 0;
}
// データのクリア
void cls() {
digit[0] = 0; digit[1] = 0; digit[2] = 0; digit[3] = 0;
}
// 数値の設定
void setNumber(uint16_t n, uint8_t dt = 0) {
if (n>9999)
return;
cls();
uint8_t dec = 0;
// 4桁目
if (n >= 1000) {
digit[0] =font[ n / 1000]; n = n % 1000; dec = 1;
}
// 3桁目
if (n >= 100) {
digit[1] = font[n / 100]; n = n % 100; dec = 1;
} else if (dec) {
digit[1] = font[0];
}
// 2桁目
if (n >= 10) {
digit[2] = font[n / 10]; n = n % 10; dec = 1;
} else if(dec) {
digit[2] = font[0];
}
// 1桁目
digit[3] = font[n];
// 小数点
if(dt && dt <=4) {
digit[4-dt] |= BIT_P;
}
}
void setup() {
// 桁ピンの初期化
for (uint8_t i = 0; i < 4; i++) {
pinMode(pin_dig[i], OUTPUT_OPEN_DRAIN);
digitalWrite(pin_dig[i], DIG_OFF);
}
// セグメントピンの初期化
for (uint8_t i = 0; i < 8; i++) {
pinMode(pin_seg[i], OUTPUT_OPEN_DRAIN);
digitalWrite(pin_seg[i], SEG_OFF);
}
// 表示データの初期化
for (uint8_t i = 0; i < 4; i++) {
digit[i] = 0;
}
// LEDダイナミック点灯用割り込み設定
ticker.set(REFTIME, dinamic_update); // REFTIME間隔で dinamic_update()を呼び出す
ticker.start(); // タイマー割り込み実行開始
}
void loop() {
static uint16_t n = 0;
setNumber (n,millis()%1000>500?1:0);
delay(100);
n++; if (n>9999) n = 0;
}
タイマー割り込みは4m秒間隔で実行させています。
一回の割り込みで4桁のうちの1つを表示させています。
全桁更新周期は 4m秒 x 4 = 16m秒 ≒ 1/60秒 です。
これは、人間の目がちらつきを感じない周期です。
これ以上遅くすると、ちらついて見えます。
電圧を5Vではなく、3.3Vにしても問題なく点灯出来ました。
VF 3.3Vとありますが、実際はもっと低い値のようです。
最近のコメント