Dasar · 15 mnt baca

Tutorial EEPROM Arduino: Read, Write, Update, Put, dan Get

Penjelasan EEPROM Arduino: 1024 byte di Uno, read, write, update, put dan get, batas 100.000 kali tulis, menyimpan penghitung dan kata sandi, serta Preferences di ESP32.

EEPROM Arduino adalah memori permanen kecil yang tetap menyimpan isinya meskipun board kehilangan daya. ATmega328P di Arduino Uno, Nano, dan Pro Mini punya 1024 byte EEPROM, dan kamu mengaksesnya dengan perintah EEPROM.read(), EEPROM.write(), EEPROM.update(), EEPROM.put(), dan EEPROM.get() dari library EEPROM yang sudah ikut terpasang bersama Arduino IDE. RAM yang menyimpan variabelmu terhapus setiap kali board di-restart, tetapi pengaturan, penghitung, atau kata sandi yang kamu tulis ke EEPROM masih ada ketika board dinyalakan lagi.

Di panduan ini kamu akan melihat cara kerja EEPROM, berapa kapasitasnya di tiap board, apa beda tiap perintah, dan pertanyaan yang paling sering muncul: apa arti umur sekitar 100.000 kali tulis dalam praktik. Setelah itu kita akan membuat, langkah demi langkah, penghitung yang tetap ingat nilainya meski listrik padam, struktur pengaturan yang menyimpan kata sandi dan opsi sekaligus, serta ring buffer yang melipatgandakan umur tulis sampai 16 kali. Di bagian terakhir kamu akan belajar melakukan hal yang sama di ESP32, yang tidak punya EEPROM sungguhan, dengan library Preferences, dan di Raspberry Pi Pico dengan sistem file MicroPython.

Arduino Uno: prosesor ATmega328P berisi EEPROM 1 KB
EEPROM Arduino Uno bukan chip terpisah; letaknya di dalam ATmega328P dan menyimpan 1024 byte data permanen di alamat 0–1023.

Apa itu EEPROM dan bagaimana cara kerjanya?

EEPROM adalah singkatan dari Electrically Erasable Programmable Read-Only Memory (memori hanya-baca yang dapat diprogram dan dihapus secara elektrik). Setiap sel memori menyimpan informasi sebagai muatan listrik yang terperangkap di dalam gate berinsulasi, dan muatan itu tetap di tempatnya ketika daya mati. Bayangkan EEPROM Uno sebagai lemari dengan 1024 laci: setiap laci punya alamat dari 0 sampai 1023 dan menampung tepat 1 byte, yaitu angka antara 0 dan 255. Sel yang belum pernah ditulis terbaca 255 (0xFF). Membaca hampir instan dan tidak terbatas; menulis butuh sekitar 3,3 ms per byte dan sedikit mengikis sel. Datasheet ATmega328P menjamin minimal 100.000 siklus tulis/hapus per sel EEPROM dan retensi data 100 tahun pada 25 °C.

FiturFlash (memori program)SRAMEEPROM
Ukuran di Uno32 KB (0,5 KB untuk bootloader)2 KB1 KB (1024 byte)
Apa yang disimpan?Sketch yang kamu uploadVariabel, arrayPengaturan, penghitung, skor tertinggi
Ketika daya hilangTetap tersimpanTerhapusTetap tersimpan
Bisa ditulis selama sketch berjalan?Biasanya tidak (hanya dibaca lewat PROGMEM)Ya, tanpa batasYa, dengan library EEPROM
Ketahanan tulisSekitar 10.000Tanpa batasSekitar 100.000 per sel
Kecepatan tulisHanya ketika uploadSatu siklus clockSekitar 3,3 ms per byte

Singkatnya, SRAM itu papan tulis dan EEPROM itu buku catatan. Papan tulis bisa kamu tulisi dan hapus sesering apa pun, tetapi semuanya hilang begitu lampu padam; yang kamu tulis di buku catatan tetap ada, tetapi kamu tidak bisa menghapus dan menulis ulang halaman yang sama selamanya. Karena itu EEPROM ideal untuk informasi yang kecil dan jarang berubah: nilai kalibrasi, pengaturan pengguna, kecerahan atau volume, skor tertinggi game, kode pintu, kartu RFID yang terdaftar, atau status terakhir lampu. Untuk data besar yang sering ditulis, seperti log suhu yang mencatat setiap detik, modul kartu SD adalah pilihan yang lebih baik. Kalau kamu penasaran kenapa RAM cepat sekali penuh, baca memori Arduino tidak cukup.

Berapa kapasitas EEPROM di tiap board?

BoardProsesorEEPROMCatatan
Arduino Uno R3, Nano, Pro MiniATmega328P1024 byteEEPROM sungguhan
Arduino Mega 2560ATmega25604096 byteEEPROM sungguhan
Arduino Leonardo, MicroATmega32U41024 byteEEPROM sungguhan
Arduino Nano EveryATmega4809256 byteEEPROM sungguhan, tapi kecil
Arduino Uno R4 Minima, WiFiRenesas RA4M18 KBData flash; library EEPROM bekerja dengan perintah yang sama
ESP32ESP32 (Xtensa)Tidak adaPartisi NVS di flash; disarankan memakai Preferences
ESP8266 (NodeMCU, Wemos D1)ESP8266Tidak adaDiemulasikan di flash; perlu EEPROM.begin() dan commit()
Raspberry Pi PicoRP2040Tidak adaBerupa file di MicroPython, EEPROM emulasi di flash dengan core Arduino

Kalau kodemu akan dipindah-pindah antarboard, jangan menulis ukuran EEPROM secara tetap di kode; EEPROM.length() mengembalikan ukuran EEPROM board yang sebenarnya (1024 di Uno, 4096 di Mega), sehingga kode penghapus atau pembaca isi yang sama bisa jalan di mana saja. Untuk detail memori dan pin Uno lainnya, lihat Pinout Arduino Uno, dan untuk memilih board baca Arduino Mana yang Sebaiknya Kubeli?.

