2021-07-26
要望があったので、2年前に製作したRC可動化キングタイガーの回路図を掲載します。
当時の資料を探しましたが、時間がたっていますので、違っているところがあるかもしれません。
1: /* PS4BT_arduino_pro mini_tank_DRV8835_KING_TIGER_ser_ver04c
9: 【操作方法】
10: SHARE PSボタンでペアリング開始。インジケータランプ高速点滅。
11: 戦車の電源投入。
12: インジケータランプ青色点灯でペアリング完了。
13:
14: 【走行コントロール】
15: コントローラーの左スティック上下で前後進、
16: 右スティックの左右でステアリングを制御。
17: ステアリングを振っていくと回転軸側が減速していき(緩旋回から信地旋回)、
18: 一杯に倒すと回転軸側は停止。(信地旋回)
19: 左スティック中央で右ステアリングを一杯に振ると超信地旋回(速度50%)
20:
21: 【砲身上下】右スティック上下で砲身上下。R3ボタンでセンター。
22: // 右側の△ボタンで砲身上、×ボタンで砲身下、□ボタンでセンター位置になる。
23: 【砲塔旋回】左スティック左右で砲塔旋回。離した位置で止まる。
24: 【主砲】R1ボタンで主砲発射
25: 【機銃】L1ボタンで機銃射撃
26: 【ヘッドライト】RIGHTボタンで点灯、LEFTボタンで消灯。
27: 【車間表示灯】UPボタンで点灯、DOWNボタンで消灯。
28:
29: モータドライバはDRX8835
30: 砲撃時のリコイルアクション車体
31: 主砲発光はミニUSBシールドのGPOUTピン0を使用
32:
33: サブシステムで実行
34: irremote PIN3 赤外線発光(砲撃)システム
35: 赤外線受光モジュール出力を接続し、被弾処理を追加
36: MP3プレーヤーで効果音を発生
37:
38: シリアル通信データ
39: エンジン始動100
40: 砲撃101
41: 銃撃102
42: 被弾103
43: 破壊105
44: エンジン停止/始動110
45:
46: Arduino IDE 1.8.7
47: 最大30720バイトのフラッシュメモリのうち、スケッチが23682バイト(77%)を使っています。
48: 最大2048バイトのRAMのうち、グローバル変数が1146バイト(55%)を使っていて、
49: ローカル変数で902バイト使うことができます。
50:
51: 最大30720バイトのフラッシュメモリのうち、スケッチが23818バイト(77%)を使っています。
52: 最大2048バイトのRAMのうち、グローバル変数が1146バイト(55%)を使っていて、
53: ローカル変数で902バイト使うことができます。
54: */
55:
56: #include <PS4BT.h>
57: #include <usbhub.h>
58:
59: #ifdef dobogusinclude
60: #include <spi4teensy3.h>
61: #endif
62: #include <SPI.h>
63:
64: USB Usb;
65: //USBHub Hub1(&Usb); // Some dongles have a hub inside
66: BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
67:
68: /* You can create the instance of the PS4BT class in two ways */
69: // This will start an inquiry and then pair with the PS4 controller - you only have to do this once
70: // You will need to hold down the PS and Share button at the same time, the PS4 controller will then start to blink rapidly
indicating that it is in pairing mode
71: PS4BT PS4(&Btd, PAIR);
72:
73: // After that you can simply create the instance like so and then press the PS button on the device
74: //PS4BT PS4(&Btd);
75: //Local Bluetooth Address: 00:1B:DC:00:4B:53 BTドングルE
76:
77:
78: bool printAngle, printTouch;
79: uint8_t oldL2Value, oldR2Value;
80:
81: //#include <Usb.h> // needed by Arduino IDE
82: #include <USB_Host_Shield_GPIO.h> // GPOUTピンで主砲LEDを発光させるため
83: MaxGPIO max;
84:
85: int cnt = 0 ;
86: byte ser_deta;
87:
88: #include <VarSpeedServo.h>
89: VarSpeedServo myservo_1;
90: VarSpeedServo myservo_2;
91: VarSpeedServo myservo_3;
92: int servo1_pos = 60;
93: int servo_pos = servo1_pos;
94: const int servo1_sp = 5;
95: const int servo2_sp = 1;
96: int servo3_pos = 50;
97: int ch = 0;
98: int pos_y;
99: int pos_x;
100: int pos_ry;
101: int pos_rx;
102: int motor_speed;
103: float steering;
104: int PWMA = 5; // A入力2/AENABLE 左モータAIN2
105: int PWMB = 6; // B入力2/BENABLE 右モータBIN2
106: int AIN1 = 4; // A入力1/APHASE 左モータAIN1
107: int BIN1 = 7; // B入力1/BPHASE 右モータBIN1
108: const int LED_2 = 2; //機銃
109: const int LED_3 = 8; //ブレーキランプ
110: const int LED_4 = A2; //車間表示灯
111:
112: void setup() {
113: Serial.begin (115200);
114: #if !defined(__MIPSEL__)
115: while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial
connection
116: #endif
117: if (Usb.Init() == -1) {
118: Serial.print(F("\r\nOSC did not start"));
119: while (1); // Halt
120: }
121: Serial.print(F("\r\nPS4 Bluetooth Library Started"));
122:
123: pinMode(PWMA, OUTPUT);
124: pinMode(PWMB, OUTPUT);
125: pinMode(AIN1, OUTPUT);
126: pinMode(BIN1, OUTPUT);
127: pinMode(LED_2, OUTPUT); //機銃
128: pinMode(LED_3, OUTPUT); //ブレーキライト
129: pinMode(LED_4, OUTPUT); //車間表示灯
130: pinMode(A4, OUTPUT); //servo 1 砲身上下
131: pinMode(A5, OUTPUT); //servo 2 砲塔旋回
132: pinMode(A1, OUTPUT); //servo 3 砲身リコイル
133:
134: //ペアリングミス改善のためサーボの設定はBT接続の後にする
135: myservo_1.attach(A4); //servo1 砲身上下
136: myservo_1.write(servo_pos);
137: myservo_2.attach(A5); //servo2 砲塔旋回
138: myservo_2.write(90);
139: //myservo_2.detach();
140: myservo_3.attach(A1); //servo3 砲身リコイル
141: myservo_3.write(servo3_pos);
142:
143: }
144:
145: void loop() {
146: Usb.Task();
147: if (PS4.connected()) {
148: //受信バッファに2バイト(ヘッダ+データ)以上のデータが着ているか確認
149: if ( Serial.available() >= 2 ) {
150: // ヘッダの確認
151: if ( Serial.read() == 'H' ) {
152: ser_deta = Serial.read() ;
153: }
154: }
155:
156: if (ser_deta == 103) { //被弾信号受信
157: Hit();
158: }
159:
160: //エンジン音停止
161: if (PS4.getButtonClick(CIRCLE)) {
162: sendData(110);
163: }
164:
165: //スティックの中央は127だけどピタリと止まらないので+-10ほど余裕を持たせる。
166: //左スティック上下の値(最上部0、中央127、最下部255)を読み込む
167:
168: // 砲身UP/DOWN
169: if ( PS4.getButtonClick(R3)) { //CENTER
170: myservo_1.attach(A4);
171: myservo_1.write(servo1_pos, servo1_sp, true);
172: // myservo_1.detach();
173: }
174: pos_ry = PS4.getAnalogHat(RightHatY);
175: if (pos_ry < 10) { // UP
176: myservo_1.attach(A4);
177: myservo_1.write(servo1_pos - 40, servo1_sp, true);
178: // myservo_1.detach();
179: } else if (pos_ry > 245) { //DOWN
180: myservo_1.attach(A4);
181: myservo_1.write(servo1_pos +25, servo1_sp, true);
182: // myservo_1.detach();
183: } else { //停止
184: myservo_1.detach();
185: }
186: /*
187: if (PS4.getButtonClick(TRIANGLE)) { // UP
188: myservo_1.attach(A4);
189: myservo_1.write((servo_pos - 35), servo1_sp, true);
190: myservo_1.detach();
191:
192: } else if (PS4.getButtonClick(CROSS)) { //DOWN
193: myservo_1.attach(A4);
194: myservo_1.write((servo_pos + 35), servo1_sp, true);
195: myservo_1.detach();
196:
197: } else if (PS4.getButtonClick(SQUARE)) { //CENTER
198: myservo_1.attach(A4);
199: myservo_1.write(servo_pos, servo1_sp, true);
200: myservo_1.detach();
201: }
202: */
203:
204: //砲塔旋回
205: //pos_rx = PS4.getAnalogHat(LeftHatX);
206: if ( PS4.getAnalogHat(LeftHatX) > 230) { //右旋回
207: myservo_2.attach(A5);
208: myservo_2.write(95, servo2_sp);
209: } else if (PS4.getAnalogHat(LeftHatX) < 26) { //左旋回
210: myservo_2.attach(A5);
211: myservo_2.write(85, servo2_sp);
212: } else { //停止
213: myservo_2.write(90, 255);
214: myservo_2.detach();
215: }
216:
217: //砲撃+ リコイル
218:
219: if (PS4.getButtonClick(R1) && ch == 0 ) {
220: sendData(101); // 砲撃信号送信
221: delay(100);
222: max.write(0, HIGH); //主砲発光
223: //myservo_3.attach(A1);
224: myservo_3.write(servo3_pos+50, 255); //砲身リコイル
225: delay(100);
226: motor_run(200, 1, 200, 1, 1);
227: ch = 2000; //約2秒間は砲撃不可
228: myservo_3.write(servo3_pos, 15);
229: delay(100);
230: motor_run(0, 0, 0, 0, 1);
231: // myservo_3.write(servo3_pos, 20);
232: delay(40);
233: max.write(0, LOW); //主砲消灯
234: motor_run(100, 0, 100, 0, 1);
235: delay(260);
236: motor_run(0, 0, 0, 0, 1);
237: delay(140);
238: //myservo_3.detach();
239: } else {
240: if (ch > 0) {
241: ch--;
242: }
243: }
244:
245: //銃撃
246: if ( PS4.getButtonClick(L1)) {
247: sendData(102); // 銃撃信号送信
248: delay(100);
249: for ( int i = 0; i < 5 ; i++) {
250: digitalWrite(LED_2, HIGH);
251: delay(80);
252: digitalWrite(LED_2, LOW);
253: delay(120);
254: }
255: }
256:
257:
258: //ヘッドライト
259: if (PS4.getButtonClick(RIGHT)) { //点灯
260: max.write(1, HIGH);
261: }
262:
263: if (PS4.getButtonClick(LEFT)) { //消灯
264: max.write(1, LOW);
265: }
266:
267: //車間表示灯
268: if (PS4.getButtonClick(UP)) { //点灯
269: digitalWrite(LED_4, HIGH);
270: }
271:
272: if (PS4.getButtonClick(DOWN)) { //消灯
273: digitalWrite(LED_4, LOW);
274: }
275:
276:
277: //走行コントロール
278: pos_y = PS4.getAnalogHat(LeftHatY);
279: pos_x = PS4.getAnalogHat(RightHatX);
280:
281: /*
282: //左スティックがセンター付近は停止(ブレーキ)
283: if (pos_x >= 102 && pos_x <= 152 && pos_y >= 102 && pos_y <= 152) {
284: motor_run(0, 0, 0, 0, 1);
285: }
286: */
287:
288: //前進
289: if (pos_y <= 102 && pos_x >= 102 && pos_x <= 152) {
290: motor_speed = map(pos_y, 102, 0, 0, 255);
291: motor_run(motor_speed, 0, motor_speed, 0, 0);
292: }
293:
294: //後進
295: else if ( pos_y >= 152 && pos_x >= 102 && pos_x <= 152) {
296: motor_speed = map(pos_y, 152, 255, 0, 255) ;
297: motor_run(motor_speed, 1, motor_speed, 1, 0);
298: }
299:
300: //前進右緩旋回、信地旋回
301: //else if ( pos_y <= 102 && pos_x > 152 && pos_x <= 245) {
302: else if ( pos_y <= 102 && pos_x > 152) {
303: motor_speed = map(pos_y, 102, 0, 0, 255);
304: steering = motor_speed * (1.00 - (map(pos_x, 152, 255, 0, 255) / 255.00));
305: motor_run(motor_speed, 0, steering, 0, 0);
306: }
307:
308: //前進左緩旋回、信地旋回
309: //else if ( pos_y <= 102 && pos_x < 102 && pos_x >= 10) {
310: else if ( pos_y <= 102 && pos_x < 102) {
311: motor_speed = map(pos_y, 102, 0, 0, 255);
312: steering = motor_speed * (1.00 - (map(pos_x, 102, 0, 0, 255) / 255.00));
313: motor_run(steering, 0, motor_speed, 0, 0);
314: }
315:
316: //後進右緩旋回、信地旋回
317: //else if ( pos_y >= 152 && pos_x > 152 && pos_x <= 245) {
318: else if ( pos_y >= 152 && pos_x > 152 ) {
319: motor_speed = map(pos_y, 152, 255, 0, 255);
320: steering = motor_speed * (1.00 - (map(pos_x, 152, 255, 0, 255) / 255.00));
321: motor_run(motor_speed, 1, steering, 1, 0);
322: }
323:
324: //後進左緩旋回、信地旋回
325: //else if ( pos_y >= 152 && pos_x < 102 && pos_x >= 10) {
326: else if ( pos_y >= 152 && pos_x < 102 ) {
327: motor_speed = map(pos_y, 152, 255, 0, 255);
328: steering = motor_speed * (1.00 - (map(pos_x, 102, 0, 0, 255) / 255.00));
329: motor_run(steering, 1, motor_speed, 1, 0);
330: }
331:
332: //右超信地旋回
333: else if (pos_x > 245 && pos_y >= 102 && pos_y <= 152) {
334: motor_speed = 128;
335: motor_run(motor_speed, 0, motor_speed, 1, 0);
336: }
337:
338: //左超信地旋回
339: else if (pos_x < 10 && pos_y >= 102 && pos_y <= 152) {
340: motor_speed = 128;
341: motor_run(motor_speed, 1, motor_speed, 0, 0);
342: }
343:
344: else { //停止(ブレーキ)
345: motor_run(0, 0, 0, 0, 1);
346: }
347: }
348: }
349:
350: void motor_run(int D0, int D1, int D2, int D3, int D4) {
351: /* D0 : モータスピード(左)
352: D1 : モータA(左)1 = HIGH / 0 = LOW
353: D2 : モータスピード(右)
354: D3 : モータB(右)1 = HIGH / 0 = LOW
355: D4 : LED_3 ON/OFF 1 = HIGH / 0 = LOW
356: */
357: analogWrite(PWMA, D0);
358: digitalWrite(AIN1, D1);
359: analogWrite(PWMB, D2);
360: digitalWrite(BIN1, D3);
361: digitalWrite(LED_3, D4);
362: }
363:
364: // ====被弾====
365: void Hit() {
366: ser_deta = 0;
367: motor_run(255, 1, 255, 0, 0);
368: delay(150);
369: motor_run(0, 0, 0, 0, 1);
370: delay(100);
371: motor_run(200, 0, 200, 1, 0);
372: delay(200);
373: motor_run(0, 0, 0, 0, 1);
374: delay(50);
375: cnt++;
376: if ( cnt >= 5 ) {
377: sendData(105); //被弾破壊信号送信
378: motor_run(0, 0, 0, 0, 0);
379: for ( int i = 0; i < 15 ; i++) {
380: max.write(1, HIGH); //ヘッドライト点灯
381: delay(1000);
382: max.write(1, LOW); //ヘッドライト消灯
383: delay(1000);
384: }
385: //delay(30000); //復活までに30秒
386: cnt = 0;
387: } else {
388: delay(1000);
389: }
390: }
391:
392: void sendData(byte val) {
393: Serial.write('H'); // ヘッダ送信
394: Serial.write(val); // データ送信
395: }
396:
2: 2019-06-15
3:
4: 本サブシステムの内容
5: irremote PIN3 赤外線発光(砲撃)システム
6: 赤外線受光モジュール出力を接続し、被弾処理を追加
7: MP3プレーヤーで効果音を発生
8: エンジン始動信号受信でエンジン始動、アイドリング音発生。
9:
10: シリアル通信データ
11: エンジン始動100
12: 砲撃101
13: 銃撃102
14: 被弾103
15: 破壊105
16: エンジン停止/始動110
17:
18: Arduino IDE 1.8.7
19: 最大30720バイトのフラッシュメモリのうち、スケッチが9816バイト(31%)を使っています。
20: 最大2048バイトのRAMのうち、グローバル変数が585バイト(28%)を使っていて、
21: ローカル変数で1463バイト使うことができます。
22:
23: */
24:
25: #include <SoftwareSerial.h>
26: #include <DFRobotDFPlayerMini.h>
27:
28: SoftwareSerial mySerial(A2, A3); // DFPlayer TX,RX
29: DFRobotDFPlayerMini myDFPlayer;
30:
31: #include <IRremote.h>
32: IRsend irsend;
33: int RECV_PIN = A0 ; //赤外線受光部をPIN A0に
34: IRrecv irrecv(RECV_PIN);
35: decode_results results; //受信信号を格納する
36: const long sign_hit = 0x4CB0FADD;
37: byte recv_data; // 受信データ
38: const int LED_1 = 8; //受信表示
39: int silent = 1;
40: int khz = 38; // 38kHz carrier frequency for the NEC protocol
41: unsigned int irSignal[] = {4100, 1000, 2050, 2050, 1000};
42: // vs BATTLE TANK jr T-72 40MHz
43: // AnalysIR Batch Export (IRremote) - RAW
44: int d_time = 200;
45:
46: void setup() {
47: irrecv.enableIRIn(); // Start the receiver
48: pinMode(RECV_PIN, INPUT) ; // 赤外線受信モジュールに接続ピンをデジタル入力に設定
49:
50: Serial.begin (115200);
51: mySerial.begin (9600);
52:
53: /*Serial.println();
54: Serial.println(F("DFRobot DFPlayer Mini Demo"));
55: Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
56:
57: if (!myDFPlayer.begin(mySerial)) { //Use softwareSerial to communicate with mp3.
58: Serial.println(F("Unable to begin:"));
59: Serial.println(F("1.Please recheck the connection!"));
60: Serial.println(F("2.Please insert the SD card!"));
61: while (true);
62: }
63: Serial.println(F("DFPlayer Mini online."));
64: */
65: myDFPlayer.begin(mySerial);
66: delay(100); //設定待ち時間は仮置き
67: myDFPlayer.volume(22); //Set volume value (0~30).
68: //pinMode(LED_1, OUTPUT); //通信受信
69: }
70:
71: void loop() {
72: if (irrecv.decode(&results)) { // 受信コードの値が
73: if (results.value == sign_hit) { // 0x4CB0FADDだったら被弾
74: sendData(103); //被弾信号送信
75: myDFPlayer.play(17);
76: delay(1000);
77: }
78: irrecv.resume();
79: }
80:
81: //受信バッファに2バイト(ヘッダ+データ)以上のデータが着ているか確認
82: if ( Serial.available() >= 2 ) {
83: // ヘッダの確認
84: if ( Serial.read() == 'H' ) {
85: recv_data = Serial.read() ;
86: }
87: }
88:
89: if (recv_data == 110) {
90: //エンジン停止_始動
91: silent = 1 - silent;
92: // recv_data = 0;
93: }
94:
95: if (silent == 1) {
96: myDFPlayer.disableLoop(); //アイドリング停止
97: } else if ( (silent == 0) && (recv_data == 110)) { //エンジン始動
98: myDFPlayer.play(3); //エンジン始動
99: delay(2000);
100: myDFPlayer.loop(5); //Loop 5th mp3 アイドリング
101: delay(d_time);
102: } else {
103: myDFPlayer.loop(5); //Loop 5th mp3 アイドリング
104: delay(d_time);
105: }
106:
107: // 受信したデータに基づいて効果音再生
108: if ( recv_data == 101) { // 砲撃信号受信
109: irsend.sendRaw(irSignal, (sizeof(irSignal) / sizeof(irSignal[0])), khz);
110: //irsend.sendRaw(data buf, length, hertz)
111: irrecv.enableIRIn(); // 受信を再開する
112: PLAY_MP3(15); //砲撃音
113:
114: } else if ( recv_data == 102 ) { //銃撃信号受信
115: PLAY_MP3(10);
116:
117: } else if ( recv_data == 105 ) { //破壊信号受信
118: PLAY_MP3(18);
119: delay(30000); //復活までに30秒
120: PLAY_MP3(3);
121: delay(2000);
122: }
123: /*
124: else if ( recv_data == 100 ) { //エンジン始動信号受信
125: PLAY_MP3(3);
126: }
127: */
128: recv_data = 0;
129: }
130:
131: void sendData(byte val) {
132: Serial.write('H'); // ヘッダ送信
133: Serial.write(val); // データ送信
134: }
135:
136: void PLAY_MP3(int LT) {
137: recv_data = 0;
138: //digitalWrite(LED_1, HIGH);
139: myDFPlayer.play(LT);
140: delay(900);
141: //digitalWrite(LED_1, LOW);
142: }
143: