M5AtomでBLEマウスっぽいものを作った
唐突なんですが、右手の親指を動かすとめちゃめちゃ痛むようになり、リモートワークで使っているLenovoキーボードの左ボタンが押せなくなりました。
休日と業務時間外は私物のmacなので全く困らないのですが、これでは仕事ができないので、急遽マウスの左ボタンだけを別で使う機能が必要になりました。
手元にあった使えそうなもの
残念ながらUSBデバイスとして使えるものArduino Pro MicroやArduino Leonardoを持っていない。
ESP32でBLEマウスを作れると言う情報はいくつかあったので、手近なところでM5Atomを選部ことに。
最終的にできたもの
- BLEでPCと接続して、以下の動作をするもの
- M5Atom Liteのボタンを押すと左クリック
- M5Atom Liteのボタンを押すと左ボタン長押し
※ダブルクリックのことは頭になかったけど、使ってみたら無くても困らなかったので除外した。
コード
限定用途なのでたいしたものではないですが、ライブラリ「ESP32-BLE-Mouse」を使うとこんなあっさりしたコードでPCと接続できると言うのは結構衝撃でした。
姉妹品?にESP32-BLE-Keyboardというのもあるので、それぞれサンプルをチェックしていただければ使いどころはイメージできるのではと思います。
#include "M5Atom.h" #includeBleMouse bleMouse; void setup() { M5.begin(true, false, true); Serial.begin(115200); Serial.println("Starting BLE work!"); bleMouse.begin(); M5.dis.drawpix(0, 0xffffff); delay(500); } void loop() { if(bleMouse.isConnected()) { if (M5.Btn.wasPressed() ) { M5.dis.drawpix(0, 0x00f000); Serial.println("Left click"); bleMouse.click(MOUSE_LEFT); M5.dis.drawpix(0, 0x000000); }else if(M5.Btn.isPressed()){ M5.dis.drawpix(0, 0x000f00); Serial.println("press"); bleMouse.press(MOUSE_LEFT); }else if(M5.Btn.isReleased()){ M5.dis.drawpix(0, 0x000000); bleMouse.release(MOUSE_LEFT); } delay(300); M5.update(); } }
参考
M5StickCの加速度センサを利用したものではこんな作品も。
qiita.com
失念したこと
ボタンの代わりに、タッチセンサか圧力センサを使いたかったのですが、無線接続を有効にした途端にセンサの値が意図しないものになってしまい、平日深夜だったので切り捨てました。(無念)
原因
ESP32にお詳しい たなかまさゆき さん曰く、無線有効時のアナログピンはピン32以上の数字のものしか正常動作しないのだとか。。
→ピン33などでも試していたのですが、ESP32 Pico Kitなので挙動が違う可能性も??
と言うことで一旦アナログは無視することにしました。
当初は赤丸のところにタッチセンサを設置するつもりでした。
実際試してみた感想
100点ではないけれど、手の痛みを緩和する目的は果たせたのでまずまず。
しかし、今の仕事で手に負荷がかかっているのがドキュメント作成やドキュメントレビューの画面スクロールやセル移動の動きなので、本当に必要なUI/UXはキーボードやマウスではないということに気がつきました。
顧客が本当に欲しかったのは、左手用のボタン付きジョイスティックでは?
今回はLenovoキーボードの左ボタン押しすぎでドケルバン症候群になったようなのですが、普通のマウスを使うと腱鞘炎&昔患った三角繊維軟骨複合体(TFCC)損傷の再発もあり。
右手は使わず、左手でスムーズに使えるインターフェース、、Nintendo Switchのようなものが理想なのかも。
たぶん↓に筐体をつけてやるのが理想形な気がしています。
ちなみに
公私とも色んな方からオススメいただいたのがケンジントンのトラックボールでした。
安価なところではロジクールも良いらしい。
トラックボールは以前に新宿ヨドバシで色々試したものの、手が小さすぎてちょっと合わなかったのですが、普通に指を動かせるようになったら再検討しようかと思います。。(その頃にはコーディングに入って、使わなくなってる可能性もあり)
Maixduinoで使える部品類(※8/24追記)
※追記) 2020/8/24 カメラとスピーカー
付属カメラのケーブルが断線した時、結構苦労したのでこれもメモ。
デュアルカメラやマイク等はスイッチサイエンスで買えるものの、以外とちょっとしたものを探すのに悩んだ。
カメラ
魚眼レンズ(純正)
一番安いのはスイッチサイエンスですが、現在は品切れ。
Shigezoneに在庫がある場合も。
www.sengoku.co.jp
通常レンズ(互換品?)
アリエクで発見してしまったので、国内では探していないです。
2つ購入して、正常動作を確認しています。
その他
M5StickVですが、OV2640と同様に使用可能なカメラについて情報をお寄せいただきました。感謝!!
Maixpyで使えるカメラ(CMOS)の比較表ざっくりまとめた
— muu (@muudev) August 24, 2020
カメラ≠CMOSなので実際と違うところあるかもhttps://t.co/HYvymNNDnx#sipeed #Maixpy #M5StickV pic.twitter.com/zGyAbcNulb
ケーブル延長基板
カメラ断線を繰り返さないためにネットで調べてAitendoにて購入。
Aitendoは今、お品切れの様子。
検索キーワード「FFB FFC 0.5 24P」で出てきます。
アリエクなら、これの24Pが同じだと思います。
延長ケーブル
前述の基板に接続するもの。向き注意。
最初Aitendoで表-表しか買ってなくて、慌ててAmazonで表-裏を追加発注した記憶。。
検索キーワード「FFC 0.5 24P」で出てきます。
カメラ用
表-裏向きのものが必要。0.5mmピッチ24ピン。
Aitendoで言うところの「Wタイプ」、アリエク・Amazonで言う「Bタイプ」が該当。
LCD用
表-表向きが必要。
Aitendoで言うところの「Sタイプ」、アリエク・Amazonで言う「Aタイプ」が該当。
色々接続するとこう。LCDのケーブルも断線怖いので、マスキングテープで固定しています。
LCD
付属のものと全く同じSeeed製品。
アリエクでもっと安価なものがあるかもしれませんが、探してないです。
スピーカー
1.25mmピッチコネクタ(molex 51021)がついたもの。
検索"1.25mm スピーカー"である程度引っかかってくるはず。
うちのはAitendoで買った適当なものに、ケーブルをハンダ付けしたので正確な型番は不明ですが、おそらくTwitterなど見る限りではスイッチサイエンスのこれが使える。
失敗編
互換性あるかなーと思って失敗したもの。
大きめ3.2インチLCD(ST7789 8bit版) ←NG
付属の2.4インチより大きいものが欲しかったので。
発注当時、回路図探せなかったけれどピン数、ピッチ、ドライバーは同じなのでとりあえず試してみた。
結果、配線が違ったのでNG。連結基板を自作すれば使えるのかもしれないけれど、時間をかける余裕がないので保留。
購入当時は到着品のコネクタに書かれた型番"jlt32018b-v"を、百度で探さないと見つからなかったけれど、今はアリババのリンクが出てくる。
→これは普通にseeedが売ってるので探せる。モノもAmazonで買える。
・・・まとめてみたら結構な人柱感ありますね。
MaixduinoでMakerDrive(モータードライバ )制御
注意) BLINKアプリでの操作は、MaixPyにuselectが実装されていないので、2020/8/23現在はできません!!
ようやくスタートラインに立った感。
Maixduinoでモータードライバ を動かすまで、結構長い道のりだった。
MaixduinoとMaker Driveでモーター動かしてみたんだけど、宙に浮かせるための台(マウスレスト)がずれて、なんか荒ぶった動きに。 pic.twitter.com/FGS26quSyF
— パリピ般若(hack-tenorion) (@hack_tnr) August 23, 2020
用意したもの
- Maixduino
- USB type-Cケーブル(Maixduino用)
- MakerDrive (モータードライバ )
- タミヤ ダブルギヤボックス
- 外部電源(3.3V or 5V) ※↑の動画では3.3V使用
- ジャンパーピン
- オスーメス 5本(MakerDrive - Maixduino用)
- 外部電源用2本 ※何を使うかによる
加えて、モーターにコンデンサー 100nF、外部電源のところにパスコンとしてコンデンサー 1μFつけるのがベターなのですが、そもそもArduino・ラズパイを通らずMaixduinoにチャレンジする人はそうそういないので割愛。
USBから3.3Vor5V取るのは、みんなのラボさんの「ブレッドボード電源モジュール」が重宝してます。マルツ本店2Fに在庫が買えるとラッキーです。
実体配線図
データを作る余力がありませんでした。。
あと前述のコンデンサー書いてないですが、まぁ動きます。
コード
前進、後進、右回転、左回転をするだけです。MakerDrive用のライブラリは不要。
トラ技2019年11月号に掲載されているPCA9685はライブラリがあるので、これとは違った内容になります。
import time from machine import Timer,PWM from Maix import GPIO freq=100000 max_duty=50 #最大100。大きいほど速い。 tim_1 = Timer(Timer.TIMER0, Timer.CHANNEL0, mode=Timer.MODE_PWM) tim_2 = Timer(Timer.TIMER0, Timer.CHANNEL1, mode=Timer.MODE_PWM) tim_3 = Timer(Timer.TIMER0, Timer.CHANNEL2, mode=Timer.MODE_PWM) tim_4 = Timer(Timer.TIMER0, Timer.CHANNEL3, mode=Timer.MODE_PWM) #右タイヤ前進(ボード 8番ピン) ch_r1 = PWM(tim_1, freq=freq, duty=0,pin=14) #右タイヤ後進(ボード 9番ピン) ch_r2 = PWM(tim_2, freq=freq, duty=0,pin=13) #左タイヤ前進(ボード 10番ピン) ch_l2 = PWM(tim_3, freq=freq, duty=0,pin=12) #左タイヤ後進(ボード 11番ピン) ch_l1 = PWM(tim_4, freq=freq, duty=0,pin=11) #前進 ch_r1.duty(max_duty) ch_l1.duty(max_duty) ch_r2.duty(0) ch_l2.duty(0) time.sleep(3) #後進 ch_r1.duty(0) ch_l1.duty(0) ch_r2.duty(max_duty) ch_l2.duty(max_duty) time.sleep(3) #右回転 ch_r1.duty(0) ch_l1.duty(max_duty) ch_r2.duty(0) ch_l2.duty(0) time.sleep(3) #左回転 ch_r1.duty(max_duty) ch_l1.duty(0) ch_r2.duty(0) ch_l2.duty(0) time.sleep(3) ch_r1.disable() ch_r2.disable() ch_l2.disable() ch_l1.disable()
参考資料
PWMは最大12こまで扱える。
Timerは0-3まで。それぞれにChannel 0-4が割り当てられている。
ピンアサインはSipeedのGitHubからmaixduino_pins.pngを参照。
この先やりたいこと
一旦はBLINKアプリで動作させたかったけれど、uselectが使えないのでそれは先のお話。
カメラを使って自動運転できると良いなぁ。
そういえばM5Atom(Arduino) + MakerDrive + BLINKアプリの記事を書いてないので、後で書く予定。
MaixduinoをMaixPyでPWM制御する方法
さて、前回 でようやくGPIOの出力を理解したので、PWMが使えるようになりました。
MaixPyでPWMでLチカ。なるほど🤔https://t.co/22jpzRVdpz pic.twitter.com/C4GcTOfvNa
— パリピ般若(hack-tenorion) (@hack_tnr) August 23, 2020
コード
例によって、ボードの9番ピンからLEDをちょっとずつ明るく光らせるだけの簡素なものです。
ピンアサインはSipeedのGitHubからmaixduino_pins.pngを入手して確認してください。
import time from machine import Timer,PWM from Maix import GPIO tim = Timer(Timer.TIMER0, Timer.CHANNEL0, mode=Timer.MODE_PWM) # ボードの9番 =pin13 ch = PWM(tim, freq=500000, duty=0,pin=13) duty =0 for duty in range(100): ch.duty(duty) time.sleep(0.5)
ドキュメント
ちょっと紛らわしいのですが、MaixduinoのAnalog I/Oの項ではなく、MaixPyのPWMの項に掲載されています。
参考資料
高度な応用例についてはトラ技201911月号の、砂川寛行さんの記事「第4章 K210の研究4 ニューラル・ネットワークとI/O」に二足歩行AIロボットの例があるのでそちらがオススメです。
以上。作業の日が空くと忘れてしまうので備忘録でした。
MaixduinoのMaixPyでGPIO制御
※理解が正しくない部分など、ちょいちょい加筆・修正しています
前回、MaixduinoでMaixPyからESP32よぶにはシリアル通信が必要と書きましたが、間違いでした。。
どうもこれが正解のようです。。
MaixduinoでMaixPyからGPIO使うの、Arduinoと併用せずにやる方法をようやく理解した。。(›´Δ`‹ ) pic.twitter.com/oooWkrkSCS
— パリピ般若(hack-tenorion) (@hack_tnr) August 22, 2020
読むべき資料
SipeedのGitHubから以下の資料を入手する
- maixduino_pins.png
- 青枠の数字を"IO"はつけずに定義してやればOK
- 定数もあるけれど資料と合ってない部分があったので、かえってつまづくかも
- MaixDunio(Pin assignment table).xlsx
- 前述の青枠の数字の代わりに、Functionの定数を使うこともできる
- しかし、print(board_info.LED_R) で戻ってきたのが13ではなく14だった(あれ?)
その他、MaixPyで下記を実行すると、ピンに割り当てる機能の定数が確認できる。(fm.fpioa.GPIO0など)
from fpioa_manager import fm print(fm.fpioa.help())
コード
ボードの9番ピンからLEDを光らせるだけですが。
import time from Maix import GPIO from fpioa_manager import fm # ボードの9番にLEDを繋いで光らせる場合 fm.register(13, fm.fpioa.GPIO0) led_1 = GPIO(GPIO.GPIO0, GPIO.OUT) flg=0 while(1): led_1.value(flg) if flg==0: flg=1 else : flg=0 time.sleep(1)
ハマった点
ESP32のFWは通常と異なるので、Arduino IDEでも通常のESP32のコードの流用はできないこともある。
- ArduinoIDEでledcSetupなど対応していないメソッドを呼ぶと、ESP32が延々再起動する
- ArduinoIDEはanalogWriteもコンパイルエラーになった。
- Maixduino_esp32_fimwareをESP32で入れた状態で、MaixPyからanalogWriteはできるらしい
- analogReadは動く。(逆にMaixPy上で動かせない)
MaixPyのPWM制御はトラ技にあったので、こちらを参考にしようと思います。
GPIOのピンアサインさえわかれば、あとはM5StickVでググるのが吉。
・・・そういえばBLEって使えないんですかね。
まぁ、通常のESP32のようなことがしたいなら、M5Atom LiteかM5StickCと接続した方が良い気もします。
MaixduinoでBLINK使おうとして失念した話
※理解が正しくない部分など、ちょいちょい加筆・修正しています
本当は「M5Atom LiteとBLINKでモータードライバ を動かす」話を先にかくべきだったのに、順序が逆になってしまうのですが。。
失敗まとめは時間が経つと書く気が無くなるので、勢いがあるうちに書いておきます。
BLINKとは
試そうとしたライブラリ
Readmeの手順参照
失念した理由
- Maixpyがライブラリ"uselect"を扱わなくなったため、blinklib_mp.pyの読み込みでエラーになる。
- uselectは公式から綺麗さっぱり消えてる。。
- replでhelp('modules')を叩いても出てこない。
- 結論)現段階では無理そう。
- 追記)2020/8/22現在は、Ano研さんがSipeedにIssueをあげてくださってるので、今後に期待。
古いバージョンなら使えるとか、Micropythonのソースから持ってくる手もあるのかもしれないけれど、今時間をかけてやる意義はないと判断した。
失念したけれど勉強になったこと
MaixduinoでK210からESP32を呼び出すには、K210とESP32でシリアル通信をする必要がある。MaixPyから直接DIGITAL/PWM呼ぶ方法がわかったので、別記事書きました。(ANALOG INはK210とESP32をシリアル通信で良いらしい)- K210はMaixPy IDEから書き込み。ESP32は Arduino IDEから書き込みを行う。
- シリアルポートに2種類出てくる。AがK210、BがESP32。
- シリアル通信やWi-FI接続でエラーが出る場合は、ESP32のファーム書き換えが解決する場合がある。
- この辺のまとまった情報については、Ano研さんの「MAiX MAniaX」が良い。
- Maix Bitを使ったGPIO制御ならトラ技の2019年11月号も情報量がある。(ESP32ではない)
- Wi-Fiの処理はK210側でやるのが基本らしい。
- 試しにESP32側でWi-Fi処理書いたら、ひたすら再起動かかってダメだった。
ちなみにArduino IDEで、全手の処理をArduinoで書くという手もあるけれど、IDEのバージョンなどでSDカード読み込めなくてはまるなどあって、今は触っていない。(もしかしたらファームの更新で改善されたかも?)
mac OSによるESP32のファーム更新
参考になった記事。
自分の環境ではこうなりました。
/Users/ユーザー名/.pyenv/versions/anaconda3-5.0.1/envs/py/bin/esptool.py --chip esp32 --port /dev/tty.usbserial-00002114B --baud 115200 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0x000 ./maixduino_esp32_firmware_v1.4.1_0x0.bin
M5StackでLED万華鏡を作ってみた
なんとなく思いついて、部品を取り寄せた勢いだけで作ってみました。
M5Stack用NeoPixel互換LED搭載 六角形ユニットで、簡素なLED万華鏡を作ってみた。(1箇所信号不良あり)
— パリピ般若(hack-tenorion) (@hack_tnr) August 2, 2020
小学校の夏休みの宿題でも作れそう。 pic.twitter.com/s3euogI5Qd
材料
- どこのご家庭にもあるM5Stack(AtomやStickCでもOK)
- ミラーシート
- マスキングテープ
- M5Stack用NeoPixel互換LED搭載 六角形ユニット
- M5Stack用Groveケーブル
- (あると尚良し)拡散版
作り方
ミラーシートを1.8mm×10.5mmカットする。6本用意する。
ミラーシートの間隔を約1mm開けて、マスキングテープで止める。
1箇所だけ写真のように深さ3mm程度の切れ目を入れる。
上から見るとこんな状態になります。
M5StackにLED37こをランダム点灯するコードを書き込みます(後述)
拡散板がないので、折りたたんだティッシュペーパーをかぶせてみました。
だいぶ柔らかくなります。
Arduinoコード
37個すべてランダム色にしていますが、色を白ベースにして赤系・青系などに絞ったほうが綺麗だと思います。
せっかくM5Stackを使っているのだから画面にも何か出したかったのですが、空いてるのが画面破損しているものしかなかった。。
#include <M5Stack.h> #include "FastLED.h" #define DATA_PIN 21 #define LED_TYPE WS2812B #define COLOR_ORDER GRB #define NUM_LEDS 37 #define BRIGHTNESS 5 CRGB leds[NUM_LEDS]; uint8_t direction;//0: clockwise 1: anti-clockwise void setup() { M5.begin(true, false, true); Wire.begin(); Serial.begin(115200); FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); // initializes LED strip FastLED.setBrightness(BRIGHTNESS); showLedCleanUp(1); M5.Lcd.clear(); M5.Lcd.setCursor(0, 0); showLedRandom(500); } void showLedCleanUp(long delayTime) { for (int i = 0; i < NUM_LEDS; ++i) { leds[i] = CRGB::Black; } FastLED.show(); delay(delayTime); } void showLedRandom(long delayTime) { while(1) { for (int i = 0; i < NUM_LEDS; ++i) { leds[i] = CHSV(random8(), 255, 255); } FastLED.show(); delay(delayTime); } } void loop() { }
未解決事件簿
LEDのうち1つだけ(10番)信号の制御がうまくいかず、点灯しないor意図した色にならないという問題がありました。
詳しい方々から教えていただいたのですが、ESP32のあるある問題らしい。。
もしかしたら検索「Fast LED 一部 光らない」などでこのブログに辿り着くことがあれば、以下参考になさってください。
- Adafruits_NeopixelはESP32だと誤点灯が起きる(Arduinoだと問題なし)
- RTOS等入ってないので信号生成系ライブラリはESP32だと大体死ぬ
- AVRだと割り込み禁止にしておけば、正確にCPUとGPIOで信号生成処理出来るが、ESP32だとRTOSとかキャッシュとかいろんな要因で難しい
- パルス幅とかが正確じゃ無いと困る系は、ESP32対応と謳っているものを使うのが無難
10番のLEDだけなんだか動きが怪しい pic.twitter.com/NbXjcKhAva
— パリピ般若(hack-tenorion) (@hack_tnr) August 2, 2020