ラジコンカー用スピードメータ開発!

2023-02-20 · Tomoki Ikegami

"スマホで見れるラジコンカー用のスピードメータを自作してみた!"

~ 目次 ~


1. 今回やりたいこと

 ラジコンカーのスピードをリアルタイムで知りたいと思い、スピードメータを自作することにしました! 

 ラジコンでは、GNSS(中でもやっぱGPSが有名?)を使用してスピードを測定する方法が主流で、TRAXXASのTQi1もGNSSでスピードを測っています。便利な方法で速度も正確なのですが、高価、電波の届かない環境では速度が計算できないなどの欠点があります。

 今回はラジコンカーのシャフト回転数からスピードを計算し、スマホ画面に表示します!!

 値段も格安??(マイコンとセンサ合わせて、材料費2000円以下)

スマホがスピードメータになったら嬉しいなあ (/・ω・)/
☝ スマホがスピードメータになったら嬉しいなあ (/・ω・)/

2. シャフト4駆のラジコンカーについて(設計の前に)

2.1. 定番のレイアウト

 スピードメータ設計の前に、ラジコンカーの駆動原理について説明します!

 図(a)はラジコンカーでは定番、シャフト4駆の構成です。

 ラジコンカーは前輪を左右に動かすためのステア機構、車輪を回転させるための駆動機構で構成されています。ステア機構、駆動機構を動かすためにそれぞれモータサーボがあります。そしてモータやサーボを動かすには電気・電子回路が必要です。

 図(a)はごちゃごちゃしてるので、スピードメータ設計に関わるところだけを取り出したのが、図(b)です。

 センターシャフトの回転数から車速を計算します!

図(a) ラジコンカー基本構成
☝ 図(a) ラジコンカー基本構成
図(b) スピード測定関連部分のみ
☝ 図(b) スピード測定関連部分のみ

2.2. 駆動部分を詳細に

 下の図はラジコンカーの駆動部分をより詳しく描いたものです。

 センターシャフトの回転数を測定することで、最終的なタイヤの回転数を求めることができます!(後で説明します…)

 ピニオンギアの回転数を測定しても良いですが、今回はセンサ無しのモータでも使えるようにしたいので、センターシャフトの回転数を測定します。あとは計算を簡単にする目的もあります。  

ラジコンカー基本構成、駆動部分の詳細
☝ ラジコンカー基本構成、駆動部分の詳細

3. 設計

3.1. システム概要

 下の図が今回作成したスピードメータシステムの概要です。大まかな動作を説明すると、

  1. センサ(フォトリフレクタ)でシャフトの回転を検出
  2. マイコン(ESP32)でセンサ出力から回転数を計算
  3. 回転数から速度を計算
  4. 計算した速度をマイコン(ESP32)からスマホに送る
  5. 送られてきた速度をスマホ画面に表示

 となります。センサにはフォトリフレクタ※を使用します。使い方をまとめている方2の記事やデータシート3を参考に使いました。

※フォトリフレクタ
赤外線LED(発光部)とフォトトランジスタ(受光部)がセットになったセンサです。赤外線LEDを物体に向けて発光した時に、その跳ね返ってくる光をフォトトランジスタで受光します。物体の色によって赤外線の跳ね返ってくる光の量が変化するので、色が分かります。(実際の画像は3.2.2. ハードウェアを参照)

スピードメータシステム概要
☝ スピードメータシステム概要

3.2. 使った装置

 作業にあたって使用したソフトとハードウェア(装置)を整理しておきます。

3.2.1. ソフトウェア

  1. MIT App Inventor(スマホアプリ作成)
  2. Arduino IDE(マイコン用のプログラム開発)
  3. KiCAD(回路図の作成)

3.2.2. ハードウェア

  1. マイコンボード:ESP32-WROOM-32E
  2. フォトリフレクタ:LBR-127HLD
  3. スマホ:Moto g pro(Android 12)
使った装置
☝ 使った装置

(参考:以下の装置は、今回の話題でそこまで重要ではないです。)

3.3. 車速の計算

