Nick Chung gửi vào
- 68825 lượt xem
Bấy lâu nay bạn đã sử dụng sai eeprom của arduino? ..Một ngày bạn sử dụng eeprom bao nhiêu lần? Có bao giờ bạn lo lắng tới tuổi thọ của EEPROM ?
EEPROM là còn được hiểu như một thẻ nhớ có thể lưu trữ dữ liệu ngay cả khi mất điện.
Bộ nhớ EEPROM có sẵn của arduino có số lần ghi/xóa 100000 lần, nếu dùng hết số lần ghi cho phép, eeprom sẽ hỏng. Để khắc phục điều này, chúng ta cần sử dụng một ic eeprom ngoại vi thay vì sử dụng eeprom của arduino.
Tuổi thọ của eeprom.
Tuổi thọ của eeprom trên các dòng AVR từ 10000 đến 100000 lần xóa/ghi, đó là con số do nhà sản xuất đưa ra.
Trong quá trình xóa/ghi dữ liệu, các ô nhớ của eeprom sẽ bị “ bào mòn” dần, một cách tương đối, khi vượt quá giới hạn trên, dữ liệu không còn được lưu trữ chính xác nữa. Các bạn đều biết, dữ liệu mà sai một li, thì kết quả đi một dặm. Do đó quan ngại và giải quyết vấn đề về độ bền của eeprom trên arduino là vô cùng quan trọng.
Hướng giải quyết: Sử dụng ic eeprom.
Cùng tìm hiểu nào!
Đầu tiên bạn nên nhớ vài điều này:
- Ô nhớ trên eeprom bị bào mòn dần khi ta thực hiện thao tác ghi dữ liệu hoặc xóa dữ liệu.
- Nếu chỉ đọc dữ liệu thì không ảnh hưởng đến tuổi thọ của eeprom.
- Không sớm thì muộn bạn cũng cần phải biết cách sử dụng eeprom ngoại vi thay vì eeprom có sẵn trên arduino.
Giới thiệu về memory ic – eeprom. 24cxx và cách sử dụng
Về chức năng và cách thức ghi dữ liệu giống với eeprom trên arduino. Nó thường đi kèm với mọi loại thiết bị số ngày nay để lưu trữ các cài đặt trên thiết bị. IC epprom 24Cxx ở nước ta rất dễ tìm mua và nó cũng rất phổ biến trong làng arduino/mcu trên thế giới. Sử dụng dễ dàng, giá thành hợp lí.
Dòng ic 24Cxx của atmel sử dụng chuẩn kết nối 2 dây I2c
Có nhiều chủng loại tùy theo dung lượng cho bạn lựa chọn: 24c01, 24c02, 24c04,..vv
Số lần ghi/xóa là 1 triệu lần, gấp cả chục lần arduino.
Vì là ic ngoại vi nên bạn có thể dễ dàng thay thế, nâng cấp, vận chuyển, và cả cộng gộp sức mạnh của các eeprom.
PINOUT
A0
|
3 chân này để đặt địa chỉ
|
A1
|
|
A2
|
|
GND
|
Nối xuống 0v
|
5V
|
Nối lên 5v
|
WP (write protect)
|
Cho phép ghi dữ liệu: Nối chân này xuống 0v
|
Không cho phép ghi dữ liệu: Nối lên 5v.
|
|
SCL (Serial Clock)
|
2 chân cho giao tiếp i2c.
|
SDA (Serial DATA)
|
Giao tiếp với arduino
Chuẩn bị phần cứng:
- 1 Arduino uno r3
- 1 ic eeprom 24Cxx loại bất kì, trong ví dụ là ic 24c04.
- 2 điện trở 4.7k (hoặc 10k)
- Dây nối, máy hàn…
Thư viện
Đây là thư viện đa năng, nó được dùng cho mọi loại ic eeprom 24cxx.
Tải về tại đây: Link
Nối dây
Tạo một module i2c như thế này:
C1: Với arduino thường
Trên arduino r3, 2 chân A4 và A5 được nối ra 2 jack chuyên biệt. SDA và SCK.
Sử dụng thư viện
Thủ tục khai báo
#include <Wire.h>//b1 #include <Eeprom24Cxx.h>//b2 static Eeprom24C eeprom(4,0x50);// b3
B1, B2: cài 2 thư viện. (bạn có thể bỏ đi dòng #include <Wire.h>)
B3:
Static
|
Eeprom24C
|
eeprom
|
4
|
0x50
|
Biến tĩnh
|
Tên class
|
Tạo và quản lí đối tượng có tên “eeprom”
|
Mã ic: 04
|
Địa chỉ của ic.
|
Mã ic nói lên dung lượng của ic eeprom đó (số Page của ô nhớ).
Ta từng biết arduino atm128 có thể lưu 512 biến byte, atm328 có thể lưu 1024 biến byte.
ATmega 48A/PA
|
ATmega 88A/PA – 168A/PA
|
ATmega328/P
|
ATmega 640/V-1280/V-1281/V-2560/V-2561/V
|
256 bytes
|
512 bytes
|
1 Kbytes
|
4 Kbytes
|
Công thức để tính dung lượng của eeprom là : Số byte=( 1024 * mã ic)/8=128 * mã ic.
Bảng 1. Bảng tra dung lượng chip nhớ 24cx
Tên ic
|
Mã (số page)
|
Dung lượng
|
24c01
|
1
|
128 bytes
|
24c02
|
2
|
256 bytes
|
24c04
|
4
|
512 bytes
|
24c08
|
8
|
1024 bytes
|
24c16
|
16
|
2048 bytes
|
24c32
|
32
|
4096 bytes
|
24c64
|
64
|
8192 bytes
|
24c128
|
128
|
16384 bytes
|
24c256
|
256
|
32768 bytes
|
Vân vân…
Địa chỉ của ic
Tất cả các ic đều có địa chỉ: 0x50. Khi ta nối các chân A0,A1,A2 xuống Low(0v).
Địa chỉ để làm gì?? Nó giúp arduino tìm đến chip eeprom trong giao tiếp i2c thui.
Ghi dữ liệu
void write_1_byte(unsigned int memory_address, byte data);
Ex: eeprom.write(500,123);
Ghi vào byte thứ 500 giá trị bằng 123
Đọc dữ liệu
byte read_1_byte(unsigned int memory_address);
Ex: byte data= eeprom.read(500); Serial.println(data);
Bảng 2. Tra cứu địa chỉ đánh số dung lượng
Tên ic
|
Dung lượng
|
memory_address
|
24c01
|
128 bytes
|
0->127
|
24c02
|
256 bytes
|
0->255
|
24c04
|
512 bytes
|
0->511
|
24c08
|
1024 bytes
|
0->1023
|
24c16
|
2kb
|
0->2047
|
24c32
|
4kb
|
0->4095
|
24c64
|
8kb
|
0->8191
|
24c128
|
16kb
|
0->16383
|
24c256
|
32kb
|
0->32767
|
24c512
|
65,5 kb
|
0->65635
|
Ví dụ mẫu
Code test đầy đủ: ic 24c04
Các bạn lưu ý nhớ chọn đúng mã ic trên eeprom của bạn nhé.
#include <Wire.h> #include <Eeprom24Cxx.h> static Eeprom24C eeprom(4,0x50);// mình chọn 24c04. void setup() { Serial.begin(9600); const int address = 500; eeprom.write_1_byte(address, 123); delay(5); byte data = eeprom.read_1_byte(address); Serial.print("Read byte = "); Serial.print(data); Serial.println(""); } void loop() { }
Trạng thái ô nhớ
Cách lưu số lớn hơn kiểu byte ( >255) vào eeprom
Như ví dụ trên, số 123 (0->255) cần 8bit để lưu trữ, giờ để lưu một số lớn hơn 255 ( từ 16 bit trở lên) thì ta sẽ làm như sau:
Gỉa sử mình cần lưu số 345 vào eeprom ở ô địa chỉ 500.
#include <Wire.h> #include <Eeprom24Cxx.h> #define type_ic 4 static Eeprom24C eeprom(type_ic,0x50); void setup() { Serial.begin(9600); unsigned int a=345; } void loop() {}
Đầu tiên ta biết số 345 được biểu diễn nhị phân là 0x0000000101011001.
B1: Ghi
Tách lấy 8bit cao (00000001) lưu vào ô địa chỉ 500.
Tách 8 bít thấp (01011001) lưu vào ô 501.
B2: đọc
Code thực thi
#include <Wire.h> #include <Eeprom24Cxx.h> #define type_ic 4 static Eeprom24C eeprom(type_ic, 0x50); void setup() { Serial.begin(9600); unsigned int a = 345; //ghi byte cao_8 = ((a >> 8) & 0xFF); eeprom.write_1_byte(500, cao_8); delay(5); byte thap_8 = (a & 0xFF); eeprom.write_1_byte(500 + 1, thap_8); delay(5); // đọc byte doc_cao_8, doc_thap_8; doc_cao_8 = eeprom.read_1_byte(500); // 0000,0001 doc_thap_8 = eeprom.read_1_byte(501); // 0101,1001 unsigned int doc_a; // khai báo// 0000,0000,0000,0000 doc_a = (doc_cao_8 << 8); //0000,0001,0000,0000 doc_a = doc_a | doc_thap_8; //0000,0001,0101,1001 Serial.print(doc_a); } void loop() { }
Một điều cần lưu ý
- Số muốn lưu phải là nguyên dương.
- Gỉa sử địa chỉ mà chúng ta muốn lưu là ô 500, khi dùng để lưu một biến có cỡ 2byte thì ô 501 nghiễm nhiên đã bị sử dụng để lưu 8 bit còn lại, do đó, mặc định bạn không được dùng ô 501 để làm địa chỉ lưu , mà phải bắt đầu từ ô 502, bạn nhớ nhé.
- Phải xem sét việc ghi nhiều byte có đang ghi trùng lên các ô khác hay không. Ví dụ ô 500 đã có dũ liệu,Ta dùng ô 488 để lưu 4 byte, việc này sẽ ghi đè dữ liệu vào ô 500, gây sai lệch.
- Kích cỡ lưu trữ của biến trên arduino và arduino mega khác nhau, Ví dụ kiểu double trên uno là 4 bytes nhưng trên arduino due là 8 bytes, do đó kích cỡ để lưu cũng khác.
Đây là toàn bộ hàm hỗ trợ ghi theo kiểu dữ liệu mong muốn.
- void write_1_byte( unsigned int address, byte data);
- byte read_1_byte( unsigned int address);
- uint16_t read_2_byte( unsigned int address);
- void write_2_byte( unsigned int address, uint16_t data);
- void write_4_byte( unsigned int address, uint32_t data);
- uint32_t read_4_byte( unsigned int address);
- void write_8_byte( unsigned int address, uint64_t data);
- uint64_t read_8_byte( unsigned int address);
Như đã đề cập, các kiểu dữ liệu trên các dòng arduino có thể không giống nhau, để biết kiểu dữ liệu (trên arduino của bạn ) chiếm bao nhiêu byte, chúng ta dùng hàm sizeof();
Ví dụ: kiểu “unsigned int” trên arduino uno r3 chiếm 2 byte.
void setup() { Serial.begin(9600); unsigned int a = 4002; Serial.print(sizeof(a)); } void loop() { }
Code test lưu các số trên arduino uno r3
#include <Wire.h> #include <Eeprom24Cxx.h> #define type_ic 4 static Eeprom24C eeprom(type_ic, 0x50); void setup() { Serial.begin(9600); byte a = 255; unsigned int b = 62770; unsigned long c = 4000000000; //4 tỷ eeprom.write_1_byte(0, a); eeprom.write_2_byte(10, b); eeprom.write_4_byte(40, c); Serial.println(eeprom.read_1_byte(0)); Serial.println(eeprom.read_2_byte(10)); Serial.println(eeprom.read_4_byte(40)); } void loop() { }
Thư viện này còn có thể làm điều tương tự trên eeprom của arduino.
Bạn truy cập các phương thức với tên thực thể là: AVR_EEPROM.
Đồng thời không khai báo ic eeprom, thư viện sẽ tự hiểu là chúng ta đang muốn dùng eeprom trên arduino.
- void write_1_byte( unsigned int address, byte data);
- byte read_1_byte( unsigned int address);
- uint16_t read_2_byte( unsigned int address);
- void write_2_byte( unsigned int address, uint16_t data);
- void write_4_byte( unsigned int address, uint32_t data);
- uint32_t read_4_byte( unsigned int address);
- void write_8_byte( unsigned int address, uint64_t data);
- uint64_t read_8_byte( unsigned int address);
#include <Wire.h> #include <Eeprom24Cxx.h> void setup() { // viết và ghi dữ liệu lên eeprom của arduino Serial.begin(9600); byte a = 255; unsigned int b = 62770; unsigned long c = 4000000000; //4 tỷ AVR_EEPROM.write_1_byte(0, a); AVR_EEPROM.write_2_byte(10, b); AVR_EEPROM.write_4_byte(40, c); Serial.println(AVR_EEPROM.read_1_byte(0)); Serial.println(AVR_EEPROM.read_2_byte(10)); Serial.println(AVR_EEPROM.read_4_byte(40)); } void loop() { }
Hoàn thiện kĩ năng
100.000 lần ghi/xóa của arduino hay 1 triệu lần của ic 24Cxx đều là con số lớn. Lớn đến vậy mà chuyện ghi/xóa vô tội vạ cũng khiến bạn phải thường xuyên thay thế 1 ic eeprom mới.
Mình xin gợi ý một vài thủ thuật để nâng cao tuổi thọ và tốc độ cho ic eeprom:
- Vì bạn có thể đọc thoải mái dữ liệu mà không làm giảm tuổi thọ, nên trước khi ghi, bạn hãy kiểm tra xem dữ liệu đưa vào, nếu trùng khớp với dữ liệu cũ thì không cần ghi. (Cái này thư viện đã hỗ trợ rồi ).
- Nếu được, bạn hãy thường xuyên thay đổi vị trí ghi, để san sẻ số lần ghi cho các ô nhớ khác, nó giúp ta tránh việc phải vứt cả ic eeprom chỉ vì một hai ô nhớ bị hỏng.
- PIN số 7 (wp) trên ic giúp ta ngăn việc ghi dữ liệu bằng cách nối chân này lên HIGH (5v).
- Để tốc độ được nhanh, nếu phải liên tục đọc lại dữ liệu ở cùng một ô nhớ trên eeprom, bạn hãy khai báo một biến, gán cho nó giá trị tại ô nhớ cần đọc, rồi chỉ đọc trên biến đó thôi.
- Phải delay ít nhất 5 mili giây(ms) sau khi ghi để đảm bảo dữ liệu được lưu hoàn toàn.
- Bạn không cần thiết phải ghi dữ liệu lên eeprom, hãy lưu tạm dữ liệu vào ram (khai báo một biến rồi thực hiện tính toán như bình thường cho biến đó), khi thật sự cần thiết thì mới cho lưu eeprom. Cách này thường dùng để tránh mất mát dữ liệu đang tính toán khi có sự cố mất điện. Cái này bạn có thể tìm hiểu thêm.
Vọc vạch..
Bạn muốn dung lượng cao hơn??
Tất nhiên là có ic cho bạn 24c1024. (1mb)
IC eeprom 24Cxx tháo máy !!!
Do mình viết lại thư viện, để đảm bảo tính chất lượng, nên đã mình đặt mua các loại ic khác nhau về để test trước khi đăng lên arduino.vn. Tuy nhiên trước đó, mình đã từng vọc loại ic eeprom này ở khá nhiều thiết bị khác nhau
Tivi có chú 24c04, tivi nào cũng có cả, mình nghĩ chúng để lưu các cài đặt của người dùng .
Cái main tivi cũ kĩ này cũng có cái để vọc đấy^^
Trên thanh ram có ic 24C02.
Trên card mạng có để lưu địa chỉ MAC, bạn nào có ý định thay địa chỉ MAC để thành HACKER thì đúng bài rồi ..hehe (Cái này mình không khuyến khích đâu nhé ).
Trong cái ổ VCD của máy tính có chú 93c865 cơ ^^
Hầm hố nhất đây: 39sf512 (4mb), at49f001(1mb)
Module Ic thời gian thực cũng có nhé.
Tất nhiên các eeprom trên đều đã có “tuổi”, nếu không tin tưởng nên mua mới ic thay vì dùng lại như trên.
Tự chế một module.
Vì ic nhỏ gọn, nên có thể bạn sẽ cần dùng nó giống như một usb eeprom. Hãy chế theo cách của bạn.
ở phiên bản này, mình có thêm led và tranzitor PNP -D8550 đèn sẽ sáng khi có tín hiệu mức thấp, báo là đang có truyền dẫn data.
Download thư viện.
Tải lên lần 1 ( 9:16 pm16/12/2016 ):
https://drive.google.com/file/d/0BzMEcyRK_uUFUl9tUHRZVVBYOHc/view?usp=sharing
Thư viện này hỗ trợ eeprom ic 24Cxx từ 24c01->24c512.
Với những bạn gặp lỗi này : Arduino/libraries/Eeprom24Cxx/Eeprom24Cxx.cpp:131: error: 'EEPROM' was not declared in this scope
Là do bản IDE của bạn chưa có thư viện "EEPROM.h" Có 2 cách giải quyết:
- Bạn hãy cập nhật bản IDE mới nhất cho máy tính của mình.
- Hoặc bạn tải thêm thư viện EEPROM.h tại địa chỉ : https://drive.google.com/file/d/0BzMEcyRK_uUFbjF2SXhlY3NOanM/view?usp=sharing
Hãy liên hệ với mình nếu thư viện có bất cứ lỗi cài đặt nào.
BUS IC
Dòng ic 24cxx có địa chỉ nằm trong khoảng 1010A2 A1A0 ( 0x50->0x57), có nghĩa là ta có thể có tới 8 ic eeprom dùng chung một bus i2c. Vậy bạn có muốn độ eeprom thành super eeprom không??. Hãy đón đọc bài tiếp theo nhé. Bài 2: Sử dụng cùng lúc nhiều ic eeprom 24Cxx trên bus
Cái kết có hậu
Có lẽ sau khi ta sử dụng được ic này rồi, hẳn sẽ thấy nó không quá khó. Đặc biệt hơn, chúng ta sẽ không còn phụ thuộc vào cái eeprom của arduino, và tất nhiên là bạn đã lên level rồi đấy.
Hi vọng bài viết hữu ích và bạn thấy thích bài viết này.
Tác giả: Thái Sơn.