EEPROM در آردوینو – آموزش آردوینو جلسه نهم
EEPROM چیست؟
این اولین سوالیه که باید بهش جواب بدیم و بعد بریم سراغ تابع های EEPROM در آردوینو.
EEPROM مخفف Electrically Erasable Programmable ROM هستش ، و از اسمش مشخصه دیگه ! یک نوع حافظه است و با سیگنال های الکتریکی قابلیت پاک شدن و برنامه ریزی مجدد رو داره و اطلاعات این نوع حافظه ها دائمی هستش و بعد از قطع تغذیه حفظ میشه.
میکورکنترلرهای AVR مقدار اندکی حافظه ی EEPROM دارن. مثلا مگا8 512بایت داره، و آی سی های دیگه که ممکنه بدردمون بخورن هم میزان حافظشون به شرح زیره:
ATmega328 : 1024 bytes
ATmega168 و ATmega8 : 512 bytes
ATmega1280 و ATmega2560 : 4 KB (4096 bytes)
Genuino 101 boards have an emulated EEPROM space of 1024 bytes
توضیحات خاصی نداره این حافظه ها ولی باید بدونین هر میکرویی که توی بردتون استفاده شده یا حافظه خارجی ای که متصل کردین چقدر ظرفیت داره تا بتونین هر خونه رو به درستی مدیریت کنید.
تابع های کتابخونه EEPROM.h رو بریم که بشناسیم 😉
تابع های EEPROM در آردوینو
تابع EEPROM.write
این تابع برای نوشتن داده ی هشت بیتی (1 بایت) در آدرس مشخص شده به کار میره:
EEPROM.write(addr,val);
ورودی اول (addr) تابع آدرس حافظه ورودی هستش و
(val) داده ای که میخواین توی اون خونه از حافظه بنویسید.
مثلا فرض کنیم 512 بایت حافظه EEPROM داریم ، پس 0 تا 511 تا آدرس خونه حافظه داریم.
طبق گفته ی بخش EEPROM سایت آردوینو ، نوشتنر EEPROM در آردوینو حدود 3.3ms طول میکشه.
و باید اینو هم بدونیم که طول عمر EEPROM حدود 100 هزار بار نوشتن/پاک کردن هست، پس توی پروژتون این نکته رو فراموش نکنید 😉
مثال ها : برنامه ی پاک کردن تمام خانه های EEPROM در آردوینو: (بعد از پاک کردن تمامی خونه ها led پایه ی 13 رو روشن میکنم برای تایید انجام عملیات)
1 2 3 4 5 6 7 8 9 10 |
#include <EEPROM.h> void setup() { // write a 0 to all 512 bytes of the EEPROM for (int i = 0; i < 512; i++) EEPROM.write(i, 0); // turn the LED on when we're done digitalWrite(13, HIGH); } void loop(){} |
این عمل چون یکبار قراره اتفاق بیوفته و دائمی نیست از حلقه ی setup استفاده میکنیم.
تابع EEPROM.update
این تابع مثل write میمونه ، فقط قبل از اینکه مقدار رو روی حافظه ذخیره کنه اون رو میخونه و اگر مقداری که قراره بریزه و مقداری که روی خونه ی حافظه هست با هم برابر باشن ، دیگه اون رو روی خونه ی حافظه نمیریزه .
اینطوری هم زمان 3.3ms از دست نمیره، هم زیاد عمل نوشتن/پاک شدن انجام نمیشه و طول عمر EEPROM رو افزایش میده.
فرمت اونم به شکل زیره:
1 |
EEPROM.update(addr, val) |
addr آدرس خونه ی حافظه مورد نظره.که قراره اونجا اطلاعات ریخته بشه.
val هم مقداریه که قراره توی خونه ریخته بشه.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <EEPROM.h> void setup() { for (int i = 0; i < 255; i++) { // this performs as EEPROM.write(i, i) EEPROM.update(i, i); } for (int i = 0; i < 255; i++) { // write value "12" to cell 3 only the first time // will not write the cell the remaining 254 times EEPROM.update(3, 12); } } void loop(){} |
توی for اول ، شماره ی هر خونه رو توی خودش میریزه، یعنی خونه ی یک برابر یک میشه و خونه ی شماره ده برابر ده . این اتفاق برای خونه های صفر تا 255 میوفته.
توی for دوم، مقدار 12 توی خونه ی 3 ریخته میشه و به 254 خونه ی دیگه کاری نداره!
تابع EEPROM.read
این تابع برای خواندن داده از آدرس تعیین شده به کار میره:
1 |
val = EEPROM.read(addr); |
متغیر addr آدرس خونه ی حافظ ایه که متغیر val توی اون نوشته میشه.
متغیر addr از صفر شروع میشه و تا n-1 ادامه پیدا میکنه که n نشون دهنده ی اندازه EEPROM هستش. و مشخصه که خروجی تابع هم مقدار val هستش که داده رو برمیگردونه.
تابع EEPROM.length
ممکنه یادتون نیاد که بردتون چقدر حافظه EPPROM داره ، با نوشتن این کد براتون مقدار حافظه رو برگشت میده.
تابع EEPROM.get
این تابع برای خوندن همه نوع دیتا (int , float , string & …) از EEPROM در آردوینو کاربرد داره.
1 |
EEPROM.get(address, data) |
address که خونه ی حافظه رو مشخص میکنه و از صفر شروع میشه. (int)
data هم اون اطلاعاتی هست که قراره بخونه ( int یا float یا هر دیتای دیگه میتونه باشه ).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
void setup(){ float f = 0.00f; //Variable to store data read from EEPROM. int eeAddress = 0; //EEPROM address to start reading from Serial.begin( 9600 ); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } Serial.print( "Read float from EEPROM: " ); //Get the float data from the EEPROM at position 'eeAddress' EEPROM.get( eeAddress, f ); Serial.println( f, 3 ); //This may print 'ovf, nan' if the data inside the EEPROM is not a valid float. // get() can be used with custom structures too. eeAddress = sizeof(float); //Move address to the next byte after float 'f'. MyObject customVar; //Variable to store custom object read from EEPROM. EEPROM.get( eeAddress, customVar ); Serial.println( "Read custom object from EEPROM: " ); Serial.println( customVar.field1 ); Serial.println( customVar.field2 ); Serial.println( customVar.name ); } void loop(){ /* Empty loop */ } |
تابع EEPROM.put()
این تابع برای نوشتن همه نوع دیتا (int , float , string & …) روی EEPROM در آردوینو کاربرد داره .
میتونید اعداد اعشاری float و string هم حتی روی eeprom بریزید، فقط باید توجه کنید که هر کدوم از این متغیر ها دیگه 1 بایتی نیستن و فضای بیشتری رو دربر میگیرن. اگه یادتون باشه آموزش برنامه نویسی آردوینو جلسه دوم : متغیر ها و عملگرها فضای اشغالی هر بایت نوشته شده بود.
فرمت کلی این تابع هم به شکل زیره:
1 |
EEPROM.put(address, data) |
address محل ذخیره ی داده هست و
Data اون دیتایی که قراره داخل حافظه ریخته بشه.
این تابع برای نوشتن از قوانین تابع EEPROM.update() تبعیت میکنه. یعنی اگر مقداری که قراره بنویسید با مقداری که قبلا توی اون خونه بوده برابر باشه دیگه مقدار رو مجددا روی اون خونه نمیریزه.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
#include <EEPROM.h> struct MyObject { float field1; byte field2; char name[10]; }; void setup() { Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } float f = 123.456f; //Variable to store in EEPROM. int eeAddress = 0; //Location we want the data to be put. //One simple call, with the address first and the object second. EEPROM.put(eeAddress, f); Serial.println("Written float data type!"); /** Put is designed for use with custom structures also. **/ //Data to store. MyObject customVar = { 3.14f, 65, "Working!" }; eeAddress += sizeof(float); //Move address to the next byte after float 'f'. EEPROM.put(eeAddress, customVar); Serial.print("Written custom data type! \n\nView the example sketch eeprom_get to see how you can retrieve the values!"); } void loop() { /* Empty loop */ } |
تابع []EEPROM
این تابع اجازه میده از EEPROM در آردوینو مثل یک آرایه استفاده کنیم و بتونیم روی اون هم بنویسیم و هم بخونیم.(آرایه اگر یادتون نیست چیه باید توی آموزش های c دنبال مفهومش بگردین ، توی جلسات آخر آموزش C سعی میکنم اونو توضیح بدم)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
EEPROM[address] address : مکانی که میخواید برای خواندن/نوشتن استفاده کنید. #include <EEPROM.h> void setup(){ unsigned char val; //Read first EEPROM cell. val = EEPROM[ 0 ]; //Write first EEPROM cell. EEPROM[ 0 ] = val; //Compare contents if( val == EEPROM[ 0 ] ){ //Do something... } } void loop(){ /* Empty loop */ } |
سلام
من توی یک برنامه حافطه خونه 1تا4 رو 2 کردم ولی توی یک برنامه دیگه نوشتم که اگر خونه 1تا4 ,2بود متغیر a رو برابر با1 بکنه,ولی a تغییری نمی کنه.
چیکار باید بکنم تا این مشکل حل بشه؟؟
ممنون
سلام
خسته نباشید
آیا توی آردوینو حافظه داخلی غیر از eeprom هست که محدودیتی در خواندن و نوشتن نیست؟
اگر هم هست لطف کنید آموزشش رو بذارید.
ممنون
سلام، حافظه فلش هم هست که برنامه داخل اون ریخته میشه. چند دستور برای خوندن و نوشتن داره و استفاده ازش پیچیده نیست.
سلام جناب مهندس
خسته نباشین
اگه بیش از ۱۰۰ هزار بار توی حافظه eeprom خوندن و نوشتن انجام بشه چی میشه؟ رجیسترا اعداد اشتباه رو ذخیره میکنن یا کلاً دسترسی به حافظه مختل میشه؟
و این که اکه این اتفاق افتاد، باید کل برد آردوینو رو عوض کنیم یا فقط تعویض آی سی کافیه؟ یعنی سوالم اینه که حافظه eeprom و رجیسترای مربوط بهش آی سی جدا دارن یا توی همون آی سی اصلیش هست؟
ممنون
سلام. ممنونم
یکبار امتحان کردم و بیشتر از 100هزار بار انجام شد 😀 اما دسترسی به بخشی از حافظه ها بعد 130هزار بار مختل شد و نمیشد خوند و نوشت.
افرادی که با میکرو کارکردن گاهی تجربه اینو دارن که بعضی از پایه ها میسوزن اما میکرو کار میکنه .یعنی فقط بخشی از عملکرد میکرو و رجیستری ها از دسترس خارج میشن.
در آردوینو eeprom بخشی از داخل میکرو هستش و آی سی جداگانه نداره ولی اینجور مواقع اصطلاحا میکرونیم سوز میشه و از عملکرد آیندش نمیشه اطمینان داشت