3.3.1. 車速の計算原理

 ググってみると、モータの回転数から車速を計算するWebアプリを自作している方4もいらっしゃいましたが、私はそこまでの猛者ではないので簡単な計算方法でやります… 

 これから紹介する方法はシャフト4駆に限定されますが、シャフト4駆は結構ありふれているので便利だと思います。(私的には)

 下の図はセンターシャフトの回転数から車速 $v_{app}$ [m/s](アプリの表示値なので$app$という添え字をつけてます)を計算する方法です。計算式は、

\begin{equation} \label{v_app} v_{app}=\frac{D \times 0.001}{2} \times 2 \pi f \times \frac{Z_1}{Z_2} \end{equation}

 という感じになります。シャフト周波数(回転数) $f$ [Hz] と、ベベルギアの歯数 $Z_1$ [枚]、リングギアの歯数 $Z_2$ [枚]、タイヤの直径 $D$ [mm] が分かれば、車速 $v_{app}$ [m/s] を計算することができます。

車速の計算原理
☝ 車速の計算原理

 ここで、式(\ref{v_app})を求める手順について、下の図を使って説明します!

車速の計算原理-計算式の導出
☝ 車速の計算原理-計算式の導出

 まず円運動の式から、タイヤの半径を $r$ [m] 、タイヤの角速度を $\omega_2$ [rad/s] とすると、車速 $v_{app}$ [m/s]は、

\begin{equation} \label{v_app_1} v_{app}=r \times \omega_2 \end{equation}

 で計算できます。ここで、タイヤの半径 $r$ [m] は直径 $D$ [mm] を使って、

\begin{equation} \label{r} r=\frac{D \times 0.001}{2} \end{equation}

 と書き直せます。0.001を掛けているのは、単位を[mm]から[m]に直すためです。次に、角速度 $\omega_2$はシャフト周波数 $f$ [Hz]、ベベルギア歯数 $Z_1$ [枚]、リングギア歯数 $Z_2$ [枚]を使って、

\begin{equation} \label{omega_2} \omega_{2}=\omega_1 \times \frac{Z_1}{Z_2} =2 \pi f \times \frac{Z_1}{Z_2} \end{equation}

 で計算できます。最後に式(\ref{r})、(\ref{omega_2})の $r$ と $\omega_2$ を式(\ref{v_app_1})の右辺に代入すれば、求めたかった式(\ref{v_app})を得ることができます。

\begin{equation} \label{v_app_2} v_{app}=r \times \omega_2 = \frac{D \times 0.001}{2} \times 2 \pi f \times \frac{Z_1}{Z_2} \end{equation}

 この式を使えば、車速を計算することができますが、シャフト周波数(回転数) $f$ [Hz] と、ベベルギアの歯数 $Z_1$ [枚]、リングギアの歯数 $Z_2$ [枚]、タイヤの直径 $D$ [mm] は調べる必要があります。

 タイヤの直径 $D$ [mm] は調べるか、定規やノギスで測ればよいです。しかしギアはケースに覆われているので、簡単に歯数を数えられません。また、シャフト周波数も測定する必要があります。

 ギアの歯数シャフト周波数は次のように求めました。

3.3.2. 歯数はどうする?

 分解するのは大変なので説明書5から探します。部品図からベベルギア・リングギアの品番(ここではECX212009とECX212010)を調べて、部品表の品番から歯数を探します。(下の画像のように)

歯数の探し方(説明書から画像を抜粋して追記)
☝ 歯数の探し方(説明書から画像を抜粋して追記)

3.3.3. シャフト周波数(回転数)はどうする?

 色々考えた結果、シャフト周波数は下の図のように求めることにしました。パルスの出現回数を数えるのは直接係数形式6っていうみたいです。

 排他的論理和 EX-OR(NOR)では、2つの入力が違うときに1を出力します。この性質を使ってパルスの立ち上がり、立ち下がりを検出します。例えば、下の図のようにある時刻でセンサが取得した値Aが0、その次の時刻で取得した値Bが1だったときは、EX-ORの出力Zは1になります。

 この方法ではパルスの立ち上がりと立ち下がりの両方を検出します。このため、パルス値変化数は実際の周波数の倍になります。パルス変化数を2で割れば、実際のシャフト周波数 $f$ [Hz] を得ることができます。

 

