浮く球体ディスプレイを作った話

# 前置き
[eeic Advent Calendar 2017](https://qiita.com/advent-calendar/2017/eeic)の12/20の記事です。2017上半期に作っていたドローンの話をします。qiitaなのでプログラミングが関連するところに重点を置きます。
球体ディスプレイが「浮いた」話です。
# 作ったもの
浮く球体のディスプレイ

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">昔つくった飛ぶ回転ディスプレイ <a href="https://t.co/G9mTQw9ZqA">pic.twitter.com/G9mTQw9ZqA</a></p>&mdash; kentegrate (@kentegrate) <a href="https://twitter.com/kentegrate/status/943251486611456000?ref_src=twsrc%5Etfw">2017年12月19日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 構成の紹介
## 全体構成
![Untitled Diagram (1).png](https://qiita-image-store.s3.amazonaws.com/0/113446/a09d9170-712e-594c-27f0-0cf7900bb20b.png)

## ドローン本体
ハードウェアは[Raspberry Pi Zero](https://www.raspberrypi.org/products/raspberry-pi-zero/) と [PXFmini](https://erlerobotics.com/blog/product/pxfmini/) を使用して、ソフトウェアはAPMというオープンソースのドローンの制御ソフトウェアを使用しました。筐体は回転ディスプレイと接合がしやすいよう、3Dプリンタとアルミニウムを削ったフレームで自作しました。
## 回転ディスプレイ
### マイコン
ESP32を使用しました。その理由としては入手性がいい、大きさが小さい、なのに240MHzデュアルコアのCPUを搭載していたからです。
### モーター制御
#### 制御モデル
今回は電流を一定に保つPID制御を行いました。


回転ディスプレイが定常的に回転していると仮定して、簡単のため重力は無視すると（本当は無視できません）、モーターに加えるべきトルクは摩擦力と一致します。

![latex_41f2ea0cfc91b3741e4f01b72c56c24e.png](https://qiita-image-store.s3.amazonaws.com/0/113446/4c8b3776-7fea-c86b-3577-8df9fdfa59bd.png)
（Iは慣性モーメント、fは摩擦力、τはトルク、αは角加速度で、角速度一定より、α = 0）

摩擦力が一定なのか、という話ですが回転速度は一定であるとすると、リングはどの位置にあっても空気から速度に比例した一定の摩擦を受けるため、回転ディスプレイ単体では一定です。しかし、ドローンのプロペラの風によってリングにおける気流もかなり乱れるため、かなり影響を受けることがわかりました。その気流の影響を考慮したモデルは残念ながら今回はやっていません。ここでは摩擦力が一定であると思って話を進めます。

以上の議論から、一定のトルクを与えれば回転ディスプレイは一定速度で回転をします。

一方でDCモーターにおけるトルクと電流は比例関係にあるため、電流を一定に保てばトルクも一定となるばずです。
従って、今回の仮定においては電流を一定に保つとディスプレイは一定速度で回転します。

![Untitled Diagram.png](https://qiita-image-store.s3.amazonaws.com/0/113446/e7b8c654-4f9c-a6a8-5466-b44666b7d2e7.png)

電流を制御するのにPID制御を使用しました。
[こちら](https://www.as-1.co.jp/academy/15/15-5.html)を参考に、回転の安定性を音と目で見ながらP, I, Dの順にチューニングしていきました。

#### 電流のセンシング
電流のセンシングはシャント抵抗で行います。シャント抵抗に流れる電流に応じてかかる電圧が変わるので、それをオペアンプで増幅してマイコン搭載のA/Dコンバータで電圧を読み取ります。
使用したチップは[Linear TechnologyのLT6106](http://www.linear.com/product/LT6106)です。データシートに書いてある回路をそのまま使えば動くのでとても楽です。
<img width="246" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/113446/51c39295-7279-f7c4-ef01-d1d95af4ed42.png">
図　LT6106 Typical Application [元PDF](http://cds.linear.com/docs/en/datasheet/6106fb.pdf)

### LED制御
現在回転ディスプレイがどの方向を向いているかの情報は、モーターに取り付けらていているロータリーエンコーダーから読み取ります。具体的には[こちら](https://www.pololu.com/product/3081)の製品を使いました。
こちらのロータリーエンコーダーは一回転あたり12段階の分解能があり、モーターの減速比は100:1なので、回転ディスプレイの1回転あたり1200段階センシングできるという計算です。

しかし、1回転あたり1200段階しか取れないと、LEDの信号を出すタイミングが限られてしまいます。そこでカルマンフィルタで回転ディスプレイの等角速度運動モデルを仮定して、より早い周期でアップデートをかけ、センサのデータがとれたときはその情報で更新をかけるようにしました。

ロータリーエンコーダーは回転の位置に応じて出すパルスを変えます。このパルスをESP32内蔵のパルスカウンターで受けて回転を数えています。

# ぶつかった壁
## ESP32のサンプルコードが少ない
ESP32はArduino IDEでもプログラミングできますが、そのためのライブラリは未実装なところも多く、実装されていない機能(パルスカウンタなど）を使いたかったため、ESP-IDFを使用しました。サンプルコードが全然なかったのですが、[このリポジトリ](https://github.com/espressif/esp-idf/tree/master/examples)は様々なコードがあり、大変参考になりました。
## 回転ディスプレイの回転数が出ない
上のほうで計算したときに必要だったトルクではモーターは300rpmという設計値は出せる予定だったのですが、回転ディスプレイの軸の回転摩擦が大きいこと、そしてドローンのプロペラによる気流の乱れで空気抵抗が大きくなり、100rpmほどしか出ませんでした。改善策としてはモーターをアップグレードすることです。
## このディスプレイのキラーアプリケーションがない
ある製品がインパクトを残すには「ユニークさ」「なぜ今やるのか」などが求められます。
例えば「ライブで使う」というアプリケーションがあると思います。そうすると「気球でよくない？」「墜落したらどうするの？」「回転ディスプレイの気球に対する優位性は？」となります。このドローンのディスプレイの強みは、「あらゆる方向から死角なく見える」「ダイナミックな運動ができる」「高精細な映像を映せる」ということですが、自分にはこのようなアプリケーションが思い浮かびませんでした。
# 最後に
今回作った回路やプログラムは公開するつもりでいたのですが、あまりきれいに整備できてないのでまだ公開していません。気になるところがあればTwitterで連絡等してください！
現在私は別のプロジェクトに身をささげていたり、この製品に対する将来性を感じなかったしたりしたので、このプロジェクトはdiscontinuedです。
プログラミング重視するといいながら触れている量が少ない気がするので、後日具体的なコードの解説を追加しようかと思います。
# 参考文献
[ESP-IDF README](https://github.com/espressif/esp-idf/blob/master/README.md)