• 082226375801
  • alfianmaarif@ee.uad.ac.id
  • Yogyakarta
Materi
Tutorial Arduino: Cara Membuat Game Edukasi Kuis Perkalian Angka Interaktif Menggunakan Layar OLED SSD1306, Rotary Encoder, Buzzer, & LED pada WOKWI

Tutorial Arduino: Cara Membuat Game Edukasi Kuis Perkalian Angka Interaktif Menggunakan Layar OLED SSD1306, Rotary Encoder, Buzzer, & LED pada WOKWI

Pada bagian ini akan dibahas pembuatan proyek game edukasi matematika interaktif (Educational Multiplication Game Device) berbasis mikrokontroler Arduino/ESP32, layar OLED SSD1306 (128×64 I2C), rotary encoder sebagai pengatur menu dan penambah/pengurang nilai jawaban, buzzer efek suara (tone sukses, salah, dan alarm), lampu LED indikator, serta platform simulasi WOKWI. Skematik rangkaian ditunjukkan pada Gambar 1, program Arduino pada Kode 1, dan video pembuatan pada tautan Video 1. Sistem dilengkapi dengan menu pengaturan lengkap (pilihan mode tingkat kesulitan Easy/Medium/Hard dengan timer hitung mundur, jumlah angka perkalian 2 hingga 10, serta pilihan level bilangan satuan, puluhan, hingga ratusan) untuk menguji kecepatan dan ketepatan berhitung perkalian secara seru.

Gambar 1. Skematik rangkaian sistem

List Pin:

  • Modul Rotary Encoder
    CLK (Clock Pin) => Digital Pin 2 (CLK)
    DT (Data Pin) => Digital Pin 3 (DT)
    SW (Switch Pin) => Digital Pin 4 (SW – dengan internal pull-up)
    VCC => 5V / 3.3V
    GND => GND
  • Layar OLED Display I2C (128×64 SSD1306)
    SDA => Pin SDA (GPIO 21 pada ESP32 / A4 pada Arduino Uno)
    SCL => Pin SCL (GPIO 22 pada ESP32 / A5 pada Arduino Uno)
    VCC => 5V / 3.3V
    GND => GND
  • Aktuator Indikator & Audio
    Buzzer Alarm (Positive Terminal) => Digital Pin 5 (BUZZER)
    LED Indikator Jawaban Benar => Digital Pin 6 (LED_PIN via Resistor 220 Ohm)

List Virtual PIN:

  • Proyek ini dirancang sebagai perangkat konsol game edukasi interaktif mandiri (standalone/offline) pada platform WOKWI menggunakan layar OLED, rotary encoder, dan buzzer tanpa koneksi internet/cloud. Oleh karena itu, pemetaan Virtual Pin Blynk tidak diterapkan pada modul proyek ini.
//ALFIAN CENTER
//SUBSCRIBE
//=== PROGRAM DI SHARE KALO LIKE LEBIH DARI 50 KOMEN LEBIH DARI 20 ===

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Encoder.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Pin
#define CLK 2
#define DT 3
#define SW 4
#define BUZZER 5
#define LED_PIN 6

// Rotary Encoder
Encoder encoder(CLK, DT);
#define ENCODER_STEPS_PER_TICK 4
#define ENCODER_DIRECTION -1
long lastRawEncoder = 0;

int readEncoderStep() {
  long newRaw = encoder.read();
  long delta = newRaw - lastRawEncoder;
  int step = 0;

  if (delta >= ENCODER_STEPS_PER_TICK) {
    step = 1;
    lastRawEncoder += ENCODER_STEPS_PER_TICK;
  } else if (delta <= -ENCODER_STEPS_PER_TICK) {
    step = -1;
    lastRawEncoder -= ENCODER_STEPS_PER_TICK;
  }
  return step * ENCODER_DIRECTION;
}

// ================== STATE ==================
enum SystemState { STATE_MENU, STATE_GAME };
SystemState systemState = STATE_MENU;

enum MenuState { MENU_NAVIGATE, MENU_EDIT };
MenuState menuState = MENU_NAVIGATE;

// Menu Data
int menuIndex = 0;
String modeOptions[3] = {"Easy", "Medium", "Hard"};
int modeIndex = 0;

int angkaOptions[9] = {2,3,4,5,6,7,8,9,10};
int angkaIndex = 0;

String levelOptions[3] = {"Satuan", "Puluhan", "Ratusan"};
int levelIndex = 0;

// Game Data
int soal[10];
int jumlahAngka = 2;
int jawabanBenar = 0;
int jawabanPlayer = 0;
int skor = 0;
int kesempatan = 3;
bool swPressed = false;


//ALFIAN CENTER
//SUBSCRIBE
// Timer
unsigned long startTime = 0; // waktu soal dimulai
int timeLimit = 0;           // batas waktu detik per soal

// ================== SETUP ==================
void setup() {
  pinMode(BUZZER, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  pinMode(SW, INPUT_PULLUP);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    for(;;); // stop kalau OLED gagal
  }

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Game Tebak Angka");
  display.display();
  delay(1500);
}

