יום שישי, 17 בינואר 2014

Arduino And EEPROM


שנה חדשה נפתחה בבלוג, היא עמוסה באתגרים חדשים את זה אני יכול להבטיח לכם, את המאמר הראשון השנה החלטתי להקדיש לכוכב מהשנה שעברה, הפעם נתעסק בכיצד ניתן להרחיב את הזיכרון המוגבל ב Arduino שהוא 32K בלבד.

דרישות

  • Arduino Uno
  • 24LC256 EEPROM
  • Wires
  • Breadboard




EEPROM - Electrically Erasable Programmable Read-Only Memory

אין ספק שהשם מפוצץ אבל בסופו של דבר מדובר ביחידת זיכרון שמאפשרת לשמור על המידע גם כאשר המכשיר כבוי, הרכיב שבחרתי עליו להדגים הוא 24LC256 שמאוד נפוץ במחיר 2 $ בלבד מאפשר לנו להרחיב את הזיכרון בעוד 256K ,הוא אינו נדיף בניגוד ל Ram ובנוסף הכתיבה והקריאה הן ברמת Bit בודד בניגוד לזיכרון Flash שלצורך שינוי ביט אחד יש לקרוא בלוק של מידע ,לטעון אותו לזיכרון ה Ram, לעשות את השינוי ולכתוב בחזרה ל Flash מה שהופך את העסק למסורבל אבל חיוני מאוד למידע בנפחים גדולים.

256K של זיכרון לא נדיף
הרגליים האנלוגיות (A5, A4) ב Arduino Uno מאפשרות לעבוד בתקשורת I2C Inter-Integrated Circuit שדומה מאוד ל SPI שראינו במאמר Arduino and MicroSD ההבדל העיקרי הוא שב SPI עבור כל רכיב נצטרך רגל אחת מה Arduino לעומת I2C שבו כל הרכיבים מתחברים לאותן כניסות בלוח ובקלות ניתן להוסיף עוד רכיבים, מדובר על 2 רגליים שבעזרתן מייצרים Bus הרגל הראשונה היא השעון, והשניה ל Data, לכל רכיב יש כתובת ייחודית שדרכה מתחברים בעזרת הממשק.

המון חיבורים עם 2 רגליים בלבד

קוד

החלטתי לתת דוגמה קצת יותר מורכבת מאשר כתיבה וקריאה של ערך בודד אלא לכתוב ולקרוא מחרוזות, ניתן לכתוב ולקרוא  16bytes  בלבד בכל פעם לכן יש להתקדם בכתובות בזיכרון בעזרת חלוקה ל Pages. 

#include <Wire.h>

//unique address for the eeprom 24LC256
#define eeprom1 0x50 
#define readblock 100
#define pageblock 16

//size of the message
unsigned char length = 0;
//receive data buffer
unsigned char rdata[readblock];

 
void setup(void)
{
  //example of parsable string
  unsigned char str_data[]={"{message:this is working! using EEPROM}\n"};

  Serial.begin(9600);

  //Active I2C interface
  Wire.begin();

  //writing  data to 24LC256
   writeData(str_data);
}

 void loop(){

    Serial.println("DATA READ");
 
    //reading data to 24LC256 
    readData(rdata,readblock);
    Serial.write(rdata,readblock);

    delay(1000);
}


void writeData( unsigned char * str_data)
{

  unsigned char pages = 0;
  unsigned char offset = 0;
  unsigned char index = 0;
  unsigned char counter = 0;

  //get the length of data
  length = getStrLength(str_data);
  //get the number of page to write
  pages = length / pageblock;

  //make the magic
  for(index = 0; index <= pages;index++)
  {
       //connecting to the device
       Wire.beginTransmission(eeprom1);
 
       //set the position of writing,
       Wire.write((int)((offset) >> 8));   //MSB -  Most significant bit
       Wire.write((int)((offset) & 0xFF)); // LSB - Least significant bit
     
       //total bytes writed to jump the next page address
       unsigned char i= 0;
     
       for(i= 0; i < pageblock;i++)
        {
                //writing the char to the memory unit.
                Wire.write((byte) str_data[counter]);
 
                //if counter equal data length quit!
                if(counter == length)
                      break;
                   
                 //increment the total counter of length
                 counter++;                
        }
   
       //end I2C transmission
        Wire.endTransmission();
     
        //move offset to the next page  
        offset += i;
     
        //give it some time...
        delay(10);
     
  }

}

 void readData(unsigned char* data, unsigned int length)
 {
 
   unsigned char offset = 0;
   unsigned char counter = 0;
 
   //start reading pages until new line break
  while(true)
  {
     //total bytes writed to jump the next page address 
     unsigned char i=0;
      Wire.beginTransmission(eeprom1);
   
      //set position of reading
      Wire.write((int)(offset >> 8));   //MSB -  Most significant bit
      Wire.write((int)(offset & 0xFF)); //LSB - Least significant bit
   
     //end I2C transmission
      Wire.endTransmission();

       //request data from device
      Wire.requestFrom(eeprom1,length);

      while(Wire.available())
      {
          //write char to position data
          data[counter] = Wire.read();
       
          //end of message!
          if(data[counter] == '\n')
          {
              return;
          }
       
         i++;
         counter++;
     }
   
     offset+=i;
     delay(10);
  }
}

 //get the length from chars array
 unsigned char getStrLength(unsigned char * data)
 {
   unsigned char str_len=0;
    do{ str_len++; } while(data[str_len]);
    return str_len;
 }



מבנה סופי



סיכום

אפשרות הרחבת הזיכרון מאפשרת  לשמור מידע יעודי עבור התוכניות שלנו ועדיין להשאיר מספיק מקום לקוד ב Arduino, החיבור עצמו פשוט ומאפשר לתפעל מספר רכיבים מבלי לבזבז רגליים, ממשק I2C נפוץ מאוד ויש בו שימוש רחב במוצרים רבים לכן חשוב להכיר אותו.

שנה חמישית, ואו!


אין תגובות:

הוסף רשומת תגובה