マイコン工作実験日記

Microcontroller を用いての工作、実験記録

BM20からのAVRCPイベントを調べる

2017-09-18 13:50:22 | WT32/BM20
BM20をシリアルでつなげる事によって得られる大きなメリットのひとつがAVRCPを使っての情報取得制御が可能となる事です。コマンドを送信する事で音楽プレーヤの再生開始(play), 休止(pause), 停止(stop)といった操作が行えますし、再生中のトラックの曲名やアルバム名を要求するコマンドを送信してやり、その応答としてそれらの情報を取得することができます。

特に何の操作もしなくても、AVRCPがつながると、次のようなイベントが上がってきました。

BM20から上がってくるイベントについては、SPK_Module_UARTCommandParameters.xlsというExcelファイルのそのフォーマットの説明があるのですが、どうも説明内容と実際に出力されるフォーマットが一致していないようです。もともと、フォーマット概要が記されているだけで、その内容の意味まで踏み込んだ説明があるわけでもないので、自分で調べるしかありません。AVRCPの仕様書を元に上記のパケットの意味を調べてみると、どうやらつぎのようになっているようです。
0F           Response: INTERIM
48           subunit_type: PANEL, subunit_id: 0
00           Opcode: Vendor Dependent
00 19 58     Company ID
31 00        PDU ID: Register Notification
00 02        Parameter Length = 2
01 02        EVENT_PLAYBACK_STATUS_CHANGED = PAUSED

マイコンソフトでは何もAVRCPのコマンドを投入していないのにもかかわらず、プレーヤの現在の状態を報告してくれているようです。最初の INTERIM応答というのは本来であれば、マイコン側から通知(Notification)の要求を出した際に、その暫定応答として帰ってくるべきパケットです。この動きからマイコン側から何もコマンドを出さずともBM20が自動的にプレーヤの状態変化通知の要求を出してくれているであろうことが推察できます。

プレーヤ側で音楽の再生を開始してみると次のような2つのパケットが出てきました。

先に出てきたパケットでは最初のパケットの最初のバイトが 0x0F (INTERIM) から 0x0D (CHANED)に変化し、最後のバイトが 0x02 (PAUSED)から0x01(PLAY)に変化しており、状態変化が発生したことを通知する内容となっています。

後のパケットは最初のパケットと同じように最初のバイトが0x0F (INTERIM)になっているので、BM20が次の状態変化に備えての通知要求を自動的に発行してくれた結果を示す応答であろうことがわかります。

このようにどうやらBM20は状態変化については自動的にAVRCP の通知要求を出してくれることがわかりました。しかし、そのほかの情報についてはマイコン側から明示的に通知要求を出してやる必要があります。そこで次のような内容のAVRCPパケットを組み立ててAVC_SPECIFIC_CMDとして送信してやる title コマンドを用意して、これを実行してみました。このコマンドパケットは、再生中の曲のタイトルとアーティスト名を要求するものです。
00                       dbindex = 0
20                       PDU ID: GetElementAttribute
00
00 11                    length = 17
00 00 00 00 00 00 00 00  Identifier: PLAYING
02                       AttributeCount = 2
00 00 00 01              Title of Media
00 00 00 02              Name of the artist



取得される情報が長くなるので、応答中の曲名とアーティスト名はデコードして表示するようにしています。

このようにAVRCPを使うことで、プレーヤの状態や再生中の曲に関する情報を取得することができますので、これらの情報をLEDやLCDを使って表示することも可能になります。

NUCLEO-L452RE

2017-09-10 20:03:57 | WT32/BM20
BM20を制御するためのボードを組み立てました。今回使用するのはBM20と一緒に購入しておいたNUCLEO-L452です。手持ちのNUCLEO-L476でも良かったのですが、Crystalress USBをためしてみたいというだけの理由で購入。



これまではジャンパでBM20基板をつなげていたのですが、EEPRM書き換えの時にはFTDIに常げ、プログラム動作の時にはSTM32にジャンパし直すという作業が面倒なので、基板を組むことにしました。STM32への接続がピンコネクタに刺すだけで済むので、かなり作業が楽になりました。コネクタの向きの都合上、BM20基板が裏向きになってしまいましたけど。

