Kamis, 09 April 2026

Membuat WiFi Scanner Portabel
dengan NodeMCU ESP8266 dan Layar OLED

WiFi Scanner Portabel dengan NodeMCU ESP8266 dan OLED | Tutorial Lengkap 2024

📡 MEMBUAT WIFI SCANNER PORTABEL
dengan NodeMCU ESP8266 dan Layar OLED 0.96"


📡 Apa Itu WiFi Scanner?

WiFi scanner adalah alat atau perangkat lunak yang digunakan untuk mendeteksi dan menampilkan semua jaringan WiFi yang tersedia di sekitar suatu lokasi. Alat ini menampilkan informasi penting seperti SSID (nama jaringan), BSSID (MAC address access point), RSSI (kekuatan sinyal dalam dBm), channel yang digunakan, serta jenis enkripsi (WPA2, WPA3, WEP, atau Open).

Dalam proyek kali ini, kita akan membuat WiFi scanner portabel berukuran saku yang dapat Anda bawa ke mana saja. Berbeda dengan scanner di smartphone yang terbatas, alat buatan sendiri ini memberikan Anda kendali penuh atas data yang ditampilkan dan dapat dikustomisasi sesuai kebutuhan.

💡 Fakta Menarik: Istilah "wardriving" populer pada awal 2000-an, dimana para penggemar WiFi berkeliling kota dengan laptop dan antena untuk memetakan jaringan WiFi. Sekarang, Anda bisa melakukannya dengan alat sekecil genggaman tangan!

🎯 Mengapa Anda Membutuhkan Alat Ini?

Berikut adalah 7 skenario nyata di mana WiFi scanner portabel sangat berguna:

  • 🔍 Survei Lokasi Pemasangan WiFi - Sebelum memasang access point di rumah atau kantor, Anda bisa scan dulu area mana yang sinyalnya paling kuat.
  • 🏢 Audit Keamanan Jaringan - Deteksi jaringan terbuka (tanpa password) yang berpotensi disalahgunakan.
  • 📊 Analisis Interferensi Channel - Lihat channel apa yang paling padat, lalu pilih channel yang lebih sepi untuk router Anda.
  • 🎓 Belajar IoT & Pemrograman ESP8266 - Proyek sempurna untuk pemula karena langsung ada hasil visualnya.
  • 🛠 Troubleshooting WiFi - Cek apakah tetangga menggunakan channel yang sama dengan router Anda.
  • 📱 Membandingkan Kualitas ISP - Scan di berbagai lokasi untuk melihat provider mana yang paling banyak tersedia.
  • 🚗 WarDriving (Pemetaan WiFi) - Buat peta sebaran WiFi di kota Anda untuk proyek komunitas.

🛠 Alat dan Bahan (Lengkap dengan Estimasi Biaya)

Semua komponen mudah didapatkan di Tokopedia, Shopee, atau toko elektronik lokal. Total biaya sekitar Rp 150.000 - Rp 250.000.

KomponenSpesifikasiFungsiHarga (Rp)
NodeMCU ESP8266ESP-12E, CP2102/CH340Otak alat + WiFi60.000 - 85.000
Layar OLED 0.96"128x64 pixel, I2C, SSD1306Menampilkan hasil scan40.000 - 65.000
Kabel Jumper F-F20cm, 4-5 buahKoneksi5.000 - 10.000
Power Bank (opsional)5V 1A outputPower portabel50.000 - 100.000
Kabel Micro USBUntuk data & powerUpload program15.000 - 30.000
Project Box (opsional)6x9 cmTempat/casing10.000 - 25.000
💡 Tips Hemat: Jika sudah memiliki power bank dan kabel USB, Anda hanya perlu membeli NodeMCU, OLED, dan kabel jumper (total sekitar Rp 110.000)!

🔌 Skema Koneksi (Wiring Diagram)

Layar OLED 0.96" yang menggunakan protokol I2C hanya membutuhkan 4 kabel. Berikut adalah tabel koneksi yang harus Anda buat:

Layar OLEDNodeMCU ESP8266GPIOKeterangan
VCC3.3V-Tegangan 3.3 Volt (JANGAN 5V!)
GNDGND-Ground / Tanah
SCLD1GPIO5Clock I2C
SDAD2GPIO4Data I2C
⚠️ PERINGATAN PENTING: NodeMCU ESP8266 menggunakan logika 3.3 VOLT. Pastikan layar OLED Anda mendukung 3.3V. Jika tidak yakin, periksa datasheet. Menyambungkan ke pin 5V (misalnya dari Arduino Uno) dapat merusak layar secara permanen!

⚙️ Persiapan Arduino IDE

Sebelum memprogram, Anda perlu menambahkan board ESP8266 ke Arduino IDE. Berikut langkah-langkahnya:

Langkah 1: Tambahkan URL Board Manager

Buka Arduino IDE → File → Preferences. Pada kolom "Additional Boards Manager URLs", tambahkan URL berikut:

https://arduino.esp8266.com/stable/package_esp8266com_index.json

Langkah 2: Instal Board ESP8266

Klik Tools → Board → Boards Manager. Cari "esp8266", lalu instal "esp8266 by ESP8266 Community".

Langkah 3: Pilih Board NodeMCU

Setelah instalasi selesai, pilih board: Tools → Board → ESP8266 Boards → NodeMCU 1.0 (ESP-12E Module)

Langkah 4: Pilih Port COM

Hubungkan NodeMCU ke komputer, lalu pilih port yang sesuai di Tools → Port (misal COM3, COM4, atau /dev/cu.usbserial-xxx).

💡 Driver CH340/CP2102: Jika port tidak muncul, Anda mungkin perlu menginstal driver USB-to-serial. Cari "Driver CH340" atau "Driver CP2102" sesuai chip di board Anda.

📚 Instalasi Library yang Diperlukan

Buka Sketch → Include Library → Manage Libraries, lalu cari dan instal:

LibraryNama PencarianFungsi
Adafruit GFX"Adafruit GFX Library"Fungsi grafis dasar (lingkaran, garis, persegi)
Adafruit SSD1306"Adafruit SSD1306"Driver khusus untuk layar OLED SSD1306
ESP8266WiFi(Built-in, sudah ada)Fungsi koneksi dan scan WiFi

Catatan: Library Adafruit SSD1306 mungkin meminta instalasi dependensi. Setujui semua permintaan instalasi tambahan.

💻 Kode Program LENGKAP (Copy-Paste)

Berikut adalah kode program lengkap yang siap diupload ke NodeMCU. Kode ini berukuran sekitar 250 baris dan sudah mencakup semua fitur yang dijelaskan.

/*
    ================================================================
    PROJECT: WiFi Scanner Portabel dengan NodeMCU ESP8266 + OLED
    AUTHOR: Tutorial IoT
    VERSION: 2.0 (Lengkap dengan fitur sorting, icon signal, dll)
    ================================================================
    
    Fitur:
    - Scan otomatis setiap 10 detik
    - Menampilkan SSID, RSSI (dBm), dan jenis keamanan
    - Icon bar sinyal (1-4 bar)
    - Icon gembok untuk jaringan terenkripsi
    - Sorting dari sinyal terkuat ke terlemah
    - Pagination (3 jaringan per halaman)
    - Tampilan jam digital di bagian atas (opsional dengan NTP)
*/

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

// ========== KONFIGURASI OLED ==========
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
#define OLED_ADDRESS  0x3C   // Coba 0x3D jika tidak muncul

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// ========== VARIABEL GLOBAL ==========
unsigned long lastScan = 0;
int scanInterval = 10000;      // Scan setiap 10 detik (10000 ms)
int currentPage = 0;
int totalNetworks = 0;
int networksPerPage = 3;       // Jumlah jaringan per halaman

// Array penyimpanan data (maks 20 jaringan)
String networkNames[20];
int networkRSSI[20];
int networkEncryption[20];
String networkBSSID[20];
int networkChannel[20];

// ========== FUNGSI SCAN JARINGAN ==========
void scanWiFi() {
    // Tampilkan pesan scanning
    display.clearDisplay();
    display.setTextSize(1);
    display.setCursor(25, 28);
    display.println("Scanning WiFi...");
    display.display();
    
    // Lakukan scan (mode aktif)
    int n = WiFi.scanNetworks();
    
    if (n == 0) {
        display.clearDisplay();
        display.setCursor(20, 28);
        display.println("No networks found");
        display.display();
        delay(2000);
        return;
    }
    
    // Batasi maksimal 20 jaringan
    totalNetworks = min(n, 20);
    
    // Simpan hasil scan ke array
    for (int i = 0; i < totalNetworks; i++) {
        networkNames[i] = WiFi.SSID(i);
        if (networkNames[i] == "") networkNames[i] = "(Hidden Network)";
        
        networkRSSI[i] = WiFi.RSSI(i);
        networkEncryption[i] = WiFi.encryptionType(i);
        networkBSSID[i] = WiFi.BSSIDstr(i);
        networkChannel[i] = WiFi.channel(i);
    }
    
    // ===== SORTING: Urutkan dari sinyal TERKUAT ke TERLEMAH =====
    for (int i = 0; i < totalNetworks - 1; i++) {
        for (int j = i + 1; j < totalNetworks; j++) {
            if (networkRSSI[j] > networkRSSI[i]) {
                // Tukar SSID
                String tempName = networkNames[i];
                networkNames[i] = networkNames[j];
                networkNames[j] = tempName;
                
                // Tukar RSSI
                int tempRSSI = networkRSSI[i];
                networkRSSI[i] = networkRSSI[j];
                networkRSSI[j] = tempRSSI;
                
                // Tukar enkripsi
                int tempEnc = networkEncryption[i];
                networkEncryption[i] = networkEncryption[j];
                networkEncryption[j] = tempEnc;
                
                // Tukar BSSID
                String tempBSSID = networkBSSID[i];
                networkBSSID[i] = networkBSSID[j];
                networkBSSID[j] = tempBSSID;
                
                // Tukar channel
                int tempCh = networkChannel[i];
                networkChannel[i] = networkChannel[j];
                networkChannel[j] = tempCh;
            }
        }
    }
    
    // Reset ke halaman pertama
    currentPage = 0;
    
    // Hapus hasil scan dari memory (hemat RAM)
    WiFi.scanDelete();
}