// ================== LOOP ==================
void loop() {
  int step = readEncoderStep();

  // MENU
  if (systemState == STATE_MENU) {
    if (menuState == MENU_NAVIGATE) {
      if (step != 0) {
        menuIndex = (menuIndex + step + 4) % 4;
      }
    } else if (menuState == MENU_EDIT) {
      if (step != 0) {
        if (menuIndex == 0) modeIndex = (modeIndex + step + 3) % 3;
        else if (menuIndex == 1) angkaIndex = (angkaIndex + step + 9) % 9;
        else if (menuIndex == 2) levelIndex = (levelIndex + step + 3) % 3;
      }
    }
  }


//ALFIAN CENTER
//SUBSCRIBE
  // GAME
  else if (systemState == STATE_GAME) {
    if (step == 1) jawabanPlayer++;
    else if (step == -1 && jawabanPlayer > 0) jawabanPlayer--;

    // ===== Timer cek =====
    if (timeLimit > 0) {
      unsigned long elapsed = (millis() - startTime) / 1000;
      if (elapsed >= timeLimit) {
        kesempatan--;  // darah berkurang
        tone(BUZZER, 400, 200);
        if (kesempatan <= 0) {
          gameOver();
        } else {
          buatSoalBaru();  // soal baru & reset timer
        }
      }
    }
  }

  // BUTTON
  if (digitalRead(SW) == LOW && !swPressed) {
    swPressed = true;
    handleSelect();
    delay(200);
  } else if (digitalRead(SW) == HIGH) {
    swPressed = false;
  }

  if (systemState == STATE_MENU) drawMenu();
  else if (systemState == STATE_GAME) drawGame();
}


//ALFIAN CENTER
//SUBSCRIBE
// ================== HANDLE BUTTON ==================
void handleSelect() {
  if (systemState == STATE_MENU) {
    if (menuState == MENU_NAVIGATE) {
      if (menuIndex == 3) { 
        // Start ditekan -> masuk game
        tone(BUZZER, 1000, 150);
        digitalWrite(LED_PIN, HIGH);
        delay(150);
        digitalWrite(LED_PIN, LOW);
        startGame();
      } else {
        menuState = MENU_EDIT;
      }
    } else if (menuState == MENU_EDIT) {
      menuState = MENU_NAVIGATE;
    }
  } else if (systemState == STATE_GAME) {
    // Submit jawaban player
    if (jawabanPlayer == jawabanBenar) {
      skor++;
      digitalWrite(LED_PIN, HIGH);
      tone(BUZZER, 1500, 150);
      delay(200);
      digitalWrite(LED_PIN, LOW);
      buatSoalBaru();
    } else {
      kesempatan--;
      tone(BUZZER, 500, 400);
      if (kesempatan <= 0) {
        gameOver();
      }
    }
  }
}


//ALFIAN CENTER
//SUBSCRIBE
// ================== GAME LOGIC ==================
void startGame() {
  systemState = STATE_GAME;
  skor = 0;
  kesempatan = 3;
  buatSoalBaru();
}

void buatSoalBaru() {
  jumlahAngka = angkaOptions[angkaIndex];
  int maxVal = 9;
  if (levelIndex == 1) maxVal = 99;
  else if (levelIndex == 2) maxVal = 999;

  jawabanBenar = 1;   // mulai dari 1, karena perkalian
  for (int i = 0; i < jumlahAngka; i++) {
    soal[i] = random(1, maxVal+1);
    jawabanBenar *= soal[i];   // ganti += jadi *=
  }
  jawabanPlayer = 0;
  encoder.write(0);   
  lastRawEncoder = 0;

  // Atur timer
  if (modeIndex == 0) timeLimit = 0; // Eazy
  else if (modeIndex == 1) timeLimit = 20; //Medium
  else if (modeIndex == 2) timeLimit = 10; //Hard

  startTime = millis();
}


void gameOver() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0,0);
  display.println("GAME OVER!");
  display.setCursor(0,16);
  display.print("Score: ");
  display.println(skor);
  display.display();
  delay(3000);
  systemState = STATE_MENU;
  encoder.write(0);
  lastRawEncoder = 0;
}


//ALFIAN CENTER
//SUBSCRIBE
// ================== OLED ==================
void drawMenu() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0,0);
  display.println("Tebak Perkalian");

  // Mode
  display.setCursor(0,12);
  display.print(menuIndex == 0 ? ">" : " ");
  display.print("Mode: ");
  if (menuState == MENU_EDIT && menuIndex == 0) display.print("[");
  display.print(modeOptions[modeIndex]);
  if (menuState == MENU_EDIT && menuIndex == 0) display.print("]");

  // Angka
  display.setCursor(0,24);
  display.print(menuIndex == 1 ? ">" : " ");
  display.print("Angka: ");
  if (menuState == MENU_EDIT && menuIndex == 1) display.print("[");
  display.print(angkaOptions[angkaIndex]);
  if (menuState == MENU_EDIT && menuIndex == 1) display.print("]");

  // Level
  display.setCursor(0,36);
  display.print(menuIndex == 2 ? ">" : " ");
  display.print("Level: ");
  if (menuState == MENU_EDIT && menuIndex == 2) display.print("[");
  display.print(levelOptions[levelIndex]);
  if (menuState == MENU_EDIT && menuIndex == 2) display.print("]");

  // Start
  display.setCursor(0,48);
  display.print(menuIndex == 3 ? ">" : " ");
  display.print("Start");

  display.display();
}

