ESP32とHUB75のドットマトリクスパネルでNTP時計を作ってみた

ESP32とHUB75のドットマトリクスパネルでNTP時計を作ってみた

3年前に作成したESP32マイコンボードとMAX7219 LEDディスプレイ4連x2を使ったNTP時計は、昨年の夏にLEDパネルの一部が不調となり、時刻が正しく表示できなくなってしまいました。このNTP時計で使用していたのは、8x8ドットのLEDパネルを4枚連結したものを2セット組み合わせた、64x8ドットの表示が可能なLEDディスプレイでした。しかし、今回は以前のパネルではなく、LEDドット数が4倍の64x32ドットのLEDマトリクスパネルを新たに購入しました。このタイプのパネルは「HUB75」というキーワードで検索すると見つけることができます。

新しい64x32ドットパネルは、以前のものに比べて消費電力が大きく、ESP32などのシングルボードコンピュータの5V電源出力ピンだけでは必要な電力を供給することができません。そのため、LEDパネルを動作させるには別途5V/8A程度の電流を供給できるACアダプタやスイッチング電源が必須となります。LEDの明るさや表示のスムーズさを保つためには十分な電力供給が欠かせないため、電源選びには特に注意が必要です。

実は、新しいパネルとACアダプタは昨年(2023年)の夏、前回のNTP時計が壊れた直後にすぐ購入していました。しかし、ちょうどその頃、体調を崩して入院することになり、その後も長期間静養していたため、修理に手をつけることができませんでした。そのまま年が明け、2024年になってもなかなかやる気が湧かず、さらに他の用事に追われてしまった結果、このパネルを使ったNTPクロックのことはすっかり忘れ去られていました。そのため、新しいパネルや電源を用意してから、実に1年半近く放置されることになってしまいました。

それが、ようやくやる気スイッチが入り、長らく手を付けられずにいた新NTPクロック作成をスタートすることができました。今回は新しい64x32ドットパネルいっぱいにNTP時計を表示する部分についてを紹介します。パネルの額縁や背面隠しについても綺麗に作成する予定を立てていますが、もしかするとブログでは取り上げないかもしれません。今回の記事の写真では、パネルを立てて固定するために発泡ボードを切り出して簡易的な衝立を作成し、それを仮付けした状態で撮影しました。この方法はあくまで作業の便宜上行ったものであり、完成版ではよりしっかりとした支持構造を採用する予定です。

ESP32とHUB75のドットマトリクスパネルでNTP時計を作ってみた 1
LEDパネルの電源には、一般的には小型のスイッチング電源が利用されることが多いかもしれません。しかし、電源への埃の侵入を防ぎたかったため、密閉ケースに収められたACアダプタを採用しました。写真のACアダプタの出力は5V8Aで、40W程度の容量があります。パネルを最大輝度で全ドット点灯させるのでない限り、20〜30Wでも運用可能ですが、供給できる最大電力には余裕を持たせることが重要です。電源に余裕がないと、動作が不安定になったり表示できなくなる可能性があります。

ESP32とHUB75のドットマトリクスパネルでNTP時計を作ってみた 2
ACアダプタのプラグに合うソケットを用意し、パネル付属の電源ケーブルをはんだ付けしました。パネル付属の電源ケーブルはプラス・マイナスが2本ずつで、さらに増設パネルに電力を供給できるようにそれがダブル構成になっていましたが、今回は増設パネルを使用しないため増長分は取り外しています。その後、接続部を保護するために熱収縮チューブで覆っています。これによりうっかりによるショートを発生させないようになっています。上の写真は電源ソケットにACアダプタを接続した様子を示しています。

ESP32とHUB75のドットマトリクスパネルでNTP時計を作ってみた 3
パネルの背面には、中央に電源ソケットが配置され、上の写真では右側のHUB75ソケットは隠れていますが、左右にHUB75ソケットがあり、左のソケットが入力用、右のソケットが出力用です。左側のソケットを使用してESP32ボードなどからパネルへの信号を入力します。

