LA M3 Communication

      

Laporan Akhir



 Percobaan 2 Game Geomerty Jump


a. Prosedur [Kembali]

1. Buat dua project baru pada STM32CubeIDE menggunakan mikrokontroler STM32 NUCLEO G474RE.

    •Project_Master

    •Project_Slave

2. Konfigurasi Project Master

    a. Aktifkan I2C1 dengan pengaturan:

    Mode: I2C

    •Clock Speed: 100 kHz (Standard Mode)

    •Addressing Mode: 7-bit

    •Pin yang digunakan:

    •PB6 → SCL

    •PB7 → SDA

    b. Aktifkan SPI1 dengan pengaturan:

        •Mode: Full Duplex Master

        •Direction: 2 Lines

        •Data Size: 8-bit

        •Clock Polarity: Low

        •Clock Phase: 1 Edge

        •NSS: Software

        •Baudrate Prescaler: 16

        •First Bit: MSB First

    Pin yang digunakan:

        •PA5 → SCK

        •PA6 → MISO

        •PA7 → MOSI

3. Konfigurasi Project Slave

    a. Aktifkan SPI1 dengan pengaturan:

        •Mode: Full Duplex Slave

        •Direction: 2 Lines

        •Data Size: 8-bit

        •Clock Polarity: Low

        •Clock Phase: 1 Edge

        •NSS: Hardware Input

        •First Bit: MSB First

    Pin yang digunakan:

        •PA5 → SCK

        •PA6 → MISO

        •PA7 → MOSI

        •PA4 → NSS

b. I2C tidak digunakan pada Slave

4. Setelah seluruh konfigurasi selesai, lakukan Generate Code untuk masing-masing project.


b. Hardware dan Diagram Blok [Kembali]

Hardware


STM32 NUCLEO-G474RE



LED

Buzzer

Resistor

Push Button

Oled



 Diagram blok




c. Rangkaian Simulasi dan Prinsip Kerja [Kembali]

  • Rangkaian Simulasi




  • Prinsip Kerja

    Sistem bekerja dengan STM32 Master sebagai pusat pengendali permainan Dino yang ditampilkan pada OLED melalui komunikasi I2C. Master membaca input tombol melalui GPIO untuk mengatur gerakan karakter Dino agar dapat melompat, kemudian menghitung perubahan posisi menggunakan parameter velocity dan gravitasi sehingga animasi terlihat bergerak secara real-time. Selain itu, Master juga mengatur pergerakan rintangan berupa kaktus, melakukan pembaruan tampilan seperti garis tanah, skor, dan objek permainan pada OLED secara terus-menerus. Ketika karakter berhasil melewati rintangan maka skor akan bertambah, sedangkan jika terjadi tabrakan antara Dino dan kaktus maka sistem akan masuk ke kondisi game over dan menampilkan pesan Game Over beserta high score pada layar.

    Selain mengelola logika permainan, STM32 Master juga mengirimkan data kondisi permainan ke STM32 Slave menggunakan komunikasi SPI melalui jalur MOSI, MISO, SCK, dan NSS. Data yang dikirim berupa status permainan seperti mode berjalan, efek lompatan, maupun kondisi tabrakan, kemudian diterima oleh Slave menggunakan fungsi HAL_SPI_Receive(). STM32 Slave bertugas mengendalikan perangkat output tambahan seperti LED hijau, LED merah, dan buzzer. Saat permainan berlangsung normal LED hijau akan aktif, sedangkan LED merah menyala ketika permainan berakhir. Buzzer juga menghasilkan bunyi tertentu saat karakter melompat maupun ketika terjadi collision. Pembagian fungsi antara Master dan Slave membuat sistem bekerja lebih efektif karena pemrosesan game dan pengendalian output dilakukan secara terpisah.


d. Flowchart dan Listing Program [Kembali]

  • Flowchart
  1. Logika Game



  2. Master



  3. Slave




  • Listing Program
    #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();
      }
    }

e. Video Demo [Kembali]





f. Analisa [Kembali]








g. Download File [Kembali]

File Analisa [Klik disini]

Video Demo [Disini]



Kembali ke Halaman Atas


Tidak ada komentar:

Posting Komentar

  BAHAN PRESENTASI UNTUK MATA KULIAH  ELEKTRONIKA     Oleh : Farhan Hamid 2310951007     Dosen Pengampu : Darwison, M.T.     Darwison, 2010,...