/*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▶ // Arduino ヘッダインクルード #include ◀JQ6500_Serial.h▶
#include ◀IRremoteESP8266.h▶ #include ◀IRsend.h▶
const uint16_t kIrLed = 4; //IRsend Pin IRsend irsend(kIrLed); // Set the GPIO to be used to sending the message. uint16_t rawData[5] = {4150, 1000, 2050, 2000, 1000};
#include ◀IRrecv.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); // use HardwareSerial UART2 (16pin=RX, 17pin=TX) JQ6500_Serial mp3(Serial_df);
void printDetail(uint8_t type, int value);
#include ◀Ps3Controller.h▶
#include ◀ESP32Servo.h▶ Servo servo1; // create four servo objects 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 = 100;
int angle_servo1 = 90; // 上下 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(); // Start the receiver
servo1.setPeriodHertz(50); // Standard 50hz servo PWMサイクル:20mS servo1.attach(servo1Pin, 500, 2400); // (servo1Pin, minUs, maxUs) servo2.setPeriodHertz(50); // Standard 50hz servo PWMサイクル:20mS servo2.attach(servo2Pin, 900, 2100); // (servo1Pin, minUs, maxUs) servo3.setPeriodHertz(50); // Standard 50hz servo PWMサイクル:20mS servo3.attach(servo3Pin, 500, 2400); // (servo1Pin, minUs, maxUs)
Serial.begin(115200); Serial_df.begin(9600); // RX2 = 16, TX2 = 17 mp3.reset(); mp3.setVolume(22);
Ps3.begin("00:11:22:33:44:55"); //SixaxisPairToolで調べたmac addressに修正 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);
//エンジン始動 mp3.playFileByIndexNumber(3); delay(2000);
}
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 ▶ 90) { for (anglenow = anglenow; anglenow ▶= 90; anglenow -= 1) { servo1.write(anglenow); delay(40); } //delay(100); } else { for (anglenow = anglenow; anglenow ◀= 90; anglenow += 1) { servo1.write(anglenow); delay(40); } //delay(100); } }
if ( Ps3.event.button_down.triangle) { // up for (anglenow = anglenow; anglenow ◀= 135; anglenow += 1 ) { servo1.write(anglenow); delay(40); } //delay(100); }
if ( Ps3.event.button_down.cross) { // down for (anglenow = anglenow; anglenow ▶= 45; anglenow -= 1 ) { servo1.write(anglenow); delay(40); } //delay(100); }
if (Ps3.event.button_down.circle) { if (s == 0) { s = 1; //myDFPlayer.play(3); //エンジン始動 mp3.playFileByIndexNumber(3); delay(2000); mp3.playFileByIndexNumber(5); mp3.setLoopMode(MP3_LOOP_ONE); delay(d_time); } else { //アイドリング停止 mp3.setLoopMode(MP3_LOOP_ONE_STOP); s = 0; delay(500); } }
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(); mp3.playFileByIndexNumber(26); delay(50); servo3.write(angle_servo3 - 30); // 砲身リコイル delay(20); motor_run(180, 1, 180, 1, 1); // 車体リコイル delay(80); 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); } motor_run(60, 0, 60, 0, 1); delay(290); motor_run(0, 0, 0, 0, 1); delay(100); if (s == 1) { //Loop 5th mp3 アイドリング mp3.playFileByIndexNumber(5); mp3.setLoopMode(MP3_LOOP_ONE); delay(d_time); } }
if (Ps3.event.button_down.l1) { //銃撃 mp3.playFileByIndexNumber(24); //delay(20); for ( k = 0; k ◀ 6; k++) { digitalWrite(LED_4, HIGH); //発光 delay(80); digitalWrite(LED_4, LOW); delay(120); } if (s == 1) { //Loop 5th mp3 アイドリング 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_x ▶ 102 && pos_x ◀ 152 && pos_y ▶ 102 && pos_y ◀ 152) { motor_run(0, 0, 0, 0, 1); } */
//前進 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) { //D0 : モータスピード(左) //D1 : モータA(左)1 = HIGH / 0 = LOW //D2 : モータスピード(右) //D3 : モータB(右)1 = HIGH / 0 = LOW //D4 : LED_3 ON/OFF 1 = HIGH / 0 = LOW
//analogWrite(PWMA, D0); ledcWrite(PWMA, D0); //(チャンネル,解像度) digitalWrite(AIN1, D1); //analogWrite(PWMB, D2); 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(50); irrecv.enableIRIn(); // 受信を再開する }
void HitCHK() { if (irrecv.decode(&results)) { // 受信コードの値が if (results.value == value) { // 0x4CB0FADDだったら被弾 mp3.playFileByIndexNumber(17); Hit(); //被弾 } irrecv.resume(); delay(500); } }
// ====被弾==== 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); } } |