実際にBM20基板をつなげて動作を確認していたら、クロック源としてMSIを選択するとちゃんと動くのに、HSIを使うと送受信ができないというトラブルに遭遇。単純にクロック源の選択を変更するだけで動かなくなってしまうので、原因はクロックにあるとしか思えません。TIM15のタイマキャプチャを使ってLSEの周期を測定することでHSIの周波数を逆算してみると、16MHzで発振すべきところが13.8MHz程度になっていることが判明。コードを確認してもおかしなところは見つからないので、STM32 Forumでサーチしてみると「同じお悩み」が見つかりました。

CubeMXが吐いたコードが間違っているという良くあるバグなのですが、この問題のタチが悪いのはRMの解説の記述も間違っているという点です。マニュアルで説明されているHSIのキャリブレーションのディフォルト値がもともと間違った値なので、CubeMXが生成したコードを読んでも正しいコードのようにしか見えないのです。毎度のことですがCubeMX使って新しいプロジェクト起こすと、必ずバグに当たるんですよねー。

BM20の機能概要

2017-09-02 14:32:03 | WT32/BM20
今更ではありますが、データシートやアプリケーションノートに明記されていないことがありすぎるので、簡単に整理しておこうかと思います。これらの機能概要については、UI Toolの設定項目となっているので、実際にこれを使って設定を変更して動作を確認することで動作仕様を把握するということになります。なんか、 説明しなくても使えばわかるだろ!? と言われている感じ。

  • 基本的にハンズフリーのスピーカ用に設計されているデバイスである。HFP/HSP, A2DP/AVRCPに対応しているが、サポートするのはHF UnitならびにSink側だけ。AG (Audio Gateway)や Sound Source側の役割を果たすことはできない。
  • データシートににはPBAP v1.0対応と書かれているが、入手したデバイスではサポートされていなかった。どうすればPBAP対応したデバイスが入手できるのかは不明。また、PBAP対応のデバイスでは、HSPがサポートされないように思われる。
  • 初期設定ではSPPはイネーブルされていない。SPPデータの送受のためにはマイコンでの制御が必要。
  • 全てのプロファイルをイネーブルすると、BM20からのSPPデータ送信が動かないように思われる。さらに調査必要。
  • 8台までのペアリング相手を記憶できる。設定により、台数制限可能。
  • ディフォルトではイネーブルされていないが、マルチポイントをサポートできる。同時に2つのHFならびにA2DP/AVRCP接続を保持することができるようである。UARTコマンドでも2つのリンクのどちらを使うかを指定するパラメータが用意されている。
  • 起動時に最後に接続したデバイスに対して自動的に再接続することが可能。ペアリング情報を参照して、接続したことのあるデバイスに順次再接続を試みることもできる。
  • UARTコマンド上では、iAPにも対応できるようになっているが、詳しい使い方は不明。ライセンスがないと、情報開示もできないと思われる。


EMPETの使い方が間違っていた

2017-08-31 09:58:22 | WT32/BM20
BM20を使っていると次のように動作が不安定な点がありました。
  • ペアリング状態においてしばらくするとハングすることがある。
  • ペアリングしたはずなのに、電源を入れ直すと、再度ペアリングを要求されてしまう。

ずっと原因がわからずにいたのですが、Microchipのフォーラムで問題解決法を見つけました。MPETツールの使い方がまずかったようです。もともと、アプリケーションノートの説明の通りに操作していたのですが、ノートの説明が不十分だったためハマってしましました。

注意すべきはファイルをマージするステップです。ディフォルトのBINファイルを開くと3つのファイルが入っていることがわかりますが、これまではこれらのファイルを引き継がずに、新たにDSPファイルとUIファイルを指定していました。



しかし、"BM20_203_A2N_Except_GE.txt" というファイルを引き継ぐ必要があるようです。このファイルを選択して、青いマージボタンを押します。DSPファイルも何も変更しないので、引き継ぐことにしました。



UIファイルはUI Toolで設定変更したものに入れ替えたいので、緑のAddボタンを押してファイルを追加してやります。