Perintah EEPROM: read, write, update, put, dan get

Library EEPROM sudah ikut dalam paket board, jadi tidak ada yang perlu diinstal; cukup tambahkan baris #include <EEPROM.h> di bagian atas sketch-mu. Alamat dimulai dari 0 dan berakhir di 1023 pada Uno. Tabel di bawah merangkum fungsi tiap perintah dan apakah perintah itu mengikis sel:

PerintahFungsinyaUkuranKeausan
EEPROM.read(alamat)Membaca satu byte (0–255)1 byteTidak ada, membaca itu gratis
EEPROM.write(alamat, nilai)Menulis ulang byte di setiap pemanggilan1 byteMemakai satu siklus di setiap pemanggilan
EEPROM.update(alamat, nilai)Membaca dulu, menulis hanya kalau nilainya berbeda1 byteHanya ketika nilainya berubah
EEPROM.put(alamat, data)Menulis int, float, array, atau struct byte demi byte; di dalamnya memakai updatesizeof(data)Hanya byte yang berubah
EEPROM.get(alamat, variabel)Membaca kembali apa yang ditulis put, dengan tipe yang samasizeof(variabel)Tidak ada
EEPROM[alamat]Akses gaya array; membaca gratis, menetapkan nilai dengan = sama seperti write1 byteSetiap penetapan nilai
EEPROM.length()Mengembalikan ukuran total EEPROM-Tidak ada
EEPROM.write() dan EEPROM.read() hanya menangani satu byte. Kalau kamu menulis angka yang lebih besar dari 255, misalnya 300, sketch tetap terkompilasi tanpa error, tetapi yang tersimpan hanya byte rendahnya: 300 − 256 = 44. Untuk data multi-byte seperti int, long, float, dan struct, selalu pakai EEPROM.put() dan EEPROM.get(). Begitu juga, penetapan EEPROM[5] = x bekerja seperti write, bukan update.

Sketch pertama: menulis dan membaca EEPROM

C++ (Arduino IDE)
1#include <EEPROM.h>
2
3void setup() {
4  Serial.begin(9600);
5  Serial.print(F("EEPROM boyutu / size: "));
6  Serial.println(EEPROM.length());            // Uno'da 1024 / 1024 on the Uno
7
8  byte first = EEPROM.read(0);                // 0. adresi oku / read address 0
9  Serial.print(F("Adres 0 / address 0: "));
10  Serial.println(first);                      // ilk seferde 255 / 255 the first time
11
12  EEPROM.update(0, 42);                       // farklıysa yazar / writes only if different
13  EEPROM.write(1, 7);                         // her seferinde yazar / writes every time
14
15  int number = 300;
16  EEPROM.put(10, number);                     // int = 2 bayt: 10 ve 11 / int = 2 bytes: 10 and 11
17  float temperature = 23.75;
18  EEPROM.put(12, temperature);                // float = 4 bayt: 12-15 / float = 4 bytes: 12-15
19
20  int readNumber;
21  float readTemperature;
22  EEPROM.get(10, readNumber);                 // put ile aynı tür / same type as put
23  EEPROM.get(12, readTemperature);
24  Serial.println(readNumber);                 // 300
25  Serial.println(readTemperature);            // 23.75
26
27  EEPROM.update(20, 300);                     // HATA: yalnız alt bayt (44) kalır / BUG: only the low byte (44) is kept
28  Serial.println(EEPROM.read(20));            // 44
29}
30
31void loop() {}

Upload sketch-nya dan buka Serial Monitor di 9600 baud. Pada percobaan pertama, alamat 0 terbaca 255, karena sel itu belum pernah ditulis. Sekarang tekan tombol reset board atau cabut lalu colokkan lagi kabel USB: kali ini terbaca 42. Itulah bukti bahwa EEPROM menyimpan datanya. Sebaliknya, baris write() untuk alamat 1 menulis ulang sel itu di setiap boot meskipun nilainya selalu 7; dengan update() sel itu hanya akan ditulis sekali di awal. Nilai 300 di baris terakhir menunjukkan jebakan dari peringatan di atas, dan yang muncul di layar adalah 44. Kalau pengaturan Compiler warnings di Preferences bukan None, compiler menandai baris ini dengan large integer implicitly truncated to unsigned type.

Ketika memakai put() dan get(), kamu perlu tahu berapa byte yang dipakai tiap data; kalau tidak, kamu akan menulis dua variabel saling menimpa dan salah satunya rusak. Di contoh ini int menempati alamat 10 dan 11, jadi float dimulai di alamat 12. Berikut ukuran tipe data di Uno:

Tipe dataUkuran di UnoRentangContoh penggunaan
byte, bool, char (tipe 8-bit)1 byte0–255, true/false, atau satu karakterStatus nyala/mati, pilihan mode
int2 byte−32.768 sampai 32.767Offset kalibrasi
unsigned int, uint16_t2 byte0–65.535Skor tertinggi game
long, unsigned long (tipe 32-bit)4 byteSekitar ±2,1 miliar atau 0–4,29 miliarPenghitung jangka panjang
float4 bytePresisi 6–7 digitFaktor kalibrasi sensor
char array[10]10 byte9 karakter ditambah karakter penutupKata sandi, nama perangkat
Buat peta alamat di bagian atas sketch-mu, misalnya const int ADDR_MODE = 0; const int ADDR_SCORE = 1; const int ADDR_CAL = 3;. Selalu hitung alamat berikutnya sebagai alamat sebelumnya + sizeof(data sebelumnya), dan sisakan beberapa byte cadangan di antaranya supaya kamu bisa menambah field baru nanti.

Ketahanan tulis EEPROM: apa arti batas 100.000 itu?

100.000 kali tulis terdengar banyak, tetapi sketch yang strukturnya buruk bisa menghabiskannya dalam hitungan menit. Rumus umurnya sederhana: umur = 100.000 ÷ seberapa sering kamu menulis ke sel yang sama. Poin pentingnya, batas itu berlaku untuk tiap sel secara terpisah, bukan untuk EEPROM secara keseluruhan; kalau kamu terus menulis ke alamat yang sama, hanya sel itu yang aus. Membaca sama sekali tidak memengaruhi umur. Tabel ini menunjukkan berapa lama sebuah sel bertahan kalau alamat yang sama ditulis dengan frekuensi berbeda:

