UNIT-VでopenMV使ってIMEモード判別してみた
初めに
ブラインドタッチができない人間(私)が日々悩まされている、「日本語モードだと思って打っていたら英数モードだった(その逆もしかり)問題」の対策として「あ」or「A」を判別させるAIカメラの作成に取り掛かった。
ファーストステップとしてM5StickVのV-Trainingで狙いの動作をさせることができた。詳細は以下の記事にて。
pikapikalight.hatenadiary.com
M5StickVにはLCDとバッテリーがついていて便利なのだが、今回やりたいことに対してはこの機能は不要、むしろいらない機能といえる。 今回の目的に対してはUNIT-Vを使うのが最適なので、セカンドステップとしてUNIT-Vで同じものを作ることにした。
エッジAIの挫折
M5StickVでは割とすんなりできたので、UNIT-Vでも簡単にできると思って始めたのだが、これが予想外の苦戦を強いられる。
V-Trainingは学習曲線を見るかぎり問題なく学習できていそうなのだが、そのKモデルをUNIT-Vにいれて動かすと正答率がすこぶる悪い。カメラの位置、角度をシビアに調整してやっと正解が出るといった具合で、使い物にならないレベル。
写真の撮り方、写真サイズ、ブライトネス、コントラスト、色々変えてみたりしたが、うまくいかず。果てはV-Trainingを使わず、自力で学習してモデル作成するということもやってみたが、それでもやっぱり実機動作で正答率悪し。
そのあたりのいきさつはこちら。
V-TrainingでのUNIT-Vの画像判別がうまくいかないので、自力で学習させる方法ないかと検索したら、からあげ先生の記事に行きつく。
— PikaPikaらいと (@KPmilk3) 2021年4月13日
困った時はだいたいたどり着くからあげ先生。ありがたや。https://t.co/MxS8OZnid1
結局はAIによる判別はあきらめたのですが、Google Colaboratoryを使っての自力学習の方法など非常に得たものは大きかったので、詳細は別の記事にしたいと思います。V-Trainingを使わない、M5UNIT-V用のモデルの自力作成。
— PikaPikaらいと (@KPmilk3) 2021年4月14日
からあげ先生の記事にリンクされていたNabeshinさん作の修正版コードを使わせていただき、なんとか学習とモデル変換できました😁
ただ、学習結果がダメダメ😓これは写真の撮り方が悪いのだと思うのでやり直す。https://t.co/xdN5j6jrvu
openMVに挑戦
色々と試している過程で必然的にMaixPyの機能について調べることとなったのだが、思っていた以上にいろいろな機能があることが分かった。openMVとやらの機能が使えて、フィルターをかけたり、特定の色の領域を判別させたりと、AI使わなくてもひょっとしてできるかもと思い始めた。
さらに調べるとこのような記事を発見
マーカーシールを使ってメーターの針の位置を読み取るというもの。このマーカーシールを使う方法で今回やりたいことを実現することができた。
概要
- マーカーシールを「あ」の真下に貼る
- sensor.set_auto_gain(False) でオートゲインを無効にする
- MaixPyのしきい値エディタでマーカーのしきい値と「あ」「A」のしきい値を確認
- .find_blobsでマーカーシールの領域を特定
- マーカーシールの領域情報から「あ」の領域を特定し、その領域を切り出す
- 切り出した領域に対して.find_blobsで「あ」「A」の領域サイズを判定
- マーカーシールのサイズと「あ」「A」の領域サイズの比から「あ」を判別(「あ」のほうが明らかにサイズが大きいので区別ができる)
しきい値エディタ
MaixPyでフレームバッファにカメラの絵が出ている状態で メニューの「ツール」→「マシンビジョン」→「しきい値エディタ」→ソースイメージの場所 フレームバッファ でしきい値エディタを起動する。 スライドバーを適当に動かして、マーカーシールのみが表示されるしきい値を確認する。 同じように「あ」「A」のしきい値も確認する
コード
import sensor, image, time #import gc, math from board import board_info from Maix import GPIO from fpioa_manager import fm import sys while 1: try: sensor.reset() #Reset sensor may failed, let's try some times break except: time.sleep(0.1) continue sensor.set_hmirror(1) sensor.set_vflip(1) # run automatically, call sensor.run(0) to stop sensor.set_pixformat(sensor.RGB565) # Set pixel format to RGB565 (or GRAYSCALE) sensor.set_framesize(sensor.QVGA) # Set frame size to QVGA (320x240) sensor.skip_frames(time = 1000) # Wait for settings take effect. #sensor.set_brightness(-2) #sensor.set_contrast(-2) sensor.set_auto_gain(False) #これ重要。無効にしないと周りの明るさで大きく変化してしまう。 #clock = time.clock() # Create a clock object to track the FPS. #LED点灯用 fm.register(35, fm.fpioa.GPIOHS0, force=True) pinout35 = GPIO(GPIO.GPIOHS0, GPIO.OUT) pinout35.value(0) mark_threshold = (0, 100, -128, -28, -128, 127) #マークシールのしきい値 text_threshold = (100, 34, -128, 127, 127, -128) #「あ」のしきい値 while True: img=sensor.snapshot() blobs = img.find_blobs([mark_threshold]) if blobs: for b in blobs: if b.area() > 1000: #ゴミとりのため、小さい領域は無視する。 #print(b) tmp = img.draw_rectangle(b[0:4],color=(0,255,0)) tmp = img.draw_cross(b[5], b[6],color=(0,255,0)) mark_x = b[0] mark_y = b[1] mark_w = b[2] mark_area = b.area() try: tmp = img.draw_rectangle(mark_x,mark_y - int(mark_w*1.5),mark_w,mark_w,color=(0,0,255)) #シールの位置から文字の位置を特定 img2 = img.copy((mark_x,mark_y - int(mark_w*1.5),mark_w,mark_w)) #文字の領域を切り出す blobs2 = img2.find_blobs([text_threshold]) #切り出した領域に対してしきい値判定 if blobs2: for b in blobs2: #print(b.area()) if b.area() > 200: #小さい領域は無視する。 img.draw_rectangle(mark_x+b[0],mark_y - int(mark_w*1.5) + b[1],b[2],b[3],color=(255,255,255)) text_area = b.area()/mark_area #比を計算 print(text_area) if text_area > 0.2: #「あ」の判定基準。実機確認の結果より。 pinout35.value(1) else: pinout35.value(0) except: pass
サードステップ
今回の実施条件は照明がほとんど一定の環境下のもの。照明条件が大きく変わるような条件、例えば直射日光が当たるような場所では正しく動かないはずである。
ホワイトバランスをとるような仕組みがあればより安定した動作ができると思う。今後の検討課題である。
また、「あ」と「A」の区別を領域のサイズ比で行ったが、この判定部分をAIにさせることでより精度の高い判定ができそうな気がする。 マシンビジョンとAIの組み合わせ、なんかカッコいいのでトライしてみたい。
【作品まとめ】M5Stackで霹靂一閃
Twitterにあげていた作品のまとめ
ハーフミラーを使って面白もの作れないかと考えていて思いつきました。M5Stackでホログラム その8
— PikaPikaらいと (@KPmilk3) 2021年3月12日
霹靂一閃#M5Stack #ホログラム #LovyanGFX pic.twitter.com/PluWAKEUue
Yin and Yangの絵はM5Stackライブラリの中のサンプルコードより。 M5Stack\examples\Advanced\Display\Sprite\one_bit_Yin_Yang
これをベースにLovyanGFXを使って上側の絵と下側の絵を別のspriteで作成し、パカッという動きを実現させています。
クモの絵はパワーポイントに入っていた素材を使用。M5Stackで 霹靂一閃 六連
— PikaPikaらいと (@KPmilk3) 2021年3月17日
縦撮りバージョン
クリックすれば全面見れるはず https://t.co/gmfCdPFWS6 pic.twitter.com/ozvvp3zvSV
WS2812を144個使用。M5Stackでは144個の制御ができなかったので、WS2812の制御とM5Stack2台へのタイミング信号の送り出しは別のマイコンで実現。
クモの絵のパカッという動きのプログラムはspriteを理解することで実現。 もしリクエストあればコード公開します。(現状、全然整理してないコードなのでとてもお見せできない)
光モノの工作を色々してきたが、ここにきて影の面白さに目覚めた。M5Stackで 霹靂一閃
— PikaPikaらいと (@KPmilk3) 2021年3月24日
影絵バージョン
RGB LEDテープを使った影絵、楽しい。色々な可能性ありそう😊#M5Stack pic.twitter.com/isG1cRRPaM
舞台裏編
M5Stackでホログラム その8
— PikaPikaらいと (@KPmilk3) 2021年3月12日
霹靂一閃の舞台裏
陰陽は上下で2つのspriteを使って表示。それでパカッとする動きを実現。ミラーフィルム使った瞬間移動は想像よりそれっぽくできた😆
思い付いたら作らずにはいられない。PoCを超えたいとは思うのだが🤔#M5Stack #ホログラム #LovyanGFX https://t.co/fgbYAHmnfB pic.twitter.com/WI5NBRGUBL
M5Stackで 霹靂一閃 六連の舞台裏
— PikaPikaらいと (@KPmilk3) 2021年3月16日
WS2812 144個使用
M5Stackは磁石追加で隙間あけてホワイトボードに貼付
クモのspriteを2つのspriteに座標ずらしてpushする事で分断
こそこそ噂話
M5StackでWS2812を144個制御出来なかったので、別のマイコンも使ったらしいですよ#M5Stack #LovyanGFX https://t.co/gmfCdPFWS6 pic.twitter.com/jhH5NWsCP1
M5Stackで 霹靂一閃
— PikaPikaらいと (@KPmilk3) 2021年3月24日
影絵バージョンの舞台裏
ハード、ソフトは前回の構成をほぼ使い回し。ダンボールステージはこれからも活躍予定 https://t.co/HxQtFN7l6i pic.twitter.com/b8xp5HO3ML
【作品まとめ】M5Stackでホログラム
Twitterにあげていた作品のまとめ
www.hitachi.co.jp
こちらの記事を見て、M5Stackなら自分でプログラム作れば好きな絵を浮かばせられるじゃん、と思って始めました。
実際にはこれは「ホログラム」とは違うものとは承知していますが、他に呼びようないのでホログラムと言っちゃってます。
LovyanGFXの描画速度の速さが体感できます。一番早いのは30回転首振りしているはずですが全然見えません。#M5Stack で #ホログラム#PartyParrot にチャレンジ
— PikaPikaらいと (@KPmilk3) 2021年2月19日
LovyanGFXの描画速度は凄い😲
スマホカメラでは全然追いつけない😓 https://t.co/e9HdtBpFH0 pic.twitter.com/5FbBNDPo2i
Wio Terminalのほうが画面サイズ大きいので向いているかもしれません。#WioTerminal でも #ホログラム
— PikaPikaらいと (@KPmilk3) 2021年2月20日
M5Stackと全く同じコードで動いた。 https://t.co/e9HdtBpFH0 pic.twitter.com/eQ2O721QjO
もともとM5Stack 2台持っていましたが。これやるために2台買い増し。#M5Stack で #ホログラム
— PikaPikaらいと (@KPmilk3) 2021年2月21日
思いついたらどうしてもやりたくなってM5stack買い増ししちゃった😅
楽しくなる予感しかないから悔い無し pic.twitter.com/QLSMm0WyfK
このために電動ターンテーブルも購入M5Stackでホログラム その4
— PikaPikaらいと (@KPmilk3) 2021年2月27日
電動ターンテーブル買っちった😅
4台使っての #PartyParrot
GIFアニメに白線2本使うと飛び出す感出せるとの記事見て、LovyanGFXを駆使して追加してみた😁#M5Stack #ホログラム pic.twitter.com/bqCCuPErPA
M5Stackでホログラム その5#PartyParrot にどうしてもChoo Choo TRAINさせたくなって考えた。
— PikaPikaらいと (@KPmilk3) 2021年3月5日
4台直列は厳しかったので2x2に#M5Stack #ホログラム pic.twitter.com/8wzD75aE2Q
M5Stackでホログラム その6
— PikaPikaらいと (@KPmilk3) 2021年3月7日
すごい動画みて、かめはめ波に挑戦したくなった。
あらゆるレベルの低さを痛感しつつも、最初の一歩として記録。ここからマイコンならではのエフェクトを考えてみようhttps://t.co/nyve34I9Jo @YouTubeより#M5Stack #ホログラム #LovyanGFX pic.twitter.com/SZaAH00HsO
M5Stackでホログラム その7
— PikaPikaらいと (@KPmilk3) 2021年3月10日
かめはめ波のあのシーンに挑戦。
マイコンの基本技、Lチカを活用。
日本語表示、さらに鏡に写すため反転表示という難題もLovyanGFXの力でなんなくクリア。
もう少し時間かけて作品に仕上げたい。#M5Stack #ホログラム #LovyanGFX pic.twitter.com/S1gsviEZFV
M5StickVでIME入力モードを判別してLチカさせてみた
構想
M5StickVでパソコンのモニター画面のIMEのモード表示「あ」or「A」を判別させ、「あ」ならLEDを点灯させ、日本語モードであることがキーボードに目線を置いていても分かるようにする。ブラインドタッチができない人間(私)が日々悩まされている問題に先端技術を持って取り組む。
環境&Version
Windows10
SDカード:SanDisk 32G HC Class10
EasyLoader(V5.1.2)
VTraining-Client-VerA02B01
V-Training実施レポ
M5StickVはV-Trainingという画像判別のための至れり尽くせりなサービスがある。
M5Stack Docs - The reference docs for M5Stack products.
基本的にはこのページに従って進めていけばOK。
EasyLoaderでファームウェアの書き込み
VTraining-Client.zipをダウンロードして中身をSDカードに書き込み。
M5StickVの電源を入れると学習用データ撮影モードのソフトが起動する。
学習には3クラス以上必要で、1クラス35枚以上の写真が必要と書いてあるので、「あ」、「A」、「×」の3種類の写真を35枚ずつ撮影。
trainフォルダとvaildフォルダができるので二つのフォルダを選択した状態で(これ肝心らしい)→送る→圧縮(zip形式)フォルダ でzipファイルを作成。
それをデータアップロードページでアップロード
http://v-training.m5stack.com/
しばらく待つとメールで結果が返ってくる。
が、1回目の結果は
[V-Trainer] *** Online Training Request Failed
Hi! Sorry for that, there is some error happened during the training process. We attached the reason below, if you have any questions, welcome to report to us through Twitter, Facebook, or Forum. Or, check out our docs here: https://docs.m5stack.com/#/en/related_documents/v-training
USERID: *** CONTENT: Lake of Enough Train Dataset, Only 78 pictures found, but you need 90 in total.Notice:
Image 16.jpg was removed for being too close to 82.jpg, hashdiff: 2
Image 93.jpg was removed for being too close to 82.jpg, hashdiff: 2
・・・
自分のつたない英語力でも読み取れます。「90個以上の写真がないとだめだけど君のは78個しかなかったよ。ちなみに似た画像があったから消しちゃったよ。 」
なるほど。似た画像になってしまうのは避けられないので、これはいっぱい写真を撮るしかない、ということで2回目は各100枚の写真を撮って、再チャレンジ。
今度は成功。
[V-Trainer] *** Online Training Request Finished
Model: Classification MobileNetV1 Alpha: 0.7 Depth: 1
学習曲線がついていて、学習がうまくいったのか分かる仕組み。これが無料でつかえるとは有り難い。
メールのURLから結果ファイルをダウンロードして、中身をSDカードに書きこめばOK
SDカード直下のboot.pyが起動時に実行されるようなので、最初の撮影用のファイル一式は別フォルダ作って移動させておいた。
起動して、パソコン画面にカメラを向けると、「おお!判別している」 (文字ちっちゃ ) けど正答率はいまいち。
手持ち撮影による不安定さが原因かもしれないと思い、今度はカメラを台座に固定して、しっかり位置キープした状態で再々チャレンジ。
初めてのPython
M5StickV、ボタン押しにくい。台座に固定した状態ではなおさら。なので1回押したら100回連続で撮影するようにプログラムを修正することにした。
元のコード のこの部分に
try: while(True): img = sensor.snapshot() if but_a.value() == 0 and isButtonPressedA == 0: if currentImage <= 30 or currentImage > 35:
for文を追加
try: while(True): img = sensor.snapshot() if but_a.value() == 0 and isButtonPressedA == 0: for num in range(100): if currentImage <= 30 or currentImage > 35:
生まれて初めてのPythonプログラミング 。コンパイルとかせずに、ただ書いたコードをSDに入れるだけで動くというのも驚きの仕組み。
ドキドキしながらシャッター(Aボタン)オン → 画面固まる → カチャ音100回 → 同じ写真が100枚取れる。
forループの中に img = sensor.snapshot() を入れてなかった。サウンドも消してなかったので延々カチャカチャ。
それでもエラーではなかったので、気を取り直して修正。
validationデータが31-35の5枚だけなのもよくないかと思い、5枚に1枚をvalidationデータにするように修正。
try: while(True): img = sensor.snapshot() if but_a.value() == 0 and isButtonPressedA == 0: for num in range(100): #100回撮影 time.sleep(0.1) #100ms delay入れておく。 img = sensor.snapshot() #if currentImage <= 30 or currentImage > 35: if currentImage % 5 != 0: #5枚に1枚をvalidationデータにする #以下略。play_sound("/sd/kacha.wav")はコメントアウト
再々チャレンジの結果はまずまず。カメラ位置の調整はしないといけないが、ちゃんと3クラスの判別ができている。
こんなに簡単にAIカメラが作れるとは驚き。
試しているとフリーズする現象が発生。調子いい時もあるが、だいたい途中でフリーズする。USBシリアルでログを見てみると pmax=max(plist) のところで型エラーが起きているみたい。 Pythonの型が全く分かっていないのでエラーを読み解けない。とりあえず覚えたての必殺技 try: except: pass でエラー起きても無視させてみる。結果、フリーズすることはなくなった。こんなんでいいのかと思いながらも先に進む。
あとは「あ」の時にLEDを光らせる仕組みを入れる。
M5StickV自身にもLEDはついているがカメラ側についているのでこれは使えない。使えるピンはGroveコネクタのところだけなので、ここを使うしかない。LED光らせるだけなら直接ドライブさせてもいいと思うが、手持ちにLEDドライバの基板があったのでこれを利用。コード的には直接ドライブと一緒。
あとLCDの画面は位置合わせの時には便利だが、常時ついていると気になるので、ボタンを押したら消せるようにしてみた。
最終的なコードがこれ(初めてのPython)
import image import lcd import sensor import sys import time import KPU as kpu from fpioa_manager import * from board import board_info import KPU as kpu from Maix import GPIO fm.register(board_info.BUTTON_A, fm.fpioa.GPIO1) but_a=GPIO(GPIO.GPIO1, GPIO.IN, GPIO.PULL_UP) #PULL_UP is required here! fm.register(35, fm.fpioa.GPIOHS1, force=True) pinout35 = GPIO(GPIO.GPIOHS1, GPIO.OUT) pinout35.value(0) lcd.init() lcd.rotation(2) try: from pmu import axp192 pmu = axp192() pmu.enablePMICSleepMode(True) except: pass try: img = image.Image("/sd/startup.jpg") lcd.display(img) except: lcd.draw_string(lcd.width()//2-100,lcd.height()//2-4, "Error: Cannot find start.jpg", lcd.WHITE, lcd.RED) task = kpu.load("/sd/XXX_mbnet10_quant.kmodel") labels=["1","2","3"] #You can check the numbers here to real names. sensor.reset() sensor.set_pixformat(sensor.RGB565) sensor.set_framesize(sensor.QVGA) sensor.set_windowing((224, 224)) sensor.run(1) lcd.clear() isButtonPressedA = 0 off_flg = 0 while(True): try: img = sensor.snapshot() fmap = kpu.forward(task, img) plist=fmap[:] pmax=max(plist) max_index=plist.index(pmax) if pmax > 0.95: # lcd.draw_string(40, 60, "Accu:%.2f Type:%s"%(pmax, labels[max_index].strip())) print(labels[max_index]) if max_index == 0: pinout35.value(1) else: pinout35.value(0) if but_a.value() == 0 and isButtonPressedA == 0: isButtonPressedA = 1 if off_flg == 0: lcd.set_backlight(False) lcd.clear() off_flg = 1 else: lcd.set_backlight(True) lcd.clear() off_flg = 0 if but_a.value() == 1: isButtonPressedA = 0 if off_flg == 0: a = lcd.display(img) except: pass a = kpu.deinit(task)
ファーストステップ完成
M5StickVでIMEの入力モード判別ができた🎵#M5Stack pic.twitter.com/enQfF1fcqe
— PikaPikaらいと (@KPmilk3) 2021年4月2日
セカンドステップ
M5StickVにはLCDとバッテリーがついていて便利なのだが、今回やりたいことに対してはこの機能は不要、むしろいらない機能といえる。
今回の目的に対してはUNIT-Vを使うのが最適なので、UNIT-Vで同じものを作ることにする。
2021/4/16現在、取組中。学習はいい結果が出せているが、モデルをUNIT-Vに入れて判別動作をさせると正答率がかなり悪いという問題で苦闘中。
その結果はまた記事にしたいと思います。
【作品まとめ】M5Stackで万華鏡
Twitterにあげていた作品のまとめ
ヤマザキミノリ先生のCUMOSを意識した作品です。 Twitterではガラスブロックと言ってますが多分アクリルの間違いです。キャン★ドゥで購入したものですが現在見かけません。買いだめしておけばよかった。M5Stackで万華鏡 その1
— PikaPikaらいと (@KPmilk3) 2021年2月26日
100均で見つけた直方体のガラスブロックを3個重ねることで広がりを出してます。#CUMOS を再現。と言いたいところですが、立体ではないので見えかたでおよびません😓立体にするには、さてどうするか🤔#M5Stack#万華鏡 pic.twitter.com/Hc0Oz2eA0m
LovyanGFXの描画が凄すぎて、あえてボールの数を減らしてますM5Stackで万華鏡 その2
— PikaPikaらいと (@KPmilk3) 2021年3月1日
ダイソーの万華鏡そのまま使ってます😅
表示プログラムはこれまたLovyanGFXのサンプルをちょっとだけ改造したもの
単純な方法ですがポテンシャルはあると思うので、もっといろいろやってみたいです🪞#M5Stack#万華鏡 pic.twitter.com/MZJo1b1zvF
カラーだとめまいを起こしそうなくらい激しかったので白黒に変換して投稿M5Stackで万華鏡 その3
— PikaPikaらいと (@KPmilk3) 2021年3月1日
つい出来心で
カラーだと点滅激しいのでモノクロにて#M5Stack#万華鏡#PartyParrot pic.twitter.com/oR9FZh753m
キモカワイさがお気に入りで、このシリーズは何種類も作りました。M5Stackで万華鏡 その4
— PikaPikaらいと (@KPmilk3) 2021年3月2日
想像を超えるものが生まれるところが万華鏡の醍醐味
表示プログラムはM5Stackライブラリのサンプルone_bit_Yin_Yangをちょこっと改造したものです#M5Stack#万華鏡 pic.twitter.com/6yM3gNyKeH
M5Stackで万華鏡 その5
— PikaPikaらいと (@KPmilk3) 2021年3月9日
絵柄の方を動かす事で変化させる#M5Stack #万華鏡#どこかの誰かに刺さればそれで良い pic.twitter.com/4UMjKyVsIr
M5Stackで万華鏡 その5の2
— PikaPikaらいと (@KPmilk3) 2021年3月13日
魚眼レンズで怪しさ倍増#M5Stack #万華鏡 pic.twitter.com/3EJgt9aauJ
M5Stackで万華鏡 その6#CUMOS っぽい絵柄
— PikaPikaらいと (@KPmilk3) 2021年3月13日
100均の魚眼レンズを装着
spriteの残像はあえて残して模様に#M5Stack #万華鏡 pic.twitter.com/uVfri9epl6
M5Stack プロトモジュールの基板データを開いて寸法を測ってみた。
本記事は2021/4/12の情報です。
OS: Windows10
初めに
M5Stackのアクセサリにプロトモジュールという拡張用のボードがあります。
www.switch-science.com
しかしながらこのボード、MBUSコネクタから配線が引き出されていないため、コネクタの足に直接ワイヤーをはんだ付けして配線するという、若干残念な代物です。基板設計できる人であればボードを自作したくなります。
基板自作にあたって、一番必要なのはMBUSコネクタの位置寸法ですが、公式にはこの寸法図はないようです。
基板データ発見?
M5StackのGitHubを散策していてそれらしいデータを見つけました。
GitHub - m5stack/M5-3D_and_PCB
ここに PROTO.stl と PROTO_254.PcbDoc というファイルがあります。
PROTO.stlはプロトモジュールの筐体のデータでした。
PROTO_254.PcbDoc はボードのCADデータである可能性高そうです。
拡張子からAltiumのデータだと見当つきます。実は私、基板CADには詳しく、基板設計だけでなくCADのシステム管理などしていたこともあります。Altiumもちょっとだけ使ったことがあります。
Altium Designer でデータ開いてみる
Altium のホームページ
https://www.altium.com/jp でAltium Designerビューワーの無償ライセンス(有効期間6か月)を手に入れます。
名前、電話番号、メールアドレス等を登録すると、すぐにメールが届きます。メールにダウンロードのURLとライセンスの設定方法など記載されているので、その通りに進めれば簡単にセットアップできました。特に詰まるところはありませんでした。
データを開いてみると、
どうやら当たりのようです。
主要な寸法を測定
MBUSコネクタの下にあるので分かりにくいですが、位置固定用のボス穴があります。これ入れておかないとコネクタの実装するときに位置決めるの大変なので、自作する場合忘れずに入れましょう。
虹を投影する懐中電灯を作った
2021/4/7 追記(サンプルコード、紫色について)
初めに
以前からLEDを使った光モノの工作をしていました。 前々から一つの目標だったものに「虹を投影する懐中電灯」がありました。 今回それなりにイメージに近いものが作れたのでその作り方を紹介します。
Handy Rainbow Light
— PikaPikaらいと (@KPmilk3) 2021年3月26日
虹を映し出す懐中電灯の試作初号機完成。
100均の懐中電灯を改造して中にM5AtomLiteとM5StackHEX(LED37個のボード)を仕込むことでスッキリ出来た。
単三電池3個で駆動。
レンズなどの光学部品は無し。
#虹 pic.twitter.com/qex5RuHxGK
注意
- 使用しているLEDボードの光量は強烈です。プログラムで光量を設定しますので、強くしすぎないようにしましょう。LED直視は厳禁です。
- 市販の懐中電灯を改造しています。もし同じことされる場合は自己責任でお願いします。
きっかけ
アイデアのきっかけはRGB LEDテープを使って7色の影を作っていた時でした。
このとき指と指の隙間の影が虹の形になっていることに気づきました。
そこで思いついたのが虹色の順にLEDを並べてスリットを通すという方法です。
このツイートの写真には載せていませんでしたが、これはRGB LED16個を虹色の並び(紫→赤)で点灯させ、ある程度の距離においた型紙に虹型のスリットを設けてそこを通して投影したものです。WS2812SテープとM5Atomを使っての虹色実験中
— PikaPikaらいと (@KPmilk3) 2021年3月22日
虹の形の投影ができた。
これで念願のHandy Rainbow Lightを作れそう😆 https://t.co/DuLXxOsnSf pic.twitter.com/gUn8NlYqLY
とても幅広ですが虹の形と色で光を投影することができました。
原理
スリットを通すことで虹型が作れる理由はこんな感じだと思います。 LEDの光は放射状に照射されますが、スリットを通すことである程度直進させることができます。赤色のLEDを下側に紫色のLEDを上側に配置してスリットを通すと、赤の光は下から上の方向にスリットを通るので上側が赤くなります。同じように紫色の光は上から下方向にスリットを通るので下側が紫になります。このように各色の光をスリットを通すことで虹の形と色を再現することができました。
試作
RGB LEDテープを使ったのではどうしても幅広になってしまうのでコンパクトに7色並べられる方法を考えていた時に目についたのがM5StackのHEX RGB LED Board です。
www.switch-science.com
これはちょうど7列あって、サイズもちょうど懐中電灯に収まりそう。
100円ショップで大きめの懐中電灯を買ってきました。単3電池3本使用で4.5Vですが、LED点灯させることできました。
コントローラーに極小のM5Atom-Liteを使うことで懐中電灯の頭の部分に収めることができました。
各LEDの色は固定なのでサンプルコードをベースにすれば簡単にプログラムできます。
void show_rainbow(void) { float zz = 2.0; //明るさの調整用 for (int i = 0; i < 4; i++) { // violet pixels.setPixelColor(i, pixels.Color(125 / zz, 0, 255 / zz)); } for (int i = 4; i < 9; i++) { // indigo pixels.setPixelColor(i, pixels.Color(50 / zz, 0, 255 / zz)); } for (int i = 9; i < 15; i++) { // blue pixels.setPixelColor(i, pixels.Color(0, 0, 255 / zz)); } for (int i = 15; i < 22; i++) { // green pixels.setPixelColor(i, pixels.Color(0, 255 / zz, 0)); } for (int i = 22; i < 28; i++) { // yellow pixels.setPixelColor(i, pixels.Color(255 / zz, 255 / zz, 0)); } for (int i = 28; i < 33; i++) { // orange pixels.setPixelColor(i, pixels.Color(255 / zz, 100 / zz, 0)); } for (int i = 33; i < 37; i++) { // red pixels.setPixelColor(i, pixels.Color(255 / zz, 0, 0)); } pixels.show(); // Send the updated pixel colors to the hardware. delay(100); }
配線がごちゃつくのを防ぐために、このようにLEDボードの拡張コネクタのほうに電源を接続し、そこからM5Atomのほうに給電する方法を考えました。
色の並びは先ほど説明したように赤色が下。上側が紫です。
これにある程度の距離をとって虹型のスリットを配置します。
大き目の紙コップがジャストサイズでこれを利用しました。
スリットのサイズは半径5センチくらいの半円に1センチくらいのスリット幅にしました。この辺は検討の余地ありです。
スリットなしだと色が混ざってしまって白色になってしまいますが、スリットを通すことで虹の形と色を再現することができました。
紫色について
虹の一番下の色は紫色です。これは紫色の波長が一番短いことを示しています。
ところが、RGB LEDで紫色を作る場合、波長の短い青と波長の長い赤を同時に点灯することで、紫色に見えます。
これって不思議ですね。このことに関してはまた別の機会に語ってみたいと思います。
今後の構想
今回は37個のRGB LEDボードを使用していますが、それぞれの色は固定で使っているので、単純に7色のLEDを並べれば同じことができるはずです。
もっと言えば、白色の光源を7色のラインが並んだフィルターに通してからスリットに通せばいけるはずです。
そこまでコストダウンできれば将来100円ショップとかで売られる日も夢ではないかもしれません。
子供向けの工作教室でも作れるくらい、より手軽に作れる方法を考えてみたいと思います。
また今回レンズ等の光学部品は使用していません。なのでLED自体の光量はかなり明るいですが、スリットを通った後の光はわずかで、暗いとことでないとちゃんと見えません。100円ショップで入手できるようなものをレンズ代わりに使ってもっと明るさを出せないかも検討してみたいです。
最後に
ブログを始めようと思ったのは、尊敬する人気ブロガーからあげ先生が書籍の中でアウトプットをすることが大事だと言われていたことに共感したからです。ツイッターは最近始めてみたのですが、そこではここまで詳しい解説はできないし、つぶやきはすぐに流されていくものなので、記事として残したいものはちゃんと書きたいなと。
初めてのはてなブログの記事作成で、Markdown記法から勉強したり、思ったより苦労しました。
けれど、これまで一方的に多くの方のブログ記事に助けられてきたので、自分も楽しいことを共有できればと思い、何とか書き上げました(晩酌の時間削って^^)
万一この虹投影の仕組みが特許化とかされて自由に使えなくなるとかは嫌なので、こうして記事にして公知にしておきたかった、という思いもあります。