← Back to list

Modul 7 (Display dan Aktuator)

DISPLAY

Sonya · 2025-05-02 12:20 · 0 claps · 13.6 min read
#esp32 #display #aktuator
Open on Medium ↗

Modul 7 (Display dan Aktuator)

DISPLAY

Pendahuluan Pada percobaan ini, dilakukan uji coba penggunaan mikrokontroler ESP32 untuk menampilkan teks sederhana pada modul OLED 128x64 dengan chip SSD1306. Percobaan ini bertujuan memahami integrasi perangkat keras dan pemrograman dasar menggunakan Arduino IDE.

Alat dan Bahan

  • 1 buah ESP32 Dev Module
  • 1 buah OLED Display 128x64 SSD1306 (I2C interface)
  • Kabel jumper (male to female)
  • Breadboard
  • Laptop dengan Arduino IDE versi terbaru

Langkah-Langkah Percobaan

  1. Menginstal Library
  • Buka Arduino IDE.
  • Buka menu Sketch → Include Library → Manage Libraries.
  • Cari dan instal Adafruit GFX Library dan Adafruit SSD1306. Jika setelah meng-install library tersebut muncul perintah untuk meng-install library lainnya yang berkaitan, install semuanya.

2. Menyiapkan Rangkaian Koneksi

  • Sambungkan VCC pada OLED ke 3.3V pada ESP32.
  • Sambungkan GND pada OLED ke GND pada ESP32.
  • Sambungkan SCL pada OLED ke GPIO22 (pin SCL ESP32).
  • Sambungkan SDA pada OLED ke GPIO21 (pin SDA ESP32).

3. Upload Program I2C Scanner (Deteksi Alamat OLED)

  • Salin kode program berikut.
#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(115200);
  Serial.println("\nI2C Scanner");
}

void loop() {
  byte error, address;
  int nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for(address = 1; address < 127; address++ ) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
      nDevices++;
    }
    else if (error==4) {
      Serial.print("Unknow error at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0) {
    Serial.println("No I2C devices found\n");
  }
  else {
    Serial.println("done\n");
  }
  delay(5000);          
}
  • Upload ke ESP32.
  • Buka Tools → Serial Monitor di Arduino IDE (baud rate 115200).
  • Catat alamat I2C yang terdeteksi (biasanya muncul seperti 0x3C).

Keterangan: program ini membantu memastikan alamat I2C OLED sebelum menjalankan program utama.

4. Upload Program OLED Demo

  • Salin kode program berikut.
/**************************************************************************
 This is an example for our Monochrome OLEDs based on SSD1306 drivers

 Pick one up today in the adafruit shop!
 ------> http://www.adafruit.com/category/63_98

 This example is for a 128x64 pixel display using I2C to communicate
 3 pins are required to interface (two I2C and one reset).

 Adafruit invests time and resources providing this open
 source code, please support Adafruit and open-source
 hardware by purchasing products from Adafruit!

 Written by Limor Fried/Ladyada for Adafruit Industries,
 with contributions from the open source community.
 BSD license, check license.txt for more information
 All text above, and the splash screen below must be
 included in any redistribution.
 **************************************************************************/

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

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library. 
// On an arduino UNO:       A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO:   2(SDA),  3(SCL), ...
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define NUMFLAKES     10 // Number of snowflakes in the animation example

#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16
static const unsigned char PROGMEM logo_bmp[] =
{ 0b00000000, 0b11000000,
  0b00000001, 0b11000000,
  0b00000001, 0b11000000,
  0b00000011, 0b11100000,
  0b11110011, 0b11100000,
  0b11111110, 0b11111000,
  0b01111110, 0b11111111,
  0b00110011, 0b10011111,
  0b00011111, 0b11111100,
  0b00001101, 0b01110000,
  0b00011011, 0b10100000,
  0b00111111, 0b11100000,
  0b00111111, 0b11110000,
  0b01111100, 0b11110000,
  0b01110000, 0b01110000,
  0b00000000, 0b00110000 };

