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.

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.
| Fitur | Flash (memori program) | SRAM | EEPROM |
|---|---|---|---|
| Ukuran di Uno | 32 KB (0,5 KB untuk bootloader) | 2 KB | 1 KB (1024 byte) |
| Apa yang disimpan? | Sketch yang kamu upload | Variabel, array | Pengaturan, penghitung, skor tertinggi |
| Ketika daya hilang | Tetap tersimpan | Terhapus | Tetap tersimpan |
| Bisa ditulis selama sketch berjalan? | Biasanya tidak (hanya dibaca lewat PROGMEM) | Ya, tanpa batas | Ya, dengan library EEPROM |
| Ketahanan tulis | Sekitar 10.000 | Tanpa batas | Sekitar 100.000 per sel |
| Kecepatan tulis | Hanya ketika upload | Satu siklus clock | Sekitar 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?
| Board | Prosesor | EEPROM | Catatan |
|---|---|---|---|
| Arduino Uno R3, Nano, Pro Mini | ATmega328P | 1024 byte | EEPROM sungguhan |
| Arduino Mega 2560 | ATmega2560 | 4096 byte | EEPROM sungguhan |
| Arduino Leonardo, Micro | ATmega32U4 | 1024 byte | EEPROM sungguhan |
| Arduino Nano Every | ATmega4809 | 256 byte | EEPROM sungguhan, tapi kecil |
| Arduino Uno R4 Minima, WiFi | Renesas RA4M1 | 8 KB | Data flash; library EEPROM bekerja dengan perintah yang sama |
| ESP32 | ESP32 (Xtensa) | Tidak ada | Partisi NVS di flash; disarankan memakai Preferences |
| ESP8266 (NodeMCU, Wemos D1) | ESP8266 | Tidak ada | Diemulasikan di flash; perlu EEPROM.begin() dan commit() |
| Raspberry Pi Pico | RP2040 | Tidak ada | Berupa 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:
| Perintah | Fungsinya | Ukuran | Keausan |
|---|---|---|---|
| EEPROM.read(alamat) | Membaca satu byte (0–255) | 1 byte | Tidak ada, membaca itu gratis |
| EEPROM.write(alamat, nilai) | Menulis ulang byte di setiap pemanggilan | 1 byte | Memakai satu siklus di setiap pemanggilan |
| EEPROM.update(alamat, nilai) | Membaca dulu, menulis hanya kalau nilainya berbeda | 1 byte | Hanya ketika nilainya berubah |
| EEPROM.put(alamat, data) | Menulis int, float, array, atau struct byte demi byte; di dalamnya memakai update | sizeof(data) | Hanya byte yang berubah |
| EEPROM.get(alamat, variabel) | Membaca kembali apa yang ditulis put, dengan tipe yang sama | sizeof(variabel) | Tidak ada |
| EEPROM[alamat] | Akses gaya array; membaca gratis, menetapkan nilai dengan = sama seperti write | 1 byte | Setiap penetapan nilai |
| EEPROM.length() | Mengembalikan ukuran total EEPROM | - | Tidak ada |
Sketch pertama: menulis dan membaca EEPROM
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 data | Ukuran di Uno | Rentang | Contoh penggunaan |
|---|---|---|---|
| byte, bool, char (tipe 8-bit) | 1 byte | 0–255, true/false, atau satu karakter | Status nyala/mati, pilihan mode |
| int | 2 byte | −32.768 sampai 32.767 | Offset kalibrasi |
| unsigned int, uint16_t | 2 byte | 0–65.535 | Skor tertinggi game |
| long, unsigned long (tipe 32-bit) | 4 byte | Sekitar ±2,1 miliar atau 0–4,29 miliar | Penghitung jangka panjang |
| float | 4 byte | Presisi 6–7 digit | Faktor kalibrasi sensor |
| char array[10] | 10 byte | 9 karakter ditambah karakter penutup | Kata sandi, nama perangkat |
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 ditulis | Perkiraan umur |
|---|---|
| write() di loop() tanpa delay (sekitar 300 kali per detik) | 5–6 menit |
| Setiap detik | Sekitar 28 jam |
| Setiap menit | Sekitar 69 hari |
| Setiap 10 menit | Sekitar 1,9 tahun |
| Sekali per jam | Sekitar 11 tahun |
| 10 kali sehari | Sekitar 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.
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.
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.
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.
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:
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?.
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() {}| Perintah | Fungsinya |
|---|---|
| prefs.begin("nama", false) | Membuka namespace; false berarti baca dan tulis, true berarti hanya baca |
| putUInt, putInt, putFloat, putBool, putString, putBytes | Menyimpan 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.
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.
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
| Gejala | Penyebab | Solusi |
|---|---|---|
| Boot pertama membaca 255, -1, 65535, atau nan | EEPROM belum pernah ditulis; sel kosong bernilai 0xFF | Tulis nilai bawaan kalau pemeriksaan angka ajaib atau 0xFF gagal |
| Menulis 300, terbaca 44 | write() dan read() hanya membawa 1 byte | Pakai put() dan get() untuk data multi-byte |
| Dua nilai saling merusak | Alamatnya tumpang tindih; int memakai 2 byte, float 4 | Buat peta alamat dan hitung alamat dengan sizeof |
| Teks berubah jadi sampah setelah restart | Objek String ditulis dengan put() | Simpan teks sebagai char array |
| Kode baru membaca pengaturan proyek lama | Upload biasa tidak menghapus EEPROM | Pakai angka ajaib dan field versi, atau hapus EEPROM |
| Pengaturan hilang setelah upload | Upload dengan programmer di Uno, opsi Erase All Flash di ESP32 | Upload biasa lewat USB, atur opsi ESP32 ke Disabled |
| Nilai tidak tersimpan di ESP32 | EEPROM.begin() atau EEPROM.commit() tidak ada | Tambahkan keduanya, atau beralih ke Preferences |
| Preferences selalu mengembalikan nilai default | Membaca dengan tipe berbeda, nama lebih dari 15 karakter, atau namespace berbeda | Samakan 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 lama | Penulisan terus-menerus di loop() atau tegangan catu daya turun ketika sedang menulis | Pakai update() dan penyimpanan tertunda, tambahkan ring buffer dan CRC |
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.
Proyek untuk dibuat setelah membaca ini
Lihat semua proyek
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

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

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

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

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

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

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

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.
Artikel lainnya
Aplikasi BlueGrays
Rakit rangkaian ini langkah demi langkah di ponselmu
Skema pengkabelan, kode, dan daftar komponen dalam satu layar. 200+ proyek Arduino, ESP32, dan Pico siap dibuat.
Pindai dengan ponselmu
Arahkan kamera ke kode ini dan toko aplikasi di ponselmu akan terbuka.
atau buka toko aplikasi

