過去記事の改良② LEDマトリックス表示を割り込み化 

 

 今回は、Arduino UNO R4 WiFiに搭載されているLEDマトリックス関連の改良をしようと思う。

過去の記事では以下が相当する。

 

 

 

 

 

 

 

 私のブログで紹介しているLEDマトリックス関連のプログラムは、サンプルプログラムを見ることもなく独自で作ったものだ。

 自分では満足のいく動作をしているのでいいのだが、実用を考えるとある欠点がある。

 それは、LEDマトリックス表示をloop関数内で行っているため、LEDマトリックス表示以外の動作を同時にさせることができないのだ。

 

 LEDマトリックス用に用意されているサンプルプログラムでは、タイマー割り込みを使った制御を行っている。

なので、俺の作ったプログラムでもそのようにしてみようと思う。

 

 やりかたは、サンプルプログラムでも使われている"FspTimer.h"のヘッダーファイルをインクルードする。

そしてタイマー割り込みの設定をして起動。

割り込みが発生したら設定したコールバック関数が実行されるので、そのコールバック関数の中をいままでloop関数で記述してたLEDマトリックス表示プログラムを移す。

・・・だけでは綺麗に表示されない。

 タイマー割り込み1回で一つのLEDを制御しているので、割り込み96回でLEDマトリックス全体を表示している。 そのため、そんな制御に会ったプログラムに変えないといけない。

 

 とりあえず一番最初のプログラム、タイ語でI love youをスクロール表示させているプログラムを、タイマー割り込み化してみたので、参考にしてもらえればと思う。

改造箇所で何をしているかわかれば、他の文字列スクロール系のプログラムにも応用できるはずだ。

LEDマトリックスでグラデーションさせているプログラムは、この改良ではうまくいかない。 それはまた別途考えることにする。

#include "Arduino_LED_Matrix.h"
#include "FspTimer.h"

//スクロール時間
#define SCROLL_TIME 100   //ミリ秒

//表示文字列
unsigned char matrix[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x08, 0x10, 0xd6, 0x56, 0x52, 0x0f, 0x00,        //cha
0x10, 0x28, 0x1f, 0x01, 0x02, 0x3d, 0x02, 0x00,  //n
0x09, 0x15, 0xd5, 0x55, 0x55, 0x02, 0x00,        //ra
0x0b, 0x1c, 0x28, 0x20, 0x10, 0x0f, 0x00,        //k
0x3f, 0x01,                                      //e
0x18, 0x2b, 0x29, 0x29, 0x27, 0x20, 0x00,        //t
0x13, 0x25, 0x27, 0x21, 0x11, 0x0f,              //o
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

unsigned long tm = 0;
int idx = 0;
int ic1 = 0;

static FspTimer fsp_timer;

void setup() {
  //タイマー割り込みの設定
  uint8_t timer_type;
  int8_t timer_ch = FspTimer::get_available_timer(timer_type);
  if (timer_ch < 0) {
    Serial.println("get_available_timer() failed.");
    return;
  }
  fsp_timer.begin(TIMER_MODE_PERIODIC, timer_type, timer_ch, 10000.0, 50.0, timer_callback, nullptr);
  fsp_timer.setup_overflow_irq();
  fsp_timer.open();
  fsp_timer.start();

  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(500);
}

void timer_callback(timer_callback_args_t *arg)
{
  //スクロール時間が経過したらスライドさせる。末端に到達したら始めに戻る
  if(tm + SCROLL_TIME <= millis()) {
    if (idx < 55)
      idx++;
    else{
      idx = 0;
    }

    //経過時間を再計測
    tm = millis();
  }

  //12x8LED View
  turnLed(ic1, matrix[idx + ic1 % 12] >> (7 - ic1 / 12) & 0x01);
  ic1++;
  if(ic1 > 96)
    ic1 = 0;
}