void setup() {
  Serial.begin(9600);

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

  // Draw a single pixel in white
  display.drawPixel(10, 10, SSD1306_WHITE);

  // Show the display buffer on the screen. You MUST call display() after
  // drawing commands to make them visible on screen!
  display.display();
  delay(2000);
  // display.display() is NOT necessary after every single drawing command,
  // unless that's what you want...rather, you can batch up a bunch of
  // drawing operations and then update the screen all at once by calling
  // display.display(). These examples demonstrate both approaches...

  testdrawline();      // Draw many lines

  testdrawrect();      // Draw rectangles (outlines)

  testfillrect();      // Draw rectangles (filled)

  testdrawcircle();    // Draw circles (outlines)

  testfillcircle();    // Draw circles (filled)

  testdrawroundrect(); // Draw rounded rectangles (outlines)

  testfillroundrect(); // Draw rounded rectangles (filled)

  testdrawtriangle();  // Draw triangles (outlines)

  testfilltriangle();  // Draw triangles (filled)

  testdrawchar();      // Draw characters of the default font

  testdrawstyles();    // Draw 'stylized' characters

  testscrolltext();    // Draw scrolling text

  testdrawbitmap();    // Draw a small bitmap image

  // Invert and restore display, pausing in-between
  display.invertDisplay(true);
  delay(1000);
  display.invertDisplay(false);
  delay(1000);

  testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
}

void loop() {
}

void testdrawline() {
  int16_t i;

  display.clearDisplay(); // Clear display buffer

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
    display.display(); // Update screen with each newly-drawn line
    delay(1);
  }
  for(i=0; i<display.height(); i+=4) {
    display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=display.width()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.height(); i+=4) {
    display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=0; i<display.width(); i+=4) {
    display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000); // Pause for 2 seconds
}

void testdrawrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=2) {
    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
    display.display(); // Update screen with each newly-drawn rectangle
    delay(1);
  }

  delay(2000);
}

void testfillrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=3) {
    // The INVERSE color is used so rectangles alternate white/black
    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
    display.display(); // Update screen with each newly-drawn rectangle
    delay(1);
  }

  delay(2000);
}

void testdrawcircle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
    display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillcircle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
    // The INVERSE color is used so circles alternate white/black
    display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
    display.display(); // Update screen with each newly-drawn circle
    delay(1);
  }

  delay(2000);
}

void testdrawroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    // The INVERSE color is used so round-rects alternate white/black
    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, SSD1306_INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawtriangle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
    display.drawTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfilltriangle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
    // The INVERSE color is used so triangles alternate white/black
    display.fillTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawchar(void) {
  display.clearDisplay();

  display.setTextSize(1);      // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(0, 0);     // Start at top-left corner
  display.cp437(true);         // Use full 256 char 'Code Page 437' font

  // Not all the characters will fit on the display. This is normal.
  // Library will draw what it can and the rest will be clipped.
  for(int16_t i=0; i<256; i++) {
    if(i == '\n') display.write(' ');
    else          display.write(i);
  }

  display.display();
  delay(2000);
}

void testdrawstyles(void) {
  display.clearDisplay();

  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.setCursor(0,0);             // Start at top-left corner
  display.println(F("Hello, world!"));

  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
  display.println(3.141592);

  display.setTextSize(2);             // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.print(F("0x")); display.println(0xDEADBEEF, HEX);

  display.display();
  delay(2000);
}

void testscrolltext(void) {
  display.clearDisplay();

  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 0);
  display.println(F("scroll"));
  display.display();      // Show initial text
  delay(100);

  // Scroll in various directions, pausing in-between:
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
}

void testdrawbitmap(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - LOGO_WIDTH ) / 2,
    (display.height() - LOGO_HEIGHT) / 2,
    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.display();
  delay(1000);
}

#define XPOS   0 // Indexes into the 'icons' array in function below
#define YPOS   1
#define DELTAY 2

