1. Prosedur [Kembali]

  • Pahami terlebih dahulu kondisi yang akan digunakan
  • Buka Wokwi
  • Persiapkan alat dan bahan
  • Buat rangkaian sesuai dengan kondisi dan modul 
  • Sesuaikan konfigurasi pin
  • Buat kode program untuk mengoperasikan rangkaian tersebut sesuai dengan kondisi 
  • Jalankan simulasi rangkaian.  
  • Proses selesai

2. Hardware dan Diagram Blok[Kembali]

a. Hardware
1. STM32 NUCLEO-G474RE
STM32 NUCLEO-G474RE adalah development board (papan pengembangan) terjangkau dan fleksibel dari STMicroelectronics, yang didasarkan pada mikrokontroler STM32G474RE (Arm® Cortex®-M4 @170MHz, 512KB Flash). Papan ini mendukung konektivitas Arduino Uno V3 dan ST Morpho, serta dilengkapi debugger ST-LINK terintegrasi, menjadikannya ideal untuk pembuatan prototipe cepat.

2. LCD OLED

LCD I2C dan OLED I2C adalah modul layar karakter atau grafis yang menggunakan protokol komunikasi serial I2C (Inter-Integrated Circuit).

3. Pushbutton
Pushbutton adalah komponen sakelar mekanis sederhana yang dioperasikan dengan cara ditekan untuk menghubungkan (on) atau memutuskan (off) aliran arus listrik dalam suatu rangkaian..


4. Buzzer
Buzzer adalah suatu komponen elektronika yang berfungsi untuk mengubah energi listrik menjadi energi suara (bunyi) melalui mekanisme getaran. Komponen ini termasuk dalam kategori output device karena digunakan untuk memberikan respon berupa suara terhadap suatu kondisi atau perintah dalam rangkaian elektronik.

5. Resistor 

Resistor adalah komponen elektronik pasif yang berfungsi untuk membatasi arus listrik dalam suatu rangkaian. Resistor bekerja berdasarkan hukum Ohm, yang menyatakan bahwa tegangan (V) = arus (I) × resistansi (R). Resistor memiliki satuan Ohm (Ω) dan digunakan dalam berbagai aplikasi seperti pembagian tegangan, kontrol arus, dan proteksi rangkaian elektronik.

6. LED

LED adalah komponen elektronik semikonduktor yang memancarkan cahaya ketika dialiri arus listrik.

b. Diagram Blok


3. Rangkaian Simulasi dan Prinsip Kerja[Kembali]



Prinsip Kerja :

Prinsip kerja rangkaian dimulai ketika sistem dinyalakan dan push button pada sisi slave ditekan sebagai input untuk memulai permainan. Setelah tombol ditekan, slave mengirimkan sinyal ke master melalui komunikasi antar board. Selanjutnya master mengaktifkan LED hijau sebagai tanda bahwa game telah dimulai. Pada kondisi ini OLED menampilkan status permainan aktif dan sistem menunggu input tombol lompat yang berada pada sisi slave.

Ketika tombol lompat pada sisi slave ditekan, sinyal dikirim ke master untuk menjalankan aksi karakter lompat. Pada saat proses lompat terjadi, buzzer akan berbunyi sebagai indikator bahwa karakter berhasil melompat. Setelah itu sistem akan memeriksa apakah karakter terkena rintangan atau tidak berdasarkan logika program pada master.

Jika karakter tidak terkena rintangan, maka permainan akan terus berlanjut dan sistem kembali menunggu input tombol lompat berikutnya dari sisi slave. LED hijau tetap menyala sebagai indikator game masih berjalan normal.

Namun apabila karakter terkena rintangan atau pemain gagal menekan tombol lompat pada waktu yang tepat, maka master akan mengirim kondisi game over. Pada kondisi ini LED merah menyala dan buzzer berbunyi sebagai penanda permainan selesai. Setelah itu sistem berhenti dan menunggu permainan dimulai kembali melalui tombol input pada sisi slave.


4. Flowchart dan Listing Program[Kembali]

A. Flowchart


B. Listring Program

a) Master