// ========== FUNGSI IKON KEKUATAN SINYAL ==========
void drawSignalIcon(int x, int y, int rssi) {
    int bars = 0;
    
    // Konversi RSSI ke jumlah bar (1-4)
    if (rssi > -50) bars = 4;      // Excellent
    else if (rssi > -60) bars = 3; // Good
    else if (rssi > -70) bars = 2; // Fair
    else if (rssi > -80) bars = 1; // Weak
    else bars = 0;                  // Very Weak
    
    // Gambar bar sinyal
    for (int i = 0; i < 4; i++) {
        int barHeight = (i + 1) * 2;
        int barX = x + (i * 3);
        int barY = y + 8 - barHeight;
        
        if (i < bars) {
            display.fillRect(barX, barY, 2, barHeight, SSD1306_WHITE);
        } else {
            display.drawRect(barX, barY, 2, barHeight, SSD1306_WHITE);
        }
    }
}

// ========== FUNGSI IKON KEAMANAN ==========
void drawSecurityIcon(int x, int y, int encryptionType) {
    switch(encryptionType) {
        case ENC_TYPE_TKIP:   // WPA
        case ENC_TYPE_CCMP:   // WPA2
        case ENC_TYPE_AUTO:   // WPA/WPA2
            // Gembok TERTUTUP (terenkripsi)
            display.drawRect(x, y + 2, 5, 5, SSD1306_WHITE);
            display.fillRect(x + 1, y + 1, 3, 2, SSD1306_BLACK);
            display.fillRect(x + 2, y + 3, 1, 2, SSD1306_WHITE);
            break;
        case ENC_TYPE_WEP:    // WEP (lama, tidak aman)
            display.drawRect(x, y + 2, 5, 5, SSD1306_WHITE);
            display.drawLine(x + 1, y + 1, x + 3, y + 3, SSD1306_WHITE);
            break;
        default:               // OPEN (tanpa password)
            display.drawRect(x, y + 2, 5, 5, SSD1306_WHITE);
            display.drawLine(x + 2, y + 1, x + 2, y + 3, SSD1306_WHITE);
            break;
    }
}

// ========== FUNGSI MENAMPILKAN HASIL SCAN ==========
void displayScanResults() {
    display.clearDisplay();
    
    // ===== HEADER =====
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 0);
    display.println("WiFi Scanner v2.0");
    display.drawLine(0, 9, 128, 9, SSD1306_WHITE);
    
    // ===== ISI (3 jaringan per halaman) =====
    int startIdx = currentPage * networksPerPage;
    int endIdx = min(startIdx + networksPerPage, totalNetworks);
    
    for (int i = startIdx; i < endIdx; i++) {
        int yPos = 12 + ((i - startIdx) * 16);
        
        // Icon sinyal
        drawSignalIcon(5, yPos + 2, networkRSSI[i]);
        
        // Nama SSID (potong jika terlalu panjang)
        String ssid = networkNames[i];
        if (ssid.length() > 12) {
            ssid = ssid.substring(0, 10) + "..";
        }
        display.setCursor(18, yPos);
        display.print(ssid);
        
        // Icon keamanan
        drawSecurityIcon(110, yPos + 2, networkEncryption[i]);
        
        // Nilai RSSI (dBm)
        display.setCursor(18, yPos + 8);
        display.setTextSize(0.8);
        display.print(String(networkRSSI[i]) + " dBm");
        display.setTextSize(1);
    }
    
    // ===== FOOTER (info halaman) =====
    if (totalNetworks > 0) {
        display.setCursor(0, 56);
        display.print("Page ");
        display.print(currentPage + 1);
        display.print("/");
        int totalPages = (totalNetworks + networksPerPage - 1) / networksPerPage;
        display.print(totalPages);
        display.print("  ");
        display.print(totalNetworks);
        display.print(" nets");
        
        // Indikator scan berikutnya
        int remaining = (scanInterval - (millis() - lastScan)) / 1000;
        if (remaining < 0) remaining = 0;
        display.setCursor(85, 56);
        display.print("Next:");
        display.print(remaining);
        display.print("s");
    }
    
    display.display();
}

// ========== SPLASH SCREEN AWAL ==========
void showSplashScreen() {
    display.clearDisplay();
    display.setTextSize(2);
    display.setCursor(15, 12);
    display.println("WiFi");
    display.setCursor(10, 32);
    display.println("Scanner");
    display.setTextSize(1);
    display.setCursor(18, 52);
    display.println("NodeMCU + OLED");
    display.display();
    delay(2500);
}

// ========== SETUP ==========
void setup() {
    Serial.begin(115200);
    Serial.println("\nWiFi Scanner Tool Starting...");
    
    // Inisialisasi OLED
    if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS)) {
        Serial.println("OLED gagal diinisialisasi! Cek koneksi.");
        for(;;); // Hentikan program jika OLED tidak terdeteksi
    }
    
    display.clearDisplay();
    showSplashScreen();
    
    // Set WiFi ke mode station (bukan access point)
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
    delay(100);
    
    Serial.println("NodeMCU siap melakukan scan WiFi");
    
    // Scan pertama kali
    scanWiFi();
    lastScan = millis();
}

// ========== LOOP UTAMA ==========
void loop() {
    unsigned long now = millis();
    
    // Scan ulang setiap interval
    if (now - lastScan > scanInterval) {
        scanWiFi();
        lastScan = now;
    }
    
    // Tampilkan hasil
    if (totalNetworks > 0) {
        displayScanResults();
    } else {
        display.clearDisplay();
        display.setCursor(15, 28);
        display.println("No WiFi found");
        display.display();
    }
    
    // ===== NAVIGASI TOMBOL (Opsional) =====
    // Jika Anda menambahkan tombol fisik di pin D3 dan D4, 
    // uncomment kode di bawah ini:
    /*
    pinMode(0, INPUT_PULLUP);  // D3 untuk NEXT
    pinMode(2, INPUT_PULLUP);  // D4 untuk PREV
    
    if (digitalRead(0) == LOW) {
        delay(200);
        int totalPages = (totalNetworks + networksPerPage - 1) / networksPerPage;
        currentPage = (currentPage + 1) % totalPages;
    }
    
    if (digitalRead(2) == LOW) {
        delay(200);
        int totalPages = (totalNetworks + networksPerPage - 1) / networksPerPage;
        currentPage = (currentPage - 1 + totalPages) % totalPages;
    }
    */
    
    delay(500); // Refresh rate 0.5 detik
}

📖 Penjelasan Kode (DETAIL Setiap Bagian)

Agar Anda bisa memodifikasi dan memahami program, berikut penjelasan mendetail setiap fungsi:

1. Bagian Header dan Library

#include <Wire.h> : Library untuk komunikasi I2C antara NodeMCU dan OLED.
#include <Adafruit_GFX.h> : Library grafis yang menyediakan fungsi menggambar seperti drawCircle(), drawLine(), fillRect().
#include <Adafruit_SSD1306.h> : Driver spesifik untuk layar OLED SSD1306.
#include <ESP8266WiFi.h> : Library bawaan ESP8266 untuk semua fungsi WiFi, termasuk scan jaringan.

2. Konfigurasi Layar OLED

#define SCREEN_WIDTH 128 dan SCREEN_HEIGHT 64 : Resolusi layar OLED (umum untuk model 0.96 inch).
#define OLED_ADDRESS 0x3C : Alamat I2C default layar OLED. Jika tidak merespon, coba ganti ke 0x3D.

3. Variabel Global

scanInterval = 10000 : Interval scan ulang dalam milidetik (10 detik).
networksPerPage = 3 : Jumlah jaringan yang ditampilkan per halaman (karena tinggi layar terbatas).
Array networkNames[20], networkRSSI[20], dll : Menyimpan data hingga 20 jaringan.

4. Fungsi scanWiFi()

Fungsi ini adalah jantung dari program. Cara kerjanya:

  • WiFi.scanNetworks() - Melakukan scan sinkronus, mengembalikan jumlah jaringan ditemukan.
  • Hasil scan disimpan ke array menggunakan WiFi.SSID(i), WiFi.RSSI(i), dll.
  • Jaringan tersembunyi (SSID kosong) diberi label "(Hidden Network)".
  • Algoritma Bubble Sort - Mengurutkan jaringan dari RSSI tertinggi (sinyal terkuat) ke terendah.
  • WiFi.scanDelete() - Membersihkan memory agar tidak bocor (memory leak).

5. Fungsi drawSignalIcon()

Menggambar bar sinyal (1-4 bar) berdasarkan nilai RSSI:

  • RSSI > -50 dBm → 4 bar (Excellent)
  • RSSI -50 s/d -60 dBm → 3 bar (Good)
  • RSSI -60 s/d -70 dBm → 2 bar (Fair)
  • RSSI -70 s/d -80 dBm → 1 bar (Weak)
  • RSSI < -80 dBm → 0 bar (Very Weak)