Seberapa sering alamat yang sama ditulisPerkiraan umur
write() di loop() tanpa delay (sekitar 300 kali per detik)5–6 menit
Setiap detikSekitar 28 jam
Setiap menitSekitar 69 hari
Setiap 10 menitSekitar 1,9 tahun
Sekali per jamSekitar 11 tahun
10 kali sehariSekitar 27 tahun

100.000 adalah angka minimum yang dijamin pabrik; banyak chip bertahan jauh lebih lama, tapi jangan merancang proyekmu dengan mengandalkan itu. Sel yang aus tidak mati mendadak; sel itu mulai gagal menyimpan nilai yang kamu tulis dan beberapa bitnya berubah sendiri. Kalau itu terjadi, kamu bisa memindahkan data ke alamat lain, karena sel lain tidak terpengaruh. Cara memperpanjang umurnya:

  • Pakai update() dan put(): Keduanya membaca sel sebelum menulis dan sama sekali tidak menulis kalau nilainya sama.
  • Tulis hanya ketika ada perubahan: Simpan pengaturan ketika pengguna benar-benar mengubahnya, bukan di setiap putaran loop().
  • Tunda penyimpanan: Kalau sebuah nilai berubah berkali-kali dalam waktu singkat, tulis sekali saja beberapa detik setelah perubahan terakhir; millis() membuat ini mudah.
  • Tulis berdasarkan kejadian: Simpan skor tertinggi ketika game selesai dan pengaturan menu ketika pengguna keluar dari menu.
  • Sebarkan penulisan: Tulis penghitung yang sering berubah ke beberapa alamat secara bergiliran, bukan ke satu alamat (lihat contoh ring buffer di bawah).
  • Pakai memori eksternal kalau perlu: Untuk penyimpanan yang sangat sering, pilih EEPROM eksternal dengan rating 1 juta siklus, FRAM, atau kartu SD.

Contoh 1: penghitung yang tetap bertahan meski listrik padam

Di contoh pertama kita akan membuat penghitung yang bertambah setiap kali tombol ditekan dan melanjutkan dari angka terakhir setelah board dimatikan lalu dinyalakan lagi. Hubungkan satu kaki tombol ke D2 dan kaki lainnya ke GND; kita memakai resistor pull-up internal, jadi tidak perlu resistor tambahan (detailnya di Cara Menghubungkan Push Button ke Arduino, letak pin di alat Pinout). Triknya, sketch tidak menyimpan penghitung di setiap tekanan, melainkan 5 detik setelah tekanan terakhir. Jadi meskipun seseorang menekan tombol 20 kali berturut-turut, EEPROM hanya ditulis sekali.

C++ (Arduino IDE)
1#include <EEPROM.h>
2
3const byte BUTTON_PIN = 2;                     // buton D2 ile GND arasında / button between D2 and GND
4const int  COUNT_ADDR = 0;                     // sayaç 0-3. baytlarda / counter in bytes 0-3
5const unsigned long SAVE_DELAY = 5000;         // son basıştan 5 sn sonra yaz / write 5 s after the last press
6
7unsigned long count = 0;
8bool dirty = false;                            // kaydedilmemiş değişiklik / unsaved change
9unsigned long lastPress = 0;
10unsigned long lastChange = 0;
11bool lastReading = HIGH;
12bool stableState = HIGH;
13
14void setup() {
15  Serial.begin(9600);
16  pinMode(BUTTON_PIN, INPUT_PULLUP);
17  EEPROM.get(COUNT_ADDR, count);
18  if (count == 0xFFFFFFFF) count = 0;          // boş EEPROM / blank EEPROM
19  Serial.print(F("Kayitli sayac / stored count: "));
20  Serial.println(count);
21}
22
23void loop() {
24  bool reading = digitalRead(BUTTON_PIN);
25  if (reading != lastReading) {                // pin değişti, sayacı başlat / pin changed, restart timer
26    lastChange = millis();
27    lastReading = reading;
28  }
29  if (millis() - lastChange > 30 && reading != stableState) {   // 30 ms sabit kaldı / stable for 30 ms
30    stableState = reading;
31    if (stableState == LOW) {                  // yeni basış / new press
32      count++;
33      dirty = true;
34      lastPress = millis();
35      Serial.println(count);
36    }
37  }
38
39  if (dirty && millis() - lastPress > SAVE_DELAY) {   // sessiz dönemden sonra yaz / write after a quiet period
40    EEPROM.put(COUNT_ADDR, count);
41    dirty = false;
42    Serial.println(F("EEPROM'a yazildi / saved to EEPROM"));
43  }
44}

Variabel dirty berarti ada perubahan di RAM yang belum disimpan. Penghitungnya bertipe unsigned long, jadi memakai 4 byte (alamat 0–3) dan bisa menghitung lebih dari 4 miliar tekanan. Di EEPROM yang masih kosong keempat byte itu bernilai 0xFF, sehingga boot pertama membaca 4.294.967.295; ketika kode melihat nilai itu, penghitung dimulai dari nol. Karena put() hanya menulis byte yang berubah, biasanya hanya byte terendah yang aus ketika penghitung bertambah. Kalau listrik padam dalam 5 detik sebelum penyimpanan, tekanan terakhir akan hilang; itu harga kecil untuk melindungi EEPROM.

Contoh 2: menyimpan pengaturan dan kata sandi dalam struct

Daripada menulis beberapa pengaturan ke alamat masing-masing, lebih rapi dan lebih aman mengumpulkannya dalam sebuah struct lalu menyimpannya dengan satu put(). Di contoh ini kita menyimpan kecerahan LED dan kata sandi 4–6 karakter. Dua field pertama struktur ini wajib ada: magic (angka ajaib) memberi tahu apakah pengaturan sketch ini benar-benar sudah ditulis ke EEPROM, dan version mencegah data lama yang tidak kompatibel terbaca setelah nanti kamu menambah field baru ke struktur. Kalau salah satunya tidak cocok, sketch menulis pengaturan bawaan.