#include "main.h"
#include "stm32g4xx_hal_i2c.h"
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
#define SSD1306_I2C_PORT hi2c1
/* Variabel Game */
int dinoY = GROUND_Y;
int velocityY = 0;
const int gravity = 2;
uint8_t isJumping = 0;
int cactusX = 128;
uint32_t score = 0;
char scoreBuf[10];
uint8_t gameOver = 0;
uint32_t highScore = 0;

/* Private function prototypes -----------------------------------------------*/
void ResetGame(void);

int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();

  /* USER CODE BEGIN 2 */
  ssd1306_Init();
  ssd1306_Fill(Black);
  ssd1306_UpdateScreen();
  /* USER CODE END 2 */

  while (1)
  {
    if (!gameOver)
    {
      /* 1. Input Handling (Pull-up: LOW = Pressed) */
      if (HAL_GPIO_ReadPin(JUMP_BTN_GPIO_Port, JUMP_BTN_Pin) == GPIO_PIN_RESET && !isJumping)
      {
        velocityY = -12;
        isJumping = 1;
      }

      /* 2. Physics Update */
      dinoY += velocityY;
      velocityY += gravity;

      if (dinoY >= GROUND_Y)
      {
        dinoY = GROUND_Y;
        isJumping = 0;
        velocityY = 0;
      }

      /* 3. Obstacle Update */
      cactusX -= 6;
      if (cactusX < -10)
      {
        cactusX = 128;
        score++;
      }

      /* 4. Collision Detection */
      // Hitbox sederhana: Jika kaktus berada di area Dino dan Dino tidak cukup tinggi
      if (cactusX < 25 && cactusX > 5 && (dinoY + DINO_HEIGHT) > 48)
      {
        gameOver = 1;
      }

      /* 5. Rendering */
      ssd1306_Fill(Black);

      // Menggambar Dino (Kotak)
      ssd1306_DrawRectangle(10, dinoY, 10 + DINO_WIDTH, dinoY + DINO_HEIGHT, White);

      // Menggambar Kaktus (Isi penuh)
      ssd1306_FillRectangle(cactusX, 48, cactusX + 8, 60, White);

      // Garis Tanah
      ssd1306_Line(0, 61, 127, 61, White);

      // Menampilkan Score
      sprintf(scoreBuf, "Score: %lu", score);
      ssd1306_SetCursor(0, 0);
      ssd1306_WriteString(scoreBuf, Font_7x10, White);

      ssd1306_UpdateScreen();
    }
    else
    {
        char hsBuf[20];

        ssd1306_Fill(Black);

        ssd1306_SetCursor(35, 25);
        ssd1306_WriteString("GAME OVER", Font_7x10, White);

        ssd1306_SetCursor(20, 10);
        sprintf(hsBuf, "HighScore: %lu", highScore);
        ssd1306_WriteString(hsBuf, Font_7x10, White);

        ssd1306_UpdateScreen();

        // Update high score
        if (score > highScore)
        {
            highScore = score;
        }

        // restart
        if (HAL_GPIO_ReadPin(JUMP_BTN_GPIO_Port, JUMP_BTN_Pin) == GPIO_PIN_RESET)
        {
            ResetGame();
            HAL_Delay(300);
        }
    }

  }
}
void ResetGame(void)
{
  dinoY = GROUND_Y;
  velocityY = 0;
  isJumping = 0;
  cactusX = 128;
  score = 0;
  gameOver = 0;
}



void MX_I2C1_Init(void)
{
  hi2c1.Instance = I2C1;
  hi2c1.Init.Timing = 0x00303D5D;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;

  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
}

void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  __HAL_RCC_GPIOA_CLK_ENABLE();

  /* Konfigurasi PA0 sebagai Input Pull-up */
  GPIO_InitStruct.Pin = JUMP_BTN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(JUMP_BTN_GPIO_Port, &GPIO_InitStruct);
}

void Error_Handler(void)
{
  __disable_irq();
  while (1) {}
}
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4;
  RCC_OscInitStruct.PLL.PLLN = 85;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;

  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType =
      RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|
      RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
}

