LA1




a. Prosedur[Kembali]

  • Rangkai komponen sesuai skema — Master dihubungkan ke OLED via I2C (PB6=SCL, PB7=SDA) dan ke Slave via SPI (PA5=SCK, PA6=MISO, PA7=MOSI, PA4=CS)
  • Buka STM32CubeIDE, buat dua project baru dengan board NUCLEO G474RE
  • Konfigurasi Project Master: aktifkan I2C1 (Standard Mode 100kHz, 7-bit addressing), SPI1 (Full Duplex Master, 8-bit, NSS Software), dan GPIO PA0 sebagai input push button dengan pull-up
  • Konfigurasi Project Slave: aktifkan SPI1 (Full Duplex Slave, 8-bit, NSS Hardware Input), GPIO untuk LED Hijau, LED Merah, dan buzzer sebagai output
  • Generate Code pada kedua project, lalu masukkan listing program sesuai modul
  • Tambahkan library SSD1306 (file ssd1306.h, ssd1306.c, ssd1306_fonts.h, ssd1306_fonts.c) ke project Master
  • Flash program ke masing-masing board
  • Tekan push button untuk memulai game dan uji respons sistem
  • b. Hardware dan Diagram Blok[Kembali]

    HARDWARE

     1. STM32G474RE

    Microcontroller

    STM32G474RE (ARM Cortex-M4F)

    Operating Voltage

    3.3 V

    Input Voltage (recommended)

    5 V via USB (ST-LINK) atau 7–12 V via VIN

    Input Voltage (limit)

    4.5  15 V (VIN board Nucleo)

    Digital I/O Pins

    ±51 GPIO pins (tergantung konfigurasi fungsi)

    PWM Digital I/O Pins

    Hingga 24 channel PWM (advanced, general-purpose, dan high-resolution timers)

    Analog Input Pins

    Hingga 24 channel ADC (12-bit / 16-bit dengan oversampling)

    DC Current per I/O Pin

    Maks. 20 mA per pin (disarankan  8 mA)

    DC Current for 3.3V Pin

    Hingga ±500 mA (tergantung regulator & sumber daya)

    Flash Memory

    512 KB internal Flash

    SRAM

    128 KB SRAM (termasuk CCM RAM)

    Clock Speed

    Hingga 170 MHz

        2.LED



        3. Push Button

    Tombol tekan merupakan salah satu komponen elektronik yang memiliki fungsi yang sangat penting. Tombol ini dapat digunakan untuk memutuskan atau menghubungkan aliran listrik pada suatu rangkaian.

    Ketika tombol ditekan, aliran listrik akan terputus atau terhubung tergantung dari mekanisme yang digunakan.

    Mekanisme pemutusan dan penghubungan aliran ini disebut dengan sistem unlock atau tidak mengunci. Saat tombol tidak ditekan, sirkuit akan berada dalam keadaan normal. Tombol ini dioperasikan secara manual dengan cara ditekan.

    Tombol tekan juga sangat penting pada mesin-mesin industri, terutama dalam mematikan dan menyalakan mesin. Tombol ini merupakan tombol utama dalam operasional mesin, yang digunakan pada berbagai jenis mesin industri.







        3. Resistor
    4.OLED




    Lapisan OLED terdiri dari beberapa komponen utama, termasuk:

    1. Substrat: Bagian dasar yang mendukung struktur OLED, yang dapat berupa kaca atau plastik fleksibel.
    2. Lapisan Anoda dan Katoda: Elektroda yang berfungsi untuk mengalirkan arus listrik.
    3. Lapisan Emisi: Tempat terjadinya proses electroluminescence, di mana cahaya dihasilkan.
    4. Lapisan Konduksi dan Pemblokir: Meningkatkan efisiensi dan membantu mengarahkan arus listrik ke lapisan emisi.
    5.BUZZER


    Pada dasarnya, prinsip kerja dari buzzer elektronika hampir sama dengan loud speaker dimana buzzer juga terdiri dari kumparan yang terpasang secara diafragma. Ketika kumparan tersebut dialiri listrik maka akan menjadi elektromagnet sehingga mengakibatkan kumparan tertarik ke dalam ataupun ke luar tergantung dari arah arus dan polaritas magnetnya. Karena kumparan dipasang secara diafragma maka setiap kumparan akan menggerakkan diafragma tersebut secara bolak-balik sehingga membuat udara bergetar yang akan menghasilkan suara.



    DIAGRAM BLOK



                                                                                                                                                                   

    c. Rangkaian Simulasi dan Prinsip Kerja[Kembali]











    Prinsip Kerja

         Prinsip kerja pada percobaan 2 Game Geometry Jump menggunakan komunikasi SPI dan I2C antara dua buah mikrokontroler STM32 NUCLEO G474RE. Pada sistem ini, board master bertugas menjalankan logika utama permainan, sedangkan board slave menerima data perintah melalui komunikasi SPI. Selain itu, OLED digunakan sebagai media tampilan permainan dengan komunikasi I2C.

    Saat sistem mulai dijalankan, mikrokontroler master akan menginisialisasi komunikasi SPI, I2C, OLED, tombol push button, dan variabel permainan seperti posisi karakter, rintangan, skor, serta status permainan. OLED diaktifkan menggunakan komunikasi I2C sehingga data gambar dan teks permainan dapat ditampilkan pada layar. Setelah inisialisasi selesai, permainan dimulai dengan menampilkan karakter dino dan rintangan kaktus pada layar OLED.

    Pada saat permainan berlangsung, mikrokontroler master akan membaca kondisi push button sebagai input untuk melakukan lompatan. Ketika tombol ditekan dan karakter belum melompat, sistem memberikan kecepatan awal ke atas pada karakter sehingga karakter tampak melompat pada layar. Setelah itu, gravitasi akan bekerja dengan menambah nilai kecepatan secara bertahap sehingga karakter kembali turun menuju tanah. Proses ini menghasilkan animasi gerakan lompat seperti pada permainan Geometry Jump atau Dino Game.

    Rintangan berupa kaktus akan bergerak dari kanan ke kiri layar secara terus menerus. Kecepatan rintangan akan meningkat seiring bertambahnya skor sehingga tingkat kesulitan permainan ikut meningkat. Ketika karakter berhasil melewati rintangan, skor akan bertambah. Namun jika posisi karakter bertabrakan dengan kaktus, maka status permainan berubah menjadi game over. Sistem kemudian menampilkan tulisan “GAME OVER” dan nilai skor tertinggi pada OLED.

    Komunikasi SPI digunakan untuk mengirimkan perintah tertentu dari master ke slave, seperti kondisi permainan berjalan, suara lompat, suara tabrakan, dan game over. Data dikirim menggunakan fungsi HAL_SPI_Transmit() dengan bantuan pin CS (Chip Select) untuk sinkronisasi komunikasi. Saat karakter melompat, master mengirimkan perintah CMD_JUMP_SOUND, sedangkan saat terjadi tabrakan master mengirimkan CMD_HIT_SOUND. Dengan demikian slave dapat memberikan respon tertentu sesuai data yang diterima, misalnya menyalakan indikator atau menghasilkan efek suara.

    Secara keseluruhan, percobaan ini menunjukkan bagaimana komunikasi SPI dapat digunakan untuk pertukaran data cepat antar mikrokontroler, sedangkan komunikasi I2C digunakan untuk mengendalikan OLED sebagai media tampilan. Kombinasi kedua protokol tersebut memungkinkan sistem permainan sederhana dapat berjalan secara sinkron antara proses tampilan, logika permainan, dan komunikasi antar perangkat.


    d. Flowchart dan Listing Program[Kembali]

    FLOWCHART
     



















    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]


    LAPORAN AKHIR [Klik Disini]

    Datasheet : 

          Datasheet Led  [klik disini]













     

     

     

    Komentar

    Postingan populer dari blog ini

    Tugas Besar