~ 目次 ~
1. 今回やりたいこと
いやぁ~(※)新年(2023)一発目の投稿ですね!!(※いやぁ~は東北とか北海道の人が使いがちみたいで、私もその一人です笑。特に深い意味はないです笑)
今回はスマホからラジコン用サーボモータを操作します!
スマホでスライダを操作し、その操作量に応じてサーボモータの角度をコントロールしました。
これを作るにあたって、PWM制御とシリアル通信という技術を使ったので、まずはその説明から始めます(^^)/

2. 使った技術
2.1. PWM制御
PWMというのは Pulse Width Modulation の頭文字を取ったものです。日本語に直すとパルス(Pulse)幅(Width)変調(Modulation)となります。と言われてもあんまりしっくり来ないと思うので、図を使って説明します!
下の図がPWM制御のイメージ図です。このカクカクした波形をパルス波といいます。このパルス幅を変える(図中ではTonの幅を変える)ことで、サーボモータの角度を制御するのがPWM制御です。
具体的には、ONになってるところのパルス幅を1000~2000[μs]の間(メーカによって異なる1が大体一緒)で変えて制御します。
例えば、パルス幅が1000[μs]のときは右回転(角度:0°)、1500[μs]のときはニュートラル(角度:90°)、2000[μs]のときは左回転(角度:180°)となります。
2.2. シリアル通信
1本の(伝送)経路上にデータを順番に流して通信する方法です。送れるデータの種類やビット数など細かい話はあるのですが、ここではイメージのみを説明します。
例えば、“ラジコン"という文字を送りたければ、まず"ラ"を送ってから、“ジ”、“コ”、“ン"と順番に送ります(同時に送らない)。一見効率が悪そうですが、高速通信が可能です。身近な場面では、USBやBluetoothの通信に使われています。
3. 使ったもの
作業にあたって使用したソフトとハードウェア(装置)を整理しておきます。
3.1. ソフトウェア
- MIT App Inventor(スマホアプリ作成)
- Arduino IDE(マイコン用のプログラム開発)
- KiCAD(回路図の作成)
3.2. ハードウェア
- 操縦用スマホ(送信機):Moto g pro(Android 12)
- マイコン(受信機):ESP32-WROOM-32E
- サーボモータ:Hitec DB777WP
(参考:以下の装置は、今回の話題でそこまで重要ではないです。)
- ラジコンカー本体:ECX Barrage 1.9(1/12スケールロッククローラRC)←お気に入りです!
- モバイルバッテリー:SANYO KBC-L54D (3.7V Li-ion 5400mAh ※INPUT,OUTPUT=5.0V) ←マイコンに電源供給
- 走行用バッテリー:Dynamite Speedpack (7.2V Ni-MH 700mAh) ←ESCに電源供給
- クローラ用ESC:TEKIN BXR ←ESCからサーボモータに電源供給
4. 回路図
ESP32(マイコンボード)とサーボモータの接続です。
サーボモータには線が3本あります。サーボモータの電源(+)端子に6[V]、PWM信号線に5[V]が入るように自由に回路を組み立ててください。GND(-)は共通にしてください。
サーボモータのPWM信号線は、ESP32の(PWMが使える)好きな端子に繋げてください。このとき、ESP32の端子番号は確認しておきます(プログラム書くときに使う)。
ここでは例としてラジコン用のスピードコントローラー(ESC)から、サーボモータ用の6[V]電源を取る回路を載せておきます(‘ω’)/
5. スマホアプリ
MIT App Inventor を使って作ったスマホアプリです。
スライダの位置によって、ラジコンカー側に送信するパルス幅を変化させます。パルス幅の値はBluetoothで無線送信します。