ESP32とHUB75のドットマトリクスパネルでNTP時計を作ってみた 4
今回使用するHUB75 64×32ドットのLEDパネルをESP32で制御するには、tidbyt/ESP32-HUB75-MatrixPanel-I2S-DMAライブラリを利用すると非常に簡単です。
ESP32とHUB75のドットマトリクスパネルの接続のデフォルトはこの画像のとおりです。この接続であればスケッチ(ソース)内で接続ピンを宣言する必要はありません。理由があってデフォルトと異なるGPIOピンを使用して接続するならそのスケッチ内で変更する接続ピンを指定する必要があります。
64x32ドットの1/16スキャンのパネルを使用する場合は、パネルとESP32を接続するために14本のジャンパケーブルが必要です。64x64ドットの1/32スキャンのパネルを使用する場合はHUB75のEピンとESP32の空きピンを接続するするので15本のジャンパケーブルが必要です。今回は64x32ドットパネルを使用するのでEピンは接続していません。

ESP32とHUB75のドットマトリクスパネルでNTP時計を作ってみた 5
今回採用した64×32ドットのパネルは2.5mmピッチ(P2.5)で、サイズは160×80mmです。以前使用していた8×8ドットの4連パネルは3.5mmピッチ(P3.5)だったため、4連(130mm)×2パネルで260mmです。8ドット×4連×2パネルで今回のパネルと同じ横64ドットなので今回のパネルはドット密度が約4割高まっています。なお、HUB75のパネルはピッチの異なるバリアントが存在するので好みのピッチのものを購入してください。
NTPクロック用のスケッチは、jenizar/esp32-p5-rgb-32x64-ntp-clockをベースにしました。1から作成する必要がなくなるため大幅に作成時間を短縮できました。ただし、デフォルトの文字のデザインに満足できなかったため、フォントを変更しました。日付や曜日、秒数の表示にはビルトインの6×8ドットフォントを使用し、「時:分」部分には自作の縦長(Tall)フォントを採用しました。ただし、秒数の表示が小さすぎるため、ビルトインフォントより一回り大きなフォントを作成することにしました。(次)

ESP32とHUB75のドットマトリクスパネルでNTP時計を作ってみた 6
新たに作成した8×12ドットのフォントを秒表示に適用しました。この変更により、秒表示がより大きく、パネル全体を効果的に活用した時計デザインとなりました。

ESP32とHUB75のドットマトリクスパネルでNTP時計を作ってみた 7
「秒」表示用に数字だけ(空白とコロンを含む)の8x12ドットのSimpleNumber8x12フォントと、「時:分」表示用の11x20ドットのTallNumber11x20フォントを自作しました。以下フォントファイルは、ユーザーの「Adruino」ディレクトリ→「スケッチ名」ディレクトリ下に「Fonts」ディレクトリを作成し、そこにSimpleNumber8x12.hとTallNumber11x20.hを置きます。
なお、文字を並べた際に隣接する部分が繋がって表示されることを防ぐため、各文字の一番右は1列空けています。つまり、8x12フォントの文字部分の領域は7x12ドット、11x20フォントの文字部分の領域は10x20ドットになっています。

SimpleNumber8x12.h
 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#pragma once
#include <Adafruit_GFX.h>

const uint8_t SimpleNumber8x12Bitmaps[] PROGMEM = {
  0xFF, 0xEA, 0x03, 0x7C, 0xFE, 0xC6, 0xCE, 0xCE, 0xD6, 0xD6, 0xE6, 0xE6,
  0xC6, 0xFE, 0x7C, 0x30, 0x30, 0x70, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30,
  0x30, 0x78, 0x78, 0x7C, 0xFE, 0xC6, 0x06, 0x06, 0x7E, 0xFC, 0xC0, 0xC0,
  0xC0, 0xFE, 0xFE, 0x7C, 0xFE, 0xC6, 0x06, 0x06, 0x1C, 0x1C, 0x06, 0xC6,
  0xC6, 0xFE, 0x7C, 0x04, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xCC, 0xFE, 0xFE,
  0x0C, 0x0C, 0x0C, 0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0xFE, 0x06, 0x06,
  0xC6, 0xFE, 0x7C, 0x7C, 0xFE, 0xC6, 0xC0, 0xC0, 0xFC, 0xFE, 0xC6, 0xC6,
  0xC6, 0xFE, 0x7C, 0xFE, 0xFE, 0xC6, 0x06, 0x0C, 0x0C, 0x0C, 0x18, 0x18,
  0x18, 0x18, 0x18, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6, 0x7C, 0x7C, 0xC6, 0xC6,
  0xC6, 0xFE, 0x7C, 0x7C, 0xFE, 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x06, 0x06,
  0xC6, 0xFE, 0x7C, 0x3C, 0x3C
};