上記の手順で"BM20_203_A2N_Except_GE.txt" というファイルを引き継いだ ipf ファイルを作成して、EEPROMに書き込んでやります。これで問題が解決できるハズだったのですが、なぜか電源投入後しばらくしてシャットダウンしてしまうという問題が発生するようになってしまいました。試行錯誤した結果、電源の供給の仕方を変更すると調子よく動いてくれることが判明。
変更前 :  BAT_IN = 3.3V, ADP_IN = オープン
変更後 :  BAT_IN = オープン,  ADP_IN = 3.3V

"BM20_203_A2N_Except_GE.txt" による設定の影響があると思われるのですが、そもそもこのファイルがどのような設定を施しているかが全く不明。このような電源の与え方が正しいのかどうかもわかりませんが、今のところこれがわたしの Best Practice です。

Versionを確認してみる

2017-08-26 21:55:50 | WT32/BM20
BM20ではマイコン側からコマンドを送り、モジュール側からは動作に応じてイベント情報が送られてくるという動作をします。基本的な動作としてはWT32と似ていますが、WT32が単純なASCII文字列の形式で通信できたのに対し、BM20ではバイナリパケットの形式で通信しなければなりません。そのため、人間が直接対話的に操作するということはできず、マイコンを使って制御してやる必要があります。前回記事のUART動作確認ではBM20から出力されるデータを収集して、それをマニュアルでデコードしていましたが、やはり少しずつでもコードを書いてデコード作業もマイコンにやらせる必要があります。

というわけで、BM20をSTM32につなげてデコード開始。イベントを受信したらそれに対するACKも返すことにしました。これまでは MFB端子は電源制御に使っていましたが、今後は送信制御に使いたいので 電源スイッチ設定をMFBスイッチからDirectlyに変更しました。



どうやら、この変更で全てのスイッチが使えなくなるらしい。当然、電源オフもスイッチ操作ではできなくなるので、電源オフするコマンドを投げるか、電源を強制的に落とすかしないといけないようです。

また、Power ONならびにStandbyへの状態遷移イベントを検出したならば、BM20のバージョン情報を取得するコマンドを投げるようにしてみました。次のログは受信したイベントと、それに対応する EVENT_ACKの送信の様子を示しています。



この結果から、モジュールがサポートするUART command set のバージョンはv146, モジュールのファームのバージョンはv305であることがわかります。Excelで提供されているUART commandのパラメータ一覧を見ると、Command Set最新バージョンはv147のようなんですが、 v147との違いがわかりません。また各バージョンには SPPAU, 5502_MCU_mode, 5502_Embedded_modeの3種類があることになっているのですが、それぞれがどのような意味なのかという説明が一切ありません。サポートするコマンドに違いがあるので、どうやら自分のBM20で使えるのは SPPAUのバージョンであろうかと思われます。SPPAUというのは SPP & Audioという意味なのかなぁ?

マイコンとの接続に用いる TXD, RXD, P00, MFBの各信号も示しておきます。


まずは全体の様子です。最初にMFB信号を400ms オンにしてやることで電源が入り、動作を開始します。起動後、Power ONと Standbyの2つの状態遷移イベントを受信し、その後 800msほど経過してから Ringtone finish indicationを受信しています。

最初のイベントデータ受信以降の部分を拡大すると...



最初のデータ送信に先立ちMFB信号を変化させていますが、これはマイコン側から(スリープしているかもしれない)BM20を Wakeupさせるための手順です。BM20からのイベントデータを受信したばかりなので、実際にはBM20はスリープしておらずWakeup手順は (この場合には)不要なようです。BM20がスリープしているかどうかを判別できればいいのですが、その方法の説明がありません。P00がLowの間はモジュールは起きているのではないかと想像しているのですが、それを裏付ける説明もありません。MFBはマイコン側が送信している間はHighにしておけということになっており、しかも最低150msはHighにする必要があるようです。

UARTプロトコルに関しては、Excelのパラメータ一覧資料と、いくつかの基本フローを図示したUART Command SOPという資料があるだけのようです。とにかく文章での真っ当な説明が無いので、細かい部分は実際に使ってみないとわからない感じ。さすがは中華デバイスですが、謎解き気分が味わえるので、それも趣味でいじくる楽しみのひとつと言えるでしょう。