6. Fungsi drawSecurityIcon()

Menggambar ikon gembok untuk menunjukkan jenis keamanan:

  • Gembok Tertutup → WPA/WPA2 (aman)
  • Gembok dengan garis miring → WEP (lama, kurang aman)
  • Gembok Terbuka → Tanpa password (Open)

7. Fungsi displayScanResults()

Menampilkan hasil scan ke layar OLED dengan format:

  • Header "WiFi Scanner v2.0" dan garis pemisah
  • 3 jaringan per halaman (sesuai networksPerPage)
  • Footer: nomor halaman, total jaringan, dan countdown scan berikutnya

8. Fungsi loop()

Loop utama yang berjalan terus:

  • Mengecek apakah sudah waktunya scan ulang (millis() - lastScan > scanInterval)
  • Memanggil displayScanResults() untuk memperbarui tampilan
  • Delay 500ms untuk menghemat resource (tidak perlu refresh terlalu cepat)

📱 Hasil dan Tampilan

Setelah program berhasil diupload, layar OLED akan menampilkan:

📋 Contoh Tampilan:

WiFi Scanner v2.0
────────────────
▂▃▄▅ HomeWiFi 🔒
-45 dBm
▂▃▄ Indihome_2G 🔒
-58 dBm
▂▃ WiFi Publik 🔓
-72 dBm
────────────────
Page 1/3 8 nets Next:5s

Informasi yang ditampilkan untuk setiap jaringan:

  • Ikon bar : Kekuatan sinyal secara visual
  • SSID : Nama jaringan (dipotong jika >12 karakter)
  • Ikon gembok : Jenis keamanan
  • Nilai dBm : Kekuatan sinyal numerik (semakin mendekati 0, semakin kuat)

🐛 Troubleshooting (10+ Solusi Masalah)

Masalah 1: Layar OLED Tidak Menampilkan Apa-apa

Solusi:
1. Periksa koneksi VCC ke 3.3V (BUKAN 5V!)
2. Periksa koneksi SCL ke D1, SDA ke D2
3. Coba ganti alamat I2C dari 0x3C menjadi 0x3D di kode
4. Gunakan sketch scanner I2C untuk mendeteksi alamat yang benar

Masalah 2: Gagal Upload ke NodeMCU

Solusi:
1. Tekan dan tahan tombol FLASH pada NodeMCU saat proses "Connecting..."
2. Lepaskan FLASH setelah tulisan "Uploading..." muncul
3. Coba ganti kabel USB (pastikan bisa transfer data, bukan hanya charging)
4. Instal driver CH340/CP2102 jika port COM tidak muncul

Masalah 3: Tidak Ada Jaringan yang Terdeteksi

Solusi:
1. Pastikan antena NodeMCU tidak tertutup atau terhalang
2. Coba di area yang banyak WiFi (mall, kantor, perumahan)
3. Periksa apakah WiFi module tidak dalam mode flight/power save
4. Reset NodeMCU dan coba lagi

Masalah 4: Tampilan Berkedip atau Rusak

Solusi:
1. Kurangi nilai delay di loop() menjadi 100ms atau 50ms
2. Pastikan power supply stabil (gunakan power bank berkualitas)
3. Periksa koneksi ground (GND) antara OLED dan NodeMCU

Masalah 5: Kompilasi Error "Adafruit_SSD1306.h not found"

Solusi:
1. Buka Library Manager (Sketch → Include Library → Manage Libraries)
2. Cari "Adafruit SSD1306" dan instal
3. Instal juga "Adafruit GFX Library"
4. Restart Arduino IDE

Masalah 6: NodeMCU Panas / Overheat

Solusi:
1. Pastikan tidak ada korsleting antar pin
2. Jangan menyambungkan VCC OLED ke 5V (gunakan 3.3V)
3. Kurangi frekuensi scan (perpanjang scanInterval menjadi 30000)

🚀 10 Ide Pengembangan Lebih Lanjut

Setelah berhasil membuat WiFi Scanner dasar, Anda bisa mengembangkannya dengan fitur-fitur berikut:

  1. 🔘 Tombol Navigasi Fisik - Tambahkan 2 tombol (NEXT/PREV) di pin D3 dan D4 untuk scroll halaman manual.
  2. 💾 Penyimpanan Data - Gunakan EEPROM atau kartu SD untuk merekam riwayat scan.
  3. 📊 Mode Grafik - Tampilkan grafik kekuatan sinyal dalam bentuk chart batang.
  4. 🔍 Filter SSID - Filter hanya menampilkan jaringan dengan nama tertentu.
  5. 🔊 Buzzer Indikator - Bunyi saat menemukan jaringan target tertentu.
  6. 📱 Bluetooth Serial - Kirim data scan ke smartphone via Bluetooth.
  7. 🌐 Web Server - Buat akses point sendiri untuk melihat hasil scan via browser.
  8. 🔋 Battery Monitor - Tampilkan level baterai jika menggunakan power bank.
  9. 📈 Export ke CSV - Simpan data dalam format CSV untuk analisis di Excel.
  10. 🗺 GPS Integration - Tambahkan module GPS untuk wardriving (pemetaan lokasi).

❓ FAQ (Pertanyaan yang Sering Diajukan)

Q: Apakah alat ini bisa digunakan untuk "hack" WiFi?

A: TIDAK. Alat ini hanya untuk scan dan menampilkan jaringan, BUKAN untuk membobol password. WiFi scanner hanya mendeteksi keberadaan jaringan, bukan menembus keamanannya.

Q: Berapa jarak maksimal deteksi?

A: Tergantung kondisi lingkungan. Di ruang terbuka bisa mencapai 50-100 meter. Di dalam ruangan dengan banyak tembok, sekitar 10-30 meter.

Q: Apakah bisa mendeteksi jaringan 5GHz?

A: NodeMCU ESP8266 hanya mendukung frekuensi 2.4 GHz. Untuk 5GHz, gunakan board ESP32.

Q: Berapa lama baterai bertahan?

A: Dengan power bank 10.000 mAh, alat ini bisa bertahan 12-24 jam non-stop.

Q: Apakah bisa menampilkan channel yang digunakan?

A: Bisa! Tambahkan WiFi.channel(i) pada kode untuk menampilkan channel setiap jaringan.

📦 Kesimpulan

Selamat! Anda telah berhasil membuat WiFi Scanner portabel menggunakan NodeMCU ESP8266 dan layar OLED 0.96". Alat ini tidak hanya berguna untuk survei jaringan, tetapi juga merupakan proyek yang sempurna untuk belajar pemrograman ESP8266, antarmuka grafis dengan OLED, dan pemrosesan data scan WiFi.

Dengan memahami kode di atas, Anda sekarang memiliki fondasi untuk mengembangkan berbagai proyek IoT lainnya seperti pemantau kualitas udara, stasiun cuaca, atau smart home controller. Kunci utamanya adalah memahami cara kerja library ESP8266WiFi.h dan Adafruit_GFX.h.

💡 Pesan Penutup: Jangan ragu untuk bereksperimen dengan kode! Ubah interval scan, tambahkan fitur baru, atau bahkan buat casing 3D untuk alat Anda. Semakin sering Anda mencoba, semakin cepat Anda menguasai IoT. Selamat berkarya!

© 2024 - Tutorial WiFi Scanner Portabel | Dibuat dengan ❤️ untuk komunitas IoT Indonesia

Dukung terus perkembangan tutorial elektronika dengan membagikan artikel ini!

Rabu, 08 April 2026

Membuat Weather Station dengan NodeMCU & OLED: Studi Kasus Pangandaran (Solusi API Key Error)

Membuat Weather Station NodeMCU & OLED: Studi Kasus Pangandaran (Solusi API Key Error)

🌤️ Membuat Weather Station dengan NodeMCU & OLED: Studi Kasus Pangandaran (Solusi API Key Error)


PS
Pidin Saripudin, S.Kom

Praktisi IoT & Embedded System | 8+ tahun pengalaman

📅 Publikasi: 7 April 2026 | Diperbarui: 7 April 2026 ⏱️ Estimasi baca: 12 menit 🏷️ #NodeMCU #ESP8266 #WeatherStation #Pangandaran

📍 1. Pendahuluan

Pernahkah Anda ingin mengetahui suhu dan kondisi cuaca terkini di Pangandaran secara real-time tanpa membuka ponsel? Dengan kombinasi NodeMCU ESP8266 (mikrokontroler murah dengan WiFi) dan OLED display 0.96 inci, Anda bisa membuat stasiun cuaca mini sendiri. Alat ini akan mengambil data cuaca langsung dari internet melalui API OpenWeatherMap, lalu menampilkannya di layar OLED. Artikel ini tidak hanya menyajikan kode lengkap, tetapi juga membahas tuntas masalah umum error 401 Invalid API Key yang sering dialami pemula.

📌 Lokasi Studi Kasus: Pangandaran, Jawa Barat (Koordinat: -7.6956, 108.6500). Cocok untuk pemantau cuaca pantai selatan Jawa.

🛠️ 2. Komponen & Skema Koneksi

Komponen yang dibutuhkan sangat sederhana dan mudah ditemukan:

  • NodeMCU ESP8266 (board dengan chip ESP-12E)
  • OLED Display 0.96" SSD1306 (komunikasi I2C)
  • Kabel jumper Female-to-Female (4 buah)
  • Power bank atau kabel USB (untuk catu daya)

