Làm thế nào để ghi nhớ các giá trị biến sau khi khởi động lại bo mạch Arduino Uno R3?


7

Có cách nào để lưu trữ các giá trị của các biến cần thiết ở đâu đó (có thể trong một tệp được chương trình cập nhật tại các sự kiện khác nhau), có thể đọc lại khi chương trình bắt đầu sau khi khởi động lại bo mạch Arduino không?

Tôi đang cố gắng điều khiển các thiết bị AC của mình bằng điều khiển từ xa IR. Nơi tôi muốn Arduino nhớ những gì đã xảy ra và những gì đã tắt trong phòng của tôi sau khi mất điện.

Sử dụng EEPROM có vẻ như là một giải pháp khá tốt, mặc dù nó có giới hạn 100.000 ghi, điều này khiến tôi cố gắng tìm một lối thoát khác.

Sử dụng EEPROM bên ngoài không có giới hạn hoặc khá lớn, là một ý tưởng thực sự tốt mà tôi có được từ fuenfundachtzig, cảm ơn vì ý tưởng tuyệt vời này. Nhưng tôi không biết làm thế nào để thực hiện điều này trong dự án của mình. Bất kỳ tài nguyên nào để thu thập kiến ​​thức về việc sử dụng EEPROM bên ngoài, sẽ được đánh giá cao.

Cảm ơn tất cả...


Nếu bạn chỉ quan tâm đến việc khởi động lại, và không chạy xe đạp, thì bạn có thể sử dụng RAM - bạn chỉ cần giữ bất kỳ mã init nào không xóa sạch nó. Tất nhiên, nếu bạn cần sống sót sau khi đạp xe, thì bạn cũng cần EEPROM.
Chris Stratton

Thật ra tôi rất quan tâm đến việc đạp xe. Tôi đang cố gắng điều khiển các thiết bị AC của mình bằng điều khiển từ xa IR. Nơi tôi muốn Arduino nhớ những gì đã xảy ra và những gì đã tắt trong phòng của tôi sau khi mất điện.
Samik Hayopadhyay

Câu trả lời:


6

RAM bên trong của Arduino sẽ được thiết lập lại khi bạn cấp lại chip, vì vậy nếu bạn muốn giữ dữ liệu của mình, bạn cần lưu trữ nó trong EEPROM.

Nếu bạn lo lắng về chu kỳ ghi / xóa giới hạn, bạn nên ước tính tần suất dữ liệu sẽ được cập nhật (tức là ghi vào EEPROM) và thời gian bạn lên kế hoạch cho thời gian sử dụng của thiết bị. Nếu 100.000 chu kỳ vẫn là một vấn đề, bạn có một số tùy chọn:

  • Giữ các biến trong RAM và chỉ ghi chúng vào EEPROM sau mỗi 5 phút (100.000 chu kỳ sau đó thực hiện khoảng một năm sử dụng liên tục cho đến khi EEPROM có thể thất bại).
  • Sử dụng EEPROM bên ngoài (trong ổ cắm) có thể dễ dàng thay thế nếu cần.
  • Nếu thay thế nó không phải là một tùy chọn, hãy xem xét sử dụng FRAM thay thế (lợi thế so với EEPROM: chu kỳ xóa / ghi nhiều hơn nhưng cũng rất tốn kém, vì vậy không phải là một tùy chọn cho số lượng lớn dữ liệu nhưng chắc chắn cho một vài biến).

Tuy nhiên, lưu ý rằng mô tả của bạn nghe giống như trường hợp sử dụng thông thường cho cài đặt người dùng mà bạn không muốn bị mất khi khởi động lại. Đối với những người, EEPROM nội bộ là nơi thích hợp: chỉ lưu trữ chúng khi chúng được thay đổi và bạn là vàng - người dùng sẽ không thay đổi chúng dễ dàng 100.000 lần ...


Tôi thường sử dụng cho loại điều này một EEPROM bên ngoài; một cái gì đó giống như AT24C02 hoạt động tốt cho hầu hết các dự án (nó là 256 byte). Tôi chỉ thích bộ nhớ ngoài vì nó kéo dài nhiều chu kỳ R / W hơn và bởi vì bạn có thể thay đổi nó nếu nó không hoạt động nữa.
Stefa168 17/05/2015

Ram không được xóa Các biến toàn cục được đặt thành 0 theo tiêu chuẩn 'c'. Ram không sử dụng giữ giá trị của nó trong quá trình thiết lập lại.
Ghi

Vâng, bạn đúng. Tôi đã suy nghĩ về sự cố mất điện dẫn đến mất dữ liệu trong RAM (và điều này làm cho việc tái cấp phép là cần thiết).
fuenfundachtzig

những gì về việc sử dụng đầu đọc sdcard. không quá đắt và sdcard sẽ sống rất nhiều thời gian.
m3nda

2

Bộ nhớ EEPROM có vòng đời được chỉ định là 100.000 chu kỳ ghi / xóa, do đó, sử dụng EEPROM có thể là một hạn chế trong đó chương trình tự động ghi các giá trị trong đó thường xuyên, tuy nhiên, nó đọc chúng khá hiếm.
Samik Hayopadhyay 17/05/2015

2

Không gian EEPROM, như đã đề cập, sẽ hoạt động nếu không bắt buộc phải bay hơi. Tuy nhiên, bạn chưa đủ điều kiện nếu nó cần phải không biến động hay không. Nếu không thì bạn có thể sử dụng __attribution__ để xác định không gian biến không được khởi tạo. Vì SRAM trên ATmega không bị xóa bằng cách đặt lại hoặc chu kỳ nguồn. Trình biên dịch mặc định để khởi tạo chúng. Trường hợp này có thể được tắt cho mỗi biến như trong ví dụ dưới đây:

