
DRV2605はバイブモーターを制御するモジュールである。モジュールはちょっと高いが、バイブの強弱、100種類以上の振動パターン、モーターの各種制御機能が備わっている。
https://www.switch-science.com/catalog/2178/
筆者がこのモジュールに接続して使用しているモーターはAmazonの安価なタイプ。
uxcell マイクロモーター 振動モーター 電動機 ブラシレス DC 1.5V-3V 10mm x 2.7mm 携帯電話用 5個セット
I2C通信で制御し、AdafruitやSparkfun等が出しているライブラリを利用して制御する事が出来る。チップに100種類以上の振動パターン内蔵されており、パターンを指定して鳴らしたり、別の入力と連動させたりと言った使い方が出来る。
ところが、最初は調子良く動いていたが、急に動かなくなった。パターンを指定しても全く動かないか、ちょっと動いたりする程度。モーターかモジュールを壊してしまったかと思い、マイコンを変えたりモーターを交換してみたりしたが回復せず。
ライブラリやデータシートを色々調べてみた所、DRV2605は単にモーターを回すだけでなく、かなり高度な制御を行っている事が分かった。
http://www.tij.co.jp/jp/lit/ds/symlink/drv2605l.pdf
かなり複雑なので深い所までは把握できていないが、モーターの過負荷による温度超過や過電流による停止機能、モーターの種別や電流の制御方法を設定・保存、自動調整、電圧を監視する機能等がついている。
ステータスレジスタ0x00を読み取ると、温度超過や過電流により停止した場合ビット0や1にフラグが立つらしい。DRV2605Lの場合正常時0xE0の値が返る。ステータスレジスタの読み取りによりこのフラグはクリアされるらしい。
レジスタ0x16~0x1Aには各種設定が入っており、この値は電源断後も保持される。このため、この値を狂わせた場合単に再起動しても元には戻らない。
ステータスレジスタの読み取りや0x16~0x1Aのレジスタにデータシート記載のデフォルト値を設定した所、正常に動作する様になった。なにかのはずみでエラー状態になっていたか、設定値が狂ったのかもしれない。
下記はSparkfunのライブラリを使い、起動時シリアルに現在の状態とレジスタ値を出力後、出荷時の設定に値を上書きし、再度設定値を出力、その後プリセットの振動パターンを順番に出力するスケッチ。
//data sheet //http://www.tij.co.jp/jp/lit/ds/symlink/drv2605l.pdf?ts=1591282871686 #include <Sparkfun_DRV2605L.h> //SparkFun Haptic Motor Driver Library #include <Wire.h> //I2C library SFE_HMD_DRV2605L HMD; //Create haptic motor driver object //0x16 - 0x1a nonvolatile device settings see ref. page 20, page 30 9.5.7 //0x1A setting #define FD_ERM 0x00 #define FD_LRA 0x80 #define FD_FACT_1X 0x00 #define FD_FACT_2X 0x10 //default #define FD_FACT_3X 0x20 #define FD_FACT_4X 0x30 #define FD_FACT_6X 0x40 #define FD_FACT_8X 0x50 #define FD_FACT_16X 0x60 #define FD_FACT_DIS 0x70 #define FD_GAIN_LOW 0x00 #define FD_GAIN_MID 0x04 //default #define FD_GAIN_HIGH 0x08 #define FD_GAIN_MAX 0x0C #define FD_ERM_0 0x00 //0.255x #define FD_ERM_1 0x01 //0.7875x #define FD_ERM_2 0x02 //1.365x default #define FD_ERM_3 0x03 //3.0x bool statusok = false; char chbuff[128]; bool checkstatus() { //The Status Register (0x00): The Device ID is bits 7-5. For DRV2605L it should be 7 or 111. //bits 4 and 2 are reserved. Bit 3 is the diagnostic result. You want to see 0. //bit 1 is the over temp flag, you want this to be 0 //bit 0 is over current flag, you want this to be zero. // Ideally the register will read 0xE0. uint8_t status = HMD.readDRV2605L(STATUS_REG); Serial.print("Status Register 0x"); Serial.print(status, HEX); if (status == 0xE0) { Serial.println(" OK"); statusok = true; } else { Serial.println(" NG"); statusok = false; } sprintf(chbuff, " Device id:%d\n", (status >> 5) & 0x07); Serial.print(chbuff); sprintf(chbuff, " Diag result:%d\n", (status >> 3) & 0x01); Serial.print(chbuff); sprintf(chbuff, " Overtemp:%d\n", (status >> 1) & 0x01); Serial.print(chbuff); sprintf(chbuff, " Overccurent:%d\n", (status >> 0) & 0x01); Serial.print(chbuff); return statusok; } void resettodefault() { //bit 7 device reset Serial.println("Device reset"); HMD.writeDRV2605L(MODE_REG, 0x80); //set register to default (from data sheet) HMD.writeDRV2605L(0x16, 0x3e); HMD.writeDRV2605L(0x17, 0x8c); HMD.writeDRV2605L(0x18, 0x0c); HMD.writeDRV2605L(0x19, 0x6c); HMD.writeDRV2605L(0x1A, 0x36); } void showsetting() { sprintf(chbuff, "Reg 0x16 : %02X (Rated voltage DEF 0x3E)\n", HMD.readDRV2605L(0x16)); Serial.print(chbuff); sprintf(chbuff, "Reg 0x17 : %02X (od clamp DEF 0x8C)\n", HMD.readDRV2605L(0x17)); Serial.print(chbuff); sprintf(chbuff, "Reg 0x18 : %02X (Auto cal comp result DEF 0x0C)\n", HMD.readDRV2605L(0x18)); Serial.print(chbuff); sprintf(chbuff, "Reg 0x19 : %02X (Auto cal BEMF result DEF 0x6C)\n", HMD.readDRV2605L(0x19)); Serial.print(chbuff); byte reg = HMD.readDRV2605L(0x1A); sprintf(chbuff, "Reg 0x1A : %02X (Feedback Control DEF 0x36)\n", reg); Serial.print(chbuff); sprintf(chbuff, " ERM/LRA:%d DEF 0\n", (reg >> 7) & 0x01); Serial.print(chbuff); sprintf(chbuff, " Brake Factor:%d DEF 3\n", (reg >> 4) & 0x07); Serial.print(chbuff); sprintf(chbuff, " Loop Gain:%d DEF 1\n", (reg >> 2) & 0x03); Serial.print(chbuff); sprintf(chbuff, " BEMF Gain:%d DEF 2\n", (reg >> 0) & 0x03); Serial.print(chbuff); reg = HMD.readDRV2605L(0x1D); sprintf(chbuff, "Reg 0x1D : %02X (Control3 Register)\n", reg); Serial.print(chbuff); sprintf(chbuff, " Noise gate threshold:%d DEF 2\n", (reg >> 7) & 0x03); Serial.print(chbuff); sprintf(chbuff, " Open loop:%d DEF 1\n", (reg >> 5) & 0x01); Serial.print(chbuff); sprintf(chbuff, " Supply compensation:%d DEF 0\n", (reg >> 4) & 0x01); Serial.print(chbuff); sprintf(chbuff, " Data format:%d DEF 0\n", (reg >> 3) & 0x01); Serial.print(chbuff); } void setup() { Wire.begin(); delay(1000); Serial.println("\n-------------"); checkstatus(); showsetting(); if (!statusok) { Serial.println("Invalid status!"); delay(5000); } Serial.println("-------------"); resettodefault(); checkstatus(); showsetting(); HMD.Mode(0); // Internal trigger input mode -- Must use the GO() function to trigger playback. HMD.Library(1); //1-5 & 7 for ERM motors, 6 for LRA motors */ } void goWait() { //wait until pattern is done while (HMD.readDRV2605L(0x0C) & 0x01) { yield(); // needed for RTOS based ESP8266/ESP32, etc. } } int wave; unsigned long lastvib = 0; void loop() { if (millis() - lastvib >= 1500 && statusok) { runeffect(wave + 1); wave = (wave + 1) % 122; lastvib = millis(); } } void runeffect(int effect) { if (effect == 1) Serial.println(F("1 - Strong Click - 100%")); else if (effect == 2) Serial.println(F("2 - Strong Click - 60%")); else if (effect == 3) Serial.println(F("3 - Strong Click - 30%")); else if (effect == 4) Serial.println(F("4 - Sharp Click - 100%")); else if (effect == 5) Serial.println(F("5 - Sharp Click - 60%")); else if (effect == 6) Serial.println(F("6 - Sharp Click - 30%")); else if (effect == 7) Serial.println(F("7 - Soft Bump - 100%")); else if (effect == 8) Serial.println(F("8 - Soft Bump - 60%")); else if (effect == 9) Serial.println(F("9 - Soft Bump - 30%")); else if (effect == 10) Serial.println(F("10 - Double Click - 100%")); else if (effect == 11) Serial.println(F("11 - Double Click - 60%")); else if (effect == 12) Serial.println(F("12 - Triple Click - 100%")); else if (effect == 13) Serial.println(F("13 - Soft Fuzz - 60%")); else if (effect == 14) Serial.println(F("14 - Strong Buzz - 100%")); else if (effect == 15) Serial.println(F("15 - 750 ms Alert 100%")); else if (effect == 16) Serial.println(F("16 - 1000 ms Alert 100%")); else if (effect == 17) Serial.println(F("17 - Strong Click 1 - 100%")); else if (effect == 18) Serial.println(F("18 - Strong Click 2 - 80%")); else if (effect == 19) Serial.println(F("19 - Strong Click 3 - 60%")); else if (effect == 20) Serial.println(F("20 - Strong Click 4 - 30%")); else if (effect == 21) Serial.println(F("21 - Medium Click 1 - 100%")); else if (effect == 22) Serial.println(F("22 - Medium Click 2 - 80%")); else if (effect == 23) Serial.println(F("23 - Medium Click 3 - 60%")); else if (effect == 24) Serial.println(F("24 - Sharp Tick 1 - 100%")); else if (effect == 25) Serial.println(F("25 - Sharp Tick 2 - 80%")); else if (effect == 26) Serial.println(F("26 - Sharp Tick 3 - 60%")); else if (effect == 27) Serial.println(F("27 - Short Double Click Strong 1 - 100%")); else if (effect == 28) Serial.println(F("28 - Short Double Click Strong 2 - 80%")); else if (effect == 29) Serial.println(F("29 - Short Double Click Strong 3 - 60%")); else if (effect == 30) Serial.println(F("30 - Short Double Click Strong 4 - 30%")); else if (effect == 31) Serial.println(F("31 - Short Double Click Medium 1 - 100%")); else if (effect == 32) Serial.println(F("32 - Short Double Click Medium 2 - 80%")); else if (effect == 33) Serial.println(F("33 - Short Double Click Medium 3 - 60%")); else if (effect == 34) Serial.println(F("34 - Short Double Sharp Tick 1 - 100%")); else if (effect == 35) Serial.println(F("35 - Short Double Sharp Tick 2 - 80%")); else if (effect == 36) Serial.println(F("36 - Short Double Sharp Tick 3 - 60%")); else if (effect == 37) Serial.println(F("37 - Long Double Sharp Click Strong 1 - 100%")); else if (effect == 38) Serial.println(F("38 - Long Double Sharp Click Strong 2 - 80%")); else if (effect == 39) Serial.println(F("39 - Long Double Sharp Click Strong 3 - 60%")); else if (effect == 40) Serial.println(F("40 - Long Double Sharp Click Strong 4 - 30%")); else if (effect == 41) Serial.println(F("41 - Long Double Sharp Click Medium 1 - 100%")); else if (effect == 42) Serial.println(F("42 - Long Double Sharp Click Medium 2 - 80%")); else if (effect == 43) Serial.println(F("43 - Long Double Sharp Click Medium 3 - 60%")); else if (effect == 44) Serial.println(F("44 - Long Double Sharp Tick 1 - 100%")); else if (effect == 45) Serial.println(F("45 - Long Double Sharp Tick 2 - 80%")); else if (effect == 46) Serial.println(F("46 - Long Double Sharp Tick 3 - 60%")); else if (effect == 47) Serial.println(F("47 - Buzz 1 - 100%")); else if (effect == 48) Serial.println(F("48 - Buzz 2 - 80%")); else if (effect == 49) Serial.println(F("49 - Buzz 3 - 60%")); else if (effect == 50) Serial.println(F("50 - Buzz 4 - 40%")); else if (effect == 51) Serial.println(F("51 - Buzz 5 - 20%")); else if (effect == 52) Serial.println(F("52 - Pulsing Strong 1 - 100%")); else if (effect == 53) Serial.println(F("53 - Pulsing Strong 2 - 60%")); else if (effect == 54) Serial.println(F("54 - Pulsing Medium 1 - 100%")); else if (effect == 55) Serial.println(F("55 - Pulsing Medium 2 - 60%")); else if (effect == 56) Serial.println(F("56 - Pulsing Sharp 1 - 100%")); else if (effect == 57) Serial.println(F("57 - Pulsing Sharp 2 - 60%")); else if (effect == 58) Serial.println(F("58 - Transition Click 1 - 100%")); else if (effect == 59) Serial.println(F("59 - Transition Click 2 - 80%")); else if (effect == 60) Serial.println(F("60 - Transition Click 3 - 60%")); else if (effect == 61) Serial.println(F("61 - Transition Click 4 - 40%")); else if (effect == 62) Serial.println(F("62 - Transition Click 5 - 20%")); else if (effect == 63) Serial.println(F("63 - Transition Click 6 - 10%")); else if (effect == 64) Serial.println(F("64 - Transition Hum 1 - 100%")); else if (effect == 65) Serial.println(F("65 - Transition Hum 2 - 80%")); else if (effect == 66) Serial.println(F("66 - Transition Hum 3 - 60%")); else if (effect == 67) Serial.println(F("67 - Transition Hum 4 - 40%")); else if (effect == 68) Serial.println(F("68 - Transition Hum 5 - 20%")); else if (effect == 69) Serial.println(F("69 - Transition Hum 6 - 10%")); else if (effect == 70) Serial.println(F("70 - Transition Ramp Down Long Smooth 1 - 100 to 0%")); else if (effect == 71) Serial.println(F("71 - Transition Ramp Down Long Smooth 2 - 100 to 0%")); else if (effect == 72) Serial.println(F("72 - Transition Ramp Down Medium Smooth 1 - 100 to 0%")); else if (effect == 73) Serial.println(F("73 - Transition Ramp Down Medium Smooth 2 - 100 to 0%")); else if (effect == 74) Serial.println(F("74 - Transition Ramp Down Short Smooth 1 - 100 to 0%")); else if (effect == 75) Serial.println(F("75 - Transition Ramp Down Short Smooth 2 - 100 to 0%")); else if (effect == 76) Serial.println(F("76 - Transition Ramp Down Long Sharp 1 - 100 to 0%")); else if (effect == 77) Serial.println(F("77 - Transition Ramp Down Long Sharp 2 - 100 to 0%")); else if (effect == 78) Serial.println(F("78 - Transition Ramp Down Medium Sharp 1 - 100 to 0%")); else if (effect == 79) Serial.println(F("79 - Transition Ramp Down Medium Sharp 2 - 100 to 0%")); else if (effect == 80) Serial.println(F("80 - Transition Ramp Down Short Sharp 1 - 100 to 0%")); else if (effect == 81) Serial.println(F("81 - Transition Ramp Down Short Sharp 2 - 100 to 0%")); else if (effect == 82) Serial.println(F("82 - Transition Ramp Up Long Smooth 1 - 0 to 100%")); else if (effect == 83) Serial.println(F("83 - Transition Ramp Up Long Smooth 2 - 0 to 100%")); else if (effect == 84) Serial.println(F("84 - Transition Ramp Up Medium Smooth 1 - 0 to 100%")); else if (effect == 85) Serial.println(F("85 - Transition Ramp Up Medium Smooth 2 - 0 to 100%")); else if (effect == 86) Serial.println(F("86 - Transition Ramp Up Short Smooth 1 - 0 to 100%")); else if (effect == 87) Serial.println(F("87 - Transition Ramp Up Short Smooth 2 - 0 to 100%")); else if (effect == 88) Serial.println(F("88 - Transition Ramp Up Long Sharp 1 - 0 to 100%")); else if (effect == 89) Serial.println(F("89 - Transition Ramp Up Long Sharp 2 - 0 to 100%")); else if (effect == 90) Serial.println(F("90 - Transition Ramp Up Medium Sharp 1 - 0 to 100%")); else if (effect == 91) Serial.println(F("91 - Transition Ramp Up Medium Sharp 2 - 0 to 100%")); else if (effect == 92) Serial.println(F("92 - Transition Ramp Up Short Sharp 1 - 0 to 100%")); else if (effect == 93) Serial.println(F("93 - Transition Ramp Up Short Sharp 2 - 0 to 100%")); else if (effect == 94) Serial.println(F("94 - Transition Ramp Down Long Smooth 1 - 50 to 0%")); else if (effect == 95) Serial.println(F("95 - Transition Ramp Down Long Smooth 2 - 50 to 0%")); else if (effect == 96) Serial.println(F("96 - Transition Ramp Down Medium Smooth 1 - 50 to 0%")); else if (effect == 97) Serial.println(F("97 - Transition Ramp Down Medium Smooth 2 - 50 to 0%")); else if (effect == 98) Serial.println(F("98 - Transition Ramp Down Short Smooth 1 - 50 to 0%")); else if (effect == 99) Serial.println(F("99 - Transition Ramp Down Short Smooth 2 - 50 to 0%")); else if (effect == 100) Serial.println(F("100 - Transition Ramp Down Long Sharp 1 - 50 to 0%")); else if (effect == 101) Serial.println(F("101 - Transition Ramp Down Long Sharp 2 - 50 to 0%")); else if (effect == 102) Serial.println(F("102 - Transition Ramp Down Medium Sharp 1 - 50 to 0%")); else if (effect == 103) Serial.println(F("103 - Transition Ramp Down Medium Sharp 2 - 50 to 0%")); else if (effect == 104) Serial.println(F("104 - Transition Ramp Down Short Sharp 1 - 50 to 0%")); else if (effect == 105) Serial.println(F("105 - Transition Ramp Down Short Sharp 2 - 50 to 0%")); else if (effect == 106) Serial.println(F("106 - Transition Ramp Up Long Smooth 1 - 0 to 50%")); else if (effect == 107) Serial.println(F("107 - Transition Ramp Up Long Smooth 2 - 0 to 50%")); else if (effect == 108) Serial.println(F("108 - Transition Ramp Up Medium Smooth 1 - 0 to 50%")); else if (effect == 109) Serial.println(F("109 - Transition Ramp Up Medium Smooth 2 - 0 to 50%")); else if (effect == 110) Serial.println(F("110 - Transition Ramp Up Short Smooth 1 - 0 to 50%")); else if (effect == 111) Serial.println(F("111 - Transition Ramp Up Short Smooth 2 - 0 to 50%")); else if (effect == 112) Serial.println(F("112 - Transition Ramp Up Long Sharp 1 - 0 to 50%")); else if (effect == 113) Serial.println(F("113 - Transition Ramp Up Long Sharp 2 - 0 to 50%")); else if (effect == 114) Serial.println(F("114 - Transition Ramp Up Medium Sharp 1 - 0 to 50%")); else if (effect == 115) Serial.println(F("115 - Transition Ramp Up Medium Sharp 2 - 0 to 50%")); else if (effect == 116) Serial.println(F("116 - Transition Ramp Up Short Sharp 1 - 0 to 50%")); else if (effect == 117) Serial.println(F("117 - Transition Ramp Up Short Sharp 2 - 0 to 50%")); else if (effect == 118) Serial.println(F("118 - Long buzz for programmatic stopping - 100%")); else if (effect == 119) Serial.println(F("119 - Smooth Hum 1 (No kick or brake pulse) - 50%")); else if (effect == 120) Serial.println(F("120 - Smooth Hum 2 (No kick or brake pulse) - 40%")); else if (effect == 121) Serial.println(F("121 - Smooth Hum 3 (No kick or brake pulse) - 30%")); else if (effect == 122) Serial.println(F("122 - Smooth Hum 4 (No kick or brake pulse) - 20%")); else if (effect == 123) Serial.println(F("123 - Smooth Hum 5 (No kick or brake pulse) - 10%")); HMD.Waveform(0, wave + 1); HMD.Waveform(1, 0); HMD.go(); goWait(); }