ESP32[19] 4桁7セグメントのダイナミック点灯

7セグメントはそれぞれのセグメントのLEDを点灯させます。桁数が増えるとI/Oの数が足りなくなるので、ダイナミック点灯という方式を取ります。これは、各桁を順番に点灯させて、目の残像を利用してすべての桁が見えるようにする方法です。本来なら、桁の切り替えはハードウエアで構築するのが良いと思いますが、ソフトで切り替えてもそこそこ使えます。目の残像を利用するので、切り替えが遅いとちらつくことになります。なので、LOOPの中の処理との兼ね合いが出てきます。今回は切り替えはタイマー割り込みで10msecで桁を切り替えるようにしてみました。

使用したLEDは秋月電子で購入できる「4桁赤色7セグメントLED表示器(コロン付) アノードコモン(アノード共通)[OSL40391-IRA]」を使ってみました。いろいろ種類はあるのでPINアサインを変えれば変更は簡単だと思います。アノードコモンとカソードコモンがありますが、イメージがわきやすいアノードコモンが私は好きですね。

コードはこんな感じ。ピンは好きに変えてもらって大丈夫です。

4桁なので、9999までいったら0に戻しています


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