Arduino
OKUDUĞUNUZ KONU
ARDUINO – EEPROM Okuma ve Yazma Teknikleri
1

ARDUINO – EEPROM Okuma ve Yazma Teknikleri

Yazar : Turgut Güneysu16 Kasım 2018

Merhaba,

Bu yazımda size ARDUINO projelerinizde verileri kaydetmekte yardımcı olacak EEPROM kullanmayı açıklamak istiyorum.

Her tip ARDUINO işlemcisinin içinde değişik ebatlarda EEPROM tipi bellek vardır. Bu belleğin özelliği ARDUINO kapatıldığı zaman bellek içeriklerinin silinmemesidir. Yazdığınız kodlarda bir çalışma devresinden ötekine veri kaydetmek ve yeni devrede bu değerleri kullanmak gerekiyorsa EEPROM işinize yarayabilir.

EEPROM fonksiyonarını kullanabilmek için önce EEPROM.h kütüphanesini programınıza eklemeniz gerekir. Bunu yapar yapmaz bir takım EEPROM işlevlerine ulaşma imkanını elde edersiniz. Bunlardan en basiti bize EEPROM belleğini boyutunu bildiren EEPROM.length() işlevidir:

int eepromBellek = EEPROM.length();

kodu eepromBellek değişkenine kullandığımız ARDUINO modelinin EEPROM boyutunu atar.

Burada dikkat etmemiz gereken bir nokta aldığımız değerin nasıl kullanılacağıdır. EEPROM adresleri sıfır (0) dan başladığı için geri gelen veri değeri adres olarak kullanıldığında sıfır ile eepromBellek – 1 arası olmalıdır. Örneğin: ARDUINO UNO da EEPROM boyutu 1024 dür. Buna göre adres olarak kullandığımızda bu değer 0 – 1023 arasında olmalıdır. Değişik modellerin boyutları değişiktir !

Bu değeri elde ettikten sonra hemen belleği temizlemek için basit bir döngü ile kullanabiliriz:

#include <EEPROM.h>
void setup()  {
  int eepromBellek = EEPROM.length();
  for (int i = 0 ; i < eepromBellek ; i++) {EEPROM.write(i, '\0');}
}

Bu kodda sıfırdan başlayarak bütün bellek adreslerine NUL ( ‘\0’ ) değerini yazıyoruz. Bunu yaparken EEPROM.write() işlevini kullanıyoruz. Burada belleğe yazdığımız değer tamamen bize kalmış bir seçenektir. NUL (\0), SIFIR (0), BOŞLUK ( ), vs gibi herhangi uygun değer kullanılabilir.

EEPROM a yazıp okuma işlemleri üç tip işlevle sağlanır:

  • EEPROM.read() ve EEPROM.write() : karakter veya bayt olarak okuyup yazma
  • EEPROM.get() ve EEPROM.put() : dizgi veya özel / değişik veri yapılarına göre okuyup yazma
  • EEPROM.update() : Eğer veri bellektekinden değişikse yaz

EEPROM.read() ve EEPROM.write() işlevleri verileri belleğe tek bayt olarak okuyup yazarlar. Yani okunacak veya yazılacak değerlerin 0 – 255 arası bir değer olması gerekir. Kodlamada kullanabileceğimiz veri tipleri char ve byte dır.

EEPROM.get() ve EEPROM.put() işlevleri ise belleğe bir bayttan daha fazla veya uzunlukta veri kaydetmek istediğimiz zaman kullanılır. Örneğin float tipi veriler dört (4) bayt olduğundan bu işlevle kaydedilmesi gerekir. Eğer uzunca bir dizgi veya dizi kaydetmek isterseniz (örneğin: “dosyaadı.txt”) bu işlevleri kullanmanız gerekir. Burada dikkat edilecek nokta, dizi veya dizgi yazıp okurken bir seçeneğin döngü ile aynı işlemi yapmaktır. Yani get() veya put() kullanacağımıza, bir döngü ile dizi veya dizgi harflerini teker teker read() veya write() kullanarak da yazıp okuyabiliriz. Tabi ki get() ve put() çok daha kolay bir uygulamadır.

Fakat bu iki teknik arasında önemli bir fark vardır: dizi ve dizgi uygulamalarında char[ ] tipi ARRAY veriler bilgisayar belleğinde genelde otomatikman bir NUL karakter ile sonuçlandırıldığından  get() ve put() işlevleri yazma ve okuma işlemlerini bu noktaya kadar yaparlar. Yani bir NUL bulunca okuma ve yazma durur. Eğer bu sizin işinize göre değilse, o zaman write() veya read() kullanmanız daha uygun olabilir. Mühim olan işlevlerin nasıl çalıştığı ve sizin ne yapmak istediğiniz !

EEPROM ın kullanılma limiti bellek başına 100.000 yazma çevrimi olduğundan bu tip belleğe devamlı veya sonsuz bir döngüde işlem yapmak doğru değildir. Yani ARDUINOnun LOOP() kısmına bu tip kodları yazarken dikkatli olun. Bu problemi çözmek için EEPROM.update() işlevi kullanmalısınız.