C++ (Arduino IDE)
1#include <EEPROM.h>
2
3const uint16_t MAGIC = 0xB6A1;                 // "ayar yazıldı" işareti / "settings written" marker
4const byte VERSION = 1;                        // yapı değişince artır / bump when the struct changes
5const int  SETTINGS_ADDR = 0;
6const byte LED_PIN = 9;                        // PWM pini / PWM pin
7
8struct Settings {
9  uint16_t magic;
10  byte version;
11  char password[7];                            // en çok 6 karakter + '\0' / up to 6 chars + '\0'
12  byte brightness;                             // LED parlaklığı 0-255 / LED brightness 0-255
13};
14
15Settings cfg;
16
17void writeDefaults() {
18  cfg.magic = MAGIC;
19  cfg.version = VERSION;
20  strcpy(cfg.password, "1234");
21  cfg.brightness = 128;
22  EEPROM.put(SETTINGS_ADDR, cfg);
23}
24
25void setup() {
26  Serial.begin(9600);
27  pinMode(LED_PIN, OUTPUT);
28  EEPROM.get(SETTINGS_ADDR, cfg);
29  if (cfg.magic != MAGIC || cfg.version != VERSION) {   // ilk açılış ya da eski yapı / first boot or old layout
30    writeDefaults();
31    Serial.println(F("Varsayilan ayarlar yazildi / defaults written"));
32  }
33  analogWrite(LED_PIN, cfg.brightness);
34  Serial.print(F("Ayar boyutu / settings size: "));
35  Serial.println(sizeof(Settings));            // Uno'da 11 bayt / 11 bytes on the Uno
36  Serial.println(F("Komutlar / commands: b0-255   p<eski>,<yeni>   ?"));
37}
38
39void loop() {
40  if (!Serial.available()) return;
41  String line = Serial.readStringUntil('\n');
42  line.trim();
43
44  if (line.startsWith("b")) {                  // örnek / example: b200
45    cfg.brightness = constrain(line.substring(1).toInt(), 0, 255);
46    analogWrite(LED_PIN, cfg.brightness);
47    EEPROM.put(SETTINGS_ADDR, cfg);            // yalnız değişen bayt yazılır / only the changed byte is written
48    Serial.println(F("Parlaklik kaydedildi / brightness saved"));
49  } else if (line.startsWith("p")) {           // örnek / example: p1234,5678
50    int comma = line.indexOf(',');
51    if (comma < 0) {
52      Serial.println(F("Bicim / format: p1234,5678"));
53      return;
54    }
55    String oldPw = line.substring(1, comma);
56    String newPw = line.substring(comma + 1);
57    if (oldPw != cfg.password) {
58      Serial.println(F("Eski sifre yanlis / wrong old password"));
59    } else if (newPw.length() < 4 || newPw.length() > 6) {
60      Serial.println(F("Yeni sifre 4-6 karakter olmali / new password must be 4-6 chars"));
61    } else {
62      newPw.toCharArray(cfg.password, sizeof(cfg.password));
63      EEPROM.put(SETTINGS_ADDR, cfg);
64      Serial.println(F("Sifre degisti / password changed"));
65    }
66  } else if (line == "?") {
67    Serial.print(F("Parlaklik / brightness: "));
68    Serial.println(cfg.brightness);
69  }
70}

Hubungkan LED ke D9 melalui resistor LED (220 ohm sudah cukup); D9 adalah pin PWM. Buka Serial Monitor di 9600 baud, atur akhir baris ke New Line, lalu coba perintah ini: b200 mengatur kecerahan ke 200, p1234,5678 mengganti kata sandi dari 1234 menjadi 5678, dan ? menampilkan kecerahan sekarang. Ketika board kamu matikan lalu nyalakan lagi, LED kembali dengan kecerahan yang sama dan kata sandi baru tetap berlaku. Struct ini memakai 11 byte di Uno; karena put() hanya menulis byte yang berubah, mengganti kecerahan hanya mengikis satu sel. Struktur yang sama bisa kamu sesuaikan untuk kunci kode keypad atau untuk menyimpan ID 4 byte kartu yang diizinkan dalam sebuah array dengan RFID RC522. Kalau perintah serial masih baru buatmu, baca Serial Monitor Arduino.

Jangan pernah memasukkan objek String ke EEPROM. String menyimpan alamat dan panjang teks di RAM, bukan teksnya sendiri; ketika kamu memanggil EEPROM.put(0, name), yang masuk ke EEPROM adalah beberapa byte pointer, bukan teksnya, dan setelah restart kamu membaca sampah. Selalu simpan teks sebagai char array berukuran tetap, seperti di contoh. Selain itu, EEPROM tidak terenkripsi: siapa pun yang menghubungkan programmer ke board bisa membacanya. Cara ini cocok untuk kunci hobi, bukan untuk sesuatu yang butuh keamanan sungguhan.

Melipatgandakan umur tulis: ring buffer (wear leveling)

Menulis penghitung yang sering diperbarui ke alamat yang sama membuat satu sel itu cepat aus. Dengan ring buffer, kamu menulis nilai ke slot yang berbeda secara bergiliran: satu penyimpanan masuk ke satu slot, penyimpanan berikutnya ke slot berikutnya, dan setelah slot terakhir kamu kembali ke awal. Setiap slot hanya ditulis sekali dalam setiap 16 penyimpanan, jadi umurnya bertambah 16 kali, menjadi sekitar 1,6 juta penyimpanan. Ketika board mulai, semua slot dibaca untuk mencari nilai terbaru; karena penghitung hanya bisa naik, nilai terbesar adalah yang terbaru.