Skema Koneksi I2C (4 kabel):

OLED PinNodeMCU PinKeterangan
GNDGNDGround
VCC3.3VPower 3.3 Volt
SDAD2 (GPIO4)Data I2C
SCLD1 (GPIO5)Clock I2C
⚠️ Catatan: Pastikan alamat I2C OLED adalah 0x3C (default). Jika tidak muncul, gunakan scanner I2C atau coba alamat 0x3D.

🔑 3. Mendapatkan API Key OpenWeatherMap

OpenWeatherMap menyediakan data cuaca gratis (60 kali/menit) dengan registrasi. Langkah-langkahnya:

  1. Buka OpenWeatherMap API
  2. Klik "Sign Up" dan buat akun (email & password)
  3. Verifikasi email melalui tautan yang dikirimkan
  4. Login ke akun, lalu buka menu "API Keys" (https://home.openweathermap.org/api_keys)
  5. Salin API key default (campuran huruf dan angka)

❌ 4. Mengatasi Error 401 "Invalid API Key"

Error ini adalah kendala paling umum saat pertama kali mencoba. Berikut penyebab dan solusinya:

📟 Pesan Error yang Muncul:
{"cod":401, "message": "Invalid API key. Please see https://openweathermap.org/faq#error401"}

Penyebab Error 401:

  • API key salah ketik — pastikan tidak ada spasi atau karakter tambahan.
  • API key belum diaktifkan — OpenWeatherMap membutuhkan waktu 2-6 jam setelah verifikasi email untuk mengaktifkan key baru.
  • Akun belum diverifikasi — cek email dan klik tautan verifikasi.
  • Menggunakan key dari akun yang berbeda — key bersifat privat per akun.

Langkah Verifikasi API Key (Sebelum Upload ke NodeMCU):

Uji key terlebih dahulu di browser dengan URL berikut (ganti KUNCI_ANDA):

🔗 Uji Coba URLCopy ke browser
https://api.openweathermap.org/data/2.5/weather?lat=-7.6956&lon=108.6500&units=metric&appid=KUNCI_ANDA

Jika berhasil, browser akan menampilkan data JSON cuaca Pangandaran. Jika error 401, tunggu 2-6 jam atau cek kembali key Anda.

💡 Tips Penting: Jangan membuat banyak API key baru. Cukup gunakan key default yang tertera di dashboard. Key baru juga memerlukan waktu aktivasi yang sama.

💻 5. Kode Program Lengkap (Arduino IDE)

Berikut kode yang sudah diuji coba untuk lokasi Pangandaran. Ganti YOUR_API_KEY dengan API key asli Anda yang sudah aktif.

📟 Weather_Station_Pangandaran.inoArduino IDE
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>

// ==================== KONFIGURASI OLED ====================
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// ==================== KONFIGURASI WIFI ====================
const char* ssid = "7G";           // Ganti dengan SSID WiFi Anda
const char* password = "forget22"; // Ganti password WiFi Anda

// ==================== API KEY OPENWEATHERMAP ====================
// Dapatkan dari: https://home.openweathermap.org/api_keys
const char* apiKey = "YOUR_API_KEY";  // <-- -="" 0="" 0x3c="" 10="" 25="" 30="" 40="" 80="" angandaran="" api="" apikey="" apisuccess="false;" asli="" assword="" attempts="" bool="" client.available="" client.connect="" client.print="" client="" close="" const="" cuaca="===================" data...="" delay="" dengan="" deskripsi="" display.begin="" display.cleardisplay="" display.display="" display.print="" display.println="" display.setcursor="" display.settextcolor="" display.settextsize="" ek="" else="" engambil="" enghubungkan...="" enghubungkan="" feelslike="0;" float="" for="" gagal="" ganti="" host.c_str="" host="" http="" i="" if="" ifi.status="" ifi="" inisialisasi="" int="" isi.length="" isi="" judul.length="" judul="" kecepatanangin="0;" kelembaban="0," key="" kondisi="" konek="" koneksi="" koordinat="" lasterror="" lastupdate="0;" latitude="" lon=" + String(longitude,4) + 
                " long="" longitude="108.6500;" menit="" millis="" n="" ngagal="" nwifi="" ok="" oled="" onnection:="" ost:="" pangandaran="==" password="" path="" r="" return="" rror="" serial.begin="" serial.print="" serial.println="" setup="" ssid="" station="" string="" suhu="0," tampilkanpesan="" tekanan="0;" terhubung="" timeout="" tring="" ukses="" units="metric&appid=" unsigned="" updateinterval="600000;" updateweatherdata="" variabel="" void="" weather="" while="" wifi.begin="" wifi="" wificlient="" wl_connected=""> 10000) {
      lastError = "Timeout API";
      tampilkanPesan("Error", lastError);
      client.stop();
      return;
    }
    delay(100);
  }
  
  String response = "";
  while (client.available()) response += (char)client.read();
  client.stop();
  
  if (response.indexOf("401") > 0) {
    lastError = "API Key Invalid!";
    tampilkanPesan("Error", "Cek API Key");
    return;
  }
  
  int jsonStart = response.indexOf("{");
  if (jsonStart == -1) {
    lastError = "Response invalid";
    tampilkanPesan("Error", lastError);
    return;
  }
  
  String jsonString = response.substring(jsonStart);
  DynamicJsonDocument doc(4096);
  DeserializationError error = deserializeJson(doc, jsonString);
  
  if (error) {
    lastError = "Parse JSON gagal";
    tampilkanPesan("Error", lastError);
    return;
  }
  
  suhu = doc["main"]["temp"];
  feelsLike = doc["main"]["feels_like"];
  kelembaban = doc["main"]["humidity"];
  kondisi = doc["weather"][0]["main"].as();
  deskripsi = doc["weather"][0]["description"].as();
  tekanan = doc["main"]["pressure"];
  kecepatanAngin = doc["wind"]["speed"];
  
  apiSuccess = true;
  Serial.println("Cuaca Pangandaran: " + String(suhu) + "°C, " + kondisi);
}

void tampilkanCuaca() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(28, 0);
  display.println("PANGANDARAN");
  display.drawLine(0, 10, 128, 10, SSD1306_WHITE);
  
  // Ikon sederhana
  display.fillCircle(20, 32, 10, SSD1306_WHITE);
  display.fillCircle(20, 32, 8, SSD1306_BLACK);
  
  display.setTextSize(2);
  display.setCursor(48, 20);
  display.print(int(suhu));
  display.cp437(true);
  display.write(167);
  display.print("C");
  
  display.setTextSize(1);
  display.setCursor(48, 40);
  display.print("RH: ");
  display.print(kelembaban);
  display.print("%");
  
  display.setCursor(4, 54);
  display.print(kondisi);
  display.display();
}

void tampilkanDetail() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(2, 2);
  display.print("Suhu: "); display.print(suhu,1); display.write(167); display.print("C");
  display.setCursor(2, 14);
  display.print("Kelembaban: "); display.print(kelembaban); display.print("%");
  display.setCursor(2, 26);
  display.print("Angin: "); display.print(kecepatanAngin,1); display.print(" m/s");
  display.setCursor(2, 38);
  display.print("Tekanan: "); display.print(tekanan); display.print(" hPa");
  display.setCursor(2, 50);
  if(deskripsi.length()>16) deskripsi = deskripsi.substring(0,14);
  display.print(deskripsi);
  display.display();
}

void loop() {
  unsigned long now = millis();
  if (now - lastUpdate > updateInterval || lastUpdate == 0) {
    updateWeatherData();
    lastUpdate = now;
  }
  if (apiSuccess) {
    tampilkanCuaca();
    delay(6000);
    tampilkanDetail();
    delay(5000);
  } else {
    tampilkanPesan("Error", lastError);
    delay(30000);
    updateWeatherData();
    lastUpdate = millis();
  }
}

Library yang Diperlukan (Install via Library Manager):

  • Adafruit SSD1306 — driver untuk OLED
  • Adafruit GFX — library grafis
  • ArduinoJson — parsing data JSON (versi 6.x)

⚙️ 6. Cara Kerja Program

  1. Koneksi WiFi — NodeMCU terhubung ke jaringan internet.
  2. HTTP Request ke API — Mengirim request GET ke OpenWeatherMap dengan koordinat Pangandaran.
  3. Parsing JSON — Data suhu, kelembaban, kondisi diekstrak dari respons.
  4. Tampilan OLED — Dua halaman bergantian setiap 6 detik (halaman utama dan detail).
  5. Update Otomatis — Data diperbarui setiap 10 menit.

🖥️ 7. Tampilan OLED

Halaman 1 (Cuaca Utama): Menampilkan nama kota (PANGANDARAN), suhu besar, kelembaban, dan kondisi cuaca singkat.

Halaman 2 (Detail): Menampilkan suhu, kelembaban, kecepatan angin, tekanan udara, dan deskripsi cuaca lengkap.

📊 Contoh Data yang Ditampilkan:
Suhu: 29°C | Kelembaban: 78% | Angin: 3.2 m/s | Tekanan: 1011 hPa | Kondisi: Light Rain

📝 8. Kesimpulan

Proyek Weather Station dengan NodeMCU dan OLED sangat memungkinkan untuk dibuat sendiri dengan biaya terjangkau. Kendala utama biasanya terletak pada aktivasi API Key OpenWeatherMap yang membutuhkan waktu 2-6 jam. Dengan mengikuti panduan di atas, Anda dapat memantau cuaca Pangandaran secara real-time dari rumah. Kembangkan lebih lanjut dengan menambahkan sensor lokal atau menyimpan data ke database. Selamat berkarya!