シャフト周波数測定原理

☝ シャフト周波数測定原理

 実際に測定すると、下の図のようなパルス出力が得られます。(AD変換後のセンサの入力値がある閾値以下なら1、そうでなければ0という処理をしています。閾値はth=3800に設定)

 スピードが上がるほど、パルスの間隔が短くなります。

 

実際のパルス出力

☝ 実際のパルス出力

3.4. 回路設計

 こちらが今回設計したスピードメータ回路です。(KiCad使用)

 センサからの出力値を25番ピンに読み込みます。ESP32では 0~3.3[V] までのアナログ電圧を 0~4095 のデジタル値に変換して読み込みます。(センサの入力電圧は5[V]ではなく3.3[V]を使う7のがポイント)

スピードメータ回路
☝ スピードメータ回路

3.5. 部品レイアウト

 3DCAD(FreeCAD)で部品の配置を設計しました。下の画像のようにシャフトの横にセンサが来るようにレイアウト(配置)しました。

部品レイアウト
☝ 部品レイアウト

4. 製作

4.1. 回路

 こちらは回路に半田つけをしている様子です(^^)/

 この写真では自作ラジコンアプリ用レシーバ製作の記事で作製した回路につぎ足す形ではんだ付けしていますが、今回の回路だけを新規に作っても大丈夫です!

回路製作
☝ 回路製作

4.2. 部品の固定

 シャフトにはコピー用紙を貼り付け、センサの土台は段ボールで製作しました(笑)。固定にはすべて両面テープを使っています。

部品の固定
☝ 部品の固定

4.3. スマホアプリ

 MIT App Inventor を使って作ったスマホアプリです。

 マイコンボード(ESP32)から受信した速度をリアルタイムに表示します。

 このアプリを使用するときは、次の手順ような作業をすれば良いです。

  1. アプリに「付近のデバイスへのアクセス権限」を付与する(やり方が分からない方はこちらの記事を参照)
  2. スマホの設定から、ESP32マイコンとペアリング※をする
  3. 画面上の「ここにタッチして接続機器を選ぶ」ボタンからESP32マイコンに接続します。
  4. 接続が完了したら画面上部の表示が「RCに接続済み(緑色)」に切り替わり、速度が表示されます。

※ペアリングの手順
 Android 12の場合は「設定>接続済みのデバイス>新しいデバイスとペアを設定」と進み、リストから接続機器を選びます。このときの名前は、4.4. プログラム(ソースコード)のsetup文の2行目で決めます。

アプリ外観(デザイン編集タブ)
☝ アプリ外観(デザイン編集タブ)
アプリの中身(ブロック編集タブ)
☝ アプリの中身(ブロック編集タブ)

4.4. プログラム(ソースコード)

 Arduino IDEで作ったプログラムです。マイコンボード(ESP32)に書き込んで動かします。

 プログラムの大まかな動きを説明すると、

  1. AD変換でセンサの出力値(0~4095のデジタル値)を読み取る
  2. センサ出力が閾値(th=3800に調整)未満なら1、そうでなければ0としてパルスを作る
  3. EX-ORでパルス出力値の変化数を計算
  4. パルス出力値の変化数からシャフト周波数 $f$ [Hz](パルス数)を求める(パルス値変化数÷2=周波数)
  5. 求めたシャフト周波数 $f$ [Hz] を式(\ref{v_app})に代入し、速度 $v_{app}$ [m/s] を計算
  6. 計算した速度 $v_{app}$ [m/s] をスケール速度※に変換(単位も[km/h]に)して無線(Bluetooth)でスマホへ送信

(ここでは0.5秒間に出現するパルス数を計算。そのパルス数を2倍することで1秒間あたりのパルス数、つまり周波数 $f$ [Hz] を計算)

※スケール速度
 ラジコンを実車サイズに換算した速度です。今回は実車の1/10程度の大きさのラジコンカーなので、実際の速度を10倍しました。