C++ (Arduino IDE)
1#include <EEPROM.h>
2
3const int  RING_START = 100;                   // halka 100. adresten başlar / ring starts at address 100
4const byte SLOTS = 16;                         // 16 yuva x 4 bayt = 64 bayt / 16 slots x 4 bytes = 64 bytes
5
6uint32_t counter = 0;
7byte slot = 0;
8
9void loadCounter() {
10  for (byte i = 0; i < SLOTS; i++) {
11    uint32_t v;
12    EEPROM.get(RING_START + i * 4, v);
13    if (v != 0xFFFFFFFF && v >= counter) {     // en büyük değer en yenisidir / the largest value is the newest
14      counter = v;
15      slot = i;
16    }
17  }
18}
19
20void saveCounter() {
21  slot = (slot + 1) % SLOTS;                   // her kayıtta sıradaki yuva / next slot on every save
22  EEPROM.put(RING_START + slot * 4, counter);
23}
24
25void setup() {
26  Serial.begin(9600);
27  loadCounter();
28  counter++;                                   // örnek: her açılışı say / example: count every boot
29  saveCounter();
30  Serial.print(F("Acilis sayisi / boot count: "));
31  Serial.println(counter);
32  Serial.print(F("Kullanilan yuva / slot used: "));
33  Serial.println(slot);
34}
35
36void loop() {}

Contoh ini menaikkan penghitung di setiap boot; kamu bisa menggantinya dengan tombol, kejadian sensor, atau pencatat jam operasi (hour meter). Makin banyak slot, makin panjang umurnya secara sebanding: 64 slot memakai 256 byte dan bertahan sekitar 6,4 juta penyimpanan. Kalau board pernah dipakai dengan sketch lain, data lama mungkin tertinggal di area ring, jadi hapus EEPROM dengan kode di bawah sebelum pemakaian pertama. Di proyek yang lebih lanjut, kamu juga bisa menambahkan checksum CRC, seperti di contoh eeprom_crc milik Arduino sendiri, untuk mendeteksi data yang rusak.

Bagaimana cara me-reset EEPROM? Apakah upload menghapusnya?

Upload biasa lewat kabel USB hanya menulis memori program; data di EEPROM tetap tersimpan. Jadi ketika kamu meng-upload proyek baru, pengaturan proyek sebelumnya masih ada di EEPROM dan kode baru bisa membaca nilai yang tidak diharapkannya. Di Uno, EEPROM hanya terhapus ketika kamu memakai programmer ISP dengan Sketch > Upload Using Programmer atau Tools > Burn Bootloader; operasi ini menghapus seluruh chip, dan bit EESAVE yang melindungi EEPROM dalam keadaan mati di pengaturan fuse Uno. Untuk menghapus EEPROM sendiri, upload sketch ini sekali:

C++ (Arduino IDE)
1#include <EEPROM.h>
2
3void setup() {
4  for (uint16_t i = 0; i < EEPROM.length(); i++) {
5    EEPROM.update(i, 255);                     // fabrika durumu 0xFF / factory state 0xFF
6  }
7  pinMode(LED_BUILTIN, OUTPUT);
8  digitalWrite(LED_BUILTIN, HIGH);             // LED yandı: bitti / LED on: done
9}
10
11void loop() {}

Contoh File > Examples > EEPROM > eeprom_clear di Arduino IDE menulis 0 ke setiap sel; kita justru mengembalikan sel ke keadaan pabriknya, yaitu 255. Dengan begitu, kode yang memeriksa angka ajaib atau 0xFF akan mengenali EEPROM sebagai kosong lagi. Karena kita memakai update(), sel yang sudah bernilai 255 sama sekali tidak ditulis. Menulis seluruh 1024 sel di Uno butuh paling lama sekitar 3,4 detik; begitu LED bawaan menyala, prosesnya selesai. Setelah itu upload sketch-mu yang sebenarnya.

EEPROM di ESP32: library Preferences

ESP32 tidak punya EEPROM sungguhan. Data permanen disimpan di partisi NVS (Non-Volatile Storage) pada memori flash eksternal; di tabel partisi bawaan, area ini berukuran 20 KB. Cara yang disarankan Espressif adalah library Preferences yang ikut dalam paket board ESP32. Preferences menyimpan data berdasarkan nama namespace dan key, bukan alamat, jadi kamu tidak perlu mengingat di alamat mana penghitung disimpan. NVS menulis setiap nilai baru ke entri kosong berikutnya di halaman dan menandai entri lama sebagai terhapus, sehingga wear leveling terjadi otomatis. Nama namespace dan key paling panjang 15 karakter dan membedakan huruf besar-kecil. Kalau kamu baru mengenal ESP32, mulai dari Apa Itu ESP32?.

C++ (Arduino IDE)
1#include <Preferences.h>
2
3Preferences prefs;
4
5void setup() {
6  Serial.begin(115200);
7  prefs.begin("bluegrays", false);             // ad alanı; false = okuma + yazma / namespace; false = read + write
8
9  uint32_t boots = prefs.getUInt("boots", 0);  // anahtar yoksa 0 / 0 if the key is missing
10  boots++;
11  prefs.putUInt("boots", boots);
12
13  if (!prefs.isKey("ssid")) {                  // ilk açılış / first boot
14    prefs.putString("ssid", "EvAgi");          // örnek değer / example value
15  }
16  String ssid = prefs.getString("ssid", "");   // kayıtlı Wi-Fi adı / stored Wi-Fi name
17  int brightness = prefs.getInt("bright", 128);   // yoksa 128 / 128 if missing
18
19  Serial.print("Acilis / boot: ");
20  Serial.println(boots);
21  Serial.print("SSID: ");
22  Serial.println(ssid);
23  Serial.print("Parlaklik / brightness: ");
24  Serial.println(brightness);
25  Serial.print("Bos kayit yeri / free entries: ");
26  Serial.println(prefs.freeEntries());
27  prefs.end();                                 // ad alanını kapat / close the namespace
28}
29
30void loop() {}
PerintahFungsinya
prefs.begin("nama", false)Membuka namespace; false berarti baca dan tulis, true berarti hanya baca
putUInt, putInt, putFloat, putBool, putString, putBytesMenyimpan nilai dengan sebuah nama key
getUInt("key", default)Membaca nilai; mengembalikan nilai default kalau key-nya tidak ada
isKey("key")Memeriksa apakah key-nya ada
remove("key")Menghapus satu key
clear()Menghapus semua key di namespace yang terbuka
freeEntries()Mengembalikan jumlah entri kosong yang tersisa di NVS
end()Menutup namespace

