自由課題

学んだり、考えたり、試したりしたこと。

Jetson NanoでFPVラジコンを作る(6)

前回はJetson Nano単体でラジコンを制御するのに失敗したので、今回は PCA9685というモータードライバーのチップを使用して制御を試みる。
実績はたくさんあるので、できないということはないはずだ。

前回記事
Jetson NanoでFPVラジコンを作る(1) - 自由課題
Jetson NanoでFPVラジコンを作る(2) - 自由課題
Jetson NanoでFPVラジコンを作る(3) - 自由課題
Jetson NanoでFPVラジコンを作る(4) - 自由課題
Jetson Nanoを使ってFPVラジコンを作る(5) - 自由課題

今回使用したのは以下のボードだが、ほとんど同じ(に見える)ものがたくさん売っており正直どれにすれば良いかわからない。

PCA9685はI2Cというシリアル通信プロトコルで接続して制御する。I2Cについては、例えばここの説明がわかりやすかった。

自分の理解によると、I2Cホスト*1(今回でいうJetson Nano)には複数のI2Cデバイス*2(今回でいうPCA9685)が接続でき、各I2Cデバイスは固有のデバイスアドレス*3を持っている。また、各I2Cデバイスは8bitのアドレス空間からなるレジスタ群を持ち、各レジスタは8bitの値を保持する。
従って、あるI2Cデバイスを制御したり現在の状態を確認したりするときは以下の情報を指定すればよい。

PCA9685のデータシートはここにある。以下の解説もわかりやすい。

zattouka.net

まずは仮配線をして動作確認をする。JetsonとPCA9685間はVcc(5V)・GND・SDA・SCLの4本を配線する。
なお、Jetson側のピン配置は以下サイトを参照した。

www.jetsonhacks.com

特にミスもなく配線でき、PCA9685の電源ランプが点灯した。PCA9685のch0にステアリングサーボ、ch1にESCの配線を接続する。

f:id:kimito_k:20210328065439j:plain

Jetson Nano上でPCA9685が認識できているか確認する。

$ i2cdetect -y -r 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: 70 -- -- -- -- -- -- -- 

データシートによると、PCA9685はI2Cデバイスアドレスが0x40がデフォルトであり、0x70は複数のPCA9685が接続されている場合のブロードキャストアドレスらしい。いずれにせよホスト側できちんと認識できている。

次にデバイスレジスタをダンプして確認してみる。

$ i2cdump -y 1 0x40
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 11 04 e2 e4 e8 e0 00 00 00 10 00 00 00 10 00 00    ??????...?...?..
10: 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00    .?...?...?...?..
20: 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00    .?...?...?...?..
30: 00 10 00 00 00 10 00 00 00 10 00 00 00 10 00 00    .?...?...?...?..
40: 00 10 00 00 00 10 XX XX XX XX XX XX XX XX XX XX    .?...?XXXXXXXXXX
50: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
70: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
80: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
90: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
a0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
b0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
c0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
d0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
e0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
f0: XX XX XX XX XX XX XX XX XX XX 00 00 00 00 1e 00    XXXXXXXXXX....?.

上で挙げたPCA9685のデータシートを見るとレジスタアドレス0x00と0x01のレジスタ値はそれぞれ0x11と0x04らしいので、きちんと読めているようだ。

いよいよ実際にラジコンの制御をしてみる。
最初にPWMの周波数を設定する。詳細は割愛するが、発振器の周波数*4とPWM信号の周波数*5から計算し、レジスタアドレス0xFEに指定する。

i2cset -y -r 1 0x40 0xFE 0x6a

次にPWMのパルスの設定をする。PCA9685ではパルスの立ち上がりのタイミングと立ち下がりのタイミングをそれぞれ指定できるようだが、今回はパルス幅しか関係がないので立ち下がりのタイミングのみを指定する。まずはごにょごにょ計算してレジスタ値を決め、ch0(ステアリングサーボ)をニュートラルのパルス幅(1.5msの場合レジスタ値は0x0162となる)に設定する。
ステアリングサーボに対応するch0のレジスタアドレスの0x08と0x09にレジスタ値を設定する。

