この記事は「M5Stack Advent Calendar 2021」22日目の記事です。
はじめに
今年の夏、M5stack社より新たなプロダクト「M5stamp pico」が発売されました。

その特徴はなんといっても圧倒的な小ささ!!
寸法がタテ24mm x ヨコ18mm と、名の通り切手サイズなのです。
発表当初から界隈で注目を集めており、省スペースに組み込むことが出来ると話題でした。
私も国内で販売されてすぐ、某電子工作パーツショップにて購入しました。
これを見た私は、
「これでプレゼンのリモコンを作れないか…?」
と、考えたわけです。
プレゼンのリモコンを作ろうと思ったワケ
私は昨年よりM5stack社製品を使っており、主にM5stickCで遊んできました。
このM5stickCというのは非常に優秀なデバイスで、ESP32搭載(Wi-FiとBTが使える)、ボタンあり、液晶あり、拡張性あり、と値段の割に素晴らしいスペックなのです。
以前、このデバイスを用いて「Bluetooth プレゼンテーション リモコン」を作製しました。
といっても、すでにM5stickCをBTキーボードとして認識させるためのライブラリが公開されており、それを用いてM5stickCのボタンにキーを割り振るという簡単なプログラムで実現できます。
しかし、M5stickCのボタンは、正面に大きいものが1つ、側面に小さいものが2つ(ただし片方は電源)、とあまり数は多くないのです。
高機能プレゼンリモコンを実現するためにはやはりもう少しボタンが必要であると感じました。
そこで出てきたのがM5stamp picoです!
これを使って、イチからプレゼンリモコンを作ってしまおうと考えたのです。
その時の理想形は以下のような感じです。
- Bluetoothで簡単接続!!
- 片手で軽く握れるコンパクトサイズ!!
- 4ボタン搭載で簡単操作!!
- 外部電源必要なし! 電池駆動!!
- ディスプレイ搭載!!
- ページ送り・戻し以外にもストップウォッチ機能など多機能に!!
この高すぎる理想が、のちに私を苦しめることとなるのです…
つくりかた
ひとまず、順を追って作製方法を記していきます。
パーツ選定
まずは使うパーツを選びます。
電源周り
今回、メインとして用いるM5stamp pico、動作電圧は3.3Vもしくは5Vです。
ESP32は非常に有用なチップであるものの、起動時に少しばかり大きな電流が流れます。
すなわち、安定して電力を供給できる電源が必要です。
今回は安定的に電力を供給することを優先するため、昇圧は諦め、降圧して電力を供給することとします。
(私があまり昇圧に関する知識が無いのと、降圧の方が低コストで済むからという理由が大きいです。)
単四電池3本、約4.5Vを3.3Vへ降圧します。その降圧用に、三端子レギュレータBA033Tを用います。
三端子レギュレータを使う際は出力電圧を安定させるためコンデンサを用いる必要があります。
そこで10μFのセラミックコンデンサと47μFの電解コンデンサを用います。
あとは単四電池が3本入る電池ケースと基盤接続用にphコネクタ、電源管理用スライドスイッチも用います。
操作系
理想に従い、ボタンを4つ搭載します。
使うのは何の変哲もないタクトスイッチ4つです。
ディスプレイ
arduinoを用いた電子工作ではもはやおなじみのSSD1306とうい制御チップのOLEDディスプレイを用います。
サイズは0.96インチ、128x64ドットのタイプです。
amazonで適当なものを購入しました。
基板作成
続いて基板作成です。
今まで私はユニバーサル基板を用いて、いちいち配線していましたが、いい加減しんどくなってきました。
さらに、大学のラボ的なところで基板加工機(CNC)があり、自由に使えることを知った私。
使わない手はありません。
EAGLEという回路設計ソフトを用いて、回路を作製します。
出来たのが以下のような回路です。
M5stampをEAGLEで表現するにあたり、@NaohiroIIDA 様の作製されたライブラリをお借りしました。
この場を借りて感謝申し上げます。
(@NaohiroIIDA 様 M5Stamp Picoを触ってみた治具作成&リフローしてみた)
それでこのEAGLEですが、回路設計だけでなくPCB(プリント基板)のデザインもできます。
これで実際の基板もデザインします。
あとは基板加工機に任せれば完成です!
Qiitaの記事用
— Koushiro (@Koushiro_A) December 22, 2021
基板加工機の映像 pic.twitter.com/6K9PQ0TjRh
てなわけで完成した基板がこちら!
あ、この二枚は失敗作でした。
左のは無駄なスペースが多すぎてボツ。
右のは間違って両面とも導体の板を選んでしまい、回路がショートしてしまったのでボツ。
まあ、いずれにしても完成形はこんな感じです。
さて、ちゃんと作成できた基板に、上で紹介したパーツをもろもろ載せたのが、下の画像です。
ここまででハード面は完成です!
ソフト作成・動作確認
ソースコード
プログラミングはVisual Studio Codeの拡張機能、PlatformIOを用いて、フレームワークはarduinoで行います。
ひとまず、ソースコードを載せます。
# include "M5Atom.h"
# include <SPI.h>
# include <Wire.h>
# include <Adafruit_GFX.h>
# include <Adafruit_SSD1306.h>
# include <BleKeyboard.h>
# include "image.h"
BleKeyboard bleKeyboard("M5stamp BLE Key"); //Bluetooth Keyboardの定義
/* OLEDの設定 */
# define SCREEN_WIDTH 128 // OLED display width, in pixels
# define SCREEN_HEIGHT 64 // OLED display height, in pixels
# define BMP_WIDTH 12
# define BMP_HEIGHT 17
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
# define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); //OLED displayの定義
/* OLEDの設定(終) */
void setup() {
M5.begin(true, false, true);
Serial.begin(115200);
delay(50);
M5.dis.drawpix(0, 0x707070);
Serial.print("Reset:\n");
pinMode(26,INPUT_PULLUP);
pinMode(18,INPUT_PULLUP);
pinMode(19,INPUT_PULLUP);
pinMode(25,INPUT_PULLUP);
bleKeyboard.begin();
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Clear the buffer
display.clearDisplay();
display.setTextSize(1); //文字サイズを設定
display.setTextColor(WHITE); //文字色を設定
display.setCursor(0, 0);
display.println("M5stamp pico");
display.println("Presen BT Con");
display.display();
delay(2000);
display.clearDisplay();
display.display();
}
void loop() {
display.clearDisplay();
if(bleKeyboard.isConnected()){
display.drawBitmap(2, 0, BT_icon, BMP_WIDTH, BMP_HEIGHT, 1);
display.setTextSize(1);
display.setCursor(0, 24);
display.print("<<<<");
display.setCursor(0, 32);
display.print("BACK");
display.setCursor(100, 24);
display.print(">>>>");
display.setCursor(100, 32);
display.print("NEXT");
display.setTextSize(2);
if(!digitalRead(26)){
M5.dis.drawpix(0, 0x00f000);
display.setCursor(55, 22);
display.print("UP");
display.display();
while(!digitalRead(26));
}
else if(!digitalRead(18)){
bleKeyboard.write(KEY_RIGHT_ARROW);
M5.dis.drawpix(0, 0x0000f0);
display.setCursor(37, 22);
display.print("RIGHT");
display.display();
while(!digitalRead(18));
}
else if(!digitalRead(19)){
M5.dis.drawpix(0, 0xf00000);
display.setCursor(42, 22);
display.print("DOWN");
display.display();
while(!digitalRead(19));
}
else if(!digitalRead(25)){
bleKeyboard.write(KEY_LEFT_ARROW);
M5.dis.drawpix(0, 0xf0f000);
display.setCursor(42, 22);
display.print("LEFT");
display.display();
while(!digitalRead(25));
}
else{
M5.dis.drawpix(0, 0x707070);
display.setCursor(42, 22);
display.print("NONE");
}
}
else{
M5.dis.drawpix(0, 0x707070);
display.clearDisplay();
display.drawBitmap(57, 0, BT_icon2, BMP_WIDTH, BMP_HEIGHT, 1);
display.setTextSize(2);
display.setCursor(46, 16);
display.print("NOT");
display.setCursor(10, 32);
display.print("CONNECTED");
}
display.display();
}
かいつまんで説明していきます。
Bluetooth Keyboardの定義
# include <BleKeyboard.h>
BleKeyboard bleKeyboard("M5stamp BLE Key"); //Bluetooth Keyboardの定義
bleKeyboard.write(KEY_RIGHT_ARROW);
ESP32 BLE Keyboardというライブラリをインポートし、上記のように定義します。
キーを送る時には3行目のようにします。使い方はarduinoのKeyboard.write()と同じです。
(特殊キーはこちらから)
OLEDの使い方
# include <Wire.h>
# include <Adafruit_GFX.h>
# include <Adafruit_SSD1306.h>
/* OLEDの設定 */
# define SCREEN_WIDTH 128 // OLED display width, in pixels
# define SCREEN_HEIGHT 64 // OLED display height, in pixels
# define BMP_WIDTH 12
# define BMP_HEIGHT 17
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
# define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); //OLED displayの定義
/* OLEDの設定(終) */
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay(); //バッファのクリア
display.setCursor(0, 0); //描画位置の設定
display.print("HELLO"); //文字の出力
display.display(); //ディスプレイに表示
display.drawBitmap(2, 0, BT_icon, BMP_WIDTH, BMP_HEIGHT, 1); //画像表示
今回はAdafruit_SSD1306というライブラリと、それに必要なAdafruit_GFX、さらにI2C通信に必要なWire.hをインポートしました。
大体の使い方は上記のコメントアウトに書かれた通りです。
画像表示に関しては、@unasenohkoku 様の記事、遊舎工房のOLEDモジュール(A01OL)に任意の画像を描画するを参考にさせて頂きました。
こちらも、この場を借りて感謝申し上げます。
SSD1306チップの解説はインターネット上に沢山あるので、それらも参考にしてください。
M5stamp picoのLED点灯
M5.dis.drawpix(0, 0x707070);
これはM5Atom.hによって使えるようになる関数ですが、もともとはM5AtomのLED用のものです。
ですが、M5stamp picoはM5Atomと同じ構造をしているため、そのまま流用できます。
二つ目の引数で3原色を16進数2桁で表現しています。
動作動画
ソフトを書きこんでみた結果です。
しっかり動作しています。
M5stamp picoを使ったプレゼンリモコン、ソフトの初期バージョン完成
— Koushiro (@Koushiro_A) November 18, 2021
BTの接続状況とどのボタンが押されたかを画面に表示する
右が押されたら次のページ、左が押されたら前のページのキーを送信
あとは筐体を作らねばならん pic.twitter.com/YsAUOVnTRz
筐体作成
筐体に関しても、今までは適当なケースを買ってきて加工していましたが、いかんせん私の加工技術が乏しく、上手く出来た試しがありません。
そこで上記でも出てきた大学のラボにある3Dプリンターを用いて、筐体を作製します。
3DCADソフトで有名なFusion360を使います。
先ほど回路設計で用いたEAGLEと同じ会社(Autodesk)が作っているので、ファイルをソフト間で連携することが出来ます。
これら連携機能を用いてモデリングしていきます。
以下、モデリング画像です。
はい、そろそろ敗北原因が見えてくるかと思います…
それはともかく、3Dプリンターで上のモデルを印刷します。
完成!
さて、いよいよ完成画像です!
こちら!!
はい…
「クソでかい」
なんと、テレビのリモコンかってくらい大きくなってしまいました。
しかも蓋の接着方法が無く、養生テープで巻きつける始末…
ちなみに、上で試した通り、プレゼンリモコンとしての機能は果たしています。
M5stamp picoを用いたプレゼンリモコン
— Koushiro (@Koushiro_A) December 22, 2021
完成映像#M5stack pic.twitter.com/FG118GSbJ9
が、決して実用的ではありません…
中身はこんな感じです…
敗因
- 電源として単四電池3本を選んでしまった
- 電源用レギュレータに場所を取った
- 自作基板にまだまだ無駄なスペースがある
などなど、原因は多岐に渡ります…
最後に
敗北したとはいえ、いい経験になりました。
今回の目標がなければ、M5stamp picoの使い方、EAGLEと基板加工機の使い方、Fusion360と3Dプリンタの使い方、PlatformIOの導入などはやっていなかったでしょう。
今回は経験を積めただけで良しとしたいと思います。
長文に渡りお読みいただきありがとうございました。
p.s.
アドベントカレンダー用に急いで書いたため、文章に乱れがあるかもしれません。
ご了承ください…










