~ 目次 ~
1. 今回やりたいこと
今年の初めごろにラジコンカー用のスピードメータを自作しましたが、スピードの更新間隔が遅い(0.5 [ms])と感じていました。
当時はこれでも問題ないと感じてたのですが、最近はラジコンカーにクルコン(クルーズコントロール)を実装しようと考え始めました。
クルコンの制御に車速を使うのですが、車速の計算間隔 0.5 [ms] で制御すると、遅れが出そうだなと思いました。
今回は前回作ったスピードメータを、車速制御に十分なスピードメータに改良します!
2. マイコンとセンサの限界
センサの応答速度は計算すると 66 [kHz] 程度が限界っぽいです(LBR-127Dのデータシートを見ると、Tr = 15 [μs])。なのでESP32マイコンのサンプリング周期をこれより早くしても意味なさそうです(こんなに早くするのはESP32のスペック的に難しそう)。プログラムでサンプリング周期を T = 1 [ms] したら丁度いい感じで値が取れたので、これで行こうと思います。サンプリング周波数 f は、サンプリング周期の逆数になるので、
f=1/T=1/(1×10−3)=1000=1 [kHz]
となります。
3. ハードウェアの変更点
前回とほとんど同じですが、シャフトに貼る紙の枚数が2枚になりました(車速の分解能を上げるため)。なので、紙の枚数を2枚に増やさないと車速が半分で表示されます(笑)
4. マイコン側プログラム
改良後のマイコン側プログラムはこちらになります。サンプリング周期を設定すると、サンプリング数が変化するようになっています。センサ出力を格納する配列yの大きさNは
N = 速度の計算周期 ÷ サンプリング周期
で計算して設定してください。 配列サイズを大きくしすぎるとプログラムが動かなくなるみたいですが、今回のプログラムでは数万個にしないとその問題は起こらなそうです1。
/* RC speedometer using reflective object sensor (for a shaft 4WD car) ************************************
Download a speedometer app:https://tomokiikegami.github.io/Happy_RC.github.io/2023/12/24/rc_speedometer_4.apk
About this Project:https://tomokiikegami.github.io/Happy_RC.github.io/2023/12/24/
◆ 動作
1. シャフトに貼り付けられた2枚の目印をセンサ(フォトリフレクタ)で読み取り、シャフトの回転数(周波数)を計算します。
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[200]; //パルス列を保存する配列
int count = 0; //パルスのカウント値
double T = 0.2; //速度の算出周期[s]
double Ts = 1*pow(10,-3); //センサのサンプリング周期[s]
/*速度計算関連の変数*/
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() {
int An = (int)(T/Ts); //パルスの読み取り回数(パルス配列yの要素数と同じ)
/*フォトリフレクタから値を読み取り、パルスの生成*/
for (i = 0; i < An; i++) { //0.01×50=0.5[s] 間隔で周波数を計算
val = analogRead(sense_pin); //センサの値などを読む
/**パルス作成**/
if (val < th) { //センサの前にシャフトの目印が通過したらパルス値を1にする
output = 1;
} else {
output = 0;
}
y[i] = output; //パルス出力値を保存
delay((int)(Ts*pow(10,3))); //Ts[s] ごとに測定。※単位をmsに直すために、10^(3)を掛けている
}
/**パルス数計算*/
for (i = 0; i < An-1; i++){ //0.01×50=0.5[s] 間隔で周波数を計算
if((y[i]^y[i+1])==1){
count++; //排他的論理和(EX-OR)でパルスの立ち上がり/立ち下がりを計算
}
}
/*周波数の計算、スマホに値を送信*/
f=((double)count/2.0)*(1.0/T)*(1.0/2.0); //周波数f[Hz]を計算。一番右の (1.0/2.0) の項は、紙の枚数が2倍になったことで周波数が2倍で算出されるのを避けるため 2で割っています)
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. スマホアプリ
画面に速度だけをでっかく表示したかったので、2画面構成にしました。アプリ起動後に「CONNECT」ボタンを押すと、速度表示画面に遷移する仕組みです。
必ずマイコン側の電源が入っている状態で「CONNECT」ボタンを押してください。マイコンに接続できないと、「CONNECT」画面に戻る仕組みになっています。




6. 動画
動作の比較結果がこちらになります。前のバージョン比べて、速度の更新周期が速くなっていることが確認できると思います。これで車速制御に応用できそうです!
7. サンプルファイル
作成したアプリのデータはこちらになります。自由に変えて遊んでみてください!
~ MIT App Inventorプロジェクトのファイル(.aia) ~
~ Androidアプリのファイル(.apk) ~
8. 関連記事
- 前回 →→→ ラジコンカー用スピードメータ開発!
9. 参考文献
-
mgo-tec電子工作「Arduino / ESP8266 の使用できるRAM 領域を再考」、(https://www.mgo-tec.com/blog-entry-arduino-esp8266-ram-size.html) ↩︎