const GFXglyph SimpleNumber8x12Glyphs[] PROGMEM = {
  {     0,   0,   0,   5,    0,    1 },   // 0x20 ' '
  {     0,   0,   0,   0,    0,    0 },   // 0x21 '!'
  {     0,   0,   0,   0,    0,    0 },   // 0x22 '"'
  {     0,   0,   0,   0,    0,    0 },   // 0x23 '#'
  {     0,   0,   0,   0,    0,    0 },   // 0x24 '$'
  {     0,   0,   0,   0,    0,    0 },   // 0x25 '%'
  {     0,   0,   0,   0,    0,    0 },   // 0x26 '&'
  {     0,   0,   0,   0,    0,    0 },   // 0x27 '''
  {     0,   0,   0,   0,    0,    0 },   // 0x28 '('
  {     0,   0,   0,   0,    0,    0 },   // 0x29 ')'
  {     0,   0,   0,   0,    0,    0 },   // 0x2A '*'
  {     0,   0,   0,   0,    0,    0 },   // 0x2B '+'
  {     0,   0,   0,   0,    0,    0 },   // 0x2C ','
  {     0,   0,   0,   0,    0,    0 },   // 0x2D '-'
  {     0,   0,   0,   0,    0,    0 },   // 0x2E '.'
  {     0,   0,   0,   0,    0,    0 },   // 0x2F '/'
  {     3,   8,  12,   8,    0,  -11 },   // 0x30 '0'
  {    15,   8,  12,   8,    0,  -11 },   // 0x31 '1'
  {    27,   8,  12,   8,    0,  -11 },   // 0x32 '2'
  {    39,   8,  12,   8,    0,  -11 },   // 0x33 '3'
  {    51,   8,  12,   8,    0,  -11 },   // 0x34 '4'
  {    63,   8,  12,   8,    0,  -11 },   // 0x35 '5'
  {    75,   8,  12,   8,    0,  -11 },   // 0x36 '6'
  {    87,   8,  12,   8,    0,  -11 },   // 0x37 '7'
  {    99,   8,  12,   8,    0,  -11 },   // 0x38 '8'
  {   111,   8,  12,   8,    0,  -11 },   // 0x39 '9'
  {   123,   2,   8,   5,    1,  -10 }    // 0x3A ':'
};

const GFXfont SimpleNumber8x12 PROGMEM = {(uint8_t *)SimpleNumber8x12Bitmaps,
  (GFXglyph *)SimpleNumber8x12Glyphs, 0x20, 0x3A,      12};
TallNumber11x20.h
 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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#pragma once
#include <Adafruit_GFX.h>

