触感フィードバックをしようとして詰まったけど何故か突然上手く行った話。
紆余曲折しているので、結論読んでから実践しましょう。
タイトルの呪文を解説しながら、実験環境を説明します。
DRV2605
www.tij.co.jp
I2Cで叩くと良い塩梅で振動モーターを駆動してくれる便利なIC(超意訳)
ブレークアウト基板はAdafruitやSparkfunから出てます。
https://learn.adafruit.com/adafruit-drv2605-haptic-controller-breakout/overview
Haptic Motor Driver Hook-Up Guide - learn.sparkfun.com
AdafruitはENピンはHIGH固定ですが、SparkfunはENピンが出ているので実デバイスに乗っけるならこちらを選んだほうが良さそう。
しかし私はSparkfunから出ていたのを知らずにAdafruitの方を買ったので、この記事ではAdafruitを使います。マルツで買いました。
触感フィードバックモジュール 2305の通販ならマルツオンライン
Sparkfunのほうはスイッチサイエンスで売っています。
DRV2605L搭載 触覚フィードバックモータードライバ - スイッチサイエンス
LRA
リニア・バイブレータ(LRA:Linear Resonant Actuator)。コイルに電流を流すことで電磁力を発生させ、これと磁石との反発力を使ってコイル自体を上下に振動させるものだ。
最新アナログ基礎用語集 - ハプティクス(触感フィードバック) - TI
いわゆるガラケーに入ってたのは偏心モーター(ERM)で、ブルンブルンって感じの振動でしたよね。最近はカチっというクリック感が出せるLRAが主流だと思います。
LRAにはリンク先の絵にあるコイン状のものと、iPhoneでTaptic Engineと呼ばれているような四角いものがあります。*1
LRAは秋月で調達。ちょっとデカイですが、Taptic Engineと同じで横方向に動くタイプです。
リニア振動アクチュエータ LD14−002: パーツ一般 秋月電子通商-電子部品・ネット通販
動かしてみよう
結線は超簡単。ArduinoのI2C用のピンをつなぐだけ。
https://learn.adafruit.com/adafruit-drv2605-haptic-controller-breakout/wiring-and-test
AdafruitからArduino用ライブラリが配布されてるのでこれを使います。
GitHub - adafruit/Adafruit_DRV2605_Library: Arduino library for Adafruit DRV2605L Haptic Controller Breakout
サンプルコードからbasicを書き込み、いざ…
なんでやねん。Adafruit_DRV2605::begin()を見に行くと
Adafruit_DRV2605.cpp
// ERM open loop // turn off N_ERM_LRA writeRegister8(DRV2605_REG_FEEDBACK, readRegister8(DRV2605_REG_FEEDBACK) & 0x7F); // turn on ERM_OPEN_LOOP writeRegister8(DRV2605_REG_CONTROL3, readRegister8(DRV2605_REG_CONTROL3) | 0x20);
デフォルトはERMのオープンループ設定らしい。
useLRAという関数が用意されているので、これを使う。ついでにLibraryもLRA用の6を選択する。
basic.ino
void setup() { Serial.begin(9600); Serial.println("DRV test"); drv.begin(); drv.useLRA(); drv.selectLibrary(6); // I2C trigger by sending 'go' command // default, internal trigger when sending GO command drv.setMode(DRV2605_MODE_INTTRIG); }
これでも動かなかった。なんでー?
電流が足らないのかなーと思い、安定化電源つないだりオシロ覗いたりしたけど原因が分からず。
GitHubで他のライブラリを探してみる。AdafruitとSparkfun以外で2つ見つかる。
FlexModule/haptic/LRA/DRV2605L/software/arduino/DRV2605 at master · FyberLabs/FlexModule · GitHub
GitHub - Seeed-Studio/Grove_Haptic_Motor
このうち、後者で動いた。Auto calibrationも機能している模様。*2
やはりAuto Calibrationが要るのか?と思い、もう一度Adafruitのプログラムを書いてみる。
動いた(白目)
結局、同じ現象を再現できず。どうもRATED_VOLTAGE(0x16)とOD_CLAMP(0x17)が小さいと鳴らないので、このせいだったのかもしれないが、電源を入れ直すとデフォルト値に戻るので理屈が合わない。
なお、データシートには明示されていないが*3、上記2つのパラメータはどうも絶対値(つまり定格3Vなら0x03)ではなく、入力電圧に対する比率(0xFF=100%)のような気がする。
振動モーターの仕様をみると
・駆動電圧:2V~6V
・駆動電流:120mA(@3V、バイポーラ駆動、150Hz、デューティー比50%)
・コイル構成:1相(バイポーラまたはユニポーラ駆動)
・コイル仕様:直流抵抗25Ω、インダクタンス210μH(@120Hz)
・本体共振周波数(fo):約150Hz(配線材、固定方法等によって変動します)
リニア振動アクチュエータ LD14−002: パーツ一般 秋月電子通商-電子部品・ネット通販
この場合、5Vを与えていて3V定格で動かすならRATED_VOLTAGE=0x99、OD_CLAMP=0xFFでいいのかな?自信ないですが、ひとまず焼けはしなかったです。
結論
よくわかんないけど動いた。
AdafruitのライブラリにAuto calibrationを追加したので、ひっそり公開しておきます。
GitHub - acho702i/Adafruit_DRV2605_Library at AutoCalibration
bool Adafruit_DRV2605::autoCal(uint8_t ratedVoltage, uint8_t overdriveClamp, uint8_t driveTime)
git上のスケッチではデフォルト値を入れてあります。
DRIVE_TIME(0x1B)はデータシートによると周期の半分を入れれば良いらしい。
Optimum drive time (ms) ≈ 0.5 × LRA Period
というわけで、今回の振動モーターでは5Vを繋いだ前提で
autoCal(0x99,0xFF,0x03)
として、モーターを固定してから実行すればOK。