© 2026 Pidin Saripudin, S.Kom | Artikel ini dilisensikan untuk edukasi. Dilarang menyalin tanpa izin.

Selasa, 07 April 2026

7 Ide Proyek NodeMCU ESP8266 dengan OLED Display

7 Ide Proyek NodeMCU ESP8266 dengan OLED Display | Tutorial IoT Lengkap

💡 7 Ide Proyek NodeMCU ESP8266 dengan OLED Display

PS
Pidin Saripudin, S.Kom

Praktisi IoT & Embedded System | 8+ tahun pengalaman

📅 Publikasi: 7 April 2026 | Diperbarui: 7 April 2026 ⏱️ Estimasi baca: 15 menit 🏷️ #NodeMCU #ESP8266 #OLED #IoT

NodeMCU ESP8266 adalah salah satu mikrokontroler favorit di kalangan penghobi IoT karena harganya yang terjangkau, memiliki WiFi terintegrasi, dan mudah diprogram dengan Arduino IDE. Ketika dipadukan dengan OLED display 0.96 inci berbasis SSD1306, potensi proyek yang bisa dibuat menjadi sangat luas. Artikel ini menyajikan 7 ide proyek menarik yang bisa Anda bangun sendiri, lengkap dengan tingkat kesulitan, komponen yang dibutuhkan, serta konsep kode sederhana. Semua proyek telah diuji coba dan aman untuk dipraktikkan.

📌 Mengapa OLED? Layar OLED memiliki kontras tinggi, konsumsi daya rendah, dan ukuran kecil (128x64 piksel) — sangat cocok untuk antarmuka pengguna pada perangkat IoT portabel.

🎯 Ringkasan Proyek

NoNama ProyekTingkatFitur Utama
1Weather Station⭐️⭐️ MenengahCuaca real-time, suhu, kelembaban
2WiFi Scanner Tool⭐️ PemulaScan & tampilkan jaringan WiFi sekitar
3Pesan dari Cloud⭐️⭐️ MenengahTampilkan pesan via web/cloud
4Desktop Pet⭐️⭐️⭐️ MahirAnimasi ekspresi lucu interaktif
5GPS Tracker⭐️⭐️⭐️ MahirTampilkan posisi real-time
6News Ticker⭐️⭐️ MenengahBerita bergulir dari internet
7Countdown Timer⭐️ PemulaHitung mundur acara spesial

🌤️ 1. Weather Station (Stasiun Cuaca)

Weather Station berbasis API
Menengah API OpenWeatherMap

Tampilkan informasi cuaca terkini dari internet menggunakan API OpenWeatherMap. Layar OLED menampilkan suhu, kelembaban, kondisi cuaca, dan ikon sederhana (cerah, hujan, mendung). Proyek ini cocok untuk meja kerja atau sebagai informasi cuaca di ruang keluarga.

Komponen: NodeMCU, OLED 0.96", kabel jumper, power bank atau USB.

Fitur: Update data setiap 10 menit, tampilan ikon grafis, suhu dalam Celsius/Fahrenheit, kecepatan angin (opsional).

Konsep kode: HTTP GET ke API, parsing JSON, menampilkan data ke OLED dengan fungsi display.

// Contoh parsing JSON cuaca
DynamicJsonDocument doc(2048);
deserializeJson(doc, http.getString());
float suhu = doc["main"]["temp"];
String kondisi = doc["weather"][0]["main"];

Pengembangan: Tambahkan sensor DHT11 untuk membaca suhu lokal, simpan data ke database, tampilkan grafik tren suhu.

📡 2. WiFi Scanner Tool

Pemindai Jaringan WiFi Portabel
Pemula ESP8266WiFi

Buat alat portable yang bisa menampilkan semua jaringan WiFi di sekitar Anda, lengkap dengan kekuatan sinyal (RSSI) dan jenis enkripsi. Sangat berguna untuk survey jaringan, troubleshooting, atau sekadar eksplorasi lingkungan.

Komponen: NodeMCU, OLED, power bank (portabel).

Fitur: Scan otomatis setiap 10 detik, tampilan SSID, bar sinyal visual, enkripsi (WPA2, WPA, Open). Scrolling manual menggunakan tombol.

#include <ESP8266WiFi.h>
int jumlah = WiFi.scanNetworks();
for(int i=0; i<jumlah; i++) {
  String ssid = WiFi.SSID(i);
  int rssi = WiFi.RSSI(i);
  // tampilkan di OLED
}

Pengembangan: Filter berdasarkan kekuatan sinyal, simpan hasil ke file, deteksi jaringan tidak aman.

💬 3. Pesan dari Cloud / IoT Text Display

Papan Pesan Digital
Menengah Web Server

Kirim pesan dari smartphone atau komputer ke OLED display melalui cloud. Cocok untuk papan pengumuman digital di rumah, pesan untuk anggota keluarga, atau notifikasi dari aplikasi eksternal.

Komponen: NodeMCU, OLED.

Fitur: Mode AP (langsung) atau Station (via router), scroll teks panjang, multiple pesan, penyimpanan pesan terakhir di EEPROM.

// ESP8266 sebagai web server
server.on("/send", [](){
  String msg = server.arg("message");
  tampilkanDiOLED(msg);
  server.send(200, "text/plain", "OK");
});

Pengembangan: Integrasi dengan Blynk, notifikasi dari Google Forms, tampilan animasi saat pesan baru tiba.

🐾 4. Desktop Pet (Hewan Peliharaan Desktop)

Tamagotchi Modern
Mahir Animasi & Interaksi

Buat karakter lucu di OLED yang bereaksi terhadap waktu, interaksi tombol, atau bahkan cuaca. Mirip dengan Tamagotchi versi modern — bisa diberi makan, diajak bermain, dan tidur.

Komponen: NodeMCU, OLED, 2-3 tombol push button, buzzer (opsional).

Fitur: 5+ ekspresi (senang, sedih, lapar, tidur, marah), perubahan berdasarkan waktu nyata (pagi/siang/malam), interaksi tombol, status "kesehatan" dan "kebahagiaan".

// Ekspresi berdasarkan jam
if (jam >= 6 && jam < 11) expression = HAPPY;
else if (jam >= 22 || jam < 5) expression = SLEEP;
else expression = NORMAL;

Pengembangan: Integrasi dengan WiFi untuk update cuaca (karakter pakai jas hujan jika hujan), penyimpanan status ke EEPROM, multi karakter.

📍 5. GPS Tracker

Pelacak Posisi Real-time
Mahir Modul GPS

Tampilkan posisi GPS real-time di OLED. Sangat berguna untuk proyek navigasi, pelacakan kendaraan, atau data logger lokasi. Modul GPS NEO-6M yang murah sudah cukup akurat untuk keperluan hobi.

Komponen: NodeMCU, OLED, modul GPS NEO-6M (atau NEO-7M/8M).

Fitur: Tampilkan koordinat Latitude/Longitude, kecepatan (km/h), arah (course), jumlah satelit, ketinggian. Update setiap 1 detik.

Koneksi GPS: VCC ke 5V, GND ke GND, TX ke RX (D3/GPIO0).

#include <TinyGPS++.h>
TinyGPSPlus gps;
while (Serial.available()) {
  gps.encode(Serial.read());
  if (gps.location.isUpdated()) {
    float lat = gps.location.lat();
    float lng = gps.location.lng();
  }
}

Pengembangan: Kirim data lokasi ke server (tracking online), tampilkan peta sederhana dengan titik-titik, simpan track log ke SD card.

📰 6. News Ticker

Berita Bergulir dari Internet
Menengah RSS Feed

Tampilkan berita terbaru dari RSS feed atau API news secara bergulir (scrolling) di OLED. Cocok untuk meja kerja agar tetap update dengan berita tanpa harus membuka HP.

Komponen: NodeMCU, OLED.

Fitur: Scroll teks horizontal, update setiap 15 menit, support RSS feed Indonesia (detik, kompas, tempo), efek transisi antar berita.

void scrollText(String text, int y) {
  for (int i = 0; i <= text.length() * 6; i++) {
    display.clearDisplay();
    display.setCursor(-i, y);
    display.print(text);
    display.display();
    delay(40);
  }
}

Pengembangan: Pilih kategori berita (olahraga, teknologi, politik), integrasi dengan Google News RSS, tampilkan waktu update terakhir.

⏰ 7. Countdown Timer / Event Reminder

Hitung Mundur Acara Spesial
Pemula NTP Client

Tampilkan hitung mundur menuju acara spesial seperti ulang tahun, liburan, atau hari raya. Dengan koneksi internet, waktu akan selalu sinkron sehingga countdown tetap akurat.

Komponen: NodeMCU, OLED, buzzer (opsional untuk alarm).

Fitur: Hitung mundur dalam hari, jam, menit, detik, ambil waktu dari NTP server, progress bar visual, ganti ekspresi mata sesuai waktu tersisa.

#include <NTPClient.h>
unsigned long target = 1704067200; // 1 Jan 2025
unsigned long now = timeClient.getEpochTime();
unsigned long selisih = target - now;
int hari = selisih / 86400;
int jam = (selisih % 86400) / 3600;

Pengembangan: Multiple event, penyimpanan target di EEPROM, alarm dengan buzzer saat countdown habis, tampilan grafis balon atau kue ulang tahun.

