ArudinoでS.BUS通信で離れたところにあるサーボを動かす

2024年1月3日

ArudinoをからRS485を使ってS.BUS通信を行い、離れたところにあるS.BUS対応のサーボをコントロールしてみるというお話です。

結論を先にいうと、ポイントは「RS485ドライバを使用して長距離通信を可能にしつつ、信号反転を同時に行う」ことです。

目的=離れたところにある複数のサーボをマイコンから制御する

人力飛行機の操舵システムや、ロボコン用ロボット、大型ラジコン、ドローン制御等の用途でArudinoなどのマイコンからサーボをコントロールしたいことがあります。

昔ながらのやり方であれば、マイコンからPPM信号(PWMと似ているがデューティ比ではなく、Hi時間で値を伝える方式)を出してサーボの角度をしてしていましたが、その方式だと動かしたいサーボの数だけマイコンのポートを消費してしまいます。

そこで、S.BUS通信を用いて、マイコンの1つのシリアルポートで複数のサーボを動かしたいです。

また、単純なパルス信号は長距離伝送に向いていません。例えばマイコンから出したPPM信号(PWM信号)を10mのケーブル経由でサーボに接続して動かそうとするとノイズやケーブル内の反射波によりサーボがぴくぴくと怪しい動きをします。

人力飛行機や大型のロボットを作ることを想定してマイコンから離れたところにあるサーボでも動かせるように、長距離伝送に対応した回路を考えてみます。

S.BUS通信とは

S.BUS通信とは双葉電子工業(Futaba)製のラジコン用サーボを制御するためのシリアル通信規格です。複数のサーボを1本のシリアル通信ラインでコントロールすることがでます。

注意点として、S.BUS信号はシリアル通信ですがマイコンのシリアル通信(RS232C)と+/-が反対です。信号反転をしないとマイコンからS.BUS信号を出せません。

通信仕様

  • 電圧:L = 0V, H = 3.3V
  • 信号極性:反転(通常のRS232通信と正負が反対、信号を送っていない時がLOW)
  • ボーレート:100 kbps
  • フレームフォーマット:1スタートビット+8データビット+1パリティービット+2ストップビット
  • 通信間隔:14msec(アナログモード) or 7ms(ハイスピードモード)
  • データ長:25Byte([startbyte] [data1] [data2] …. [data22] [flags][endbyte])
  • データ順:LSB first

データ構成

  1. startbyte = 00001111b (0x0F)
  2. 数値データ:11bitの数値(0~2047)が16ch分
  3. flags (ON/OFF情報が2ch+α)
     bit0 = ch17のON/OFF情報
     bit1 = ch18のON/OFF情報
     bit2 = 受信失敗のLED ON/OFF情報?
     bit3 = フェールセーフ有効?
     bit4 = 不使用
     bit5 = 不使用
     bit6 = 不使用
     bit7 = 不使用
  4. endbyte = 00000000b

11bitのデータは16ch分をすべて結合した後に分割され、8bit枚に1Byteとして送信されます。そのため、数値データ16ch分は、11bit × 16ch ÷ 8bit = 22Byte 分のデータになります。

そのほかにスタートバイト、フラグ情報用バイト、エンドバイトの3Byteと合わせて合計で25Byteの情報が14msec毎に送信されます。

数値データは 0~2047 で 1024 がニュートラル位置を意味します。試した限りでは、この数値の全範囲でサーボの角度が変化した。(サイトによっては上下64分は使用せず 64~1984 の値をとるとしていないという記述もあった。)

情報出典:Futaba S-BUS controlled by mbed | Mbed

16chの数値情報と2chのON/OFF情報を送ることができます。

RS485を使用した方法の提案

今回、マイコンで長距離のS.BUS通信を行い方法としてRS485ドライバを使用した方法を考えました。

実験の結果、10m以上のケーブルで安定した通信ができたので紹介します。

NPNトランジスタを用いた方法(従来方法)

Arduino等のマイコンからS.BUS信号を出す方法としてNPNトランジスタを1つ使った方法があります。

NPNトランジスタによって、Arudinoから5Vが出た時は0V、0Vが来たときは5Vというように信号を反転します。確かにS.BUS信号を出すことができます。

しかし、10m程度の長いケーブルを経由してサーボを接続すると反射波の影響で正常に通信できません。出力インピーダンスが高いため120Ωの終端抵抗を追加することもできません。(120Ωの終端抵抗を入れれば反射波の影響は抑えられる。)

上記回路で通信してみた波形をオシロスコープで確認します。

[1]:Arduinoのシリアル出力
[2]:トランジスタのコレクタ=出力信号
[3]:10m配線の先のサーボsignal入力

狙い通り、[1]に対して[2]の信号は+/-が反転していることが分かります。

しかし、最終的にサーボに届いた信号[3]を見ると立ち上がりが遅く角が丸くなっています。また、立下り後は反射波による振動波形が見られます。

今回は、サーボが無事に動きましたが、配線を長くしていくと通信が成立せず動かなくなりました。

さらにNPNトランジスタを1つ追加し、エミッタフォロア回路を構成し出力インピーダンスを低くするという方法で長距離伝送を可能にすることはできますが、そこまでするならもっと簡単で安定した方法はないかと考えてみました。

RS485ドライバを用いた方法(今回考案した方法)

長いケーブルを用いた通信といえばRS485が有名です。そこで、RS485用のドライバICを使えば、S.BUS信号を長距離伝送できると考えました。

構築したのが下記のような構成です。

ArduinoのSerial出力からSBUSの逆位相信号を出力し、RS485ドライバで差動式の低インピーダンス信号に変換、AchとBchを入れ替え(A-B相逆接続により信号を反転)受信側のRS485ドライバに接続し0-5Vシリアル信号に戻してサーボのsignal入力に接続するという構成です。

トリッキーな工夫として、発信側のRS485と受信側のRS485でA相とB相を入れ違いに接続しました。これによりマイコンから出たシリアル通信のHi/Loを反転します。そのためNPNトランジスタ等は不要です。

結果は下記は形の通りです。

Arduinoから出力されたSerial信号がRS485信号に変換され、最終的に反転されたSerial信号に変換されていることが分かります。最終出力信号は0-3.8V程度の振幅であり、SBUSの3.3Vを十分に超えています。RS485信号を見ると、A相とB相は仕様通り差動信号となっており、長距離伝送に適していること言えます。

[1]:ArduinoからのSerial信号出力
[2]:RS485のB相
[3]:RS485のA相 ([2])と重なって表示。GNDレベルは同じ
[4]:受信側RS485ドライバから出力される反転済みのSerial信号(=SBUS信号)

波形を時間方向に拡大してみてみます。はやりノイズ、振動、オーバーシュートはなく、信号誤読み取りの心配はないと考えられます。入力信号[1]に対して出力信号[4]が1µsecほど送れていますが、これはRS485ドライバの仕様通りであり異常ではありません。(仕様書では遅れは標準0.8µsecとなっている。)

RS485の規格によれば、ボーレート100 kbpsの場合、通信可能距離は1.2kmです。

この方法であれば100m先のサーボなら余裕でS.BUS信号でコントロールできそうです。

無線機が近くで使用されているようなノイジーな環境で、Arudino等のマイコンから離れたところにあるサーボをコントロールすることを考えるとこれはベストソリューションかもしれません。

電子回路

Posted by Takuma