⇩⇩⇩ ソースコード ⇩⇩⇩
/* RC speedometer using reflective object sensor (for a shaft 4WD car) ************************************
  Download a speedometer app:https://github.com/TomokiIkegami/Happy_RC_Driver/raw/main/Happy_RC_Driver.apk
  About this Project:https://tomokiikegami.github.io/Happy_RC.github.io/2023/02/20/
  ◆ 動作
  1. シャフトに貼り付けられた目印をセンサ(フォトリフレクタ)で読み取り、シャフトの回転数(周波数)を計算します。
  2. シャフトの回転数をBluetooth通信でスマホに送信します。
  ◆ 補足
  ・プログラム中で★マークがついている部分は、自分の装置に合わせて調整
************************************************************************************************************/
#include "BluetoothSerial.h" //ESP32のBluetooth通信に使用
#define PI 3.141592653589793 //円周率

/*パラメータ設定*/
const int sense_pin = 25;  //★回路に合わせる。今回は25番ピンを使用。
const double z1=14; //ベベルギアの歯数[枚]
const double z2=38; //リングギアの歯数[枚]
const double D=95; //タイヤの直径[mm]

/*センサ関連の設定*/
const int th = 3800;  //センサ閾値
int val = 0;          //センサ出力値
int output = 0;       //パルス出力(0/1)
int y[50];            //パルス列を保存する配列
int count = 0;        //パルスのカウント値

/*速度計算関連の変数*/
double f = 0;          //周波数[Hz]
double v,v_kmh = 0;          //速度v:[m/s], 速度v_kmh:[km/h]
int f_int = 0 ;       //周波数(整数)
int v_kmh_int = 0 ;       //周波数(整数)
uint8_t f_uint8 = 0;  //周波数(符号なし8bit[2byte]整数)
uint8_t v_kmh_uint8 = 0;  //周波数(符号なし8bit[2byte]整数)


/*プログラムの流れ制御用*/
int i;                //カウンタ変数

/*Bluetooth通信に必要*/
BluetoothSerial ESP_BT; //ESP_BTという名前でオブジェクトを定義

void setup() {
  Serial.begin(115200); //シリアルモニタで確認用
  ESP_BT.begin("ESP32_RC_Receiver"); //接続画面で表示される名前を設定 ★好きな名前にしてよい
}

void loop() {

  /*フォトリフレクタから値を読み取り、パルスの生成*/
  for (i = 0; i < 50; i++) { //0.01×50=0.5[s] 間隔で周波数を計算
    val = analogRead(sense_pin);  //センサの値などを読む

    /**パルス作成**/
    if (val < th) { //センサの前にシャフトの目印が通過したらパルス値を1にする
      output = 1;
    } else {
      output = 0;
    }
    y[i] = output;  //パルス出力値を保存
    delay(10); //サンプリング周期Δt=0.01[s] ごとに測定
  }

  /**パルス数計算*/
  for (i = 0; i < 49; i++){ //0.01×50=0.5[s] 間隔で周波数を計算
    if((y[i]^y[i+1])==1){
      count++; //排他的論理和(EX-OR)でパルスの立ち上がり/立ち下がりを計算
    }    
  }

  /*周波数の計算、スマホに値を送信*/
  f=((double)count/2.0)*(1.0/0.5); //周波数f[Hz]を計算
  v=(D*0.001/2.0)*2*PI*f*(z1/z2); //周波数から速度[m/s]を計算
  v_kmh=v*3600/1000; //[m/s]から[km/h]に換算
  v_kmh_int = (int)(v_kmh*10); //速度を整数値に変換(10倍してスケール速度に変換)
  v_kmh_uint8 =  v_kmh_int; //速度を符号なし8bit整数に変換
  ESP_BT.write(v_kmh_uint8); //速度をスマホに送信

  f_int = (int)f; //周波数を整数に変換
  f_uint8 = f_int; //周波数を符号なし8bit整数に変換
  Serial.print("f = "); Serial.print(f); Serial.print(" [Hz], "); //シリアルモニタに周波数(シャフト回転数)と速度を表示
  Serial.print("v_kmh = "); Serial.print(v_kmh); Serial.print(" [km/h]\n"); //シリアルモニタに周波数(シャフト回転数)と速度を表示
  //ESP_BT.write(f_uint8); //周波数をスマホに送信ESP_BT.write(f_uint8); //周波数をスマホに送信

  count=0; //カウント値をリセット
  
}

