2021-06-21
▼リクエストがあった事や個人の備忘録として、回路図とArduinoスケッチを掲載します。
MP3プレイヤー用の効果音素材は、フリーの「効果音ラボ」などからダウンロードしました。
掲載内容に関しては個人での使用に限ってフリーとします。
【注意】
内容に関する問い合わせに関しては、原則対応いたしません。
Li-Poiバッテリなど火災などの危険性があります。
掲載内容に関しては、自己責任で利用してください。
17:
18: Arduino pro min + ミニUSBホストシールド2.0 + PS4コントローラ
19: 効果音はDFPlayer Mini
20: モータドライバはDRV8835
21:
22: 砲撃時のリコイルアクション車体+砲身
23: 主砲、機銃、ヘッドライト、ブレーキランプはミニUSBシールドのGPOUTピン0,1,2,3
24: 4個のサーボで姿勢制御動作再現
25:
26: 【操作手順】
27: SHARE+PSボタンでペアリング開始。白色インジケータランプ高速点滅。
28: 戦車の電源投入。
29: インジケータランプ青色点灯でペアリング完了。
30:
31: 【走行コントロール】
32: コントローラーの左スティック上下で前後進、
33: 右スティックの左右でステアリングを制御。
34: ステアリングを振っていくと回転軸側が減速していき(緩旋回から信地旋回)、
35: 一杯に倒すと回転軸側は停止。(信地旋回)
36: 左スティック中央で右ステアリングを一杯に振ると超信地旋回(速度50%)
37: 停止時にブレーキランプ点灯ミニUSB GPOUT- 3ピン
38:
39: 【砲身上下】右スティック上下で砲身上下。R3ボタンでセンター。
40: 【砲塔旋回】左スティック左右で砲塔旋回。離した位置で止まる。
41: 【主砲】R1ボタンで主砲発射ミニUSB GPOUT- 0ピン
42: 【機銃】L1ボタンで機銃射撃ミニUSB GPOUT- 1ピン
43: 【ヘッドライト】L3ボタンを押す毎にヘッドライト点灯、消灯。
44: ミニUSB GPOUT- 2ピン
45: 【赤外線暗視装置】PSボタンを押す毎に赤外線暗視装置が点灯、消灯。
46: ミニUSB GPOUT- 4ピン
47:
48: 【姿勢制御】
49: 左のUPボタンでお辞儀、DOWNボタンで逆お辞儀
50: 左のRIGHTボタンで右お辞儀、LEFTボタンで左お辞儀
51: 右スティック上で車高低い、スティック下で車高高い
52: 右側の△ボタンで車高UP、×ボタンで車高down、□ボタンで車高水平標準(初期値)
53: */
54:
55: #include <PS4BT.h>
56: #include <usbhub.h>
57: #ifdef dobogusinclude
58: #include <spi4teensy3.h>
59: #endif
60: #include <SPI.h>
61:
62: USB Usb;
63: //USBHub Hub1(&Usb); // Some dongles have a hub inside
64: BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
65:
66: /* You can create the instance of the PS4BT class in two ways */
67: // This will start an inquiry and then pair with the PS4 controller - you only have to do this once
68: // You will need to hold down the PS and Share button at the same time,
69: // the PS4 controller will then start to blink rapidly indicating that it is in pairing mode
70: PS4BT PS4(&Btd, PAIR);
71:
72: // After that you can simply create the instance like so and then press the PS button on the device
73: //PS4BT PS4(&Btd);
74:
75: bool printAngle, printTouch;
76: uint8_t oldL2Value, oldR2Value;
77:
78: //#include <Usb.h> // needed by Arduino IDE
79: #include <USB_Host_Shield_GPIO.h> // GPOUTピンで主砲LEDを発光させるため
80: MaxGPIO max;
81:
82: int cnt = 0 ;
83: byte ser_deta;
84:
85: #include <VarSpeedServo.h>
86: VarSpeedServo myservo_1;
87: VarSpeedServo myservo_2;
88: VarSpeedServo myservo_3;
89: VarSpeedServo myservo_4;
90: VarSpeedServo myservo_5;
91: VarSpeedServo myservo_6;
92: VarSpeedServo myservo_7;
93: int servo1_pos = 75; //servo1 砲身上下
94: int servo3_pos = 50; //servo3 砲身リコイル
95: int servoF_pos = 75; //姿勢制御前
96: int servoB_pos = 70; //姿勢制御後
97: int servo_pos = 10;
98: int difF = 65; //姿勢制御前増減値
99: int difB = 50; //姿勢制御後増減値
100: const int servo1_sp = 7; //砲身上下スピード
101: const int servo2_sp = 5; //砲塔回転スピード
102: const int servo4_sp = 25; //姿勢制御スピード
103:
104: int ch = 0;
105: int pos_y;
106: int pos_x;
107: int pos_ry;
108: int pos_rx;
109: int motor_speed;
110: int steering;
111: int PWMA = 5; // A入力2/AENABLE 左モータAIN2
112: int PWMB = 6; // B入力2/BENABLE 右モータBIN2
113: int AIN1 = 4; // A入力1/APHASE 左モータAIN1
114: int BIN1 = 7; // B入力1/BPHASE 右モータBIN1
115: int silent = 1;
116: int state = 0; //変数stateを設定
117: int state1 = 0;
118:
119: #include <SoftwareSerial.h>
120: #include <DFRobotDFPlayerMini.h>
121: SoftwareSerial mySerial(A4, A5); // DFPlayer TX,RX
122: DFRobotDFPlayerMini myDFPlayer;
123:
124: void setup() {
125: Serial.begin (115200);
126: #if !defined(__MIPSEL__)
127: while (!Serial); // Wait for serial port to connect - used on Leonardo,
128: //Teensy and other boards with built-in USB CDC serial connection
129: #endif
130: if (Usb.Init() == -1) {
131: Serial.print(F("\r\nOSC did not start"));
132: while (1); // Halt
133: }
134: Serial.print(F("\r\nPS4 Bluetooth Library Started"));
135:
136: pinMode(PWMA, OUTPUT);
137: pinMode(PWMB, OUTPUT);
138: pinMode(AIN1, OUTPUT);
139: pinMode(BIN1, OUTPUT);
140: myservo_1.attach(2); //servo1 砲身上下
141: myservo_1.write(servo1_pos, servo1_sp, true);
142: myservo_1.detach();
143: myservo_2.attach(3); //servo2 砲塔旋回
144: myservo_2.write(90);
145: //myservo_2.detach(); //centerセット時はコメントアウト
146: myservo_3.attach(8); //servo3 砲身リコイル
147: myservo_3.write(servo3_pos);
148: myservo_3.detach();
149: myservo_4.attach(A0); //servo4 右前サス
150: myservo_5.attach(A1); //servo5 左前サス
151: myservo_6.attach(A2); //servo6 右後サス
152: myservo_7.attach(A3); //servo4 左後サス
153: myservo_4.write(servoF_pos, servo4_sp);
154: myservo_5.write(servoF_pos, servo4_sp);
155: myservo_6.write(servoB_pos, servo4_sp);
156: myservo_7.write(servoB_pos, servo4_sp);
157: myservo_4.wait();
158: myservo_5.wait();
159: myservo_6.wait();
160: myservo_7.wait();
161: delay(1000);
162: myservo_4.detach();
163: myservo_5.detach();
164: myservo_6.detach();
165: myservo_7.detach();
166:
167: mySerial.begin (9600);
168: myDFPlayer.begin(mySerial);
169: if (!myDFPlayer.begin(mySerial)) { //Use softwareSerial to communicate with mp3.
170: while (true);
171: }
172: myDFPlayer.volume(25); //Set volume value (0~30).
173: myDFPlayer.play(3); //エンジン始動
174: delay(2000);
175: //myDFPlayer.loop(5); //Loop 5th mp3 アイドリング
176: //delay(200);
177: }
178:
179: void loop() {
180: Usb.Task();
181: if (PS4.connected()) {
182: // myDFPlayer.play(5);
183: // delay(100);
184: if (PS4.getButtonClick(CIRCLE)) { //エンジン音停止
185: myDFPlayer.play(3); //エンジン始動
186: delay(100);
187: }
188:
189: //砲身上下
190: if ( PS4.getButtonClick(R3)) { //CENTER
191: myservo_1.attach(2);
192: myservo_1.write(servo1_pos, servo1_sp, true);
193: // myservo_1.detach();
194: }
195: pos_ry = PS4.getAnalogHat(RightHatY);
196: if (pos_ry < 10) { // UP
197: myservo_1.attach(2);
198: myservo_1.write(servo1_pos + 40, servo1_sp, true);
199: // myservo_1.detach();
200: } else if (pos_ry > 245) { //DOWN
201: myservo_1.attach(2);
202: myservo_1.write(servo1_pos - 22, servo1_sp, true);
203: // myservo_1.detach();
204: } else { //停止
205: myservo_1.detach();
206: }
207:
208: //砲塔旋回
209: pos_rx = PS4.getAnalogHat(LeftHatX);
210: if ( pos_rx > 230) { //右旋回
211: myservo_2.attach(3);
212: myservo_2.write(97);
213: } else if (pos_rx < 25) { //左旋回
214: myservo_2.attach(3);
215: myservo_2.write(83);
216: } else { //停止
217: //myservo_2.attach(3); //回転初めに一瞬反対側に回転するのでコメントアウトする
218: myservo_2.write(90);
219: myservo_2.detach();
220: }
221:
222: //砲撃+ リコイル
223: if (PS4.getButtonClick(R1) && ch == 0 ) {
224: myDFPlayer.play(2);
225: delay(100);
226: max.write(0, HIGH); //主砲発光
227: myservo_3.attach(8);
228: myservo_3.write(servo3_pos + 70, 255); //砲身リコイル
229: //myservo_3.wait();
230: delay(100);
231: motor_run(180, 1, 180, 1, 1);
232: ch = 2000; //約2秒間は砲撃不可
233: delay(100);
234: motor_run(0, 0, 0, 0, 1);
235: max.write(0, LOW); //主砲消灯
236: delay(100);
237: myservo_3.write(servo3_pos, 20);
238: motor_run(100, 0, 100, 0, 1);
239: delay(200);
240: motor_run(0, 0, 0, 0, 1);
241: myservo_3.wait();
242: delay(640);
243: myservo_3.detach();
244: } else {
245: if (ch > 0) {
246: ch--;
247: }
248: }
249:
250: //銃撃
251: if ( PS4.getButtonClick(L1)) {
252: myDFPlayer.play(10);
253: delay(100);
254: for ( int i = 0; i < 5 ; i++) {
255: max.write(1, HIGH); //機銃発光
256: delay(80);
257: max.write(1, LOW); //機銃消灯
258: delay(120);
259: }
260: }
261:
262: //ヘッドライト
263: if (PS4.getButtonClick(L3)) {
264: state = 1 - state;
265: } // L3ボタンを押す毎にstateが変化する
266: if (state == 1) {
267: max.write(2, HIGH); //点灯
268: } else {
269: max.write(2, LOW); //消灯
270: }
271:
272: //赤外線暗視装置
273: if (PS4.getButtonClick(PS)) {
274: state1 = 1 - state1;
275: } // PSボタンを押す毎にstateが変化する
276: if (state1 == 1) {
277: max.write(4, HIGH); //点灯
278: } else {
279: max.write(4, LOW); //消灯
280: }
281:
282: //走行コントロール
283: pos_y = PS4.getAnalogHat(LeftHatY);
284: pos_x = PS4.getAnalogHat(RightHatX);
285:
286: //左スティックがセンター付近は停止(ブレーキ)
287: if (pos_x >= 102 && pos_x <= 152 && pos_y >= 102 && pos_y <= 152) {
288: motor_run(0, 0, 0, 0, 1);
289: }
290:
291: //前進
292: if (pos_y <= 102 && pos_x >= 102 && pos_x <= 152) {
293: motor_speed = map(pos_y, 102, 0, 0, 255);
294: motor_run(motor_speed, 0, motor_speed, 0, 0);
295: }
296:
297: //後進
298: else if ( pos_y >= 152 && pos_x >= 102 && pos_x <= 152) {
299: motor_speed = map(pos_y, 152, 255, 0, 255) ;
300: motor_run(motor_speed, 1, motor_speed, 1, 0);
301: }
302:
303: //前進右緩旋回、信地旋回
304: //else if ( pos_y <= 102 && pos_x > 152 && pos_x <= 245) {
305: else if ( pos_y <= 102 && pos_x > 152) {
306: motor_speed = map(pos_y, 102, 0, 0, 255);
307: steering = motor_speed * (1.00 - (map(pos_x, 152, 255, 0, 255) / 255.00));
308: motor_run(motor_speed, 0, steering, 0, 0);
309: }
310:
311: //前進左緩旋回、信地旋回
312: //else if ( pos_y <= 102 && pos_x < 102 && pos_x >= 10) {
313: else if ( pos_y <= 102 && pos_x < 102) {
314: motor_speed = map(pos_y, 102, 0, 0, 255);
315: steering = motor_speed * (1.00 - (map(pos_x, 102, 0, 0, 255) / 255.00));
316: motor_run(steering, 0, motor_speed, 0, 0);
317: }
318:
319: //後進右緩旋回、信地旋回
320: //else if ( pos_y >= 152 && pos_x > 152 && pos_x <= 245) {
321: else if ( pos_y >= 152 && pos_x > 152 ) {
322: motor_speed = map(pos_y, 152, 255, 0, 255);
323: steering = motor_speed * (1.00 - (map(pos_x, 152, 255, 0, 255) / 255.00));
324: motor_run(motor_speed, 1, steering, 1, 0);
325: }
326:
327: //後進左緩旋回、信地旋回
328: //else if ( pos_y >= 152 && pos_x < 102 && pos_x >= 10) {
329: else if ( pos_y >= 152 && pos_x < 102 ) {
330: motor_speed = map(pos_y, 152, 255, 0, 255);
331: steering = motor_speed * (1.00 - (map(pos_x, 102, 0, 0, 255) / 255.00));
332: motor_run(steering, 1, motor_speed, 1, 0);
333: }
334:
335: //右超信地旋回
336: else if (pos_x > 245 && pos_y >= 102 && pos_y <= 152) {
337: motor_speed = 128;
338: motor_run(motor_speed, 0, motor_speed, 1, 0);
339: }
340:
341: //左超信地旋回
342: else if (pos_x < 10 && pos_y >= 102 && pos_y <= 152) {
343: motor_speed = 128;
344: motor_run(motor_speed, 1, motor_speed, 0, 0);
345: }
346:
347: else { //停止(ブレーキ)
348: motor_run(0, 0, 0, 0, 1);
349: }
350:
351: //姿勢制御
352: if ( PS4.getButtonClick(UP)) { //お辞儀
353: siseiseigyo(servoF_pos - difF, servoF_pos + difF, servoB_pos + difB, servoB_pos - difB);
354: }
355: if ( PS4.getButtonClick(DOWN)) { //逆お辞儀
356: siseiseigyo(servoF_pos + difF, servoF_pos - difF, servoB_pos - difB, servoB_pos + difB);
357: }
358: if ( PS4.getButtonClick(RIGHT)) { //右お辞儀
359: siseiseigyo(servoF_pos - difF, servoF_pos - difF, servoB_pos - difB, servoB_pos - difB);
360: }
361: if ( PS4.getButtonClick(LEFT)) { //左お辞儀
362: siseiseigyo(servoF_pos + difF, servoF_pos + difF, servoB_pos + difB, servoB_pos + difB);
363: }
364:
365: if (PS4.getButtonClick(CROSS)) { //車高下げる
366: siseiseigyo(servoF_pos - difF, servoF_pos + difF, servoB_pos - difB, servoB_pos + difB);
367: }
368: if (PS4.getButtonClick(TRIANGLE)) { //車高上げる
369: siseiseigyo(servoF_pos + difF, servoF_pos - difF, servoB_pos + difB, servoB_pos - difB);
370: }
371: if (PS4.getButtonClick(SQUARE)) { //車高標準水平
372: siseiseigyo(servoF_pos, servoF_pos, servoB_pos, servoB_pos);
373: }
374: }
375: }
376:
377: void motor_run(int D0, int D1, int D2, int D3, int D4) {
378: /* D0 : モータスピード(左)
379: D1 : モータA(左)1 = HIGH / 0 = LOW
380: D2 : モータスピード(右)
381: D3 : モータB(右)1 = HIGH / 0 = LOW
382: D4 : LED_3 ON/OFF 1 = HIGH / 0 = LOW
383: */
384: analogWrite(PWMA, D0);
385: digitalWrite(AIN1, D1);
386: analogWrite(PWMB, D2);
387: digitalWrite(BIN1, D3);
388: //digitalWrite(LED_3, D4);
389: if (D4 == 1) {
390: max.write(3, HIGH); //ブレーキ点灯
391: } else {
392: max.write(3, LOW); //ブレーキ消灯
393: }
394: }
395:
396: void siseiseigyo(int E4, int E5, int E6, int E7) {
397: myservo_4.attach(A0); //servo4 右前サス
398: myservo_5.attach(A1); //servo5 左前サス
399: myservo_6.attach(A2); //servo6 右後サス
400: myservo_7.attach(A3); //servo4 左後サス
401:
402: myservo_4.write(E4, servo4_sp);
403: myservo_5.write(E5, servo4_sp);
404: myservo_6.write(E6, servo4_sp);
405: myservo_7.write(E7, servo4_sp);
406: myservo_4.wait();
407: myservo_5.wait();
408: myservo_6.wait();
409: myservo_7.wait();
410: delay(100);
411:
412: myservo_4.detach();
413: myservo_5.detach();
414: myservo_6.detach();
415: myservo_7.detach();
416:
417: }