b) slave

#include "main.h"

#include "stm32g4xx_hal_spi.h"

/* =========================================================
   GLOBAL HANDLE
   ========================================================= */
SPI_HandleTypeDef hspi1;

/* =========================================================
   GLOBAL VARIABLE
   ========================================================= */
static uint8_t rxData;

/* =========================================================
   MAIN
   ========================================================= */
int main(void)
{
    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();
    MX_SPI1_Init();

    /* LED awal */
    HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,
                      LED_GREEN_Pin,
                      GPIO_PIN_RESET);

    HAL_GPIO_WritePin(LED_RED_GPIO_Port,
                      LED_RED_Pin,
                      GPIO_PIN_RESET);

    while (1)
    {
        /* =====================================
           TERIMA DATA SPI
           ===================================== */
        HAL_SPI_Receive(&hspi1,
                        &rxData,
                        1,
                        HAL_MAX_DELAY);

        /* =====================================
           PROCESS COMMAND
           ===================================== */
        switch (rxData)
        {
            /* ================================
               GAME RUN
               ================================ */
            case CMD_GAME_RUN:

                HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,
                                  LED_GREEN_Pin,
                                  GPIO_PIN_SET);

                HAL_GPIO_WritePin(LED_RED_GPIO_Port,
                                  LED_RED_Pin,
                                  GPIO_PIN_RESET);

                break;

            /* ================================
               GAME OVER
               ================================ */
            case CMD_GAME_OVER:

                HAL_GPIO_WritePin(LED_GREEN_GPIO_Port,
                                  LED_GREEN_Pin,
                                  GPIO_PIN_RESET);

                HAL_GPIO_WritePin(LED_RED_GPIO_Port,
                                  LED_RED_Pin,
                                  GPIO_PIN_SET);

                break;

            /* ================================
               JUMP SOUND
               ================================ */
            case CMD_JUMP_SOUND:

                Beep_Jump();

                break;

            /* ================================
               HIT SOUND
               ================================ */
            case CMD_HIT_SOUND:

                Beep_Hit();

                break;

            default:
                break;
        }
    }
}

/* =========================================================
   BEEP JUMP
   bib
   ========================================================= */
void Beep_Jump(void)
{
    HAL_GPIO_WritePin(BUZZER_GPIO_Port,
                      BUZZER_Pin,
                      GPIO_PIN_SET);

    HAL_Delay(80);

    HAL_GPIO_WritePin(BUZZER_GPIO_Port,
                      BUZZER_Pin,
                      GPIO_PIN_RESET);
}

/* =========================================================
   BEEP HIT
   bib bib biiiiib
   ========================================================= */
void Beep_Hit(void)
{
    /* bib */
    HAL_GPIO_WritePin(BUZZER_GPIO_Port,
                      BUZZER_Pin,
                      GPIO_PIN_SET);

    HAL_Delay(100);

    HAL_GPIO_WritePin(BUZZER_GPIO_Port,
                      BUZZER_Pin,
                      GPIO_PIN_RESET);

    HAL_Delay(100);

    /* bib */
    HAL_GPIO_WritePin(BUZZER_GPIO_Port,
                      BUZZER_Pin,
                      GPIO_PIN_SET);

    HAL_Delay(100);

    HAL_GPIO_WritePin(BUZZER_GPIO_Port,
                      BUZZER_Pin,
                      GPIO_PIN_RESET);

    HAL_Delay(100);

    /* biiiiib */
    HAL_GPIO_WritePin(BUZZER_GPIO_Port,
                      BUZZER_Pin,
                      GPIO_PIN_SET);

    HAL_Delay(500);

    HAL_GPIO_WritePin(BUZZER_GPIO_Port,
                      BUZZER_Pin,
                      GPIO_PIN_RESET);
}

/* =========================================================
   GPIO INIT
   ========================================================= */