BM20のUART出力を確認する

2017-08-23 22:56:21 | WT32/BM20
これまでの動作確認は全てBM20を単独で動かしていました。次のステップとしてBM20をマイコンとつないで使っていくことにしますが、まずは基本的なUARTポートの動きを簡単に確認しておきます。

最初にUIツールを使ってUARTポートを有効にします。



UART Commandを有効にすると"RX_INDも有効にした方が良い"と言われます。RX_INDはMFBボタンと機能が重なっていますので、Btn0のチェックを外しておきます。



MFBは電源ボタン機能も兼ねていますが、ここの設定については特に何も文句を言われなかったので、そのままにしておくことにします。

UART Commandが有効になったことで、"Part Setting"のメニューも有効になっています。



上記の設定でEEPROMへ書き込みを行い、電源を入れなおします。MFBボタンでの電源オン/オフはまだ有効なままですが、電源投入後にTXD端子からデータが送信されていることが確認できました。P00端子はTXDからのデータ送信に先だってLowレベルに変化し、BM20側からマイコンをWakeupするのに使えるようになっています。




P00がLowになってから1.8秒ほどの間に3つのパケットが送信されていることがわかります。
最初のパケットの部分をズームしてデータを読み取ってみると...


BM20から送信されるイベントのパケットの形式になっています。ダウンロードした資料では、パケットの最初のバイトは 0xAAと書いてあるのですが、実際の動作では0x00, 0xAAの2バイトを送信してくるようです。内容をデコードしてみると、「電源オン」状態に遷移したことを示すイベントのようです。


本当はイベントパケットを受け取ったら、ACKパケットを返さねばならないのですが、まだBM20のRXDには何も送っていません。おそらくBM20はタイムアウト待ちをしてからふたつ目のパケットを送信してきているのだと思われます。2つ目のパケットは、ブートが完了して「スタンバイ状態」に遷移したことを示すイベントのようです。


3つ目のイベントはリングトーンの生成を止めたことを示すイベントになっています。



P00とTXDの関係を見ると、P00がLowになってから10msほどしてからデータが送信されていることがわかります。この時間はUI Toolで設定したWakeup Delay Timeの値が反映されているようです。10msも待つ必要はないので、このディレイの値を最小値である1に変更してみました。



0.3msにはなりませんでしたが、0.8ms程度までは縮まりました。実際にWAKEUPに使うには十分な長さですので、この設定を使うことにします。

BM20実験基板 -- その2

2017-08-18 22:08:01 | WT32/BM20
この1週間ほど、BM20実験基板を使ってBM20の機能を確認する作業を続けてきました。基板を作成した際に想定した機能項目に関してはほぼ確認できたので、ここで今回作成したボードの回路図を参考のために示しておくことにします。




  • 通常動作とEEPROM設定変更時とでは、DIPの設定を変更する必要があります。実際のところEANとP2_4の2つの端子はHighレベルにしておき、変更することはありません。これらの端子は内部プルアップされているので、オープンのままでも良かったと思います。
  • LED1とLED2には電流制限抵抗は不要です。これらのLEDの明るさはUI Toolで設定変更可能です。
  • ブザー機能はBM20の出荷時設定では無効になっています。EEPROM設定で有効にできますが、生成される音は単調ですので、スピーカから流すトーンを使った方が良いと思います。
  • ディフォルト設定では、ADP_INから5Vを供給し、BAT_INには電池をつなぐことを想定しています。電池をつながずに5Vを加えるとLED2がしばらく点灯しますが、充電中表示をしているのではないかと思われます。
  • ディフォルト設定では電源オン/オフにはMFBスイッチの長押しが必要です。オンのためには2.4秒、オフのためには3.2秒ボタンを押し続ける必要があります。かなり長いです。これらの時間設定はUI Toolを使って変更可能です。
  • HFP接続時には、MFBスイッチは着信応答、切断、リダイヤルボタンとしても機能します。


今回Eleclowで作成した基板は7枚届きましたが、1枚を予備に残すことにしても残りの5枚は使うことも無さそうなので、ご希望の方がいらっしゃればお分けします。こちらの売店より購入をお願いします。