🔌 Panduan Koneksi OLED ke NodeMCU

Semua proyek di atas menggunakan protokol I2C yang sama. Berikut adalah skema koneksi standar:

OLED PinNodeMCU Pin
GNDGND
VCC3.3V
SDAD2 (GPIO4)
SCLD1 (GPIO5)
⚠️ Catatan penting: Jika layar tidak merespons, coba ganti alamat I2C antara 0x3C atau 0x3D saat inisialisasi display. Gunakan scanner I2C untuk mendeteksi alamat yang benar.

📝 Kesimpulan

Ketujuh ide proyek di atas membuktikan bahwa kombinasi NodeMCU ESP8266 dan OLED display sangat powerful untuk berbagai aplikasi IoT. Mulai dari yang sederhana seperti WiFi scanner hingga yang kompleks seperti desktop pet atau GPS tracker, semuanya bisa Anda bangun dengan biaya terjangkau. Kunci sukses adalah memahami dasar-dasar pemrograman Arduino, penggunaan library, dan koneksi hardware. Jangan ragu untuk memodifikasi dan mengembangkan proyek-proyek ini sesuai kreativitas Anda. Selamat berkarya dan terus belajar IoT!

Jika ada pertanyaan atau ingin berbagi hasil proyek Anda, silakan tinggalkan komentar di bawah. Saya, Pidin Saripudin, S.Kom, akan dengan senang hati membantu.

© 2026 Pidin Saripudin, S.Kom | Artikel ini dilisensikan untuk edukasi publik. Dilarang menyalin tanpa izin.

Sabtu, 04 April 2026

Proyek IoT: Mata Robot Mo-chan Ekspresif - Berbasis Waktu dengan OLED & NodeMCU

Proyek IoT: Mata Robot Mo-chan Ekspresif Berbasis Waktu dengan OLED & NodeMCU

🤖 Proyek IoT: Mata Robot Mo-chan Ekspresif
Berbasis Waktu dengan OLED & NodeMCU


Pernahkah Anda ingin membuat robot kecil yang bisa menunjukkan ekspresi sesuai dengan waktu sepanjang hari? Pada tutorial kali ini, kita akan membuat sebuah proyek IoT yang menarik: mata robot bergaya Mo-chan (anime) yang bisa berkedip, melihat ke kiri/kanan, dan berganti ekspresi berdasarkan waktu (pagi, siang, sore, malam) menggunakan layar OLED 0.96" dan board NodeMCU ESP8266. Proyek ini sangat cocok untuk pajangan meja kerja, jam digital unik, atau bagian dari proyek robotika Anda berikutnya!

🎯 Hasil Akhir: Layar OLED akan menampilkan sepasang mata dalam kotak persegi yang berubah ekspresi secara otomatis sesuai jam dari internet. Mulai dari mata bahagia ^^, terkejut O.O, marah, tidur dengan Zzz, hingga mata berbentuk hati.

🛠 Alat & Bahan yang Diperlukan

Pastikan Anda sudah menyiapkan komponen berikut. Total biaya relatif murah dan mudah didapatkan di toko elektronik atau online.

Komponen Spesifikasi / Model Fungsi
Board NodeMCU NodeMCU ESP8266 (CP2102/CH340) Mikrokontroler utama dengan WiFi
Layar OLED 0.96 inch, 128x64 pixel, I2C (SSD1306) Menampilkan gambar mata robot
Kabel Jumper Female to Female (F-F) 4 buah Menghubungkan OLED ke NodeMCU
Kabel USB Micro USB (yang mendukung data) Memprogram dan memberi daya
Jaringan WiFi 2.4 GHz (ESP8266 tidak support 5GHz) Mengambil waktu dari internet (NTP)

🔌 Skema Koneksi (Wiring)

Layar OLED menggunakan protokol I2C, hanya butuh 4 kabel. Hubungkan dengan NodeMCU sesuai tabel berikut:

Layar OLED NodeMCU ESP8266 Keterangan
VCC 3.3V Power (jangan 5V!)
GND GND Ground
SCL D1 (GPIO5) Clock I2C
SDA D2 (GPIO4) Data I2C
⚠️ Perhatian: Board NodeMCU menggunakan logika 3.3V. Pastikan OLED Anda juga mendukung 3.3V (kebanyakan OLED 0.96" sudah support). Jangan sampai menyambung ke pin 5V Arduino karena bisa merusak layar.

📚 Instalasi Library yang Diperlukan

Sebelum mengupload kode, Anda harus menginstal library berikut melalui Arduino IDE (Sketch → Include Library → Manage Libraries).

Nama Library Pencarian di Library Manager Fungsi
Adafruit GFX "Adafruit GFX Library" by Adafruit Fungsi grafis dasar (lingkaran, garis, dll)
Adafruit SSD1306 "Adafruit SSD1306" by Adafruit Driver untuk layar OLED SSD1306
NTPClient "NTPClient" by Fabrice Weinberg Mengambil waktu dari server internet

Tambahan: Untuk board ESP8266, pastikan Anda sudah menginstal board ESP8266 melalui Boards Manager dengan URL: https://arduino.esp8266.com/stable/package_esp8266com_index.json. Kemudian pilih board "NodeMCU 1.0 (ESP-12E Module)".

💻 Kode Program Lengkap

Berikut adalah kode lengkap yang perlu Anda upload ke NodeMCU. Jangan lupa ganti ssid dan password dengan jaringan WiFi Anda sendiri. Kode ini dapat di-scroll jika terlalu panjang.

/*
    Project: Mo-chan Expressive Eyes with Time-based Emotions
    Board: NodeMCU ESP8266
    OLED: 128x64 I2C SSD1306
    Author: Tutorial Blog
    Description: Menampilkan mata robot yang berubah ekspresi sesuai waktu (NTP)
*/

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>

// ========== KONFIGURASI WiFi ==========
const char* ssid = "NAMA_WIFI_ANDA";       // Ganti dengan SSID WiFi Anda
const char* password = "PASSWORD_WIFI_ANDA"; // Ganti password WiFi Anda

// ========== KONFIGURASI OLED ==========
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// ========== KONFIGURASI NTP (Waktu) ==========
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 25200, 60000); // 25200 = UTC+7 (WIB)

// ========== VARIABEL ANIMASI MATA ==========
unsigned long lastBlink = 0;
unsigned long lastEyeMove = 0;
bool eyesOpen = true;
int eyeDirection = 0;     // 0:center, 1:kiri, 2:kanan, 3:atas, 4:bawah
int expression = 0;       // 0:normal, 1:happy, 2:surprised, 3:sleep, 4:angry, 5:love

// ========== FUNGSI UNTUK MENENTUKAN EKSPRESI BERDASARKAN JAM ==========
int getExpressionByTime() {
  if (WiFi.status() != WL_CONNECTED) return 0; // Jika offline, tampilkan normal
  
  timeClient.update();
  int hour = timeClient.getHours();
  int minute = timeClient.getMinutes();
  int currentTime = hour * 100 + minute; // Format HHMM, contoh 0630 = jam 6:30
  
  // Logika jadwal emosi
  if (currentTime < 615) return 3;        // 00:00 - 06:14 -> Tidur (Zzz)
  else if (currentTime < 900) return 1;   // 06:15 - 08:59 -> Bahagia (^ ^)
  else if (currentTime < 1200) return 0;  // 09:00 - 11:59 -> Normal (o o)
  else if (currentTime < 1300) return 5;  // 12:00 - 12:59 -> Love (Hati)
  else if (currentTime < 1500) return 2;  // 13:00 - 14:59 -> Terkejut (O O)
  else if (currentTime < 1800) return 0;  // 15:00 - 17:59 -> Normal
  else if (currentTime < 1900) return 4;  // 18:00 - 18:59 -> Marah (/\)
  else if (currentTime < 2200) return 1;  // 19:00 - 21:59 -> Bahagia
  else return 3;                          // 22:00 - 23:59 -> Tidur
}