void MX_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* =====================================
       CLOCK ENABLE
       ===================================== */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();

    /* =====================================
       LED + BUZZER OUTPUT
       ===================================== */
    GPIO_InitStruct.Pin =
        LED_GREEN_Pin |
        LED_RED_Pin   |
        BUZZER_Pin;

    GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull  = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

    HAL_GPIO_Init(GPIOB,
                  &GPIO_InitStruct);

    /* =====================================
       SPI1 GPIO
       PA4 = NSS
       PA5 = SCK
       PA6 = MISO
       PA7 = MOSI
       ===================================== */
    GPIO_InitStruct.Pin =
        GPIO_PIN_4 |
        GPIO_PIN_5 |
        GPIO_PIN_6 |
        GPIO_PIN_7;

    GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull      = GPIO_NOPULL;
    GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;

    HAL_GPIO_Init(GPIOA,
                  &GPIO_InitStruct);
}

/* =========================================================
   SPI1 INIT
   ========================================================= */
void MX_SPI1_Init(void)
{
    hspi1.Instance = SPI1;

    hspi1.Init.Mode =
        SPI_MODE_SLAVE;

    hspi1.Init.Direction =
        SPI_DIRECTION_2LINES;

    hspi1.Init.DataSize =
        SPI_DATASIZE_8BIT;

    hspi1.Init.CLKPolarity =
        SPI_POLARITY_LOW;

    hspi1.Init.CLKPhase =
        SPI_PHASE_1EDGE;

    hspi1.Init.NSS =
        SPI_NSS_HARD_INPUT;

    hspi1.Init.FirstBit =
        SPI_FIRSTBIT_MSB;

    hspi1.Init.TIMode =
        SPI_TIMODE_DISABLE;

    hspi1.Init.CRCCalculation =
        SPI_CRCCALCULATION_DISABLE;

    if (HAL_SPI_Init(&hspi1) != HAL_OK)
    {
        Error_Handler();
    }
}

/* =========================================================
   CLOCK CONFIG
   ========================================================= */
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    HAL_PWREx_ControlVoltageScaling(
        PWR_REGULATOR_VOLTAGE_SCALE1);

    RCC_OscInitStruct.OscillatorType =
        RCC_OSCILLATORTYPE_HSI;

    RCC_OscInitStruct.HSIState =
        RCC_HSI_ON;

    RCC_OscInitStruct.PLL.PLLState =
        RCC_PLL_ON;

    RCC_OscInitStruct.PLL.PLLSource =
        RCC_PLLSOURCE_HSI;

    RCC_OscInitStruct.PLL.PLLM =
        RCC_PLLM_DIV4;

    RCC_OscInitStruct.PLL.PLLN =
        85;

    RCC_OscInitStruct.PLL.PLLR =
        RCC_PLLR_DIV2;

    HAL_RCC_OscConfig(&RCC_OscInitStruct);

    RCC_ClkInitStruct.ClockType =
        RCC_CLOCKTYPE_SYSCLK |
        RCC_CLOCKTYPE_HCLK   |
        RCC_CLOCKTYPE_PCLK1  |
        RCC_CLOCKTYPE_PCLK2;

    RCC_ClkInitStruct.SYSCLKSource =
        RCC_SYSCLKSOURCE_PLLCLK;

    RCC_ClkInitStruct.AHBCLKDivider =
        RCC_SYSCLK_DIV1;

    RCC_ClkInitStruct.APB1CLKDivider =
        RCC_HCLK_DIV1;

    RCC_ClkInitStruct.APB2CLKDivider =
        RCC_HCLK_DIV1;

    HAL_RCC_ClockConfig(
        &RCC_ClkInitStruct,
        FLASH_LATENCY_4
    );
}

/* =========================================================
   ERROR HANDLER
   ========================================================= */
void Error_Handler(void)
{
    __disable_irq();

    while (1)
    {

    }
}

5. Video Demo[Kembali]




6. Analisa[Kembali]



7Download File[Kembali]

Download Video Simulasi [Klik Disini]
Download Analisa [Klik Disini]

No comments:

Post a Comment

  BAHAN PRESENTASI UNTUK MATA KULIAH  ELEKTRONIKA 2024 Nama : Muhammad Fadhlurrahman Yuzary NIM : 2310952015 Elektronika A Dosen Pengampu ; ...