/* RCBシリーズから出るサーボ用シリアル信号をESP32C3で受け取り、その情報を基にDFPlayerMiniから音声を再生するためのスケッチ 2023/09/16 Release 1 by 666 配線図はこちら https://herdruk.web.fc2.com/RCB_play_DFP_with_ESP32C3.png 近藤化学社製のICSコマンドをESP32で受信し、音声を再生します。 RCB-4HVまたはRCB-3HVで使うことを想定しています。RCBで使う場合、3か4かは自動判定されます。 通信速度は115200bpsか1.25Mbpsで自動判定されます。 RCBからサーボを動かすのと同じようにPOSブロックで位置情報を送信すると、それに応じて音声が再生されます。 0を送信すると停止、1〜3000を送信するとそれに対応するファイル番号の音声が再生されます。 それ以外の範囲の信号はすべて無視されます。 同様にストレッチのパラメータを変更した場合も、それ応じて音声が再生されます。 0を送信すると停止、1〜126を送信するとそれに対応するファイル番号の音声が再生されます。127を送信した場合は何も起こりません。   スピードのパラメータを変更すると音量を変えることができます。0が最小、127が最大です。 ライブラリはライブラリマネージャから追加してください。ググれば追加方法出てきます。 ライブラリはArduinoIDEにバンドルされているものはなく、EspSoftwareSerialというものになります。 こちらもライブラリマネージャから追加してください。 動作テストはRCB-4HV,ESP32-WROOM-32,DFPlaerMini(HW-247A)で行いました。 ArduinoIDEで開発ができるほかのマイコンで使う場合は各自スケッチを変更してください。 ※このスケッチで起こった事故・破損などについては一切の責任を追うことができませんので、ご了承ください。 */ #include //DFPlayerのライブラリをインクルード #include //ソフトウェアシリアルのライブラリをインクルード //各種設定項目 #define DFP_RX D5 //DFplayerとシリアル通信するための受信ピン #define DFP_TX D4 //DFplayerとシリアル通信するための送信ピン #define ICS_ID 16 //RCB-4HVとシリアル通信するときに読み込むID #define ICS_BR 0 //通信速度の指定[0:自動判定 115200:115.2kbps 1250000:1.25Mbps] //ソフトウェアシリアル通信のインスタンス宣言 SoftwareSerial DFP_Serial; //DFPlaerライブラリのインスタンス宣言 DFRobotDFPlayerMini myDFPlayer; //各種変数の宣言と初期化 int last_play_number = -32768; //位置情報で最後に再生したファイル番号を格納しておく変数 int last_play_number_STR = -32768; //ストレッチ情報で最後に再生したファイル番号を格納しておく変数 int old_potision = -32768; //最後に受け取った位置情報を格納する変数 long time_count = 0; //DFPlaerにデータ送信後に待機する時間を格納する変数 byte count = 0; //同じ位置情報の受信回数を格納する変数 byte ics_read_id = ICS_ID; //読み込むときに使うIDを格納する変数 void setup() { byte i; //くり返し用変数の宣言 byte read_count; //受信回数カウント用変数の宣言 byte CMD; //シリアル信号受信用変数 if (ICS_BR == 1250000) { //通信速度が1250000に強制指定されていたら Serial0.begin(1250000, SERIAL_8E1, -1, -1, false, 256); //RCBからシリアル信号を受け取るためにハードウェアシリアルを開始(1.25Mbps,8ビット_偶数パリティ_ストップビット1) Serial0.setTimeout(10); //ハードウェアシリアルのタイムアウト時間を10ミリ秒に設定 delay(100); //シリアル信号受信待ち } else if (ICS_BR == 115200) { //通信速度が115200に強制指定されていたら Serial0.begin(115200, SERIAL_8E1, -1, -1, false, 256); //RCBからシリアル信号を受け取るためにハードウェアシリアルを開始(115.2kbps,8ビット_偶数パリティ_ストップビット1) Serial0.setTimeout(10); //ハードウェアシリアルのタイムアウト時間を10ミリ秒に設定 delay(100); //シリアル信号受信待ち read_count = 0; //受信回数カウント用変数の初期化 for (i = 0; i <= 200; i++) { //とりあえずシリアル信号を200バイト受信する CMD = Serial0.read(); //受信データをいったん変数に格納する if (CMD >= 0x81 && CMD <= 0xA0) read_count++; //ID:1以上の情報を受信したらカウントする } //※ID:1以上の情報が受信されたということは、接続されているRCBが4であることが確定する。 if (read_count == 0) { //一度もID:1以上の情報が受信できていなければ ics_read_id = 0; //受信するIDを0に設定してRCB-3HVモードにする } //(RCB-3HVのシリアル信号はID:0) } else { //通信速度が自動判定に設定されていたら Serial0.begin(1250000, SERIAL_8E1, -1, -1, false, 256); //RCBからシリアル信号を受け取るためにハードウェアシリアルを開始(1.25Mbps,8ビット_偶数パリティ_ストップビット1) Serial0.setTimeout(10); //ハードウェアシリアルのタイムアウト時間を10ミリ秒に設定 delay(100); //通信が安定するまで待機 read_count = 0; //受信回数カウント用変数の初期化 for (i = 0; i <= 200; i++) { //とりあえずシリアル信号を200バイト受信する CMD = Serial0.read(); //受信データをいったん変数に格納する if (CMD >= 0x80 && CMD <= 0xA0) read_count++; //ID情報を受信したらカウントする } //※正常にIDの情報が受信できたということは通信速度が1.25Mbpsであることが確定する。 if (read_count < 10) { //ID情報が正常に受信できていなかったら(正常に通信できていたら確実に10回以上ID情報を受信できているはず) Serial0.end(); //いったんシリアル通信を終了する delay(100); //通信が安定するまで待機 Serial0.begin(115200, SERIAL_8E1, -1, -1, false, 256); //RCBからシリアル信号を受け取るためにハードウェアシリアルを開始(115.2kbps,8ビット_偶数パリティ_ストップビット1) Serial0.setTimeout(10); //ハードウェアシリアルのタイムアウト時間を10ミリ秒に設定 delay(100); //シリアル信号受信待ち read_count = 0; //受信回数カウント用変数の初期化 for (i = 0; i <= 200; i++) { //とりあえずシリアル信号を200バイト受信する CMD = Serial0.read(); //受信データをいったん変数に格納する if (CMD >= 0x81 && CMD <= 0xA0) read_count++; //ID:1以上の情報を受信したらカウントする } //※ID:1以上の情報が受信されたということは、接続されているRCBが4であることが確定する。 if (read_count == 0) { //一度もID:1以上の情報が受信できていなければ ics_read_id = 0; //受信するIDを0に設定してRCB-3HVモードにする(RCB-3HVのシリアル信号はID:0) } } } DFP_Serial.begin(9600, SWSERIAL_8N1, DFP_RX, DFP_TX, false, 256); //DFPlayerと通信のためにハードウェアシリアルを開始(9600bps,8ビット_パリティなし_ストップビット1)P delay(1000); //DFplayerが立ち上がるのを待つ myDFPlayer.begin(DFP_Serial); //DFPlayerとの通信を開始 delay(100); //通信が安定するまで待機 myDFPlayer.volume(30); //DFPlayerのボリュームを最大に設定 delay(100); //通信が安定するまで待機 } void loop() { while (Serial0.available() == 0) {}; //シリアル信号が受信されるまで待つ byte CMD = Serial0.read(); //シリアル信号を変数に格納する if (CMD == (0x80 + ics_read_id)) { //受信した情報が設定されたIDの位置情報なら while (Serial0.available() == 0) {}; //次のシリアル信号が受信されるまで待つ byte POS_H = Serial0.read(); //位置情報の上位7ビットを変数に格納する while (Serial0.available() == 0) {}; //次のシリアル信号が受信されるまで待つ byte POS_L = Serial0.read(); //位置情報の下位7ビットを変数に格納する int potision = ((int)POS_H << 7) + POS_L; //位置情報を組み立てる if (old_potision == potision) count++; //受信した情報が1回前に受信した情報と同じだったらカウントを1増やす else count = 0; //受信した情報が1回前と異なっていたらカウントを0に初期化する old_potision = potision; //最後の位置情報を格納する int play_number = potision - 7500; //位置情報を原点からの変化量(HeartToHeartのスライドバーと同じ値)に換算する if (play_number >= 0 && play_number <= 3000) { //もし変化量が0~3000なら(変化量をファイル番号として扱う) if (count >= 6) { //同じ値を6回以上受信していたら count = 6; //countがオーバーフローしないように6に上書きする if (last_play_number != play_number) { //ファイル番号が前のファイル番号と異なっていたら if (play_number == 0) myDFPlayer.stop(); //ファイル番号が0なら[停止]を送信する else myDFPlayer.play(play_number); //ファイル番号が0以外なら、そのファイル番号を再生する last_play_number = play_number; //最後のファイル番号を格納する time_count = millis() + 150; //待機終了時間を150ミリ秒後に設定する while (millis() <= time_count) Serial0.read(); //待機終了時間まで待つ。待っている間のシリアル信号はすべて捨てる } } } } else if (CMD == (0xC0 + ics_read_id)) { //受信した情報が設定されたIDのパラメータ情報なら while (Serial0.available() == 0) {}; //次のシリアル信号が受信されるまで待つ byte SC = Serial0.read(); //パラメータ情報の種類を変数に格納する while (Serial0.available() == 0) {}; //次のシリアル信号が受信されるまで待つ byte SPD = Serial0.read(); //パラメータ情報の値を変数に格納する if (SC == 0x02) { //もしパラメータの種類がspeedなら myDFPlayer.volume((int)(SPD * 30.0 / 127.0)); //音量を変更する(スピード0→音量0,スピード127→音量30になるように換算) } else if (SC == 0x01 && last_play_number_STR != SPD) { //もしパラメータの種類がstretchで、最後に再生された番号でなければ if (SPD == 0) myDFPlayer.stop(); //ストレッチが0なら[停止]を送信する else if (SPD <= 126) myDFPlayer.play(SPD); //ストレッチが0以外で126以下なら、同じ値のファイル番号を再生する last_play_number_STR = SPD; //最後のファイル番号を格納する } //※ストレッチ変更で再生する場合、ファイル番号126までしか再生できない time_count = millis() + 150; //待機終了時間を150ミリ秒後に設定する while (millis() <= time_count) Serial0.read(); //待機終了時間まで待つ。待っている間のシリアル信号はすべて捨てる } }