void drawGame() {
  display.clearDisplay();


//ALFIAN CENTER
//SUBSCRIBE
  // Header
  display.setTextSize(1);
  display.setCursor(0,0);
  display.print("Skor:");
  display.print(skor);
  display.setCursor(64,0);
  display.print("Sisa:");
  display.print(kesempatan);

  // --- Buat string soal dulu ---
  String soalStr = "";
  for (int i = 0; i < jumlahAngka; i++) {
    soalStr += String(soal[i]);
    if (i < jumlahAngka-1) soalStr += "x";
  }

  // --- Pilih ukuran font berdasarkan panjang soal ---
  int soalLen = soalStr.length();
  int textSizeSoal = 2;
  if (soalLen > 12) textSizeSoal = 1;   // soal panjang → kecil
  else if (soalLen > 8) textSizeSoal = 2; // medium
  else textSizeSoal = 2;                 // pendek → besar

  // Tampilkan soal
  display.setTextSize(textSizeSoal);
  display.setCursor(0, 16);
  display.print(soalStr);

  // Jawaban lebih besar dari soal, tapi tetap aman
  int jawabanLen = String(jawabanPlayer).length();
  int textSizeJawab = (jawabanLen > 4) ? 1 : 2;

  display.setTextSize(textSizeJawab);
  display.setCursor(0, 40);
  display.print("= ");
  display.print(jawabanPlayer);


//ALFIAN CENTER
//SUBSCRIBE
  // Timer
  if (timeLimit > 0) {
    unsigned long elapsedMs = millis() - startTime;
    int remaining = max(0, timeLimit - (elapsedMs / 1000));

    // Angka countdown
    display.setTextSize(1);
    display.setCursor(95,50);
    display.print("T:");
    display.print(remaining);

    // Progress bar
    float ratio = 1.0 - (float)elapsedMs / (timeLimit * 1000.0);
    if (ratio < 0) ratio = 0;
    int barWidth = (int)(80 * ratio);

    display.drawRect(5, 55, 80, 6, SSD1306_WHITE);      // border
    display.fillRect(5, 55, barWidth, 6, SSD1306_WHITE); // isi
  }

  display.display();
}

Kode Arduino 1. Kode Program

Video 1. Video tutorial pembuatan

TAG:

game edukasi perkalian arduino, kuis matematika oled display, rotary encoder arduino uno, oled ssd1306 128×64, blynk wokwi math game, tutorial arduino oled, iot game edukasi anak, game tebak perkalian interaktif, library adafruit ssd1306, library encoder arduino, buzzer tone melodi game, led indikator jawaban, pinout rotary encoder clk dt sw, i2c oled display arduino, game kuis matematika oled, fungsi draw game menu, random number generator perkalian, tutorial wokwi indonesia, simulasi iot game edukasi, permainan perkalian digital, oled screen graphics menu, datastream oled display, smart educational appliances, proyek teknik elektro kreatif, mekatronika game edukasi, tugas akhir arduino oled math, skripsi iot math game, ide proyek mikrokontroler edukasi, skematik game perkalian oled, diagram rangkaian encoder oled buzzer, source code game edukasi oled, program arduino oled math game, simulasi iot tanpa hardware, platform simulasi wokwi, wokwi arduino math game, alat permainan edukasi mikrokontroler, telemetry data oled screen, proyek sains elektro, portofolio mikrokontroler edukasi, praktikum arduino uno, modul oled ssd1306 i2c, pinout arduino oled encoder, indikator suara buzzer game, grafik menu oled, game digital edukasi mini, efisiensi pembelajaran matematika, panduan arduino oled display, belajar mikrokontroler online, simulator komponen elektronik oled, wokwi custom chip game, internet of things indonesia, iot smk teknik elektro, iot universitas teknik, prototipe game oled arduino, alat kuis perkalian otomatis, smart educational project, arduino ide programming, tutorial arduino pemula, proyek elektro game edukasi, panduan lengkap wokwi oled, sensor encoder putar akurat, sistem animasi menu oled, logika kuis perkalian bertingkat, notifikasi suara jingle game, sistem pembelajaran interaktif, otomatisasi game edukasi, proyek mekatronika elektro, simulasi hardware math game, sistem tebak angka arduino, proyek arduino populer, kodingan game edukasi otomatis, oled graphics library, rangkaian encoder dan oled, tutorial mikrokontroler pemula, wawasan teknik elektro, aplikasi oled display game, konsol game edukasi mini arduino, koding logika menu oled, pemantauan skor game real time, arduino game management system

Leave a Reply

Your email address will not be published. Required fields are marked *