//non-initialized value
union configUnion{
  uint8_t    byte[6]; // match the below struct...
  struct {
    uint16_t value1;
    uint16_t value2;
    uint16_t chksum;
  } val ;
} config  __attribute__ ((section (".noinit")));

void setup() {
  uint16_t sum; 
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // prints title with ending line break
  Serial.print("Out of Reset -");
  sum = getchksum();
  printValues();

  if (sum != config.val.chksum) {
    config.val.chksum = sum;
    Serial.print("chksum is incorrect setting config.val.chksum = 0x"); Serial.println(config.val.chksum, HEX);
  }

  config.val.value1++;
  config.val.value2++;
  Serial.print("setup new values - ");
  printValues();
  config.val.chksum = getchksum();
  Serial.print("updating chksum config.val.chksum = 0x"); Serial.println(config.val.chksum, HEX);
}

int counter = 0;

void loop() {
  if (counter < 200) {
    Serial.print("after a while - ");
    printValues();
    Serial.println();
    while (true) {
      continue;
    }
  }
  counter++;
}

void printValues() {
  Serial.print(" value1 = 0x"); Serial.print(config.val.value1, HEX);
  Serial.print(", value2 = 0x"); Serial.print(config.val.value2, HEX);
  Serial.print(", sum = 0x"); Serial.print(getchksum(), HEX);
  Serial.print(", chksum = 0x"); Serial.println(config.val.chksum, HEX);
}

uint16_t getchksum() {
  int sum = 0;
  for (int position = 0; position < (sizeof(config) - sizeof(config.val.chksum)); position++) {
    sum = sum + config.byte[position];
  }
  return sum;
}

Đầu ra của mã trên là dưới đây. Lưu ý rằng đầu ra đầu tiên là kết quả của việc bật nguồn UNO lên với nút Reset được ấn xuống và sau đó được giải phóng sau khi cửa sổ Monitor được khởi động. Nếu không, bản in "cài đặt không chính xác" sẽ bị bỏ lỡ, trước khi cửa sổ màn hình có thể được khởi động.

Out of Reset - value1 = 0xBFED, value2 = 0xD2F9, sum = 0x377, chksum = 0xF457
chksum is incorrect setting config.val.chksum = 0x377
setup new values -  value1 = 0xBFEE, value2 = 0xD2FA, sum = 0x379, chksum = 0x377
updating chksum config.val.chksum = 0x379
after a while -  value1 = 0xBFEE, value2 = 0xD2FA, sum = 0x379, chksum = 0x379

Out of Reset - value1 = 0xBFEE, value2 = 0xD2FA, sum = 0x379, chksum = 0x379
setup new values -  value1 = 0xBFEF, value2 = 0xD2FB, sum = 0x37B, chksum = 0x379
updating chksum config.val.chksum = 0x37B
after a while -  value1 = 0xBFEF, value2 = 0xD2FB, sum = 0x37B, chksum = 0x37B

Out of Reset - value1 = 0xBFEF, value2 = 0xD2FB, sum = 0x37B, chksum = 0x37B
setup new values -  value1 = 0xBFF0, value2 = 0xD2FC, sum = 0x37D, chksum = 0x37B
updating chksum config.val.chksum = 0x37D
after a while -  value1 = 0xBFF0, value2 = 0xD2FC, sum = 0x37D, chksum = 0x37D

Với điều này, các biến của bạn sẽ được đặt lại. Miễn là sức mạnh không bị mất. Lưu ý ở trên, nơi bạn sẽ nhận được dữ liệu ngẫu nhiên, để bắt đầu.

Sử dụng EEPROM hoặc .noinit Tôi sẽ khuyên bạn nên kiểm tra không gian biến liên tục của mình trong khi thiết lập và nếu không chính xác, bạn có thể khởi tạo hoặc đưa ra cảnh báo.


1

Nếu bạn thực sự cần cập nhật NVRAM thường xuyên, hãy xem FRAM (Bộ nhớ truy cập ngẫu nhiên điện từ) có tuổi thọ ghi là 10 ^ 13 chu kỳ (tức là ~ 318.000 năm nếu bạn viết một lần / giây!). Chúng là 8KB và nhanh hơn Flash hoặc EEPROM ở 20 MHz (SPI).

Adaf Berry (ở Mỹ) bán chúng trên một bảng đột phá với giá khoảng 6 đô la Mỹ. Hoặc bạn có thể mua chip trần từ các nhà cung cấp thông thường với giá khoảng 1,30 đô la Mỹ, nhưng không phải là DIP, chỉ có các gói SOP8.


0

Nếu bạn đang mở một giải pháp ngoài chip, việc mua / xây dựng đầu đọc thẻ SD không quá khó khăn.


1
Vui lòng cố gắng cung cấp câu trả lời kỹ lưỡng hơn: cung cấp liên kết đến các đầu đọc thẻ SD như vậy, đăng một số mã mẫu về cách đọc / ghi các biến từ nó và đề cập đến cách nó tốt hơn EEPROM.
jfpoilpret

Gợi ý tốt. SD đang sử dụng giao diện SPI thông thường. Vì vậy, tất cả những gì bạn cần là một số chuyển đổi mức logic. Bên cạnh đó bạn nối chúng trực tiếp với Arduino. Chỉ cần hàn một số dây vào bộ chuyển đổi micro-SD sang SD.
Gerben

+ jfpoilpret Trình đọc thẻ SD IMHO có mặt khắp nơi và không cần các ví dụ hoặc trích dẫn. Mã phụ thuộc vào thương hiệu của người đọc nên không có điểm nào trong việc cung cấp mã tùy ý. Tôi đã đề cập đến cách nó tốt hơn EEPROM, không quá khó để mua hoặc xây dựng.
linhartr22
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.