2013年6月8日

BLHeli 回転数モニタへの道

電波の問題はともかくとして、Bluetoothなりなんなりでヘリから手元のPCへ情報を伝えることは簡単にできます。電波でなく有線であっても、とにかくヘリのいろんな情報をモニタできればセッティングや修理の際にとても役に立ちます。

温度や電圧は必要なら簡単にセンサーを付けるなりして知ることができますが、意外と困るのがローター回転数です。大型ヘリの高価な受信機やBESCにはモニタ機能があるのでモーター回転をモニタしてギア比で割ればわかりますが、我らがBLHeliファームウェアにはモニタ機能がありません。

ちょうど最近、XC90さんのブログでBLHeliのビルド方法を知ることができたので、モニタ出力ができるかトライしてみました。


将来のことを考えると、うまく動いたら自分だけではなくいろんな人に役立つ機能だと思います。そうすると、最大の困難はプログラム開発ではなく、出力端子のハンダ付けでしょう。
したがって、CPUそのものはシリアル通信機能を持っているのですが、自由にピンアサインができないので使わないことにしました。
取出しがもっとも簡単なのは、BLHeli利用者ならプログラム書き込みとセッティング用に既に外に出ているはずのC2インターフェイスです。

実はBLHeliBoxのメモリリードライト機能でちょいちょいとモニタができないかと考えたのですが、このC2インターフェイスはCPUをhaltしないと通信できないので、動作中の情報取出しには使えないと4712さんが教えてくれました。確かにCPUマニュアルを見たらはっきりそう書いてありました。

しかし、データ線のC2Dピンだけは、動作中にGPIOとして出力ができます。実際にソースを見ると、デバッグのためにこれをON/OFFさせて使っているような形跡もあります。
つまり、ソフトウェアシリアル通信さえ作れば、BLHeliファーム内のRAMをいろいろ外から眺めることができるはずです。

インテルのアセンブラは初めてなのでけっこう苦労しましたが、なんとかBLHeliファームウェアに、3.3V UARTのシリアル出力を追加することができました。



以下、コードの説明です。

ベースにしたのは純正10.3のソースに、XC90さんの紹介してくれたASEM-51でビルドするためのプリプロセッサ表記修正を加えたもの、です。


完全に未使用のタイマーは無いので、負荷の軽そうな128us周期のTimer2割り込みからシリアル出力ルーチンを呼び出すことにしました。

普通に毎回ビット出力をすると、1sec/128us = 7812bps になりますが、こんなビットレートを設定できるPCは普通ないと思います。マイコンなら読めると思いますが。
やはりPCから見られないと利便性が落ちると思ったので、13回に一度だけ処理をすることにして、7812/13=600.9bpsの通信速度に決定しました。

文字の取りこぼしもあり得るでしょうから、1パケット=8バイトとして、先頭バイトに必ず'U'の文字を出力してPCソフト側で同期をとることにします。

現在は試しに、8バイトの内容として
  +0  アスキー文字 'U'         通信の 同期用
  +1  Requested_Pwm          送信機からのPWM指令を0-255段階のスロットル値に直したもの?
  +2  Governor_Req_Pwm  ガバナーの目標出力を送信機PWMと同じく0-255で表現したもの?
  +3  Gov_Integral_X            ガバナー積分エラー  最上位バイト
  +4  Gov_Integral_H            ガバナー積分エラー  Hバイト
  +5  Gov_Integral_L            ガバナー積分エラー  Lバイト
  +6  Gov_Proportional_H     ガバナー比例エラー   Hバイト
  +7  Gov_Proportional_L     ガバナー比例エラー   Lバイト
を出力させています。

イメージとしては、Requested_Pwmでスロットル信号がわかって、ガバナーの目標回転数がGovernor_Req_Pwmでわかる。するとそこからのずれが、積分エラーと比例エラーに反映されるはずなので何か魔法の計算をすれば現在の回転数がわかる…はず? と考えました。

まあ、結論から言うと単位がわからないのと、単純に上記のようなものを意味する変数ではないみたいなので現時点では何もわからないんですが…。
とにかくRAMの変数を見ることはできるようになったので、後は計算でどうにでもなると思います。
場合によってはESC内でモニタ用の値を作って保持しても良いですしね。



動作風景
3.3VのUART出力なので、PC接続にはFTDIのTTL-232R-3V3を使いました。
http://www.ftdichip.com/Products/Cables/USBTTLSerial.htm


もちろんSuperCPしか持ってないのでこれでテストしています。複数の改造を混ぜるとデバッグが困難なので、XC90さんのSuperCP用改造版ではなく純正10.3をベースにして、CRノイズフィルタを付けて動かしています。


PC側の画面
こんなの。テストアプリなのでスカスカです。
回転数がちゃんと取れたらグラフとか出してあげたいです。

まだどうやれば回転数を取り出せるかもわかっていませんが、それ以前にガバナーを理解して自分の機体で使えていないので、BLHeli内のRAMのうちどんな情報をどんな形式でモニタするか考えるのは自力では無理があると思います。まずHeliFreakで聞いて反応を見てみようと思います。

最終的には、こういった機能は単独アプリではなくBLHeliSetupに内蔵されるほうが便利でしょうしね。


3 件のコメント:

  1. こんばんはXC90です。
    プログにコメント頂いたときにどこかで見覚えがある名前だなとおもったら、ブラシレス化するときにいろいろ情報収集させて頂いた Sachiho さんだったんですね。
    オシロスコープの波形本当に助かりました。

    かれこれBLHELIのコード1か月ほど解析しているので協力させてください。
    現在のロータの回転数ですが、Comm_Period4x_H,Lから計算できますよ。
    確か、
     周期(us)   : Comm_Period4x / 2 * 3
     モータ回転数: 1 /( 周期 * (極数 / 2) )
     ロータ回転数: モータ回転数 / (64/ピニオンギア数)

    返信削除
  2. おおー、コメントありがとうございます!
    XC90さんの紹介が無ければBLHeliコードに手を出そうとは全く考えもしませんでした。
    ちょうどsskaug様から似たようなコメントをいただいて試しているところでした。
    とてもいい感じに取れるのですが、ファクター2倍くらい予想と合わなくて悩んでいます。

    SuperCPで動かして見ると、Comm_Period4xが900くらいになるんですが、これを500ns*/2*3して逆数をとると、モーター回転数が1666回転/sてことになります。んでこれを60倍すると、99900rpm、となって、11000kv, 6poleモーターの4V動作としては倍くらい速過ぎですよねぇ…。

    どうも500nsあたりか極数/2だかの理解ができていない気がします。。

    返信削除
  3. 勉強しなおしてきました! XC90先生のおっしゃるとおりですね!

     周期=Comm_Period4xの1.5倍*500ns

    てのは、electric rotationの逆数ですから、電気的な周期ってことなんですね。
    そして、脳がうにうにしてますが、コイルのスロット数に関係なく、

     electric freq * 2 / poles

    がメカニカルな回転数になる、という意味だったのですね!
    これだとComm_Period4x = 900 は 33000rpmくらいになって、11000kvモーターの8割程度の能力で回ってる、てことなのでとても納得です。

    返信削除