Nilai harus dibaca kembali dengan tipe yang sama seperti ketika ditulis: kalau kamu menulis dengan putUInt lalu membaca dengan getInt, yang kamu dapat adalah nilai default. Ada juga alasan kenapa kita memanggil isKey() sebelum getString(): kalau Core Debug Level di menu Tools diatur ke Error atau lebih tinggi, membaca key teks yang tidak ada akan mencetak nvs_get_str len fail: ssid NOT_FOUND ke Serial Monitor; pesan ini tidak berbahaya, tapi membingungkan. Upload ulang lewat USB tidak menghapus NVS, tetapi kalau Erase All Flash Before Sketch Upload diatur ke Enabled, setiap upload menghapus semua entri. Menyimpan data Wi-Fi dengan Preferences sudah umum; kalau kamu lebih suka memasukkan nama jaringan dan kata sandi dari ponsel, WiFiManager ESP32 juga bisa, dan ESP32 menyimpan pengaturan Wi-Fi-nya di area NVS yang sama. Untuk nilai berumur pendek yang harus bertahan setelah bangun dari deep sleep, memori RTC lebih cocok karena sama sekali tidak mengikis flash; lihat deep sleep ESP32.

Ketika kamu memindahkan kode Arduino lama ke ESP32, library EEPROM juga bisa dipakai, dengan dua perbedaan: sebelum memakainya kamu harus memberi tahu berapa byte yang kamu perlukan dengan EEPROM.begin(size), dan setelah membuat perubahan kamu harus memanggil EEPROM.commit(). put() dan write() hanya mengubah salinan di RAM; tanpa commit() tidak ada yang sampai ke flash. Di ESP32, library ini berjalan sebagai satu blob data di dalam NVS dan Espressif menganggapnya usang (deprecated); setiap byte area yang baru dibuat bernilai 0xFF. Kode yang sama juga bisa dikompilasi untuk ESP8266, di mana ukurannya paling besar 4096 byte dan setiap commit() menghapus lalu menulis ulang satu sektor flash 4 KB, jadi panggil commit seperlunya saja.

C++ (Arduino IDE)
1#include <EEPROM.h>
2
3void setup() {
4  Serial.begin(115200);
5  EEPROM.begin(64);                            // kullanılacak bayt sayısı / number of bytes to use
6  uint32_t boots;
7  EEPROM.get(0, boots);
8  if (boots == 0xFFFFFFFF) boots = 0;          // yeni alan 0xFF dolu / a fresh area is 0xFF
9  boots++;
10  EEPROM.put(0, boots);                        // yalnız RAM'deki kopyayı değiştirir / changes only the RAM copy
11  EEPROM.commit();                             // flaşa şimdi yazılır / written to flash now
12  Serial.println(boots);
13  EEPROM.end();
14}
15
16void loop() {}

Data permanen di Raspberry Pi Pico: sistem file MicroPython

Chip RP2040 di Raspberry Pi Pico juga tidak punya EEPROM; board-nya membawa memori flash 2 MB. MicroPython menyisihkan sekitar 1,4 MB dari flash itu untuk sistem file LittleFS (lebih kecil di Pico W karena firmware Wi-Fi). Jadi di Pico, padanan EEPROM adalah menulis pengaturanmu ke sebuah file kecil. LittleFS menyebarkan penulisan ke blok flash yang berbeda-beda, jadi melakukan wear leveling sendiri, dan sistem filenya tidak rusak meskipun daya putus di tengah penulisan. Kode di bawah menyimpan pengaturan sebagai JSON, menghitung setiap boot, dan menyimpan penghitung setiap kali tombol yang dipasang di antara GP15 dan GND ditekan.

MicroPython
1import json, os, time
2from machine import Pin
3
4FILE = "settings.json"
5DEFAULTS = {"boots": 0, "count": 0, "password": "1234"}
6
7def load():
8    try:
9        with open(FILE) as f:
10            data = json.load(f)
11    except (OSError, ValueError):            # dosya yok ya da bozuk / file missing or corrupt
12        data = {}
13    for key, value in DEFAULTS.items():      # eksik anahtarları tamamla / fill in missing keys
14        data.setdefault(key, value)
15    return data
16
17def save(data):
18    with open(FILE + ".tmp", "w") as f:      # önce geçici dosyaya yaz / write a temp file first
19        json.dump(data, f)
20    os.rename(FILE + ".tmp", FILE)           # sonra eskisinin yerine koy / then replace the old one
21
22settings = load()
23settings["boots"] += 1
24save(settings)
25print("Acilis / boot:", settings["boots"], "Sayac / count:", settings["count"])
26
27button = Pin(15, Pin.IN, Pin.PULL_UP)        # buton GP15 ile GND arasında / button between GP15 and GND
28
29while True:
30    if button.value() == 0:                  # basıldı / pressed
31        time.sleep_ms(30)                    # sıçramayı bekle / let the bounce settle
32        if button.value() == 0:
33            settings["count"] += 1
34            save(settings)                   # seyrek olay, her basışta yaz / rare event, save on each press
35            print("Sayac / count:", settings["count"])
36            while button.value() == 0:       # bırakılmasını bekle / wait for release
37                time.sleep_ms(10)
38            time.sleep_ms(30)                # bırakma sıçraması / release bounce
39    time.sleep_ms(10)