void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  int8_t f, icons[NUMFLAKES][3];

  // Initialize 'snowflake' positions
  for(f=0; f< NUMFLAKES; f++) {
    icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
    icons[f][YPOS]   = -LOGO_HEIGHT;
    icons[f][DELTAY] = random(1, 6);
    Serial.print(F("x: "));
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(F(" y: "));
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(F(" dy: "));
    Serial.println(icons[f][DELTAY], DEC);
  }

  for(;;) { // Loop forever...
    display.clearDisplay(); // Clear the display buffer

    // Draw each snowflake:
    for(f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
    }

    display.display(); // Show the display buffer on the screen
    delay(200);        // Pause for 1/10 second

    // Then update coordinates of each flake...
    for(f=0; f< NUMFLAKES; f++) {
      icons[f][YPOS] += icons[f][DELTAY];
      // If snowflake is off the bottom of the screen...
      if (icons[f][YPOS] >= display.height()) {
        // Reinitialize to a random position, just off the top
        icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
        icons[f][YPOS]   = -LOGO_HEIGHT;
        icons[f][DELTAY] = random(1, 6);
      }
    }
  }
}
  • Pastikan bagian alamat I2C di kode sesuai hasil scanner (#define SCREEN_ADDRESS 0x3C).
  • Upload ke ESP32.
  • Amati hasil di layar OLED: teks, garis, bentuk, animasi bitmap.

Keterangan: program ini menguji kemampuan tampilan OLED dan penggunaan library.

5. Hasil Pengamatan

  • Pastikan OLED menyala dan menampilkan pola sesuai program. Jika tidak muncul, periksa lagi sambungan kabel, alamat I2C, dan upload ulang program.

KREASI DISPLAY

Langkah-Langkah Bagian Kreasi: Menampilkan Meme di OLED

  1. Persiapan Gambar. Download gambar yang ingin digunakan.

  1. Menghapus Background Gambar
  • Karena OLED hanya menampilkan gambar monokrom (hitam-putih), hapus background putih agar bentuk karakterlebih jelas. Saya menggunakan website seperti remove.bg untuk menghapus background.
  1. Konversi Gambar ke Format Byte Array (C File)
  • Download dan install software LCD Image Converter dari SourceForge.

[embed]lcd-image-converter Files Tool to create bitmaps and fonts for embedded applications.sourceforge.net

  • Buka software → New Image, beri nama file baru.
  • Import frame yang sudah dihapus background → Image → Import….
  • Masuk ke Options → Conversion…:
  • Tab Prepare: preset → Monochrome, scan direction → Top to Bottom, line direction → Forward.

  • Tab Image: centang Split to rows, block size → 8 bit, byte order → Little-Endian.

  • Klik OK, lalu File → Convert… → hasilnya berupa file bahasa C berisi array hexadecimal.
  1. Susun Kode di Arduino IDE
  • Berikut adalah kode program yang sudah dibuat.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

static const uint8_t image_data_cute[1020] = {
  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xaa, 0xe0, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xff, 0x58, 0x07, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xfd, 0xec, 0x0d, 0x7b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0b, 0xdf, 0xf6, 0x3b, 0xfd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xdb, 0x2f, 0xff, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x17, 0xf7, 0x7d, 0xdf, 0xef, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xdf, 0xff, 0xbe, 0xfe, 0xd0, 0x00, 0x00, 0x00, 0x1f, 0xf7, 0xff, 0xfd, 0xfb, 0xfb, 0xd0, 0x00, 0x00, 0x00, 0x20, 0x5f, 0xfd, 0xf6, 0xbf, 0xdf, 0xf8, 0x00, 0x00, 0x00, 0xbf, 0xad, 0xdf, 0xbf, 0x7f, 0xff, 0xd7, 0xf0, 0x00, 0x02, 0xaa, 0xd7, 0xff, 0xfd, 0xee, 0xfe, 0xe8, 0x1c, 0x00, 0x05, 0xdd, 0xaf, 0xf6, 0xfe, 0xbf, 0xef, 0xef, 0xe2, 0x00, 0x06, 0xb6, 0xef, 0x7f, 0xe9, 0x7f, 0xff, 0xea, 0xbd, 0x00, 0x05, 0x55, 0x57, 0xff, 0xff, 0xbd, 0xbb, 0x6d, 0xd6, 0x80, 0x1b, 0xef, 0xbf, 0xdb, 0xbb, 0xf7, 0xff, 0xd6, 0xba, 0x40, 0x2a, 0xb5, 0x55, 0xff, 0xf7, 0x5f, 0xff, 0xed, 0xad, 0x80, 0x16, 0xdb, 0x6b, 0xff, 0xe8, 0xbf, 0xb7, 0x5b, 0x76, 0xa0, 0x7b, 0x6d, 0xbb, 0xbb, 0x57, 0x7e, 0xff, 0xad, 0xab, 0xc0, 0x4d, 0xb6, 0xd4, 0xff, 0xad, 0xaf, 0xff, 0x76, 0xdd, 0x60, 0xb6, 0xdb, 0x6f, 0x08, 0xb6, 0xab, 0xfd, 0x56, 0xb6, 0xb0, 0xdb, 0x6d, 0xb4, 0xf7, 0x6d, 0xda, 0xa2, 0xdb, 0xdb, 0x50, 0xb5, 0xb6, 0xdb, 0x5a, 0xaa, 0x6d, 0x55, 0x6d, 0x55, 0xd0, 0xde, 0xdb, 0x6a, 0xd5, 0x21, 0x02, 0xda, 0xb6, 0xde, 0xa0, 0xab, 0x6d, 0xab, 0x64, 0x95, 0x54, 0x2e, 0xab, 0x6b, 0x50, 0xf5, 0xb6, 0xad, 0x12, 0x54, 0xaa, 0xa5, 0xad, 0xb5, 0xd0, 0x56, 0xda, 0xaa, 0xaa, 0x92, 0x11, 0x52, 0xd6, 0xde, 0xb0, 0x5b, 0x6b, 0x74, 0x84, 0x49, 0x4a, 0x09, 0x6b, 0x6a, 0xd0, 0x2d, 0xb5, 0x52, 0x52, 0xad, 0x29, 0x64, 0xb5, 0xb6, 0xa0, 0x15, 0x5d, 0x49, 0x29, 0x3d, 0x44, 0x95, 0x1a, 0xad, 0xa0, 0x0b, 0xea, 0xd4, 0x8a, 0xfe, 0x95, 0x08, 0xaa, 0xdb, 0x40, 0x0d, 0x35, 0x02, 0x50, 0xff, 0x44, 0xa5, 0x0a, 0xb6, 0x40, 0x05, 0x47, 0x5a, 0xaa, 0xdf, 0x2a, 0x52, 0xa6, 0xdb, 0x80, 0x01, 0xd4, 0x88, 0x11, 0xfb, 0xa1, 0x24, 0x51, 0x6c, 0x80, 0x00, 0x56, 0x55, 0x4a, 0xff, 0x4a, 0x92, 0x8a, 0x55, 0x00, 0x00, 0x4a, 0x42, 0xa8, 0xff, 0xa4, 0xa5, 0x55, 0x0a, 0x00, 0x00, 0x2d, 0x28, 0x45, 0xbf, 0xa2, 0x52, 0x08, 0xd8, 0x00, 0x00, 0x94, 0x95, 0x28, 0xf6, 0xd5, 0x24, 0xd2, 0x48, 0x00, 0x00, 0xaa, 0x49, 0x55, 0xff, 0xe9, 0x4a, 0x0a, 0x90, 0x00, 0x00, 0x54, 0xa4, 0x89, 0xff, 0xf4, 0xa1, 0x64, 0xa8, 0x00, 0x00, 0x92, 0x29, 0x53, 0xff, 0xfa, 0x15, 0x12, 0x44, 0x00, 0x00, 0x4a, 0x94, 0x27, 0xb7, 0x7e, 0xca, 0xa9, 0x2c, 0x00, 0x01, 0x54, 0x42, 0x9f, 0xff, 0xff, 0x50, 0x85, 0xe4, 0x00, 0x01, 0x22, 0xa9, 0x5d, 0xff, 0xf7, 0xea, 0x55, 0xe8, 0x00, 0x01, 0x94, 0x52, 0xbf, 0xff, 0xbf, 0xf9, 0x4b, 0xe4, 0x00, 0x01, 0x52, 0x8a, 0xff, 0xed, 0xff, 0x7c, 0xa3, 0xec, 0x00, 0x01, 0x2a, 0x47, 0xf7, 0xbf, 0xfd, 0x7e, 0x15, 0xd4, 0x00, 0x00, 0x44, 0x55, 0xdf, 0xff, 0xfc, 0x3d, 0x42, 0xc8, 0x00, 0x00, 0x52, 0x8b, 0xea, 0xff, 0xdc, 0xae, 0xa9, 0x28, 0x00, 0x00, 0x94, 0x57, 0xfd, 0xfd, 0xfa, 0x3f, 0x14, 0x48, 0x00, 0x00, 0x49, 0x47, 0xea, 0xf6, 0xfc, 0x3f, 0x49, 0x28, 0x00, 0x00, 0xa4, 0xab, 0xb7, 0xdf, 0xfc, 0xbb, 0xa8, 0x88, 0x00, 0x00, 0x56, 0x5f, 0xef, 0xff, 0xde, 0x6f, 0xfa, 0x58, 0x00, 0x00, 0x9e, 0xeb, 0xbf, 0xff, 0x7f, 0xff, 0xfd, 0x20, 0x00, 0x00, 0xaf, 0x76, 0xfb, 0xfd, 0x97, 0xfe, 0xfc, 0x90, 0x00, 0x00, 0x5b, 0xef, 0xeb, 0xbf, 0x6f, 0xff, 0xea, 0x50, 0x00, 0x00, 0x8f, 0x7b, 0xdf, 0xf7, 0x5f, 0xef, 0xf9, 0x50, 0x00, 0x00, 0x57, 0x2d, 0xf5, 0xfd, 0x7f, 0x7f, 0x75, 0x10, 0x00, 0x00, 0xa0, 0xbd, 0xb7, 0xd7, 0xfd, 0xfd, 0xe9, 0x50, 0x00, 0x00, 0x15, 0x56, 0xdf, 0xff, 0xef, 0xff, 0xd2, 0x50, 0x00, 0x01, 0x54, 0x9f, 0x6f, 0xfe, 0xff, 0xf7, 0xc9, 0x10, 0x00, 0x01, 0x4a, 0x45, 0x7f, 0x7f, 0xff, 0xdf, 0x25, 0x50, 0x00, 0x01, 0x21, 0x2f, 0xdd, 0xfb, 0xfb, 0xfe, 0x92, 0x40, 0x00, 0x00, 0x94, 0xbf, 0xdf, 0xff, 0xbf, 0xfc, 0xa9, 0x28, 0x00, 0x02, 0x55, 0x3f, 0xef, 0xef, 0xff, 0x72, 0x44, 0xa8, 0x00, 0x02, 0xa0, 0xa5, 0x5b, 0xff, 0xfb, 0xc1, 0x25, 0x44, 0x00, 0x02, 0x4d, 0x7d, 0xf7, 0xfe, 0xef, 0x7c, 0xa9, 0x28, 0x00, 0x02, 0xa2, 0x3a, 0x70, 0x03, 0xff, 0xd2, 0x92, 0x42, 0x00, 0x01, 0x19, 0x77, 0xdb, 0x57, 0xff, 0xf6, 0x49, 0x34, 0x00, 0x02, 0xa4, 0x9a, 0xf4, 0x9b, 0x7f, 0x9a, 0xa4, 0x89, 0x00, 0x02, 0x52, 0x5f, 0xe2, 0x6d, 0xf6, 0xf6, 0x92, 0x55, 0x00, 0x02, 0x89, 0x2f, 0x95, 0xbe, 0xde, 0xb5, 0xe9, 0x49, 0x00, 0x00, 0x54, 0xbf, 0xc9, 0x5f, 0xab, 0xf6, 0xe4, 0xa5, 0x00, 0x01, 0x24, 0x7d, 0xa6, 0xdf, 0xff, 0xf5, 0x75, 0x11, 0x00, 0x01, 0x52, 0xff, 0x1d, 0xaf, 0xff, 0xf6, 0xf8, 0xab, 0x00, 0x01, 0x29, 0xef, 0x5e, 0xdf, 0xff, 0xe9, 0xfd, 0x49, 0x00, 0x01, 0x45, 0xbe, 0xbd, 0x6f, 0x7d, 0x55, 0xfd, 0x25, 0x00, 0x01, 0x2b, 0xfe, 0xff, 0x5f, 0xf6, 0xab, 0xfe, 0x95, 0x00, 0x02, 0x93, 0xfd, 0xfc, 0xae, 0xca, 0xb5, 0xff, 0x51, 0x00, 0x01, 0x4f, 0x7d, 0xfd, 0xa9, 0x5b, 0x6d, 0xbf, 0x8a, 0x80, 0x02, 0x2b, 0xf7, 0xdd, 0x56, 0xed, 0xb5, 0xff, 0xe4, 0x80, 0x01, 0x5f, 0xfd, 0xfd, 0x7b, 0x56, 0xdb, 0xfb, 0xd2, 0x40, 0x02, 0x4f, 0xfb, 0xfd, 0xad, 0xbb, 0x6d, 0xff, 0xf5, 0x40, 0x01, 0x3f, 0x7b, 0xfd, 0x6a, 0xd5, 0xb6, 0xff, 0xf4, 0x40, 0x02, 0xbf, 0xeb, 0xfd, 0xbf, 0x6e, 0xda, 0xff, 0xfa, 0xc0, 0x02, 0x77, 0xfb, 0xbd, 0x65, 0xb5, 0x6d, 0xdf, 0xbc, 0x80, 0x01, 0x3f, 0x7e, 0xfd, 0xb5, 0x5a, 0x96, 0xfe, 0xfe, 0x80, 0x01, 0xbf, 0xfb, 0xfb, 0x49, 0x22, 0xaa, 0xbf, 0xff, 0x40, 0x01, 0x7f, 0xfd, 0xfa, 0x95, 0x55, 0x4d, 0x7f, 0xff, 0x80, 0x01, 0x3b, 0xdb, 0xfb, 0x55, 0xaa, 0xab, 0x7f, 0xff, 0xa0, 0x01, 0x3f, 0x7f, 0xfa, 0x56, 0x55, 0x4d, 0xbf, 0xfd, 0xf0, 0x01, 0x57, 0xf2, 0xf7, 0x55, 0x56, 0xaa, 0xbf, 0xff, 0xd0, 0x01, 0x0f, 0xdb, 0xf5, 0x2a, 0xaa, 0x9f, 0xdf, 0x77, 0xd0, 0x00, 0xd0, 0x77, 0xd5, 0xaa, 0xaa, 0xa9, 0x5b, 0xff, 0xd0, 0x00, 0x4b, 0xec, 0x56, 0xad, 0x55, 0x56, 0xcf, 0xff, 0x70, 0x00, 0x35, 0xd7, 0xfb, 0x55, 0x5a, 0xad, 0xaf, 0xfd, 0xa0, 0x00, 0x1f, 0x78, 0x2d, 0xaa, 0xd5, 0x36, 0xf7, 0xb7, 0x40, 0x00, 0x00, 0x00, 0x2a, 0xca, 0xaa, 0xdb, 0x57, 0xfd, 0x80, 0x00, 0x00, 0x00, 0x2d, 0x65, 0x55, 0x6d, 0xb6, 0xee, 0x00, 0x00, 0x00, 0x00, 0x2b, 0xb8, 0x8a, 0xb6, 0xda, 0x94, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x57, 0x77, 0x5b, 0x6b, 0xf8, 0x00
};

void setup() {
  Serial.begin(115200);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000); // Pause for 2 seconds

  // Clear the buffer.
  display.clearDisplay();

  // Draw bitmap on the screen
  display.drawBitmap(0, 0, image_data_cute, 99, 64, 1);
  display.display();
}

