・これを作ろうと思ったきっかけ
なぜ今回作ったかは、このコンテストに参加したきっかけは、先輩にコンテストの存在を教えていただいたことだった。せっかく参加するのだったら、スプレッセンスの機能や高い拡張性を活かした面白く、目新しいものを作れないかと考え、拡張機能の加速度センサーを用いた電動ポカポンゲームを作ることにした。
今回の作品
今回は、spresenseを活用して作ったのは、相手に三回ダメージを与えて倒すシンプルなゲームです。

使用部品
システムで利用した部品は、以下の通りです。
| 使用部品 | 個数 |
|---|---|
| spresense | 1 |
| spresense 拡張ボード | 1 |
| ドライバーボード (ULN2003) | 1 |
| ユニポーラー ステッピングモーター 28BYJ-48 5V | 1 |
| マイクロサーボ9g SG-90 | 2 |
| ボタンスイッチ | 2 |
| 筐体(3Dプリンター) | 1 |
設計図
ソースコード
今回のコードはアルディーノで制作しました。
spresense_v3.ino
#include <Arduino.h>
/* ===== SERVO PIN (Spresense PWM) ===== */
#define SERVO_A_PIN 5 // PWM対応ピン
#define SERVO_B_PIN 6
/* ===== SERVO PARAM (μs) ===== */
#define SERVO_DEF 1500
#define SERVO_ATK 1100
#define SERVO_HIT 1900
/* ===== BUTTON PIN ===== */
#define PIN_A 7
#define PIN_B 4
/* ===== GAME PARAM ===== */
#define ATTACK_TIME 200
#define GRACE_TIME 800
#define HIT_LIMIT 3
#define COOLDOWN 300
/* ===== STATE ===== */
bool A_attack = false;
bool B_attack = false;
unsigned long A_attackTime = 0;
unsigned long B_attackTime = 0;
unsigned long lastJudgeTime = 0;
bool A_prev = false;
bool B_prev = false;
int A_hit = 0;
int B_hit = 0;
bool gameOver = false;
/* ===== SERVO CONTROL ===== */
void servoWriteUS(int pin, int us) {
int duty = map(us, 500, 2500, 0, 255);
analogWrite(pin, duty);
}
void servoA_attack() { servoWriteUS(SERVO_A_PIN, SERVO_ATK); }
void servoA_defense() { servoWriteUS(SERVO_A_PIN, SERVO_DEF); }
void servoA_lose() { servoWriteUS(SERVO_A_PIN, SERVO_HIT); }
void servoB_attack() { servoWriteUS(SERVO_B_PIN, SERVO_ATK); }
void servoB_defense() { servoWriteUS(SERVO_B_PIN, SERVO_DEF); }
void servoB_lose() { servoWriteUS(SERVO_B_PIN, SERVO_HIT); }
void backToDefense() {
servoA_defense();
servoB_defense();
}
void setup() {
Serial.begin(115200);
pinMode(PIN_A, INPUT_PULLUP);
pinMode(PIN_B, INPUT_PULLUP);
pinMode(SERVO_A_PIN, OUTPUT);
pinMode(SERVO_B_PIN, OUTPUT);
backToDefense();
Serial.println("=== SPRESENSE GAME START ===");
}
void loop() {
if (gameOver) return;
unsigned long now = millis();
bool A_now = (digitalRead(PIN_A) == LOW);
bool B_now = (digitalRead(PIN_B) == LOW);
bool A_pressed = A_now && !A_prev;
bool B_pressed = B_now && !B_prev;
A_prev = A_now;
B_prev = B_now;
/* ===== 攻撃入力 ===== */
if (A_pressed) {
A_attack = true;
A_attackTime = now;
servoA_attack();
Serial.println("A ATTACK");
}
if (B_pressed) {
B_attack = true;
B_attackTime = now;
servoB_attack();
Serial.println("B ATTACK");
}
/* ===== 攻撃終了 ===== */
if (A_attack && now - A_attackTime > ATTACK_TIME) {
A_attack = false;
servoA_defense();
}
if (B_attack && now - B_attackTime > ATTACK_TIME) {
B_attack = false;
servoB_defense();
}
if (now - lastJudgeTime < COOLDOWN) return;
/* ===== 判定 ===== */
// 攻撃 × 攻撃 → 後出し勝ち
if (A_attack && B_attack &&
abs((long)(A_attackTime - B_attackTime)) <= GRACE_TIME) {
if (A_attackTime > B_attackTime) {
servoB_lose();
Serial.println("ATTACK vs ATTACK -> B LOSE");
} else {
servoA_lose();
Serial.println("ATTACK vs ATTACK -> A LOSE");
}
gameOver = true;
return;
}
// A防御 / B攻撃
if (!A_attack && B_attack) {
A_hit++;
Serial.print("A HIT: ");
Serial.println(A_hit);
lastJudgeTime = now;
}
// B防御 / A攻撃
if (!B_attack && A_attack) {
B_hit++;
Serial.print("B HIT: ");
Serial.println(B_hit);
lastJudgeTime = now;
}
/* ===== KO ===== */
if (A_hit >= HIT_LIMIT) {
servoA_lose();
Serial.println("A KO LOSE");
gameOver = true;
}
if (B_hit >= HIT_LIMIT) {
servoB_lose();
Serial.println("B KO LOSE");
gameOver = true;
}
}
最後に
ものづくりの分野に触れ始めてから1年目にして初めて、ものづくりコンテストに今回参加した。今までは期限が無く自分の納得するまで作り続けることができるものづくりであったが、今回は期限があったため期限に間に合わせるということがとても大変なことであることがわかった。当初は、コントローラーにつけたESP32からPCに加速度センサーのデータを送信し、PCでそのデータを処理し、結果をスプレセンスにwifiで送信することを考えていたが、実際に作成してみるとESP32から送られたデータをPCで処理することまではできたが、スプレセンスへのWi-Fi通信での送信が思うようにいかなかった。期日までに最低限で間に合わせるために、今回は有線でコントローラーのタクトスイッチを使用した制御になってしまったことが心残りである。今後の展望としては、期日までに行なえなかった、スプレセンスへのWi-Fiによるデータ送信を行えるプログラムを今後も作成していきたいと思った。


-
hibiking
さんが
前の土曜日の6:09
に
編集
をしました。
(メッセージ: 初版)
-
hibiking
さんが
前の土曜日の6:14
に
編集
をしました。
ログインしてコメントを投稿する