インスタ映えを狙え! レインボーしゃぼん玉カメラを作ってみよう

「かっこいい写真を撮りたい。」「エモい写真を撮りたい。」など、みんなから「いいね!」される写真を撮りたいと思いますよね。
初心者でもそれっぽい写真を撮影できる方法はないか考えていたところ、おもちゃのバブルマシーンを見つけました。シャボン玉なら虹色に輝いて見えるので、面白い写真が撮影できそうです。また、バブルマシーンがカメラ型だったので、そのままの形状を残して作れば面白いと思いました。

そこで、今回はシャボン玉が彩るインスタ映えカメラ、名付けて「レインボーしゃぼん玉カメラ」を作りました。
シャボン玉を七色に光らせることの難しさ
レインボーしゃぼん玉カメラのイメージは、バブルマシーンから生成されたシャボン玉にLEDの光が反射し、色とりどりにシャボン玉が輝くというものでした。まずは円盤型のイルミネーション「NeoPixel」をシャボン玉の出口に取り付け、電源を入れてみました。

ワクワクしながらバブルマシーンの電源を入れたのですが……
「あれ? 全然光らない。というかシャボン玉が透明……? 」

いきなりの挫折を味わいました。調べてみると「シャボン玉に白色を付ける」か、「シャボン玉の中に煙を入れる」と、LEDの光を反射できることがわかりました。「シャボン玉の中に煙を入れる」のは、スモークマシーンなどが必要になり装置も大型にもなるので、「シャボン玉に白色を付ける」ことにしました。


ちょっと見えづらいかもしれませんが、シャボン玉に水性絵の具でうっすらと白い色が付いて、そこにLEDが反射しています。ゴミ袋の中でシャボン玉を膨らませているのは、部屋の中でシャボン玉を生成した所、家具が水性絵の具で白くなってしまったからです。
白いシャボン玉を作る時は、家の外やお風呂場などで行わないと水玉模様だらけになるので注意が必要です。私の場合は、うっかりパソコンの前でバブルマシーンを動かしてしまいノートパソコンの画面やキーボード、コンセントタップが綺麗な水玉模様になってしまいました。皆さんはこのような失敗をしないように気を付けてくださいね。
スマートフォンのカメラをM5StickCで制御する
バブルマシーンとLEDだけでは写真を撮れないので、スマートフォンのカメラと組み合わせることにしました。「M5StickC」のBluetooth機能を使って、スマートフォンのシャッターを制御できるようにします。

M5StickCにプログラムを書き込むため、Arduino IDEで準備をしていきましょう。「ESP32 BLE Keyboard library」という、ESP32をBluetoothキーボードとして使うライブラリがあるのでArduino IDEにライブラリをインクルードします。
ESP32 BLE Keyboard libraryは、Arduino IDEのライブラリマネージャーでは検索できません。GitHubのESP32 BLE Keyboard libraryページからコードをダウンロードして、Arduino IDEメニュー「スケッチ」→「.ZIP形式のライブラリをインストール」で、ダウンロードしたファイルをインストールしてください。


続いて、NeoPixelを光らせるために「FastLED」ライブラリと、「M5StickC」のライブラリをArduino IDEの「ライブラリマネージャー」からインストールします。


プログラム作成
プログラムは「M5Stick-Cでスマホ用のリモートシャッターを自作してみた(Wak-tech)」という記事を参考にして作成してみました。
#include<M5StickC.h>
#include<BleKeyboard.h>
#include "FastLED.h" //スマートフォンで表示されるデバイス名 BleKeyboard bleKeyboard("wak-BLEshutter"); // バッテリー更新用 unsigned long nextVbatCheck = 0; // 接続確認用 bool Connected = false; // バッテリー残量取得 int getVlevel() { float vbat = M5.Axp.GetBatVoltage(); int vlevel = ( vbat - 3.2 ) / 0.8 * 100; if ( vlevel < 0 ) { vlevel = 0; } if ( 100 < vlevel ) { vlevel = 100; } return vlevel; } //Neopixelに信号を送るピンです。今回はGPIO26を使います。 #define Neopixel_PIN 26 //NeopixelのLEDの数です。今回は30個に設定 #define NUM_LEDS 30 //内部のLEDを光らせます(シャッターを押した時に光らす)GPIO10 #define LED_PIN 10/*LED光らす*/ CRGB leds[NUM_LEDS]; uint8_t gHue = 0; static TaskHandle_t FastLEDshowTaskHandle = 0; static TaskHandle_t userTaskHandle = 0; void setup() { Serial.begin(115200); M5.begin(); M5.Lcd.setRotation(3); M5.Lcd.setTextColor(YELLOW); M5.Lcd.setCursor(10, 2); M5.Lcd.println("Neopixel Example"); M5.Lcd.setTextColor(WHITE); M5.Lcd.setCursor(0, 15); M5.Lcd.println("Display rainbow effect"); //スイッチをGPIO0に設定 pinMode( 0, INPUT_PULLUP ); //LED点灯用 pinMode(LED_PIN, OUTPUT); // Neopixel initialization FastLED.addLeds<WS2811,Neopixel_PIN,GRB>
(leds, NUM_LEDS) .setCorrection(TypicalLEDStrip); FastLED.setBrightness(10); xTaskCreatePinnedToCore(FastLEDshowTask, "FastLEDshowTask", 2048, NULL, 2, NULL, 1); M5.Axp.ScreenBreath(9); setCpuFrequencyMhz(80); // 起動時にしかバッテリー残量は設定できない bleKeyboard.setBatteryLevel(getVlevel()); bleKeyboard.begin(); } void loop(){ int value; value = digitalRead( 0 ); if ( value == HIGH ){ digitalWrite(LED_PIN, HIGH); }else{ digitalWrite(LED_PIN, LOW); //音声UPボタンを押す事でシャッターを切る bleKeyboard.write(KEY_MEDIA_VOLUME_UP); } // ボタン状態更新 M5.update(); M5.Lcd.setCursor(0, 0); // キー操作 if (bleKeyboard.isConnected()) { if (Connected==false){ M5.Lcd.fillScreen(GREEN); M5.Lcd.printf("Connected"); Connected = true; } if ( M5.BtnA.wasPressed() ) { // 音量アップキーを送信 bleKeyboard.write(KEY_MEDIA_VOLUME_UP); } } else { if (Connected){ Connected = false; M5.Lcd.fillScreen(RED); M5.Lcd.printf("Disconnect"); } } // バッテリー残量更新(1分毎) if (nextVbatCheck < millis()) { M5.Lcd.setCursor(112, 0); M5.Lcd.printf("%3d%%", getVlevel()); nextVbatCheck = millis() + 60000; } // Wait delay(100); } void FastLEDshowESP32() { if (userTaskHandle == 0) { userTaskHandle = xTaskGetCurrentTaskHandle(); xTaskNotifyGive(FastLEDshowTaskHandle); const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 200 ); ulTaskNotifyTake(pdTRUE, xMaxBlockTime); userTaskHandle = 0; } } void FastLEDshowTask(void *pvParameters) { for(;;) { fill_rainbow(leds, NUM_LEDS, gHue, 7);// rainbow effect FastLED.show();// must be executed for neopixel becoming effective EVERY_N_MILLISECONDS( 20 ) { gHue++; } } }
書き込みエラーへの対応
作成したプログラムをM5StickCに書き込めば完了ですが、書き込みができなくなる現象がたびたび起こりました。
もう一度書き込んだり、再起動後に書き込みを行ったりすると成功する場合もありますが、私の場合は、再起動や書き込み直しをしても改善できませんでした。

ネットで調べた所、「GND」と「G0」をジャンパワイヤでつなぐことでプログラムが書き込める場合があるようです。実際に試してみたところ、無事書き込みが完了できました。


おもちゃのカメラの中に組み込む
M5StickCとLEDの間には、小さなブレッドボードをつなぎ、タクトスイッチを取り付けました。これは、M5StickCをバブルマシーンの中に組み込むとM5StickCのシャッターボタンが押せなくなるので、新たにカメラの表面にシャッター用のスイッチを取り付ける必要があったからです。

下の写真の左側がよく使われるブレッドボードで、右端がシャッター用スイッチのために使用したブレッドボードです。このくらい小さいと、配線をブレッドボードで行い、そのままケースなどに実装できるので、用意しておくと便利です。

バブルマシーンを分解してみると、M5StickCをそのまま実装できそうなスペースがあったので、ここにM5StickCを取り付けていきます。

M5StickCを組み込んだものが下の写真です。M5StickCを立てて収納するとピッタリ納まりました。

最後に、バブルマシーンにスマートフォンをマジックテープで取り付ければ完成です。分かりづらいですが、バブルマシーンの左側に付いた黒いボタンを押すと、スマートフォンのシャッターを切れます。小さなブレッドボードなので、そのまま取り付けられました。

使う時にはM5StickCを起動して、スマートフォンのBluetoothと接続してシャッター(タクトスイッチ)を使えるようにします。バブルマシーンの電源を入れて、シャボン玉が舞い上がってからシャッターを押すと、良い感じでインスタ映えする写真が撮れるはず!
レインボーしゃぼん玉カメラで撮影会
作ったら早く使ってみたいもの。カメラの完成後、さっそく撮影会をしてみました。
1枚目は夜に外で撮影した写真です。シャボン玉にNeoPixelのLEDと街のライティングが反射して、シャボン玉が綺麗に写真に写りました。

2枚目は室内で撮影したものです。室内では蛍光灯の光が反射してしまったため、NeoPixelのLEDは部分的に反射しています。もう少し強いNeo Pixelの光か、周りを暗くすれば、もっとはっきりシャボン玉に色が反射すると思います。

シャボン玉に色を付けて「インスタ映えする写真を撮りたい」というアイデアから始まったのですが、実際に作ってみると、カメラを向けた時にみんなが笑顔になるのがとても印象的でした。「おもちゃのカメラで写真を撮られるのかと思ったら、色とりどりのシャボン玉が出てくる」という驚きもあり、自然に笑顔になるカメラができました。