const uint8_t TallNumber11x20Bitmaps[] PROGMEM = {
  0xFF, 0xEA, 0x03, 0x3F, 0x0F, 0xF3, 0x87, 0x60, 0x6C, 0x1D, 0x83, 0xB0,
  0xB6, 0x16, 0xC4, 0xD8, 0x9B, 0x23, 0x64, 0x6D, 0x0D, 0xA1, 0xB8, 0x37,
  0x06, 0xC0, 0xDC, 0x39, 0xFE, 0x1F, 0x80, 0x0C, 0x01, 0x80, 0xF0, 0x1E,
  0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00,
  0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0xFC, 0x1F, 0x80, 0x3F,
  0x0F, 0xF3, 0x87, 0x60, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x01, 0xC7,
  0xF1, 0xFC, 0x70, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x03,
  0xFF, 0x7F, 0xE0, 0x3F, 0x0F, 0xF3, 0x87, 0x60, 0x60, 0x0C, 0x01, 0x80,
  0x30, 0x06, 0x01, 0x80, 0xE0, 0x1C, 0x00, 0xC0, 0x0C, 0x01, 0x80, 0x36,
  0x06, 0xC0, 0xDC, 0x39, 0xFE, 0x1F, 0x80, 0x03, 0x00, 0x60, 0x1C, 0x03,
  0x80, 0xF0, 0x1E, 0x06, 0xC0, 0xD8, 0x33, 0x06, 0x61, 0x8C, 0x31, 0x8C,
  0x31, 0x86, 0x3F, 0xF7, 0xFE, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0xFF,
  0xDF, 0xFB, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xFF, 0x1F,
  0xF0, 0x07, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0xC0, 0xDC, 0x39,
  0xFE, 0x1F, 0x80, 0x3F, 0x0F, 0xF3, 0x07, 0x60, 0x6C, 0x0D, 0x80, 0x30,
  0x06, 0x00, 0xDF, 0x1F, 0xF3, 0x87, 0x60, 0x6C, 0x0D, 0x81, 0xB0, 0x36,
  0x06, 0xC0, 0xDC, 0x39, 0xFE, 0x1F, 0x80, 0xFF, 0xDF, 0xFB, 0x03, 0x60,
  0x60, 0x18, 0x03, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x18, 0x03, 0x00,
  0x60, 0x0C, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0x3F,
  0x0F, 0xF3, 0x87, 0x60, 0x6C, 0x0D, 0x81, 0xB0, 0x36, 0x06, 0x61, 0x87,
  0xE0, 0xFC, 0x30, 0xCC, 0x0D, 0x81, 0xB0, 0x36, 0x06, 0xC0, 0xDC, 0x39,
  0xFE, 0x1F, 0x80, 0x3F, 0x0F, 0xF3, 0x87, 0x60, 0x6C, 0x0D, 0x81, 0xB0,
  0x36, 0x06, 0xE1, 0xCF, 0xF8, 0xFF, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30,
  0x06, 0xC0, 0xDC, 0x39, 0xFE, 0x1F, 0x80, 0x00, 0x01, 0xB0, 0x00, 0x01,
  0xB0, 0x00, 0x00
};

const GFXglyph TallNumber11x20Glyphs[] PROGMEM = {
  {     0,   0,   0,   5,    0,    1 },   // 0x20 ' '
  {     0,   0,   0,   0,    0,    0 },   // 0x21 '!'
  {     0,   0,   0,   0,    0,    0 },   // 0x22 '"'
  {     0,   0,   0,   0,    0,    0 },   // 0x23 '#'
  {     0,   0,   0,   0,    0,    0 },   // 0x24 '$'
  {     0,   0,   0,   0,    0,    0 },   // 0x25 '%'
  {     0,   0,   0,   0,    0,    0 },   // 0x26 '&'
  {     0,   0,   0,   0,    0,    0 },   // 0x27 '''
  {     0,   0,   0,   0,    0,    0 },   // 0x28 '('
  {     0,   0,   0,   0,    0,    0 },   // 0x29 ')'
  {     0,   0,   0,   0,    0,    0 },   // 0x2A '*'
  {     0,   0,   0,   0,    0,    0 },   // 0x2B '+'
  {     0,   0,   0,   0,    0,    0 },   // 0x2C ','
  {     0,   0,   0,   0,    0,    0 },   // 0x2D '-'
  {     0,   0,   0,   0,    0,    0 },   // 0x2E '.'
  {     0,   0,   0,   0,    0,    0 },   // 0x2F '/'
  {     3,  11,  20,  11,    0,  -19 },   // 0x30 '0'
  {    31,  11,  20,  11,    0,  -19 },   // 0x31 '1'
  {    59,  11,  20,  11,    0,  -19 },   // 0x32 '2'
  {    87,  11,  20,  11,    0,  -19 },   // 0x33 '3'
  {   115,  11,  20,  11,    0,  -19 },   // 0x34 '4'
  {   143,  11,  20,  11,    0,  -19 },   // 0x35 '5'
  {   171,  11,  20,  11,    0,  -19 },   // 0x36 '6'
  {   199,  11,  20,  11,    0,  -19 },   // 0x37 '7'
  {   227,  11,  20,  11,    0,  -19 },   // 0x38 '8'
  {   255,  11,  20,  11,    0,  -19 },   // 0x39 '9'
  {   283,   3,  20,   3,    0,  -19 }    // 0x3A ':'
};

const GFXfont TallNumber11x20 PROGMEM = {(uint8_t *)TallNumber11x20Bitmaps,
  (GFXglyph *)TallNumber11x20Glyphs, 0x20, 0x3A,          12};