// ========== FUNGSI MENGGAMBAR MATA MO-CHAN DALAM KOTAK ==========
void drawMoChanEyesInBox() {
  int leftEyeX = 44, rightEyeX = 84, eyeY = 32;
  int pupilOffsetX = 0, pupilOffsetY = 0;
  
  // Atur pergeseran pupil berdasarkan arah pandang
  switch(eyeDirection) {
    case 1: pupilOffsetX = -6; break;
    case 2: pupilOffsetX = 6; break;
    case 3: pupilOffsetY = -5; break;
    case 4: pupilOffsetY = 5; break;
  }
  
  // Gambar kotak bingkai mata (efek seperti panel robot)
  display.drawRoundRect(leftEyeX - 16, eyeY - 14, 32, 28, 5, SSD1306_WHITE);
  display.drawRoundRect(rightEyeX - 16, eyeY - 14, 32, 28, 5, SSD1306_WHITE);
  display.drawRect(leftEyeX - 15, eyeY - 13, 30, 26, SSD1306_WHITE);
  display.drawRect(rightEyeX - 15, eyeY - 13, 30, 26, SSD1306_WHITE);
  
  if(eyesOpen) {
    // Gambar berbagai ekspresi berdasarkan variabel 'expression'
    switch(expression) {
      case 1: // Bahagia ^ ^
        display.drawLine(leftEyeX - 10, eyeY - 2, leftEyeX - 4, eyeY - 6, SSD1306_WHITE);
        display.drawLine(leftEyeX - 4, eyeY - 6, leftEyeX + 4, eyeY - 6, SSD1306_WHITE);
        display.drawLine(leftEyeX + 4, eyeY - 6, leftEyeX + 10, eyeY - 2, SSD1306_WHITE);
        display.drawLine(rightEyeX - 10, eyeY - 2, rightEyeX - 4, eyeY - 6, SSD1306_WHITE);
        display.drawLine(rightEyeX - 4, eyeY - 6, rightEyeX + 4, eyeY - 6, SSD1306_WHITE);
        display.drawLine(rightEyeX + 4, eyeY - 6, rightEyeX + 10, eyeY - 2, SSD1306_WHITE);
        break;
      case 2: // Terkejut O O
        display.fillCircle(leftEyeX, eyeY, 12, SSD1306_WHITE);
        display.fillCircle(rightEyeX, eyeY, 12, SSD1306_WHITE);
        display.fillCircle(leftEyeX + pupilOffsetX, eyeY + pupilOffsetY, 5, SSD1306_BLACK);
        display.fillCircle(rightEyeX + pupilOffsetX, eyeY + pupilOffsetY, 5, SSD1306_BLACK);
        display.fillCircle(leftEyeX + pupilOffsetX - 2, eyeY + pupilOffsetY - 2, 2, SSD1306_WHITE);
        display.fillCircle(rightEyeX + pupilOffsetX - 2, eyeY + pupilOffsetY - 2, 2, SSD1306_WHITE);
        break;
      case 3: // Tidur (Zzz)
        display.drawLine(leftEyeX - 10, eyeY - 3, leftEyeX + 10, eyeY - 3, SSD1306_WHITE);
        display.drawLine(rightEyeX - 10, eyeY - 3, rightEyeX + 10, eyeY - 3, SSD1306_WHITE);
        display.setCursor(leftEyeX - 18, eyeY - 8); display.print("z");
        display.setCursor(leftEyeX - 14, eyeY - 12); display.print("Z");
        display.setCursor(leftEyeX - 10, eyeY - 16); display.print("Z");
        break;
      case 4: // Marah (alis turun, bentuk /\)
        display.drawLine(leftEyeX - 10, eyeY - 5, leftEyeX, eyeY + 2, SSD1306_WHITE);
        display.drawLine(leftEyeX, eyeY + 2, leftEyeX + 10, eyeY - 5, SSD1306_WHITE);
        display.drawLine(rightEyeX - 10, eyeY - 5, rightEyeX, eyeY + 2, SSD1306_WHITE);
        display.drawLine(rightEyeX, eyeY + 2, rightEyeX + 10, eyeY - 5, SSD1306_WHITE);
        display.drawLine(leftEyeX - 12, eyeY - 8, leftEyeX + 12, eyeY - 4, SSD1306_WHITE);
        display.drawLine(rightEyeX - 12, eyeY - 4, rightEyeX + 12, eyeY - 8, SSD1306_WHITE);
        break;
      case 5: // Love (pupil berbentuk hati)
        display.fillCircle(leftEyeX, eyeY, 11, SSD1306_WHITE);
        display.fillCircle(rightEyeX, eyeY, 11, SSD1306_WHITE);
        // Hati kiri
        display.fillCircle(leftEyeX - 3, eyeY - 2, 3, SSD1306_BLACK);
        display.fillCircle(leftEyeX + 3, eyeY - 2, 3, SSD1306_BLACK);
        display.fillTriangle(leftEyeX - 5, eyeY - 1, leftEyeX + 5, eyeY - 1, leftEyeX, eyeY + 4, SSD1306_BLACK);
        // Hati kanan
        display.fillCircle(rightEyeX - 3, eyeY - 2, 3, SSD1306_BLACK);
        display.fillCircle(rightEyeX + 3, eyeY - 2, 3, SSD1306_BLACK);
        display.fillTriangle(rightEyeX - 5, eyeY - 1, rightEyeX + 5, eyeY - 1, rightEyeX, eyeY + 4, SSD1306_BLACK);
        break;
      default: // Normal (mata bulat dengan pupil & sorotan)
        display.fillCircle(leftEyeX, eyeY, 11, SSD1306_WHITE);
        display.fillCircle(rightEyeX, eyeY, 11, SSD1306_WHITE);
        display.fillCircle(leftEyeX + pupilOffsetX, eyeY + pupilOffsetY, 7, SSD1306_BLACK);
        display.fillCircle(rightEyeX + pupilOffsetX, eyeY + pupilOffsetY, 7, SSD1306_BLACK);
        display.fillCircle(leftEyeX + pupilOffsetX - 3, eyeY + pupilOffsetY - 3, 3, SSD1306_WHITE);
        display.fillCircle(rightEyeX + pupilOffsetX - 3, eyeY + pupilOffsetY - 3, 3, SSD1306_WHITE);
        display.fillCircle(leftEyeX + pupilOffsetX + 2, eyeY + pupilOffsetY + 2, 1, SSD1306_WHITE);
        display.fillCircle(rightEyeX + pupilOffsetX + 2, eyeY + pupilOffsetY + 2, 1, SSD1306_WHITE);
        break;
    }
  } else {
    // Kondisi mata tertutup (sedang berkedip)
    display.drawLine(leftEyeX - 12, eyeY, leftEyeX + 12, eyeY, SSD1306_WHITE);
    display.drawLine(rightEyeX - 12, eyeY, rightEyeX + 12, eyeY, SSD1306_WHITE);
    for(int i = -10; i <= 10; i+=4) {
      display.drawLine(leftEyeX + i, eyeY, leftEyeX + i, eyeY + 5, SSD1306_WHITE);
      display.drawLine(rightEyeX + i, eyeY, rightEyeX + i, eyeY + 5, SSD1306_WHITE);
    }
  }
  
  // Tampilkan Jam Digital (HH:MM:SS) di bagian atas layar jika WiFi terhubung
  if (WiFi.status() == WL_CONNECTED) {
    timeClient.update();
    int hour = timeClient.getHours();
    int minute = timeClient.getMinutes();
    int second = timeClient.getSeconds();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(40, 0);
    if(hour < 10) display.print("0");
    display.print(hour); display.print(":");
    if(minute < 10) display.print("0");
    display.print(minute); display.print(":");
    if(second < 10) display.print("0");
    display.print(second);
  }
}

// ========== SETUP ==========
void setup() {
  Serial.begin(115200);
  
  // Inisialisasi OLED
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("OLED gagal!");
    for(;;);
  }
  display.clearDisplay();
  
  // Koneksi WiFi
  display.setCursor(10, 20);
  display.println("Menghubungkan WiFi...");
  display.display();
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi Connected!");
  
  // Inisialisasi NTP
  timeClient.begin();
  display.clearDisplay();
}

// ========== LOOP UTAMA ==========
void loop() {
  unsigned long now = millis();
  
  // Update ekspresi setiap 30 detik (sesuai jam)
  static unsigned long lastTimeCheck = 0;
  if (WiFi.status() == WL_CONNECTED && (now - lastTimeCheck > 30000)) {
    int newExpr = getExpressionByTime();
    if (newExpr != expression) {
      expression = newExpr;
      Serial.println("Ekspresi berubah!");
    }
    lastTimeCheck = now;
  }
  
  // Logika Kedipan Mata (lebih lambat saat tidur)
  int blinkInterval = (expression == 3) ? 8000 : 3000;
  if (now - lastBlink > blinkInterval && eyesOpen) {
    eyesOpen = false;
    lastBlink = now;
  }
  if (now - lastBlink > 150 && !eyesOpen) {
    eyesOpen = true;
    lastBlink = now;
  }
  
  // Logika Gerakan Mata (hanya jika tidak tidur)
  int moveInterval = (expression == 3) ? 5000 : 2500;
  if (eyesOpen && expression != 3 && (now - lastEyeMove > moveInterval)) {
    eyeDirection = (eyeDirection + 1) % 5;
    lastEyeMove = now;
  }
  
  // Gambar ulang layar
  display.clearDisplay();
  drawMoChanEyesInBox();
  display.display();
  delay(30);
}

📖 Penjelasan Detail Kode (Baris per Baris)

Berikut adalah penjelasan fungsi dan alur kode agar Anda bisa memodifikasinya nanti.

1. Bagian Header dan Library

#include <Wire.h> : Library untuk komunikasi I2C (komunikasi antara NodeMCU dan OLED).
#include <Adafruit_GFX.h> : Library grafis inti yang menyediakan fungsi menggambar seperti drawCircle(), drawLine(), dll.
#include <Adafruit_SSD1306.h> : Driver spesifik untuk layar OLED SSD1306.
#include <ESP8266WiFi.h> : Library untuk koneksi WiFi pada board ESP8266.
#include <NTPClient.h> : Library untuk sinkronisasi waktu dengan server NTP (Network Time Protocol) via internet.

2. Konfigurasi WiFi dan OLED

const char* ssid = "..." dan password : Isi dengan kredensial hotspot Anda.
#define SCREEN_WIDTH 128 ... : Mendefinisikan resolusi layar OLED (128x64).
Adafruit_SSD1306 display(...) : Membuat objek display untuk mengontrol layar. Parameter terakhir -1 berarti tidak menggunakan pin reset tambahan.

3. Konfigurasi NTP dan Zona Waktu

NTPClient timeClient(ntpUDP, "pool.ntp.org", 25200, 60000);
- pool.ntp.org : alamat server waktu global.
- 25200 : offset dalam detik untuk zona waktu WIB (UTC+7). Untuk WITA gunakan 28800, untuk WIT 32400.
- 60000 : interval update waktu setiap 60 detik.