5. 実験

5.1. 実験の概要

 アプリの表示値が正しいか確認したかったので、評価実験をしました。

 図(a)がその概要図になります。速度=移動距離÷所要時間 の関係から求めた速度 $v_{real}$ とアプリ表示値 $v_{app}$ を比べて、アプリ表示値が正しいことを確認する実験です。a点、b点を通過した時の時刻をそれぞれ $t_1$, $t_2$ [s]、移動距離を $L$ [m] とすれば、実際の車速 $v_{real}$ [m/s] は、

\begin{equation} \label{v_real} v_{real}=\frac{L}{t_2-t_1} \end{equation}

 で計算することができます。

 図(b)は実際の環境で行ったときの画像です。ラジコンカーが通りすぎる様子をスローモーション撮影して、タイマーからかかった時間(所要時間 $t_2-t_1 $ [s])を計算しました。

図(a) 実験のイメージ
☝ 図(a) 実験のイメージ
図(b) 実験画像
☝ 図(b) 実験画像

5.2. 実験動画

 こちらが先ほど説明した実験の動画になります。

 小さくて見ずらいですが、スマホ画面に速度がリアルタイムで表示されています!

5.3. 実験結果

 実験動画で取り上げた速度の他にも、色々な速度で試した結果がこちらです。こちらも表示はスケール速度です。

 多少誤差はありますが、自作にしては満足な精度が得られました!!(笑)

 誤差の原因としては、現在の計算方法では周波数が整数でしか出ないこと、AD変換の速度が遅い、タイヤ径の測定誤差…などが考えられます。

実験結果
☝ 実験結果

6. まとめ

 今回の自作スピードメータを使って、屋内でもリアルタイムな速度計測・表示できました(^▽^)。作業する中で、機械、電気・電子、情報の知識が必要だったので大変でしたが、良い勉強になったと思います!

 今後は、ラジコン操縦アプリにこのスピードメータを実装する、クルーズコントロールなどの制御をやってみる、自己位置推定に使うなど応用の幅を広げたいです!

7. 謝辞

 作業場所・材料を提供してくださった先生方、配線の確認や実験方法についてアドバイスをしてくれた友人に、この場を借りて感謝申し上げます。

8. サンプルファイル

 作成したアプリのデータはこちらになります。色々改良して遊んでみてください!

~ MIT App Inventorプロジェクトのファイル(.aia) ~

~ Androidアプリのファイル(.apk) ~

10. 参考文献


  1. TRAXXAS「Upgrade Your Traxxas Model with the TQi Telemetry Expander 2.0 and GPS Module 2.0!」、(https://traxxas.com/products/parts/6553X↩︎

  2. プチモンテ「フォトリフレクタの使い方 [Arduino]」、(https://www.petitmonte.com/robot/howto_photo_reflector.html↩︎

  3. 秋月電子通商「LBR-127Dデータシート」、(https://akizukidenshi.com/download/lbr127hld.pdf↩︎

  4. Kuma「ギヤ比計算機」、(http://www2.tokai.or.jp/mrnkmzu/rc/gearratio.html↩︎

  5. ECX「Barrage 1.9 Manual EN」、(https://www.horizonhobby.com/on/demandware.static/-/Sites-horizon-master/default/dw8eff16d0/Manuals/ECX01009-Manual-EN.pdf↩︎

  6. PIC World「Arduino で周波数を計測する – バイクのタコメーターを作りたいんだよ!(その1)」、(https://picworld.jp/2017/11/17/arduino-%E3%81%A7%E5%91%A8%E6%B3%A2%E6%95%B0%E3%82%92%E8%A8%88%E6%B8%AC%E3%81%99%E3%82%8B-%E3%83%90%E3%82%A4%E3%82%AF%E3%81%AE%E3%82%BF%E3%82%B3%E3%83%A1%E3%83%BC%E3%82%BF%E3%83%BC%E3%82%92%E4%BD%9C/↩︎

  7. ソースに絡まるエスカルゴ「【ESP32】analogReadする方法」、(https://rikoubou.hatenablog.com/entry/2017/06/29/135819↩︎