ESP32とHUB75のドットマトリクスパネルでNTP時計を作ってみた 8
今回使用したライブラリでは、文字を表示する前に描画領域をリセットしません。そのため、すでに表示されている内容の上に新しい文字が重なって表示されます。たとえば、「0」が表示されている場所にそのまま「1」を表示すると、重なった表示になります。この問題を解決するため、文字を表示する前に領域を黒などで塗りつぶすなどの処理が必要です。
先に挙げたjenizar/esp32-p5-rgb-32x64-ntp-clockの例では以下のように文字を表示する前に領域を塗りつぶす指定になっています。

uint16_t myBLACK = dma_display->color333(0,0,0); //先に宣言しておきます
dma_display->fillRect(x, y, W, H, myBLACK);  //x,y,W,Hは整数で指定します
xとyで塗りつぶす領域の左上の隅の座標を指定し、そこから幅(W)と高さ(H)の範囲を塗りつぶします。

文字は以下のように表示します。
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h> //スケッチの最初の方でインクルードしておきます
#include <Fonts/TallNumber11x20.h>           //好きなフォントをインクルードします

uint16_t myWHITE = dma_display->color333(7,7,7);   //先に宣言しておきます

dma_display->setCursor(x, y);             //文字位置の指定でx,yは整数で指定します
dma_display->setFont(&TallNumber11x20);     //フォントを指定します
dma_display->setTextSize(n);                //nで整数を指定します n倍の大きさで表示します
dma_display->setTextColor(myWHITE);
dma_display->fillRect(x, y, W, H, myBLACK); //x,y,W,Hは整数で指定します
dma_display->printf("012345");               //012345を表示
dma_display->setFont();                     //フォントの初期化

setCursor(x, y)で文字の左上の位置を指定すれば良さそうに思われる方が多いと思われますが、setCursor(x,y)のyはフォントの上辺ではなく画面上辺から文字(フォント)のベースラインまでの高さのようです。ベースラインの高さを知っていないと想定より上下どちらかにズレて表示され、微調整が必要になります。今回の自作フォントは文字単位で上下にずれて表示されるのを防ぐためベースラインを文字の下辺に統一しています。ベースラインは日本語の文字ではあまり意識しませんがアルファベットでは重要な概念です。

関連記事:

Redmi路由器 AC2100にインストールしたOpenWRTを設定する

3Redmi路由器 AC2100にインストールしたOpenWRTを設定する

前回は、Redmi路由器 AC2100 (以下Redmi AC2100)にOpenWRTをインストールしました。今回は、OpenWRTでWi-Fiアクセスポイント(AP)の設定を行います。なお、今回はルーターとしてではなく、あくまでWi-Fiアクセスポイントとしての設定を進めていきます。ルーター(PPPoE)としての設定については、Seeed Studio LinkStar-H28Kで作る超小型OpenWRTルーターの記事で紹介しています。

前回は、Xiaomiの純正ファームウェアの管理画面からエクスプロイト (exploit) を用いてSSHを有効化し、OpenWRTをインストールしました。この作業では、XiaomiのルーターのデフォルトIPアドレスである192.168.31.1にアクセスするため、192.168.31.0/24ネットワーク上の環境で作業を行いました。前回の手順が完了し、システムがOpenWRTのファームウェアに書き換わった後、デフォルトIPアドレスは192.168.1.1に変更されているため、作業を続けるには192.168.1.0/24ネットワークに接続する必要があります。PCとRedmi AC2100のLANポート (LAN1~LAN3のいずれか) をネットワークケーブルで接続し、以下の設定を行います:

  • IPアドレス:192.168.1.2~192.168.1.254
  • サブネットマスク:255.255.255.0
  • デフォルトゲートウェイ:192.168.1.1
  • DNS:設定不要

