以前、ESP32を使ってドットマトリクスLED(MAX7219)に文字を表示させました。
表示させる文字列を、いちいちプログラムを変更せずに書き換えたい。
できればスマホから書き換えられたら出先でも色々と遊べそう。
そんなモチベーションで挑戦しました。
結果、うまくできました!
まずは動作確認の様子をご覧ください。
文字表示の部分は以前のプログラムで出来ていたので、これに通信手段を追加するだけ。
今回はBLEを使うことにしました。
Arduinoのライブラリで、「ESP32_BLE_Arduino」というのがありますが、実はこれは古いものらしく、インストールすると逆に動かなくなりました。
元々ArduinoIDEに標準で入っているものを使用すると動きました。
スマホとESP32の接続は「nRF Connect for Mobile」というアプリを使用することで簡単にできました。
ちなみにこのアプリはAndroidのものですが、iPhoneでも似たようなアプリはあるかと思います。
ESP32の電源を入れて少し待ってからSCANすると、プログラムで指定したデバイス名が表示されます。
TYPEをTEXT(UTF-8)に変更するのを忘れずに。
あとは文字を入れてSENDボタンを押せばOK
ドットマトリクスを使ってやりたいことは一通りできたので、あとはちゃんとしたケースなどを作れば完成。
何気にケース作りが一番面倒だったりするんですよね~。
プログラムは下記のようにしました。
もうChatGPTは手放せない存在です。
#include <MD_MAX72xx.h>
#include <MD_Parola.h>
#include <misaki.hpp>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
// =====================================================
// MAX7219の設定
// =====================================================
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
// CSピン
#define CS_PIN 5
// =====================================================
// 文字列設定
// =====================================================
// 受信文字列の最大長
#define MAX_LENGTH 256
// =====================================================
// MD_Parola用データ
// =====================================================
// MD_Parolaに登録する文字コード
char messageCode[MAX_LENGTH];
// 90度回転したフォントデータ
uint8_t rotatedFontData[9 * MAX_LENGTH];
// =====================================================
// MD_Parola
// =====================================================
MD_Parola parola(
HARDWARE_TYPE,
CS_PIN,
MAX_DEVICES
);
// =====================================================
// BLE UUID
// =====================================================
#define SERVICE_UUID \
"12345678-1234-1234-1234-123456789abc"
#define CHARACTERISTIC_UUID \
"abcdefab-1234-1234-1234-123456789abc"
// =====================================================
// BLE変数
// =====================================================
BLECharacteristic* pCharacteristic = nullptr;
bool deviceConnected = false;
// =====================================================
// 関数プロトタイプ
// =====================================================
void addFontToParola(const char* text);
void displayMessage(const char* message);
void setupBLE();
// =====================================================
// BLE Server Callback
// =====================================================
class MyServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* pServer) override {
deviceConnected = true;
Serial.println();
Serial.println("================================");
Serial.println("BLE Connected");
Serial.println("================================");
}
void onDisconnect(BLEServer* pServer) override {
deviceConnected = false;
Serial.println();
Serial.println("================================");
Serial.println("BLE Disconnected");
Serial.println("================================");
// 再接続待ち
BLEDevice::startAdvertising();
Serial.println("BLE Advertising Restarted");
}
};
// =====================================================
// BLE Characteristic Callback
// =====================================================
class MyCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic* pCharacteristic) override {
// =================================================
// BLEから受信
// =================================================
String rxValue = pCharacteristic->getValue();
// 何も受信していなければ終了
if (rxValue.length() == 0) {
return;
}
// =================================================
// シリアルモニタへ表示
// =================================================
Serial.println();
Serial.println("--------------------------------");
Serial.println("BLE Received");
Serial.print("Length : ");
Serial.println(rxValue.length());
Serial.print("Text : ");
Serial.println(rxValue);
Serial.println("--------------------------------");
// =================================================
// 受信した文字列を表示
// =================================================
displayMessage(rxValue.c_str());
}
};
// =====================================================
// フォントデータをMD_Parolaへ登録
// =====================================================
void addFontToParola(const char* text) {
uint16_t charIndex = 1;
uint8_t charWidth;
// ===================================================
// 文字列を1文字ずつ処理
// ===================================================
while (*text && charIndex < MAX_LENGTH) {
uint16_t unicode =
utf8ToUnicode(text, &charWidth);
// =================================================
// フォントデータを取得
// =================================================
const uint8_t* fontData =
getFontData(unicode);
// =================================================
// フォントデータを90度回転して保存
// =================================================
// 1バイト目は文字幅
rotatedFontData[
(charIndex - 1) * 9
] = charWidth;
// 8列分を処理
for (uint8_t col = 0; col < 8; col++) {
uint8_t rotatedByte = 0;
// 8行分を処理
for (uint8_t row = 0; row < 8; row++) {
if (
fontData[row] &
(1 << (7 - col))
) {
rotatedByte |= (1 << row);
}
}
// 回転後のデータを保存
rotatedFontData[
(charIndex - 1) * 9 + col + 1
] = rotatedByte;
}
// =================================================
// MD_Parolaへフォント登録
// =================================================
parola.addChar(
charIndex,
&rotatedFontData[
(charIndex - 1) * 9
]
);
// =================================================
// MD_Parola用の文字コードを作成
// =================================================
messageCode[
charIndex - 1
] = charIndex;
charIndex++;
}
// ===================================================
// 文字列終端
// ===================================================
messageCode[
charIndex - 1
] = '\0';
}
// =====================================================
// 文字列をドットマトリクスに表示
// =====================================================
void displayMessage(const char* message) {
// ===================================================
// デバッグ表示
// ===================================================
Serial.println();
Serial.println("================================");
Serial.println("Display Message");
Serial.println("================================");
Serial.print("Message: ");
Serial.println(message);
// ===================================================
// 現在の表示をクリア
// ===================================================
parola.displayClear();
// ===================================================
// フォントを登録
// ===================================================
addFontToParola(message);
// ===================================================
// スクロール表示
// ===================================================
parola.displayScroll(
messageCode,
PA_LEFT,
PA_SCROLL_LEFT,
50
);
}
// =====================================================
// BLE初期化
// =====================================================
void setupBLE() {
// ===================================================
// BLEデバイス名
// ===================================================
BLEDevice::init(
"ESP32_DotMatrix"
);
// ===================================================
// BLE Server作成
// ===================================================
BLEServer* pServer =
BLEDevice::createServer();
pServer->setCallbacks(
new MyServerCallbacks()
);
// ===================================================
// BLE Service作成
// ===================================================
BLEService* pService =
pServer->createService(
SERVICE_UUID
);
// ===================================================
// BLE Characteristic作成
// ===================================================
pCharacteristic =
pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_WRITE
);
// Callback登録
pCharacteristic->setCallbacks(
new MyCallbacks()
);
// ===================================================
// BLE Service開始
// ===================================================
pService->start();
// ===================================================
// Advertising設定
// ===================================================
BLEAdvertising* pAdvertising =
BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(
SERVICE_UUID
);
pAdvertising->setScanResponse(true);
// ===================================================
// Advertising開始
// ===================================================
BLEDevice::startAdvertising();
// ===================================================
// シリアルモニタ
// ===================================================
Serial.println();
Serial.println("================================");
Serial.println("BLE Server Started");
Serial.println("================================");
Serial.println(
"Device Name : ESP32_DotMatrix"
);
Serial.println(
"Service UUID:");
Serial.println(
SERVICE_UUID
);
Serial.println(
"Characteristic UUID:"
);
Serial.println(
CHARACTERISTIC_UUID
);
Serial.println(
"Waiting for BLE connection..."
);
Serial.println("================================");
}
// =====================================================
// setup
// =====================================================
void setup() {
// ===================================================
// シリアル通信開始
// ===================================================
Serial.begin(115200);
delay(500);
// ===================================================
// 起動メッセージ
// ===================================================
Serial.println();
Serial.println();
Serial.println("================================");
Serial.println("ESP32 Dot Matrix BLE");
Serial.println("================================");
// ===================================================
// MD_Parola初期化
// ===================================================
parola.begin();
parola.displayClear();
// ===================================================
// BLE初期化
// ===================================================
setupBLE();
// ===================================================
// 起動時のテスト表示
// ===================================================
displayMessage("真野あゆみ");
}
// =====================================================
// loop
// =====================================================
void loop() {
// ===================================================
// MD_Parolaのアニメーション更新
// ===================================================
if (parola.displayAnimate()) {
parola.displayReset();
delay(1500);
}
}








