2022-06-08
ESP32 Dev ModuleでRC可動戦車コントロールの第2段、今回はIR対戦仕様の実験です。
Arduino用に作成したスケッチをESP32用に変更します。
ESP32用のIR送受信のライブラリは IRremoteESP8266.h を使います。
コマンドは少し変更するだけで利用できました。
注意が必要なのは、自分の送信した赤外線信号の反射を誤受信しない様に、
送信の前後は受信中止にしておくことが必要ということです。
Arduino用は受信再開コマンドだけでよかったのですが、ESP32用は受信中止コマンドも必要でした。
▼M26実装基板と同じ形に組上げました。
左下がモータドライバーDVR8835(秋月電子)、右下は5V出力DC昇圧コンバータ(Amazon)。
ESP32の左側にJQ6500(MP3プレーヤー)のUSBコネクタが覗いています。
▼ギヤードモータx2、サーボモータx3(内1個は連続回転仕様)、
LED、赤外線LED、赤外線受光素子、スピーカなどを接続。
▼IR対戦用送受信チェッカ
▼テスト機器全景
▼実験中の動画です。
ESP32 Dev ModuleでRC戦車コントロール(IR対戦仕様)
追伸:画像撮影後ですが、技適取得済の正規PS3コントローラの中古を○○カリで入手しました。
▼回路
回路図中でブレーキ、ヘッドライトのLEDは1個で書いてありますが、
実態は太線枠内の様に左右2個です。
IR発光LEDの電流はトランジスタ(2SC1815など)を介して増幅しています。
▼スケッチ(プログラム)
- /*PS3_ESP32_tank_JQ6500mp3_DRV8835_IR_v6.0a
- 2022-06-07
- 【操作方法】
- PS3コントローラで操縦します。
- 車体の電源をONし、コントローラのPSボタンでペアリング開始。
- インジケータランプ4個高速点滅後に1個点灯でペアリング完了。
- コントローラーの左スティック上下で前後進、右スティックの左右でステアリングを制御。
- ステアリングを切っていくと緩旋回、一杯切るとで信地旋回する。
- また、左スティック中央でステアリング左右一杯で超信地旋回。
- △ボタンで砲身UP、?ボタンで砲身DOWN、□ボタンでセンター位置になる。
- 左スティック左右で砲塔旋回。離した位置で止まる。
- R1ボタンで主砲発射。L1ボタンで機銃射撃。
- RIGHTボタンでヘッドライト点灯、LEFTボタンで消灯。
- 砲撃時のリコイルアクション車体+砲身
- IR発光、受光装置を付けるとIR対戦可能。
- メインCPU: ESP32 DevKitC
- モータドライバ:DRV8835
- MP3プレイヤー:JQ6500 MP3プレイヤーモジュール
- */
- #include <Arduino.h>
- //#include "SoftwareSerial.h"
- //#include "DFRobotDFPlayerMini.h"
- #include <JQ6500_Serial.h>
- #include <IRremoteESP8266.h>
- #include <IRsend.h>
- const uint16_t kIrLed = 4;
- IRsend irsend(kIrLed);
- uint16_t rawData[5] = {4150, 1000, 2050, 2000, 1000};
- #include <IRrecv.h>
- //#include <IRac.h>
- //#include <IRtext.h>
- #include <IRutils.h>
- const uint16_t kRecvPin = 13;
- IRrecv irrecv(kRecvPin);
- decode_results results;
- //const long sign_hit = 0x4CB0FADD;
- const uint32_t value = 0x4CB0FADD;
- HardwareSerial Serial_df(2);
- JQ6500_Serial mp3(Serial_df);
- void printDetail(uint8_t type, int value);
- #include <Ps3Controller.h>
- #include <ESP32Servo.h>
- Servo servo1;
- int servo1Pin = 27;
- Servo servo2;
- int servo2Pin = 14;
- Servo servo3;
- int servo3Pin = 12;
- int LED_1 = 23; //ブレーキランプ
- int LED_2 = 22; //ヘッドライト
- int LED_3 = 19; //砲撃
- int LED_4 = 18; //銃撃
- int k = 0;
- int s = 0;
- int d_time = 30;
- int angle_servo1 = 95; // 上下
- int anglenow = angle_servo1 ;
- int angle_servo3 = 90; // リコイル
- int motor_speed;
- float steering;
- int pos_y;
- int pos_x;
- int pos_lx;
- int AIN1 = 32; // A入力1/APHASE 左モータ AIN1
- int BIN1 = 25; // B入力1/BPHASE 右モータ BIN1
- int PWMApin = 33; //A5; // A入力2/AENABLE 左モータ AIN2 IO33 A5
- int PWMBpin = 26; //A19; // B入力2/BENABLE 右モータ BIN2 IO26 (IO0は起動時不安定)A19
- int PWMA = 2; //PWMAチャンネル 0=NG 1=NG 0〜15
- int PWMB = 3; //PWMBチャンネル 0=NG 1=NG 0〜15
- int cnt = 0;
- void setup() {
- irsend.begin();
- irrecv.enableIRIn();
- servo1.setPeriodHertz(50);
- servo1.attach(servo1Pin, 500, 2400);
- servo2.setPeriodHertz(50);
- servo2.attach(servo2Pin, 900, 2100);
- servo3.setPeriodHertz(50);
- servo3.attach(servo3Pin, 500, 2400);
- Serial.begin(115200);
- Serial_df.begin(9600); // RX2 = 16, TX2 = 17
- mp3.reset();
- mp3.setVolume(25);
- Ps3.begin("00:11:22:33:44:55"); // PS3-Eコントローラ SixaxisPairToolで調べたmac adresに修正
- Serial.println("PS3 Ready");
- ledcSetup(PWMA, 12000, 8); //チャンネル,周波数,解像度(8bit=256段階)
- ledcAttachPin(PWMApin, PWMA); //ledPinをPWMCHチャンネルに接続
- ledcSetup(PWMB, 12000, 8); //チャンネル,周波数,解像度(8bit=256段階)
- ledcAttachPin(PWMBpin, PWMB); //ledPinをPWMCHチャンネルに接続
- pinMode(AIN1, OUTPUT);
- pinMode(BIN1, OUTPUT);
- pinMode(LED_1, OUTPUT);
- pinMode(LED_2, OUTPUT);
- pinMode(LED_3, OUTPUT);
- pinMode(LED_4, OUTPUT);
- LEDtenmetsu(LED_2);
- servo1.write(angle_servo1); // 0 - 180
- delay(100);
- servo2.write(90); // 0 - 180
- delay(100);
- servo3.write(angle_servo3); // 0 - 180
- delay(100);
- //myDFPlayer.play(3); //エンジン始動
- mp3.playFileByIndexNumber(3);
- delay(1000);
- }
- void loop() {
- //被弾チェック
- HitCHK();
- if (Ps3.isConnected()) {
- pos_lx = Ps3.data.analog.stick.lx;
- pos_lx = pos_lx + 128;
- //砲塔旋回
- if ( pos_lx > 230) { //右旋回
- servo2.write(80);
- } else if (pos_lx < 25) { //左旋回
- servo2.write(100);
- } else { //停止
- servo2.write(90);
- }
- //砲身上下
- if ( Ps3.event.button_down.square) { // center
- if (anglenow > angle_servo1) {
- for (anglenow = anglenow; anglenow >= angle_servo1; anglenow -= 1) {
- servo1.write(anglenow);
- delay(40);
- }
- }
- else {
- for (anglenow = anglenow; anglenow <= angle_servo1; anglenow += 1) {
- servo1.write(anglenow);
- delay(40);
- }
- }
- }
- if ( Ps3.event.button_down.triangle) { // up
- for (anglenow = anglenow; anglenow <= (angle_servo1+60); anglenow += 1 ) {
- servo1.write(anglenow);
- delay(40);
- }
- }
- if ( Ps3.event.button_down.cross) { // down
- for (anglenow = anglenow; anglenow >= (angle_servo1-15); anglenow -= 1 ) {
- servo1.write(anglenow);
- delay(40);
- }
- }
- if (Ps3.event.button_down.circle) {
- if (s == 0) {
- s = 1;
- //myDFPlayer.play(3); //エンジン始動
- mp3.playFileByIndexNumber(3);
- delay(1000);
- mp3.playFileByIndexNumber(5);
- mp3.setLoopMode(MP3_LOOP_ONE);
- delay(d_time);
- } else {
- mp3.setLoopMode(MP3_LOOP_ONE_STOP);
- s = 0;
- delay(100);
- }
- }
- if (Ps3.event.button_down.r3) {
- mp3.setLoopMode(MP3_LOOP_ONE_STOP);
- s = 0;
- }
- if (Ps3.event.button_down.right) {
- digitalWrite(LED_2, HIGH); // Headlight ON
- }
- if (Ps3.event.button_down.left) {
- digitalWrite(LED_2, LOW); // Headlight off
- }
- if (Ps3.event.button_down.r1) { //砲撃 + リコイル(砲身&車体)
- digitalWrite(LED_3, HIGH); //主砲発光
- fire();
- //myDFPlayer.play(26);
- mp3.playFileByIndexNumber(2);
- delay(50);
- servo3.write(angle_servo3 - 40); // 砲身リコイル
- delay(20);
- motor_run(180, 1, 180, 1, 1); // 車体リコイル
- delay(60);
- motor_run(0, 0, 0, 0, 1);
- digitalWrite(LED_3, LOW);
- for (int ang3 = (angle_servo3 - 30); ang3 <= angle_servo3; ang3 += 1 ) {
- servo3.write(ang3);
- delay(20);
- }
- //digitalWrite(LED_3, LOW);
- motor_run(100, 0, 100, 0, 1);
- delay(80);
- motor_run(0, 0, 0, 0, 1);
- delay(100);
- if (s == 1) {
- //myDFPlayer.loop(5); //Loop 5th mp3 アイドリング
- mp3.playFileByIndexNumber(5);
- mp3.setLoopMode(MP3_LOOP_ONE);
- delay(d_time);
- }
- }
- if (Ps3.event.button_down.l1) { //銃撃
- mp3.playFileByIndexNumber(24);
- for ( k = 0; k < 6; k++) {
- digitalWrite(LED_4, HIGH); //発光
- delay(80);
- digitalWrite(LED_4, LOW);
- delay(120);
- }
- if (s == 1) {
- mp3.playFileByIndexNumber(5);
- mp3.setLoopMode(MP3_LOOP_ONE);
- delay(d_time);
- }
- }
- //走行コントロール
- pos_y = Ps3.data.analog.stick.ly;
- pos_x = Ps3.data.analog.stick.rx;
- pos_y = pos_y + 128;
- pos_x = pos_x + 128;
- //前進
- if (pos_y <= 102 && pos_x >= 102 && pos_x <= 152) {
- motor_speed = map(pos_y, 102, 0, 0, 255);
- motor_run(motor_speed, 0, motor_speed, 0, 0);
- }
- //後進
- else if ( pos_y >= 152 && pos_x >= 102 && pos_x <= 152) {
- motor_speed = map(pos_y, 152, 255, 0, 255) ;
- motor_run(motor_speed, 1, motor_speed, 1, 0);
- }
- //前進右緩旋回、信地旋回
- //else if ( pos_y <= 102 && pos_x > 152 && pos_x <= 245) {
- else if ( pos_y <= 102 && pos_x >= 152) {
- motor_speed = map(pos_y, 102, 0, 0, 255);
- steering = motor_speed * (1.00 - (map(pos_x, 152, 255, 0, 255) / 255.00));
- motor_run(motor_speed, 0, steering, 0, 0);
- }
- //前進左緩旋回、信地旋回
- //else if ( pos_y <= 102 && pos_x < 102 && pos_x >= 10) {
- else if ( pos_y <= 102 && pos_x <= 102) {
- motor_speed = map(pos_y, 102, 0, 0, 255);
- steering = motor_speed * (1.00 - (map(pos_x, 102, 0, 0, 255) / 255.00));
- motor_run(steering, 0, motor_speed, 0, 0);
- }
- //後進右緩旋回、信地旋回
- //else if ( pos_y >= 152 && pos_x > 152 && pos_x <= 245) {
- else if ( pos_y >= 152 && pos_x >= 152 ) {
- motor_speed = map(pos_y, 152, 255, 0, 255);
- steering = motor_speed * (1.00 - (map(pos_x, 152, 255, 0, 255) / 255.00));
- motor_run(motor_speed, 1, steering, 1, 0);
- }
- //後進左緩旋回、信地旋回
- //else if ( pos_y >= 152 && pos_x < 102 && pos_x >= 10) {
- else if ( pos_y >= 152 && pos_x <= 102 ) {
- motor_speed = map(pos_y, 152, 255, 0, 255);
- steering = motor_speed * (1.00 - (map(pos_x, 102, 0, 0, 255) / 255.00));
- motor_run(steering, 1, motor_speed, 1, 0);
- }
- //右超信地旋回
- else if (pos_x >= 245 && pos_y >= 102 && pos_y <= 152) {
- motor_speed = 204;
- motor_run(motor_speed, 0, motor_speed, 1, 0);
- }
- //左超信地旋回
- else if (pos_x <= 10 && pos_y >= 102 && pos_y <= 152) {
- motor_speed = 204;
- motor_run(motor_speed, 1, motor_speed, 0, 0);
- }
- else { //停止(ブレーキ)
- motor_run(0, 0, 0, 0, 1);
- }
- }
- }
- void motor_run(int D0, int D1, int D2, int D3, int D4) {
- ledcWrite(PWMA, D0); //(チャンネル,解像度)
- digitalWrite(AIN1, D1);
- ledcWrite(PWMB, D2); //(チャンネル,解像度)
- digitalWrite(BIN1, D3);
- digitalWrite(LED_1, D4);
- }
- void LEDtenmetsu(int LED) {
- for (int i = 0; i < 2; i++) {
- digitalWrite(LED, HIGH);
- delay(500);
- digitalWrite(LED, LOW);
- delay(500);
- }
- }
- void fire() {
- irrecv.disableIRIn(); // 自らの送信を誤受信しないように受信を停止
- irsend.sendRaw(rawData, 5, 38); //irsend.sendRaw(data buf, length, hertz)
- delay(10);
- irrecv.enableIRIn(); // 受信を再開する
- }
- void HitCHK() {
- if (irrecv.decode(&results)) { // 受信コードの値が
- if (results.value == value) { // 0x4CB0FADDだったら被弾
- mp3.playFileByIndexNumber(17);
- Hit(); //被弾
- }
- irrecv.resume();
- delay(10);
- }
- }
- // ====被弾====
- void Hit() {
- motor_run(180, 1, 180, 0, 0);
- delay(100);
- motor_run(0, 0, 0, 0, 1);
- delay(50);
- motor_run(180, 0, 180, 1, 0);
- delay(80);
- motor_run(0, 0, 0, 0, 1);
- delay(50);
- cnt++;
- if ( cnt >= 5 ) {
- mp3.playFileByIndexNumber(18);
- motor_run(0, 0, 0, 0, 0);
- for ( int i = 0; i < 15 ; i++) {
- digitalWrite(LED_2, HIGH);
- delay(1000);
- digitalWrite(LED_2, LOW);
- delay(1000);
- } //復活までに15秒
- cnt = 0;
- } else {
- delay(1000);
- }
- }
※コメント投稿者のブログIDはブログ作成者のみに通知されます