4. Variabel Animasi Mata

lastBlink, lastEyeMove : menyimpan waktu terakhir (millis) untuk mengatur interval kedipan dan gerakan.
eyesOpen : status boolean (true=terbuka, false=tertutup).
eyeDirection : 0 (tengah), 1 (kiri), 2 (kanan), 3 (atas), 4 (bawah).
expression : 0 (normal), 1 (happy), 2 (surprised), 3 (sleep), 4 (angry), 5 (love).

5. Fungsi getExpressionByTime()

Fungsi ini yang menjadi inti logika waktu. Ia mengambil jam dan menit dari NTP, lalu mengonversi ke format HHMM (misal pukul 07:30 menjadi 730). Kemudian dengan percabangan if-else, fungsi mengembalikan angka ekspresi yang sesuai. Contoh: jika jam kurang dari 6:15 pagi, akan mengembalikan 3 (tidur).

6. Fungsi Gambar drawMoChanEyesInBox()

Ini adalah fungsi paling kompleks. Langkah-langkahnya:
- Menentukan posisi mata kiri (x=44) dan kanan (x=84).
- Menggambar bingkai kotak dengan drawRoundRect() dan drawRect() untuk efek panel robot.
- Kondisi if(eyesOpen) : Jika mata terbuka, akan menggambar 6 macam ekspresi berdasarkan nilai expression menggunakan switch-case. Mulai dari garis lengkung untuk bahagia, lingkaran besar untuk terkejut, hingga bentuk hati untuk love.
- Kondisi else : Jika mata tertutup (kedip), akan menggambar garis horizontal plus bulu mata pendek.
- Terakhir, fungsi menampilkan jam digital di koordinat (40,0) jika WiFi terhubung.

7. Bagian setup()

Menjalankan inisialisasi:
- Serial.begin(115200) untuk debugging.
- Memulai koneksi ke OLED. Alamat I2C umumnya 0x3C. Jika tidak merespon, program akan berhenti (infinite loop).
- Menghubungkan ke WiFi dengan WiFi.begin() dan menunggu hingga terhubung.
- Memulai client NTP dengan timeClient.begin().

8. Bagian loop()

Ini adalah jantung animasi yang berjalan terus menerus:
- Setiap 30 detik, program memanggil getExpressionByTime() untuk mengecek perubahan ekspresi.
- Kedipan Mata : Menggunakan millis() non-blocking. Jika waktu sekarang dikurang lastBlink melebihi interval, status mata berubah. Mata akan tertutup selama 150ms.
- Gerakan Lirik : Mirip seperti kedipan, namun mengubah arah pandang setiap 2.5 detik (kecuali saat ekspresi tidur).
- Setiap iterasi, layar dibersihkan (display.clearDisplay()), lalu memanggil fungsi gambar, dan display.display() untuk mengirim buffer ke layar. Delay 30ms memberikan refresh rate yang halus.

🚀 Cara Upload dan Menjalankan

  1. Buka Arduino IDE, pilih board NodeMCU 1.0 (ESP-12E Module) dan port COM yang sesuai.
  2. Copy seluruh kode di atas ke IDE, lalu ganti ssid dan password dengan milik Anda.
  3. Klik tombol Upload (→). Jika gagal koneksi, tekan tombol FLASH pada NodeMCU saat proses "Connecting..." di log.
  4. Setelah upload selesai, buka Serial Monitor (baud 115200) untuk melihat debugging waktu dan perubahan ekspresi.
  5. Dalam beberapa detik, layar OLED akan menampilkan mata robot dan jam digital. Amati bagaimana ekspresi berubah sesuai waktu!
📌 Catatan Penting: Jika layar OLED tidak menampilkan apa-apa, coba ganti alamat I2C dari 0x3C menjadi 0x3D pada baris display.begin(SSD1306_SWITCHCAPVCC, 0x3C). Juga periksa kembali koneksi kabel SDA/SCL.

🎨 Kustomisasi Lebih Lanjut

Anda bisa mengubah jadwal emosi sesuai keinginan. Misalnya menambahkan ekspresi kaget pada jam tertentu, atau membuat mata melotot saat jam makan. Ubah saja nilai currentTime di fungsi getExpressionByTime(). Anda juga bisa mengganti bentuk kotak, menambah animasi kelopak mata, atau menampilkan teks tambahan di layar.

📦 Kesimpulan

Dengan proyek ini, Anda telah berhasil membuat sebuah perangkat IoT yang interaktif dan imut. Mata robot Mo-chan tidak hanya menjadi pajangan statis, tetapi memiliki "kepribadian" yang berubah sepanjang hari. Proyek ini menggabungkan konsep mikrokontroler, display grafis, koneksi internet, dan manajemen waktu. Selamat bereksperimen dan mengembangkan kreasi Anda sendiri! Jangan lupa bagikan hasil karya Anda di media sosial dengan tagar #RobotMoChan.

Bagikan artikel ini jika dirasa membantu teman Anda yang lain.

Sabtu, 06 September 2025

Dari Dunia Nyata ke Rak Mainan: Panduan Magic Membuat Figur Miniatur AI yang Hidup dan Bergerak

 

Belakangan ini, linimasa media sosial dihiasi oleh sebuah magic digital: foto-foto biasa yang berubah menjadi figur miniatur yang ultra-realistis, layaknya action figure koleksi terbatas yang dipajang di rak. Bahkan, si figur miniatur ini bisa hidup dan bergerak! Tren yang memadukan nostalgia mainan masa kecil dengan kecanggihan AI ini memang sedang viral.

Bagi yang penasaran, rahasia di balik magic ini adalah kombinasi dua tool AI powerful: Google Gemini sebagai "pematung digital" dan PixVerse sebagai "sihir animasi". Berikut adalah panduan lengkapnya untuk mengubah foto Anda, motor, atau hewan peliharaan menjadi karya miniatur yang mengagumkan.

Langkah 1: Memahat Digital dengan Google Gemini

Bayangkan Gemini sebagai seorang pematung berbakat yang butuh instruksi jelas. Tugas Anda adalah memberinya gambaran terperinci.

  1. Akses Workshop Digital: Buka browser dan kunjungi https://gemini.google.com/.

  2. Pilih Bahan Baku: Klik ikon "+" (unggah) dan pilih foto terbaik yang ingin Anda "kecilkan". Pastikan objek foto jelas.

  3. Berikan Perintah Magic (Prompt): Ini adalah kunci utama! Jangan hanya bilang "buat miniatur". Berikan deskripsi yang kaya dan detail. Salin dan modifikasi prompt ahli berikut untuk hasil terbaik:

    "Create a highly detailed 1/7 scale anime figure of the subject in this photo. The figure should have a realistic texture, subtle airbrush shading, and be placed on a simple circular transparent acrylic base. Set the scene on a cluttered workshop desk with a computer monitor showing a 3D modeling software (like ZBrush or Blender) in the background. Next to the monitor, include a closed BANDAI-style figure box with official artwork on it. The lighting should be soft studio lighting to highlight the figure's details."

  4. Simpan Karya Anda: Setelah Gemini selesai memproses, periksa hasilnya. Jika sudah sesuai, download gambar tersebut untuk dibawa ke tahap selanjutnya.

Langkah 2: Meniupkan Jiwa dengan PixVerse

Setelah Anda memiliki "patung"-nya, sekarang saatnya memberi nyawa. PixVerse akan mengubah gambar diam itu menjadi video animasi pendek yang memukau.

  1. Masuk ke Studio Animasi: Kunjungi https://app.pixverse.ai/ dan login dengan akun Google Anda.

  2. Unggah Figur Anda: Klik untuk mengunggah gambar hasil editan Gemini yang telah Anda simpan.

  3. Perintah untuk Bergerak (Prompt Animation): Sekarang, beri tahu AI bagaimana Anda ingin figur itu bergerak. Spesifik adalah kunci sukses. Gunakan prompt seperti ini:

    "A close-up shot of the figure. The camera slowly orbits around the figure to showcase all its details. The figure itself is completely stationary like a real collectible. All background elements, including the computer screen and the box, remain perfectly still. The focus is entirely on the figure."

  4. Buat dan Rayakan: Klik tombol "Create" dan biarkan AI bekerja. Dalam hitungan detik, Anda akan memiliki video figur miniatur Anda yang bergerak halus dan terlihat sangat nyata! Unduh dan bagikan langsung ke TikTok, Instagram Reels, atau platform favorit Anda.

Tips untuk Hasil yang Maksimal:

  • Foto Sumber Berkualitas: Gunakan foto dengan resolusi tinggi dan pencahayaan yang baik. Hasil akhir sangat bergantung pada input awalnya.

  • Eksperimen dengan Prompt: Jangan takut untuk memodifikasi prompt. Coba ubah skalanya (1/10 scale?), jenis basenya, atau suasana di latar belakang.

  • Bergerak dengan Purpose: Di PixVerse, prompt gerakan yang sederhana dan logis (seperti "slow zoom in" atau "gentle rotation") seringkali memberikan hasil yang lebih realistis daripada gerakan kompleks.

Selamat mencoba! Ubah momen biasa menjadi karya koleksi yang luar biasa dan siap-siap membuat teman-teman Anda terkagum-kagum.

Membuat WiFi Scanner Portabel<br>dengan NodeMCU ESP8266 dan Layar OLED

WiFi Scanner Portabel dengan NodeMCU ESP8266 dan OLED | Tutorial Lengkap 2024 📡 MEMBUAT WIFI SCANNER...