ESP32[19] 4桁7セグメントのダイナミック点灯
7セグメントはそれぞれのセグメントのLEDを点灯させます。桁数が増えるとI/Oの数が足りなくなるので、ダイナミック点灯という方式を取ります。これは、各桁を順番に点灯させて、目の残像を利用してすべての桁が見えるようにする方法です。本来なら、桁の切り替えはハードウエアで構築するのが良いと思いますが、ソフトで切り替えてもそこそこ使えます。目の残像を利用するので、切り替えが遅いとちらつくことになります。なので、LOOPの中の処理との兼ね合いが出てきます。今回は切り替えはタイマー割り込みで10msecで桁を切り替えるようにしてみました。
使用したLEDは秋月電子で購入できる「4桁赤色7セグメントLED表示器(コロン付) アノードコモン(アノード共通)[OSL40391-IRA]」を使ってみました。いろいろ種類はあるのでPINアサインを変えれば変更は簡単だと思います。アノードコモンとカソードコモンがありますが、イメージがわきやすいアノードコモンが私は好きですね。
コードはこんな感じ。ピンは好きに変えてもらって大丈夫です。
// 7 segments
#define SEG_A GPIO_NUM_23
#define SEG_B GPIO_NUM_2
#define SEG_C GPIO_NUM_4
#define SEG_D GPIO_NUM_5
#define SEG_E GPIO_NUM_12
#define SEG_F GPIO_NUM_13
#define SEG_G GPIO_NUM_14
#define SEG_DP GPIO_NUM_15
// com for 7segments
#define COM1 GPIO_NUM_25
#define COM2 GPIO_NUM_26
#define COM3 GPIO_NUM_27
#define COM4 GPIO_NUM_32
hw_timer_t * timer = NULL; //timer 初期化
int msec; //msec カウンター用グローバル変数
int msec_10; // 10msec カウンター
int inc_keta;
int data = 0;
// DIO initialization.
void dio_init() {
pinMode(SEG_A, OUTPUT);
pinMode(SEG_B, OUTPUT);
pinMode(SEG_C, OUTPUT);
pinMode(SEG_D, OUTPUT);
pinMode(SEG_E, OUTPUT);
pinMode(SEG_F, OUTPUT);
pinMode(SEG_G, OUTPUT);
pinMode(SEG_DP, OUTPUT);
pinMode(COM1, OUTPUT);
pinMode(COM2, OUTPUT);
pinMode(COM3, OUTPUT);
pinMode(COM4, OUTPUT);
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
digitalWrite(SEG_DP, LOW);
}
void seg_cont(int com) {
switch (com) {
case 0:
digitalWrite(COM1, HIGH);
digitalWrite(COM2, LOW);
digitalWrite(COM3, LOW);
digitalWrite(COM4, LOW);
break;
case 1:
digitalWrite(COM2, HIGH);
digitalWrite(COM1, LOW);
digitalWrite(COM3, LOW);
digitalWrite(COM4, LOW);
break;
case 2:
digitalWrite(COM3, HIGH);
digitalWrite(COM1, LOW);
digitalWrite(COM2, LOW);
digitalWrite(COM4, LOW);
break;
case 3:
digitalWrite(COM4, HIGH);
digitalWrite(COM1, LOW);
digitalWrite(COM2, LOW);
digitalWrite(COM3, LOW);
break;
default:
digitalWrite(COM4, LOW);
digitalWrite(COM1, LOW);
digitalWrite(COM2, LOW);
digitalWrite(COM3, LOW);
}
}
void disp_4digits(int num, int keta) {
int k1000;
int k100;
int k10;
int k1;
int dp;
if (num < 0) {
num * -1;
dp = true;
} else {
dp = false;
}
k1000 = num / 1000;
k100 = (num - k1000 * 1000) / 100;
k10 = (num - (k1000 * 1000) - (k100 * 100)) / 10;
k1 = num - (k1000 * 1000) - (k100 * 100) - (k10 * 10);
// Serial.printf("k1000:%d k100:%d k10:%d k1:%d\n", k1000, k100, k10, k1);
if (dp == true) digitalWrite(SEG_G, LOW);
else digitalWrite(SEG_G, HIGH);
switch (keta) {
case 0:
disp_digit(k1000);
seg_cont(0);
break;
case 1:
disp_digit(k100);
seg_cont(1);
break;
case 2:
disp_digit(k10);
seg_cont(2);
break;
case 3:
disp_digit(k1);
seg_cont(3);
break;
}
delay(1);
}
void disp_digit(int num) {
switch (num) {
case 0:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, HIGH);
break;
case 1:
digitalWrite(SEG_A, HIGH);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, HIGH);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, HIGH);
digitalWrite(SEG_G, HIGH);
break;
case 2:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, HIGH);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, HIGH);
digitalWrite(SEG_G, LOW);
break;
case 3:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, HIGH);
digitalWrite(SEG_G, LOW);
break;
case 4:
digitalWrite(SEG_A, HIGH);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, HIGH);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
case 5:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, HIGH);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
case 6:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, HIGH);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
case 7:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, HIGH);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, HIGH);
digitalWrite(SEG_G, HIGH);
break;
case 8:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
case 9:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
case 10: // A
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, HIGH);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
case 11: //b
digitalWrite(SEG_A, HIGH);
digitalWrite(SEG_B, HIGH);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
case 12: //C
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, HIGH);
digitalWrite(SEG_C, HIGH);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, HIGH);
break;
case 13: //d
digitalWrite(SEG_A, HIGH);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, HIGH);
digitalWrite(SEG_G, LOW);
break;
case 14: //E
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, HIGH);
digitalWrite(SEG_C, HIGH);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
case 15: //F
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, HIGH);
digitalWrite(SEG_C, HIGH);
digitalWrite(SEG_D, HIGH);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
default:
digitalWrite(SEG_A, HIGH);
digitalWrite(SEG_B, HIGH);
digitalWrite(SEG_C, HIGH);
digitalWrite(SEG_D, HIGH);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, HIGH);
digitalWrite(SEG_G, LOW);
break;
}
}
void serial_setup()
{
Serial.begin(115200);
delay(100);
Serial.println(""); // to separate line
}
void IRAM_ATTR msecond_10() {
inc_keta++;
if (inc_keta > 3) inc_keta = 0;
}
void setup() {
serial_setup();
dio_init();
// msec timer start
timer = timerBegin(0, 80, true); //timer=1us
timerAttachInterrupt(timer, &msecond_10, true);
timerAlarmWrite(timer, 1000, true); // 10ms
timerAlarmEnable(timer);
}
int pre_inc_keta;
void loop() {
Serial.printf("%d %d\n", msec_10, inc_keta);
disp_4digits(data, inc_keta);
data++;
if(data > 9999) data = 0;
}