สร้างเกมจับเวลาปฏิกิริยาตอบสนอง
จอแสดงผลเกมอินพุต
รอสัญญาณ แล้วกดปุ่มให้เร็วที่สุดเท่าที่จะทำได้ -- จอแสดงผลขนาดเล็กและนาฬิกาจับเวลาที่สร้างขึ้นจากโค้ดของคุณทั้งหมด
รวมชิ้นส่วนจริง 7 รายการ
ราคารวมชุดนี้: 1,800.00 ฿
ยังไม่รวมส่วนลดคำสั่งซื้อที่คุณอาจได้รับตอนชำระเงิน
สิ่งที่คุณต้องใช้
บอร์ดพัฒนา ESP32-C3 SuperMini — Wi-Fi และ Bluetooth, USB-C
670.00 ฿
โมดูลจอแสดงผล OLED I2C ขนาด 0.96 นิ้ว — 128×64, สีขาว
285.00 ฿
โมดูล Active Buzzer — 12 มม.
235.00 ฿
สวิตช์ปุ่มกดแบบสัมผัส — 12×12×7.3 มม.
85.00 ฿
เบรดบอร์ดไร้บัดกรี 830 จุด
125.00 ฿
ชุดสายจัมเปอร์ — ผู้-ผู้, ผู้-เมีย, เมีย-เมีย
220.00 ฿
สายชาร์จและซิงค์ข้อมูล USB-C — 1 ม.
180.00 ฿
แผนภาพการต่อสาย
โค้ดเริ่มต้น
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SDA_PIN 8 // ESP32-C3 default I2C SDA - adjust if your board differs
#define SCL_PIN 9 // ESP32-C3 default I2C SCL - adjust if your board differs
#define BUTTON_PIN 3 // Tactile button, other leg to GND - any digital input GPIO
#define BUZZER_PIN 4 // Active buzzer signal - any digital output GPIO
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
enum GameState { IDLE, GET_READY, ARMED, GO, SHOW_RESULT };
GameState state = IDLE;
unsigned long stateEnteredAt = 0;
unsigned long randomDelay = 0;
unsigned long goTime = 0;
bool rawPressed() {
return digitalRead(BUTTON_PIN) == LOW; // INPUT_PULLUP: LOW = pressed
}
// Returns true once, only on the release -> press transition (debounced).
bool pressedEdge() {
static bool lastStable = false;
static unsigned long lastChange = 0;
bool reading = rawPressed();
if (reading != lastStable && millis() - lastChange > 30) {
lastStable = reading;
lastChange = millis();
return lastStable; // true only on the press edge
}
return false;
}
void showMessage(const char* line1, const char* line2) {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 10);
display.println(line1);
display.setTextSize(1);
display.setCursor(0, 44);
display.println(line2);
display.display();
}
void setup() {
Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
Wire.begin(SDA_PIN, SCL_PIN);
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS)) {
Serial.println("SSD1306 init failed - check wiring/address");
while (true) delay(1000);
}
randomSeed(analogRead(0)); // floating ADC pin as an entropy source
showMessage("Reaction Timer", "Press to start");
}
void loop() {
bool edge = pressedEdge();
switch (state) {
case IDLE:
if (edge) {
showMessage("Get ready...", "");
state = GET_READY;
stateEnteredAt = millis();
}
break;
case GET_READY:
// brief pause so the player lets go of the button before arming
if (millis() - stateEnteredAt > 500) {
randomDelay = random(1500, 5000); // 1.5-5s random wait before GO
stateEnteredAt = millis();
state = ARMED;
}
break;
case ARMED:
if (rawPressed()) {
showMessage("Too early!", "Press to retry");
digitalWrite(BUZZER_PIN, HIGH);
delay(200);
digitalWrite(BUZZER_PIN, LOW);
state = SHOW_RESULT;
} else if (millis() - stateEnteredAt >= randomDelay) {
showMessage("GO!", "");
digitalWrite(BUZZER_PIN, HIGH);
goTime = millis();
state = GO;
}
break;
case GO:
if (millis() - goTime > 150) {
digitalWrite(BUZZER_PIN, LOW); // stop the short GO beep after 150ms
}
if (rawPressed()) {
unsigned long reactionMs = millis() - goTime;
char line1[16];
snprintf(line1, sizeof(line1), "%lu ms", reactionMs);
showMessage(line1, "Press to retry");
Serial.printf("Reaction time: %lu ms\n", reactionMs);
state = SHOW_RESULT;
}
break;
case SHOW_RESULT:
if (edge) {
showMessage("Get ready...", "");
state = GET_READY;
stateEnteredAt = millis();
}
break;
}
}ไม่แน่ใจขั้นตอนไหน? ถามเรา