この設定により、PCが192.168.1.0/24ネットワークに参加できるようになります ("/24"はサブネットマスクのビット数を示し、2進数で11111111111111111111111100000000、ドット付き10進数で255.255.255.0に対応します)。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 14
Redmi AC2100がOpenWRTで起動すると、ログイン画面が表示されます。OpenWRTのデフォルトのUsernameは「root」、パスワードは「password」です。「Log in」ボタンをクリックしてログインします。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 15
セキュリティ上、初期パスワードを使用し続けるのは危険です。そのため、新しい管理者パスワードを設定します。黄土色の警告ボックスに「No password set!」と表示されているので、右側の「Go to password configuration...」をクリックしてパスワード設定画面に移動します。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 16
「Router Password」にはOpenWRTの新しい管理者パスワードを設定します。第三者に推測されにくいユニークなパスワードを2回入力し、右側の「Save」ボタンをクリックして保存します。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 17
パスワードの設定が完了すると、くすんだシアン色のボックスに「The system password has been successfully changed」と表示されます。「Dismiss」ボタンをクリックします。「No password set!」の警告表示は残っていますが、無視して問題ありません。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 18
次に、Redmi AC2100を既存のLANに接続します。今回は192.168.0.0/24ネットワークに接続し、IPアドレスを192.168.0.xに設定します。
OpenWRTの初期設定では、デバイスのIPアドレスは192.168.1.1/24に設定されています。このため、ネットワーク設定を変更する必要があります。最上部メニューの「Network」タブをクリックし、「Interfaces」を選択します。
Redmi AC2100の初期状態では、インターフェースとして「lan」、「wan」(IPv4)、「wan6」(IPv6)の3つが表示されます。今回はWi-Fiアクセスポイントとしてのみ使用するため、「wan」と「wan6」の設定は変更せず、使用しません。
LAN設定を変更するため、「lan」の行の右側にある「Edit」をクリックします。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 19
設定画面の下部にある「IPv4 address」の項目でRedmi AC2100のIPアドレスを変更します。例えば、192.168.0.64のように設定します。サブネットマスクは初期値で255.255.255.0になっているので、多くの家庭や小規模なオフィス環境では多くの場合は変更の必要はありません。「IPv4 gateway」はLAN内の他のルーター(インターネット接続しているルーター等) のIPv4アドレスに設定します。今回はRedmi AC2100はアクセスポイント専用のデバイスとするため「IPv4 gateway」にRedmi AC2100のIPアドレスを入力しないようにします。
「IPv4 broadcast」にはLAN内の最大アドレスを指定します。LANのサブネットマスクが255.255.255.0の場合、アドレスの最後は255で終わります。例えば、192.168.0.0/24のネットワークでは192.168.0.255を指定します。設定が完了したら、右下の「Save」ボタンをクリックして保存します。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 20
「Interfaces」画面に戻りますが、この時点では変更は保留されています。設定を反映するには、必ず「Save & Apply」ボタンをクリックします。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 21
黄色のポップアップが表示されるので「Apply and keep settings」をクリックします。