Daripada menimpa file secara langsung, kita menulis dulu ke file sementara .tmp lalu memakai os.rename() untuk menaruhnya menggantikan file lama, sehingga file pengaturan lama tetap utuh meskipun penulisan terputus. Kalau file tidak ada atau isinya rusak, load() kembali ke nilai bawaan, dan ketika nanti kamu menambah pengaturan baru ke program, setdefault() mengisi key yang hilang secara otomatis. Kalau kamu memprogram Pico dengan Arduino IDE, kamu juga bisa memakai library EEPROM di core Arduino-Pico buatan Earle Philhower: EEPROM.begin(256) membuka area 256–4096 byte dan EEPROM.commit() menyimpan perubahanmu. EEPROM emulasi ini berada di sektor 4 KB terakhir flash dan setiap commit() menghapus lalu menulis ulang sektor itu; flash diberi rating sekitar 100.000 siklus hapus per sektor, jadi panggil commit seperlunya saja. Kalau kamu baru mulai dengan Pico, Apa Itu Raspberry Pi Pico? dan dasar-dasar MicroPython adalah titik awal yang bagus.

Memori permanen yang lebih besar: EEPROM eksternal, FRAM, dan kartu SD

Kalau 1 KB tidak cukup atau kamu perlu menyimpan sangat sering, kamu bisa menambah memori eksternal. Chip EEPROM I2C seperti AT24C256 menawarkan 32 KB dan sekitar 1 juta siklus tulis, dan cukup dihubungkan dengan kabel SDA dan SCL (Apa Itu I2C?). Detail yang jarang diketahui: banyak modul jam RTC DS3231 di pasaran sudah membawa EEPROM AT24C32 4 KB, biasanya bisa diakses di alamat I2C 0x57. Untuk pekerjaan yang menyimpan berkali-kali per detik, modul FRAM dengan rating sekitar satu triliun (10^12) siklus tulis lebih cocok, dan untuk log data besar pakai modul kartu SD yang menyimpan data sebagai file.

Ide proyek dengan EEPROM

  • Lampu yang ingat status terakhirnya: Ketika listrik menyala lagi, kembalikan lampu yang dikendalikan relay ke status sebelum listrik padam.
  • Brankas dengan kode yang bisa diganti: Tulis kode baru yang dimasukkan lewat keypad ke EEPROM, sehingga kode bisa diganti tanpa meng-upload ulang sketch.
  • Kunci pintu berkartu: Simpan ID kartu yang diizinkan yang dipindai dengan RFID RC522 dan tambahkan kartu baru dengan kartu master.
  • Skor tertinggi permanen: Simpan skor terbaik di Simon, T-Rex, atau Snake; contoh kodenya ada di proyek game Arduino.
  • Lengan robot yang merekam gerakan: Rekam sudut servo pose demi pose lalu putar ulang; kode di lengan robot Arduino melakukan ini dengan EEPROM.update().
  • Timbangan yang ingat kalibrasinya: Simpan faktor kalibrasi yang kamu temukan dengan load cell HX711 sebagai float dengan put().
  • Penghitung reset: Hitung berapa kali board restart untuk mendiagnosis masalah daya; caranya ada di Arduino terus reset.

Kesalahan umum dan cara mengatasinya

GejalaPenyebabSolusi
Boot pertama membaca 255, -1, 65535, atau nanEEPROM belum pernah ditulis; sel kosong bernilai 0xFFTulis nilai bawaan kalau pemeriksaan angka ajaib atau 0xFF gagal
Menulis 300, terbaca 44write() dan read() hanya membawa 1 bytePakai put() dan get() untuk data multi-byte
Dua nilai saling merusakAlamatnya tumpang tindih; int memakai 2 byte, float 4Buat peta alamat dan hitung alamat dengan sizeof
Teks berubah jadi sampah setelah restartObjek String ditulis dengan put()Simpan teks sebagai char array
Kode baru membaca pengaturan proyek lamaUpload biasa tidak menghapus EEPROMPakai angka ajaib dan field versi, atau hapus EEPROM
Pengaturan hilang setelah uploadUpload dengan programmer di Uno, opsi Erase All Flash di ESP32Upload biasa lewat USB, atur opsi ESP32 ke Disabled
Nilai tidak tersimpan di ESP32EEPROM.begin() atau EEPROM.commit() tidak adaTambahkan keduanya, atau beralih ke Preferences
Preferences selalu mengembalikan nilai defaultMembaca dengan tipe berbeda, nama lebih dari 15 karakter, atau namespace berbedaSamakan tipe put dan get, buat nama tetap pendek
Error “nvs_open failed: NOT_FOUND”Namespace yang belum pernah dibuat dibuka dalam mode hanya baca (true)Buka namespace dengan false dulu dan tulis sebuah nilai
Nilai rusak setelah beberapa lamaPenulisan terus-menerus di loop() atau tegangan catu daya turun ketika sedang menulisPakai update() dan penyimpanan tertunda, tambahkan ring buffer dan CRC
Melihat isi EEPROM adalah cara tercepat untuk debugging. Baca 64 alamat pertama dengan EEPROM.read() dalam perulangan for dan cetak ke Serial Monitor (atau buka contoh siap pakai Arduino eeprom_read), dan kamu akan langsung melihat sel kosong, nilai yang tertulis di alamat yang salah, dan data sisa dari proyek lama.

EEPROM adalah cara termudah memberi ingatan pada proyek Arduino-mu: dengan beberapa baris kode, kamu melindungi pengaturan, penghitung, dan kata sandi perangkatmu dari listrik padam. Satu-satunya yang perlu diperhatikan adalah ketahanan tulis; selama kamu memakai update() dan put() dan tidak menulis tanpa perlu, EEPROM Uno akan bekerja tanpa masalah selama bertahun-tahun. Di aplikasi BlueGrays kamu akan menemukan proyek yang bisa kamu kembangkan dengan EEPROM, seperti “Kunci Sandi dengan Keypad 4x4 dan LCD”, “Brankas Elektronik Pintar”, “Autentikasi RFID”, serta game Simon (“Game Memori Arduino”) dan “OLED T-Rex Run”, masing-masing dengan skema rangkaian dan kode langkah demi langkah.

Pertanyaan umum

Berapa kali EEPROM Arduino bisa ditulis?