void loop() {

}
  1. Upload dan Uji Coba
  • Upload program ke ESP32.
  • Pastikan gambar animasi tampil.

Catatan: Hasil gambar kadang perlu diperbaiki manual di kode hexadecimal agar terlihat pas di layar OLED.

AKTUATOR

Pendahuluan Percobaan ini bertujuan mempelajari cara kerja Pulse Width Modulation (PWM) pada ESP32, khususnya untuk mengatur kecerahan LED. PWM adalah teknik pengendalian daya dengan cara mengatur rasio hidup-mati sinyal (duty cycle) pada frekuensi tertentu, sehingga dapat mengontrol perangkat seperti LED, motor, atau buzzer tanpa mengubah tegangan.

Alat dan Bahan

  • 1 buah ESP32 Dev Module
  • 1 buah LED
  • 1 buah resistor 330 Ω
  • Kabel jumper
  • Breadboard
  • Laptop dengan Arduino IDE

Rangkaian

  • Sambungkan kaki anoda (panjang) LED ke GPIO 26 ESP32 melalui resistor 330 Ω.
  • Sambungkan kaki katoda (pendek) LED ke GND ESP32.
  • Pastikan koneksi rapat dan tidak ada hubungan pendek (short).

Langkah-Langkah Percobaan

1. Persiapan

  • Buka Arduino IDE.
  • Pastikan board ESP32 sudah terdeteksi di Tools → Board → ESP32 Dev Module.
  • Hubungkan ESP32 ke laptop menggunakan kabel USB.