EEPROM.update() işlevi yazılacak veriyi yazmak istediğimiz adresteki değer ile karşılaştırır ve yalnız aynı değilse yazma işlemini tamamlar. Böylece lüzumsuz yazma işlemleri engellenmiş olur. Dikkat edilecek nokta bu işlemin yanlız bayt veya karakter modunda çalıştığıdır. Yani bir dizi, dizgi, veya bir bayt tan uzun veri tipleri yazdığımızda bu tekniği bir döngü içinde uygulamamız gerekir.

ARDUINO EEPROM referansına bu bağlantıdan ulaşabilirsiniz.

Yukarıda anlatılan teknikleri uygulayan bir ARDUINO programını sunuyorum:

/*
   EEPROM OKU / YAZ

   EEPROM a DİZİ yazar.

   Yazılan diziyi EEPROM dan okur.
   CRC işlevi içerir.
*/

#include 

int EEPROMboyut = 0;
int addr = 0;                     // EEPROM addresi: 0 dan başlar

char ioString[1024] = " ";        // EEPROM addresses: 0 - 1023
char testDIZI[] = "123456789";    //DİZİ oluştur, uzunluk = 10
char benimDIZIM[] = "Örnek dizi!@@@";


void setup()
{
  EEPROMboyut = EEPROM.length();

  Serial.begin(115200);
  Serial.println(sizeof(testDIZI));
  Serial.println(testDIZI);

  Serial.print(F("\nEEPROM Boyut: "));
  Serial.println(EEPROMboyut);
  Serial.print(sizeof(benimDIZIM));
  Serial.println(benimDIZIM);

  // EEPROM sil - noktayla doldur
  // WRITE() yerine UPDATE() kullaniliyor
  for (int i = 0 ; i < EEPROMboyut ; i++) {
    EEPROM.update(i, '.');
  }
  Serial.println(F("EEPROM silindi:"));
  Serial.println(EEPROM.get(addr, ioString));

  dispCRC();

  // benimDIZIM dizisini EEPROM a yaz - PUT() tekniğiyle.
  // EEPROM noktalarla dolu olmasına rağmen benimDIZIM yazıldığında
  // NUL karakterinin gerisi okunmuyor
  // Eğer 'Dizi sonundaki NUL ı sil' satırını kullanırsanız bütün EEPROM
  // içeriğinin ekrana yazıldığını görürsünüz
  EEPROM.put(addr, benimDIZIM);
  //EEPROM.write(sizeof(benimDIZIM)-1,'*');   // Dizi sonundaki NUL ı sil
  Serial.println(F("EEPROM yazıldı:"));
  Serial.println(EEPROM.get(addr, ioString));

  dispCRC();

  // EEPROM u oku - GET() tekniğiyle.
  // DIZI sonunda NUL olduğundan DIZI gerisi okunamaz
  // Eğer yukarıdaki 'Dizi sonundaki NUL ı sil' satırını açtıysanız
  // o zaman bütün EEPROM okunur
  EEPROM.get(addr, ioString);
  Serial.println(F("EEPROM okuma GET():"));
  Serial.println(sizeof(ioString));
  Serial.println(ioString);

  // EEPROM u oku - READ() tekniğiyle.
  Serial.println(F("\nEEPROM okuma READ():"));
  Serial.print("BAYT olarak yaz:");
  // Okunanları BAYT olarak yaz
  int cols = 0;
  for (int i = 0 ; i < EEPROMboyut ; i++) {
    if (cols<16) {Serial.print(EEPROM.read(i)); Serial.print(" ");cols++; }
    else {Serial.print("\n\t\t");cols=0; }
  }
  Serial.println("\n");
  // Okunanları CHAR olarak yaz
  Serial.print("CHAR olarak yaz:");
  cols = 0;
  for (int i = 0 ; i < EEPROMboyut ; i++) {
    if (cols<16) {Serial.print(EEPROM.read(i)); Serial.print(" ");cols++; }
    else {Serial.print("\n\t\t");cols=0; }
  }
  Serial.println();

}

void loop() {  }

void dispCRC() {
  Serial.print(F("EEPROM veri CRC32 kodu: 0x"));
  Serial.println(eeprom_crc(), HEX);
}

unsigned long eeprom_crc(void) {
  const unsigned long crc_table[16] = {
    0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
    0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
    0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
  };

  unsigned long crc = ~0L;
  for (int index = 0 ; index < EEPROM.length() ; ++index) { crc = crc_table[(crc ^ EEPROM[index]) & 0x0f] ^ (crc >> 4);
    crc = crc_table[(crc ^ (EEPROM[index] >> 4)) & 0x0f] ^ (crc >> 4);
    crc = ~crc;
  }
  return crc;
}

Bununla oynayarak EEPROM kullanmanın ustası olmanızı dilerim.

İyi çalışmalar.

 

SİZCE NASIL OLMUŞ?
Beğendim
75%
İlginç
25%
Eh İşte
0%
Anlamadım
0%
Kötü
0%
Berbat
0%
YAZAR HAKKINDA
Turgut Güneysu
Turgut Güneysu
Anadolu'nun tam ortasında ufak bir köyden memleketimizin çocuklarına STEM programlarına uygun bilgisayar, robotik, yazılım, donanım, mikro işlemciler hakkında yardımcı olmaya çalışıp, emekli hayatımın zevkini çıkarıyorum. Gençlerimizin kabiliyetlerinin sonsuz olduğuna ve onları doğru yönlendirirsek değerli katkılarla ortamımızı dünya çapına ulaştıracaklarına inanıyorum.
1 YORUMLAR

YORUM YAP