Datasheet ATmega328P menjamin minimal 100.000 siklus tulis/hapus untuk setiap sel EEPROM. Batas itu berlaku per sel, dan membaca sama sekali tidak memengaruhinya. Menulis ke alamat yang sama sekali per detik membuat sel aus dalam sekitar 28 jam; kalau kamu memakai update() dan menulis hanya ketika nilainya berubah, EEPROM bisa bertahan bertahun-tahun.

Apakah meng-upload sketch baru menghapus EEPROM Arduino?

Tidak. Upload biasa lewat USB hanya menulis memori program, dan data di EEPROM tetap tersimpan. Di Uno, EEPROM hanya terhapus ketika kamu meng-upload dengan programmer ISP atau melakukan burn bootloader. Pakai pemeriksaan angka ajaib supaya proyek baru tidak membaca pengaturan lama.

Apa beda EEPROM.write dan EEPROM.update?

write() menulis ulang nilai ke sel di setiap pemanggilan dan menghabiskan satu siklus tulis setiap kali. update() membaca sel dulu dan sama sekali tidak menulis kalau nilainya sama. Hasilnya identik, tetapi update() menjaga umur EEPROM; put() memakai cara yang sama di dalamnya.

Bagaimana cara menghapus EEPROM Arduino?

Tulis 255 (atau 0) ke setiap alamat dengan perulangan for yang berjalan sampai EEPROM.length(); contoh eeprom_clear di Arduino IDE langsung menulis 0. Menghapus seluruh 1024 byte di Uno butuh sekitar 3,4 detik. Setelah selesai, jangan biarkan sketch penghapus itu tetap di board; upload program aslimu.

Apakah ESP32 punya EEPROM?

ESP32 tidak punya EEPROM sungguhan; data permanen disimpan di partisi NVS pada memori flash. Library Preferences disarankan untuk proyek baru. Library EEPROM masih bisa dipakai untuk kode lama, tetapi kamu harus memanggil EEPROM.begin(size) lebih dulu dan EEPROM.commit() setelah setiap perubahan.

Bagaimana cara menyimpan int, float, atau teks ke EEPROM?

Tulis data multi-byte seperti int, long, float, dan struct dengan EEPROM.put(alamat, variabel) dan baca dengan EEPROM.get(alamat, variabel). Int memakai 2 byte dan float 4 byte, jadi pilih alamat berikutnya sesuai ukuran itu. Simpan teks sebagai char array berukuran tetap, bukan sebagai String.

Lihat semua proyek
Nyala/Mati LED dengan Tombol (On/Off)
#10Pemula

Nyala/Mati LED dengan Tombol (On/Off)

Tekan tombol sekali dan lampu menyala, tekan lagi dan lampu mati, persis seperti sakelar lampu di kamarmu. Arduino menyadari setiap tekanan dan membalik LED ke keadaan sebaliknya, sambil menunggu sebe

4.8(100)
167
Penghitung dengan Layar 7 Segmen dan Tombol
#43Mahir
Premium

Penghitung dengan Layar 7 Segmen dan Tombol

Penghitung sederhana dengan tiga tombol: tekan satu dan angka di layar naik satu, tekan yang lain dan turun satu, dan yang ketiga mengembalikannya ke nol. Layar 7 segmen satu digit menghitung dari 0 s

4.6(35)
47
Kunci Sandi dengan Keypad 4x4 dan LCD
#64Mahir
Premium

Kunci Sandi dengan Keypad 4x4 dan LCD

Kunci pintu elektronik kecil yang menahan siapa pun yang tidak tahu kodenya. Kamu menekan tombol pagar lalu mengetik kodenya di keypad; jika benar, layar menulis akses diberikan, LED hijau menyala, da

4.8(59)
75
Brankas Elektronik Pintar
#92Mahir
Premium

Brankas Elektronik Pintar

Brankas kecil untuk barang berhargamu yang terbuka dengan kode. Kamu mengetik kode empat digitmu di keypad; jika benar, motor servo membuka kunci, lampu hijau menyala, dan layar menampilkan keadaan br

4.7(42)
63
Autentikasi RFID
#54Menengah
Premium

Autentikasi RFID

Persis seperti akses kartu di pintu apartemen: kamu mendekatkan kartumu ke pembaca RFID, dan Arduino membandingkan nomornya dengan yang tersimpan. Kartu yang benar menyalakan LED hijau selama tiga det

4.8(64)
83
Game Memori Arduino (4 LED + 4 Tombol + Buzzer)
#93Mahir
Premium

Game Memori Arduino (4 LED + 4 Tombol + Buzzer)

Percaya dengan ingatanmu? Empat LED berwarna menyala berurutan, masing-masing memainkan nadanya sendiri, dan kamu mengulang urutan yang sama dengan menekan tombol. Setiap ronde yang benar menambahkan

4.8(46)
69
OLED T-Rex Run: Game Dinosaurus Arduino
#87Mahir
Premium

OLED T-Rex Run: Game Dinosaurus Arduino

Game dinosaurus yang muncul ketika internetmu putus, sekarang ada di mejamu: dinosaurus berlari di layar OLED kecil, kaktus datang menghampiri, dan kamu melompat dengan satu tombol. Skormu naik secara

4.7(33)
53
Deep Sleep ESP32: Hemat Baterai (OLED + Penghitung RTC RAM)
#135Mahir
Premium

Deep Sleep ESP32: Hemat Baterai (OLED + Penghitung RTC RAM)

Mode Deep Sleep ESP32 menurunkan konsumsi arus hingga ~10 µA dengan mematikan CPU dan sebagian besar periferal, sehingga sangat penting untuk perangkat IoT bertenaga baterai. Di proyek ini, kita memakai tiga sumber bangun yang berbeda: timer (15 detik), pin eksternal (EXT0, tombol GPIO 33), dan sentuhan (T0/GPIO 4). Variabel yang ditandai RTC_DATA_ATTR dipertahankan selama deep sleep; penghitung boot, penghitung bangun karena timer, dan penghitung bangun karena tombol terus dilacak.

4.3(10)
16