2. Penulisan Program

  • Buat program sederhana untuk menghasilkan sinyal PWM pada GPIO 26.
  • Atur frekuensi (misalnya 5000 Hz), kanal (misalnya channel 0), dan resolusi (8 bit).
  • Gunakan perulangan untuk mengubah duty cycle dari 0 ke 255 (naik) dan dari 255 ke 0 (turun) agar LED terlihat meredup dan menyala bergantian.
  • Berikut kode programnya.
/* PWM Aktuator Testing 1 LED */

// the number of the LED pin
const int ledPin = 26;  // 26 corresponds to GPIO26

// setting PWM properties
const int freq = 5000;
const int ledChannel = 0;
const int resolution = 8;

void setup(){
  // configure LED PWM functionalitites
  ledcSetup(ledChannel, freq, resolution);

  // attach the channel to the GPIO to be controlled
  ledcAttachPin(ledPin, ledChannel);
}

void loop(){
  // increase the LED brightness
  for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++){  
    // changing the LED brightness with PWM
    ledcWrite(ledChannel, dutyCycle);
    delay(15);
  }

  // decrease the LED brightness
  for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle--){
    // changing the LED brightness with PWM
    ledcWrite(ledChannel, dutyCycle);  
    delay(15);
  }
}

3. Upload Program

  • Klik Upload di Arduino IDE.
  • Pastikan tidak ada error saat kompilasi dan upload.

4. Pengamatan

  • Perhatikan LED pada breadboard.
  • LED akan perlahan menyala semakin terang (saat duty cycle naik) lalu perlahan meredup (saat duty cycle turun), menunjukkan PWM bekerja.

KESIMPULAN

Display (OLED): ESP32 berhasil digunakan untuk menampilkan teks, gambar, dan animasi pada OLED 128x64 melalui protokol I2C, dengan bantuan library Adafruit, membuktikan kemampuannya dalam menangani komunikasi visual berbasis data.

Aktuator (PWM LED): ESP32 mampu mengontrol aktuator sederhana seperti LED dengan teknik PWM, menghasilkan variasi kecerahan yang halus melalui pengaturan duty cycle tanpa mengubah tegangan suplai, menunjukkan fleksibilitas pengendalian sinyal digital.


메타데이터
post_id
2c4f2970307b
slug
modul-7-display-dan-aktuator-2c4f2970307b
url
https://medium.com/@18223138/modul-7-display-dan-aktuator-2c4f2970307b
canonical_url
https://medium.com/@18223138/modul-7-display-dan-aktuator-2c4f2970307b
author_url
https://medium.com/@18223138
status
ok
fetched_at
2026-07-20 02:25:49