お分けするのは基板のみです。部品はご自分で調達願います。

  • BM20はDigikeyから購入しましたが、Microchip Directからも購入できるようです。
  • マイクにはWM-61A相当、リードピン付きを使いました。
  • 3.5mmオーディオジャックとタクトスイッチには手持ちの表面実装用のものを使いました。相当品はスイッチサイエンスのようなSpark Fun製品取扱店やRSオンラインのような部品販売サイトで見つかると思います。
  • ブザーには秋月で販売されている圧電サウンダを使いました。
  • EEPROM設定変更のためには、USBシリアル変換器を用いてPCと接続する必要があります。この部分の回路は基板上には含まれていませんので、別途用意してください。

BM20には、BM20SPKA1NBC-0001AAとBM20SPKS1NBC-0001AAの2種類の品番の製品があります。値段はBM20SPKAの方が安いのですが、電波法の認証を受けている型番はBM20SPKS1NBCとなっているので、わたしはこちらを買いました。

EEPROM設定を変更してみる -- その4 (BuzzerとPMU)

2017-08-17 21:16:18 | WT32/BM20


BM20では動作時にスピーカだけではなく、ブザーを鳴らすこともできるようになっています。今回作成した実験用ボードでは、ブーザとして秋月の圧電スピーカをつなげられるようにパターンを用意しておいたので、これを追加実装しました。タクトスイッチも追加実装したかったのですが、やはり手持ちを切らしてしまったようです。何かのついでに注文するまでしばらく無しのままになりそうです。

ブーザの機能はBM20のディフォルト設定ではイネーブルされていないので、UI Toolで設定を変更する必要があります。



Function EnableのところでBuzzerにチェックを入れておきます。ブーザを接続できる端子にはP0_3またはP1_5の2つがありますが、ディフォルト設定ではP0_3はボタンに割り当てられているので、今回のボードではP1_5をブザーに使うことを想定してパターンを用意してあります。



こちらはブザー関連の設定画面です。Output TypeではPulseとPWMの2種類を選択できます。Pulseは信号がアクティブになっている間鳴り続けるタイプのブーザで、圧電スピーカのように発振器を必要とする場合にはPWMを指定してやります。発振させる周波数はPWM周波数として指定できますが、結果として出てくる音は、on/offパターンは選択できるものの、周波数は単一なので音として面白くありません。スピーカからはマルチトーンで出せるので、ブーザを使うより、スピーカ鳴らした方がいいですね。

BM20のディフォルト設定では充電機能が有効になっており、電圧監視機能も有効になっています。今回の実験では電池はつないでいないので、これらの機能を無効にしておくことにしました。



これまでの動作確認実験では、すべてADP_IN端子にUSB 5Vを加えていました。BAT_IN端子からの電源の供給も可能なのですが、ディフォルトではリポ電池をつないで使用することを想定して充電と電圧監視機能が有効になっています。そのため、BAT_INに3.3Vを加えたとしても電圧監視機能が働いて電圧が低すぎると判断されて、自動的に電源がオフにされてしまうのです。

充電と電圧監視を無効にすることで、BAT_IN端子に3.3Vを加えて動作させることができました。この場合、ADP_INはオープンで構いません。

EEPROM設定を変更してみる -- その3 (音声プロンプトの追加)

2017-08-16 12:53:23 | WT32/BM20
前回の記事ではBM20で音声ガイドが出せることを確認しました。BM20では4ヶ国語の音声パターンがあらかじめ用意されていますが、日本語は含まれていません。しかしながら、UI Toolを使って音声プロンプトの追加登録が可能になっているので、これを試してみました。

追加する音声はサンプリング周波数8000Hzのモノクロ16bit PCMで用意しておき、これをwavファイルのコンテナに入れておきます。わたしは、「電源オン!!」と吹き込んだおよそ1.55秒のファイルをAudacityを使って作成しました。UI Toolのマニュアルによれば、音声の長さは3秒までで、電源オンの通知だけは4.5秒まで許容されるようです。

UI Toolを立ち上げて、用意したファイルをVoice Prompt Toneとして追加登録してやります。