i2cset -y -r 1 0x40 0x08 0x62
i2cset -y -r 1 0x40 0x09 0x01

ch1の駆動モーターもニュートラルのパルス幅は同じなので、レジスタアドレスが異なるが*6レジスタ値(コマンドの最後の引数)は同じである。

i2cset -y -r 1 0x40 0x0c 0x62
i2cset -y -r 1 0x40 0x0d 0x01

これでPWMの設定が終わったので、発振器をONにして信号を発信させる。

i2cset -y -r 1 0x40 0x00 0x01

オシロスコープを持っていないので確認することはできないが、これでPCA9685からPWM信号が出ているはずだ。
ラジコンの電源を投入すると、モーターにトルクが入り車体が少しぶるっと震える。ESCがPWM信号を受信できていなければ警告のアラーム音がなる仕様なので、もしピーピーという音が聞こえなれば成功だ。

ステアリングサーボを回転させるにはこんな感じのコマンドを投入する。右いっぱいにステアリングを切るにはパルス幅を2ms*7に設定する。

i2cset -y -r 1 0x40 0x08 0xc1

左いっぱいに切る場合はパルス幅を1ms*8に設定する。

i2cset -y -r 1 0x40 0x08 0x04

全速後退と全速前進もレジスタの数値としては同様なので下記となる。ESCの仕様上、後退と前進を切り替える際は一旦ニュートラルに戻す必要があるはず。
後退も前進も問題なくタイヤが回転した。一安心。

i2cset -y -r 1 0x40 0x0c 0x1c
i2cset -y -r 1 0x40 0x0c 0x62
i2cset -y -r 1 0x40 0x0c 0x04

ちなみに全速にすると恐怖を感じるほどタイヤが高速回転する*9ので、まずはほどほどのアクセル開度で試すのがよさそう。また、動作テストの時は車体の下に小さめの箱か何かを噛ませてタイヤを空転させるようにしたほうがよいと思う。

無事動作確認ができたのでPCA9685を経由でシャーシに組み付ける。
今回はシャーシ中央に空いていたM3ネジ用の穴にスタンドオフを取り付け*10、そのスタンドオフに透明のプラバンを固定し、さらにそのプラバンに固定したM2のスタンドオフを用いてボードを固定した。

f:id:kimito_k:20210329082148j:plain

Jetson側はケーブルを束ねるために細い結束バンドを用いた。また、PCA9685への結線をしやすくするためにピンヘッダを5連のものに換装し、ケーブルを下に通すためベースボードを一部切り取った。

f:id:kimito_k:20210329082240j:plain

ベースボードを組み戻してJetson NanoとPCA9685を結線するとこのようになる。
最終的にシャーシ内にプラバンで作ったベースボードが上下二枚配置される形となった。このシャーシはレース用の物とは異なり、もともとシャーシ内の容積が大きいので便利だ。

f:id:kimito_k:20210329083410j:plain

実際に動作させたときの動画が以下。前回も書いたが、モノが実際に動くと感動する。

これでJetsonからラジコンの制御ができることが確認できた。
次回はラジコンの送信機(コントローラー)の代わりになる入力機器をJetsonと接続する。

(追記)次回 : Jetson Nanoを使ってFPVラジコンを作る(7) - 自由課題

*1:本当はI2Cマスタというらしいが、昨今いろいろ問題がある単語なのでホストと記載する

*2:本当はI2Cスレーブというらしいが、昨今いろいろ問題がある単語なのでデバイスと記載する

*3:7bitもしくは10bitで表現される

*4:今回は内蔵の25MHzのものをそのまま使っている

*5:今回は周期を17.34msとしたので57.67Hz

*6:0x0cと0x0d

*7:レジスタ値0x01C1

*8:レジスタ値0x0104

*9:どうも前進の際は時速20kmくらい出るらしい

*10:穴が奥まっているので取り付けにかなり苦労した