Redmi AC2100の背面にあるLANポート(LAN1〜LAN3のいずれか)を、ネットワークのLANに接続します(通常はLANのL2スイッチに接続します)。PCのネットワークケーブルをRedmi AC2100のLANポートから外して、ネットワークのLANに接続します(通常はLANのL2スイッチに接続します)。
PCのブラウザでRedmi AC2100のIPアドレスを入力して、管理画面にログインします。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 22
管理画面にログインすると、OpenWRTではまずステータス画面が表示されます。画面上部の「Network」タブから「Wireless」(Wi-Fi)項目をクリックします。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 23
画面の上半分に「Wireless Overview」が表示され、ここにはWi-Fiの2.4GHz帯と5GHz帯の状態および設定ボタンが表示されます。「802.11b/g/n」は2.4GHz帯、「802.11ac/n」は5GHz帯を指します。画像はWi-Fi設定済みで通信中の状態ですが、OpenWRTの初期設定では「Wi-Fi無効」になっているため、最初はWi-Fiのステータスは空の状態のはずです。2.4GHz帯と5GHz帯のどちらを先に設定しても構いませんが、今回は2.4GHz帯から設定します。「802.11b/g/n」側の「Edit」ボタンをクリックします。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 24
2.4GHz帯のチャネル設定を行います。日本では2.4GHz帯で1〜14chが利用可能ですが、14chは日本独自のためハードウエアが非対応なことも多く、Redmi AC2100では使用できません。また、OpenWRTでは国指定を行わないと、利用する国で使用が許されないチャネルも選択できてしまいます。国指定は次の段落で。
画面下半分のInterface Configurationで「General Setup」タブを開き、モードが「Access Point」(初期値)であることを確認します。ESSID(SSIDとも呼ばれ、アクセスポイントの識別名)を入力し、スマートフォンなどのデバイスで表示される名前を入力します。使用可能な文字は半角英数字、記号(ASCII)、および空白(最初と最後を除く)で、32文字以内です。アクセスポイントをリプレイスする場合、交換前のアクセスポイントと同じSSIDとパスワードを設定すると、接続するデバイス側の設定を変更することなく接続ができます。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 25
画面上半分のDevice Configurationに戻り、「Advanced Settings」タブを選択します。
「Country Code」から「JP - Japan」を選択します。これにより、使用できるチャネルが日本で許可されている範囲内に制限されます。2.4GHz帯ではこの設定は重要ではありませんが、後の5GHz帯の設定では必要です。
また、OpenWRTでは未確認ですが、国指定を行うことで、日本で許可された電波強度に調整し適切なDFSに対応するかもしれません。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 26
2.4GHz帯の暗号化設定を行います。
「Wireless Security」タブを選択し、「Encryption」で「WPA2-PSK (strong security)」または「WPA2-PSK/WPA3-SAE Mixed Mode (strong security)」を選択します。接続するすべてのデバイスがWPA3-SAE対応の場合は「WPA3-SAE」を推奨しますが、家庭用なら「WPA2-PSK」で十分でしょう。「Key」にSSIDに対応するPSKを入力します。所謂Wi-Fiのパスワードのことです。
右下の「Save」をクリックします。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 27
Wireless Overview画面に戻ります。次は5GHz帯の設定を行います。「802.11ac/n」の「Edit」ボタンをクリックします。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 28
5GHz帯のチャネル選択を行います。5GHz帯にはW52(36, 40, 44, 48ch)、W53(52, 56, 60, 64ch)、W56(100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144ch)があり、今回はDFS(動的周波数選択)の影響を受けないW52帯の36chを選択します。
Redmi AC2100は中国向け製品なので、Xiaomi純正ファームウェアでは日本で利用可能なW53帯とW56帯が使用できず、代わりにW58帯のチャネルが利用できますがそれは日本では使用できません。OpenWRTをインストールすることで、Redmi AC2100でも日本のW53帯およびW56帯が利用できるようになります。また、国指定を行うことで中国向けW58帯のチャネルは選択肢から消えるため、日本国内で間違ってW58帯を使用してしまうというミスがなくなります。
ただし、Redmi AC2100とOpenWRTを使用する場合にW53, W56帯でDFSが適切に動作するかは不明です。

画面下半分のInterface Configurationで「General Setup」タブを開き、モードが「Access Point」(初期値)であることを確認します。ESSID(SSIDとも呼ばれ、アクセスポイントの識別名)を入力し、スマートフォンなどのデバイスで表示される名前を入力します。使用可能な文字は半角英数字、記号(ASCII)、および空白(最初と最後を除く)で、32文字以内です。アクセスポイントをリプレイスする場合、交換前のアクセスポイントと同じSSIDとパスワードを設定すると、接続するデバイス側の設定を変更することなく接続ができます。これは、2.4GHzで設定したときと同じです。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 29
画面上半分のDevice Configurationに戻り、「Advanced Settings」タブを選択します。
「Country Code」から「JP - Japan」を選択します。これにより、使用できるチャネルが日本で許可されている範囲内に制限されます。5GHz帯は国によって利用可能なチャネルが大きく異なるためこの設定は非常に重要となります。日本ではW52, W53, W56のチャネルだけが選択肢に表示されるようになります。また、OpenWRTでは未確認ですが、日本で許可された電波強度に調整し適切なDFSに対応するかもしれません。