ファイルを追加するとCurrent EEPROM Sizeの値が増えます。もともとは4096 だったのが5460に増えているので、1360バイト増えていますが、16bit PCM形式のままだと24KBは必要になるはずなので、何らかの圧縮を行なって保存するようです。複数の音声を追加しようとすれば、それだけEEPROMの領域が必要になるので、そもそもBM20が持っているEEPROMの容量を知りたいところですが、データシートにはこの値が明記されていません。探し回ったところ、IS20xx_ApplicationNote.pdfに512Kbitであるという記述がありました。

上図の最後に示されているように、追加したファイルが各トーンの設定メニューで選択可能になるので、これを選択してやります。Multi-Toneの方も同様な手順で独自のトーンを追加できますが、こちらはMIDファイルを食わせてやるようです。

こうしてEEPROMを更新することで、電源オン時に自分で作成した音声が流れることを確認できました。

EEPROM設定を変更してみる -- その2

2017-08-15 12:11:16 | WT32/BM20
使用すべきツールセットの区別がついたので、ようやくとEEPROM設定変更作業を開始します。

まずはUI Toolから。パラメータは色々ありますが、今回はSPPプロファイルをイネーブルするだけの変更にしておきます。SPPではUARTを使うことになりますが、UART CommandのチェックはUART経由でコマンドを投入したりイベントを拾ったりする場合の指定だと思われるので、チェック無しにしておきます。



Nextを押して次の画面に進みます。



うーん、読みが外れてしまいました。UART機能がdisable状態で変えられません。どうやら、最初の画面でUART Commandをチェックしておかないと、この画面でUART機能がEnableにならないようです。実際のところ、どういう風に動くのかわからないので、このまま進むことにします。



Sys. Setup2の画面です。デバイス名称を変えておきます。



スクロールすると、AACとmSBCが無効になっていたので、どちらも有効にしておきました。データシートにはAACはオプションと書いてあったので別途ライセンス料が必要なのかと思いましたが、ここでチェックするだけでいいのかな?



こちらの画面では、Link SPP..の部分がDisableだったので、A2DP Profileにしておきました。A2DPのリンクがあると、SPP接続を許可するということなんでしょうか?

LEDやボタンの設定はディフォルトのままにしておきますが、それぞれボタンに対応するアクションの紐付けや、LED点滅パターンや明るさの設定が行えます。



最後にトーン設定を変更しておきました。音声ガイドは英語だけを有効にして、電源ON/OFF時にトーンではなく、音声を流すように設定変更しました。"VP"というのが Voice Promptの意味のようです。

続いてDSP Toolを起動。チップを選択するとロードされるディフォルトの設定をそのままセーブしておきます。



次にEMPETを起動。記録のために画面だけ貼っておきますが、説明は省略。








この画面の意味がわからないのですが、とりあえず何もチェックしないで進むことにしました。



ここまでで、.ipfファイルが生成されたので、EEPROM toolを起動して書き込みを行います。前の記事に書いたようにDIP SW設定を変更して、電源を入れ直しておきます。


ファイル名を入れてWriteボタンを押すと...



無事に書き込み完了。UARTとはHCI_TXとHCI_RXの2本しかつないでいませんが、問題なく書き込みできるようです。

一旦、電源を切って DIP SW設定を元に戻します。そして、電源を入れ直します。MFBボタンを押していると、「パワー オン」という音声ガイドがスピーカから流れ、無事に設定変更できたことが確認できました。ただし、音声を最後まで聞いている間、ボタンを押しっぱなしにしていりと、ペアリングモードに入ってしまうようです。音声が聞こえた時点でボタンを離しても大丈夫。

ペアリング状態でDPを確認してみると、次のレコードが追加されていました。

Service Name: Bluetooth Serial Port
Service RecHandle: 0x10007
Service Class ID List:
  "Serial Port" (0x1101)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 6
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
Profile Descriptor List:
  "Serial Port" (0x1101)
    Version: 0x0102


SPPを許可したことで、対応するSDPレコードをアナウンスするようになったわけです。実際にPCから接続を試みたところ、SPPの接続は確立できるのですが、データの送受信が行えませんでした。データ送受をするためには、UI Toolの設定において UART Commandを有効にしなければならないようです。