6. プログラム(ソースコード)
Arduino IDEで作ったプログラムです。ラジコン側のESP32に書き込んで動かします。
スマホから送られてきたパルス幅に応じて、サーボモータの角度をPWM制御で変化させます。スマホから送られてくるのは文字なので、数値に変換して制御に使ってます。
プログラムの大まかな動きを説明すると、
- シリアル通信で、パルス幅を文字としてスマホから受信(パルス幅"1000"なら⇒'1’と'0’と'0’と'0’という文字として取得)
- 区切り文字(ここではセミコロン;)が来るまで文字を受信して、文字列に変換(‘1’と'0’と'0’と'0'⇒"1000”)
- 文字列を整数値に変換(“1000"⇒1000)
- 変換された数値でサーボモータをPWM制御
シングルコーテーション(')は文字、ダブルコーテーション(")は文字列の意味です。
PWM制御の方法2、文字列として受信して整数に変換する方法3 について紹介してくれている方に非常に感謝しています。ありがとうございます。
/**** アプリから受け取ったパルス幅でサーボを制御(サーボモータをPWM制御で動かしてみる。スマホアプリからサーボモータを操作)****/
/*ハードウェアの接続ピンの設定*/
#define SERVO_PWM_PIN 4 //サーボモータのPWMピン(信号入力ピン)をESP32の4番ピンに接続 ★回路と対応した番号にする
/*ライブラリ*/
#include "BluetoothSerial.h" //ESP32のBluetooth通信に使用
/*変数の定義*/
int PWM_period = 20000; //PWM周期をT=20000[μs]に設定
int CH1 = 1500; //パルス幅Tonを1500[μs](中立)に設定。データシートにはLeft=900[μs]、Neutral=1500[μs]、Right=2100[μs]と記載されていた。(HiTEC DB777WP)
/*Bluetooth通信に必要*/
BluetoothSerial ESP_BT; //ESP_BTという名前でオブジェクトを定義
void setup() {
pinMode(SERVO_PWM_PIN, OUTPUT); //サーボモータのピンへ、Arduinoから出力するように設定
Serial.begin(115200); //シリアルモニタで確認用。伝送速度を115200[bps]に設定
ESP_BT.begin("ESP32_RC_Receiver"); //接続画面で表示される名前を設定 ★好きな名前にしてよい
}
/*PWM制御でサーボモータの角度を制御する関数*/
void change_ST_pos(int goal_pos) {
/*20000[μs]周期で幅CH1[μs]のパルス波生成*/
digitalWrite(SERVO_PWM_PIN, HIGH); //PWMピンの電圧を5[V]に
delayMicroseconds(goal_pos); //パルス幅(goal_pos=900~2100[μs]:DB777WPの場合)
digitalWrite(SERVO_PWM_PIN, LOW); //PWMピンの電圧を0[V]に
delayMicroseconds(PWM_period); //制御周期(T=20000[μs])
}
void loop() {
if (ESP_BT.available()) { //available()で受信した文字があるか確認。あればif文内の処理を実行。
String input = ESP_BT.readStringUntil(';'); //文字をセミコロン(;)まで読んで、文字列として変数inputに保存。
CH1 = input.toInt(); //文字列を整数値(int)に変換
Serial.println(input); //数値をシリアルモニタに表示
}
change_ST_pos(CH1); //受信したパルス幅でサーボモータの角度を制御
}
7. 動作確認
スマホのスライダを操作すると、それに応じてステア(ハンドル)が動いてます!
スロットル(アクセル)も同時に操作できるようなれば、本格的なコントローラができそうです!!
8. サンプルファイル
作成したアプリのデータはこちらになります。色々改良して遊んでみてください!
~ MIT App Inventorプロジェクトのファイル(.aia) ~
~ Androidアプリのファイル(.apk) ~
9. 参考文献
-
Hori’s Library「サーボの動作原理」、(https://berry.sakura.ne.jp/technics/servo_control_p3.html) ↩︎
-
ぶらり@web走り書き「【Arduino入門編⑧】サーボモーターを動かしてみる。PWM制御についていの解説です!」、(https://burariweb.info/electronic-work/arduino-learning/aruduino-servomotor-control.html) ↩︎
-
メカトロDIYチャレンジ(Mechatro DIY Challenge)「スマホからBluetooth通信でArduinoを操作する②基本設計」、(https://mechadiy.com/bluetooth_phone_arduino_cont02/) ↩︎