5GHz帯の暗号化設定を行います。
「Wireless Security」タブを選択し、「Encryption」で「WPA2-PSK (strong security)」または「WPA2-PSK/WPA3-SAE Mixed Mode (strong security)」を選択します。接続するすべてのデバイスがWPA3-SAE対応の場合は「WPA3-SAE」を推奨しますが、家庭用なら「WPA2-PSK」で十分でしょう。「Key」にSSIDに対応するPSKを入力します。所謂Wi-Fiのパスワードのことです。
ここまで入力したら右下の「Save」をクリックします。(上の画像では「Save」ボタンは見えていません。)

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 30
Wireless Overview画面に戻ります。ここで「Save & Apply」ボタンをクリックします。2.4GHzと5GHzの両方で設定が即時に反映され、再起動せずに使用できます。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 31
画面一番上の「System」タブから「System」項目をクリックします。
「General Setting」タブ(初期値)が選択された状態で、一番下の「Timezone」を設定します。プルダウンメニューから「Asia/Tokyo」を選びます。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 32
「Time Synchronization」タブを選択します。
「Enbale NTP client」にチェックします。これでLAN内またはインターネットのNTPサーバで時刻合わせするようになります。
「Provide NTP server」にチェックします。これでLAN内でNTPサーバになり、LAN内の他のホストから時刻参照を受け付けます。
「NTP server candidates」にLAN内またはインターネットのNTPサーバを登録します。IPアドレスでもFQDNでも良さそうですが、基本的にはLAN内のNTPサーバを参照するようにします。なお、Redmi AC2100のIPアドレスを登録して自身を参照することは避けるべきでしょう。
ここまで設定したら右下の「Save & Apply」ボタンをクリックします。これをしないと設定が反映しません。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 33
画面一番上の「System」タブから「Startup」項目をクリックします。
Startupではシステム起動時に開始するサービスを設定します。家庭用ブロードバンドルーターとして使用する場合、変更する必要はないでしょうが、Wi-Fiのアクセスポイント(AP)として使用する場合は、DNSサーバとDHCPサーバの機能は必要ありません。OpenWRTではそれぞれ「dnsmqsq」「odhcpd」がそのサービスを担っています。この2つのサービスは不要なのでサービスを停止します。それぞれの緑の「Enabled」(有効化済み)と表示されているボタンをクリックして赤の「Disabled」(無効化済み)にします。それぞれその前に「Stop」をクリックするとさらに良いでしょう。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 34
画面一番上の「Status」タブから「Overview」項目をクリックします。
現在の状況を確認します。
メモリの利用率は2/3以下なのでまだ余裕はあるようです。ストレージは使用中が180KiBと表示されているため、これはOpenWRTと(動いてはいませんがXiaomiの純正ファームウエアが入っている)にも関わらず使用量が少なすぎで、明らかに間違っています。

Redmi路由器 AC2100にインストールしたOpenWRTを設定する 35
さらに下にスクロールします。
「Active DHCP Leases」は、Redmi AC2100のDHCPサーバがリースしているIPアドレスを表示する項目です。Redmi AC2100に接続しているWi-Fiデバイス等が表示されるようであれば、DHCPサーバが停まっていません。1つのLANでDHCPサーバが複数動作している状態は問題があるためRedmi AC2100のDHCPサーバをもう一度停止/無効化しなおします。

その下の「Wireless」はしっかり確認します。2.4GHz帯と5GHz帯の両方でそれぞれ指定したチャネルが使用されていること、暗号化設定が指定通りであることを確認します。間違ってもOpen Networkなどになっていないようにします。SSIDも指定したものが正しく表示されていることも確認しておきます。

Redmi AC2100にOpenWRTをインストールすることで、日本国内での5GHz帯でW53およびW56帯域の利用が可能になります。これはXiaomi純正ファームウェアでは不可能なため、オープンソースファームウェアであるOpenWRTのインストールが持つ大きな利点といえるでしょう。OpenWRTはルーター機能のカスタマイズ性やセキュリティ機能も向上させ、ユーザーに柔軟なネットワーク設定の環境を提供します。家庭内のWi-Fiネットワークの強化に加え、ネットワークセキュリティの向上も期待できます。また、Xiaomi純正ファームウエアでは家庭用エントリーWi-Fiルーターにも劣る低機能でしたが、OpenWRTの使用により、Redmi AC2100が高機能なWi-Fiルーター/アクセスポイントへと進化し、さらに自分好みのWi-Fi環境を整備できるようになります。
今回はアクセスポイントということでネットワーク設定は殆ど不要で簡単でしたが、ルーターとして設定する場合は、ネットワークの知識が無い方にとっては扱いが難しい面があります。詳細な設定はウェブのUIでは行えないこともあり、sshでの設定はハードルが高くなります。

関連記事:
Up