Как записать в свободное место на внешнем EEPROM?

Я хочу записывать координаты GPS во внешнюю EEPROM через I2C.

Например: Широта: 51.0000 Долгота: 4.0000

Если я удалю десятичный разряд, каждый из этих адресов будет занимать до двух байтов каждый.

Мой вопрос: Как мне каждый раз регистрировать каждый новый набор данных GPS по новому адресу памяти в EEPROM?

Принимая во внимание, что Arduino может быть выключен между записями.

, 👍3


4 ответа


Лучший ответ:

6

Трюк, который вы хотите реализовать здесь, заключается в возможности просмотреть EEPROM и сказать: "Это последнее место, куда я писал, теперь я напишу в следующее место".

Есть два способа сделать это: простой и правильный.

Простой способ — сохранить в EEPROM один адрес, который указывает, куда вы записывали в последний раз. Если вы пытаетесь внедрить какую-либо форму выравнивания износа, чтобы продлить срок службы вашей EEPROM, то это в основном сведет на нет его, поскольку эта одна ячейка в EEPROM изнашивается раньше остальных и становится бесполезной. Так что на самом деле это не очень хорошая идея, хотя поначалу может показаться, что это так.

Правильный способ сделать это — каждый раз сохранять больше информации в EEPROM. Вам нужно хранить не только данные, но и какой-то идентифицирующий порядковый номер.

Скажем, у вас есть 4 байта данных для записи каждый раз. Добавьте к нему пятый байт. Этот пятый байт увеличивается на единицу каждый раз, когда вы пишете. Перед записью вы сканируете EEPROM, просматривая каждый пятый байт в поисках «конца» последовательности.

Например, вы можете получить (xx байты данных) в шестнадцатеричном формате:

00: 00 xx xx xx xx
05: 01 xx xx xx xx
0A: 02 xx xx xx xx
0F: 03 xx xx xx xx
14: FF FF FF FF FF

Вы видите, что по адресу 0x14 красивая последовательность чисел обрывается. Поэтому ваша следующая запись должна быть в этот момент. Теперь, если через какое-то время вы много раз пройдетесь по EEPROM, вы можете получить что-то похожее на это:

00: FE xx xx xx xx
05: FF xx xx xx xx
0A: 00 xx xx xx xx
0F: 01 xx xx xx xx
14: 58 xx xx xx xx

Здесь вы можете увидеть четкую последовательность 0xFE 0xFF 0x01, где они каждый раз увеличиваются на 1 (0xFF + 1 = 0x00), поэтому вы можете видеть, что вы зациклились на своих порядковых номерах. Вам все равно, потому что это все еще просто плюс один. Только при переходе с 0x01 на 0x58 последовательность прерывается, поэтому вы знаете, где была последняя запись.

Здесь есть только пара небольших замечаний:

  1. Вы можете использовать только 5*n ячеек в EEPROM, так как последний 5-байтовый пакет данных может не поместиться в последний бит EEPROM (скажем, это 1024-байтовая EEPROM, у вас будет место для 204,8 пакетов, поэтому 204 пакета и осталось 4 байта).
  2. Вы должны убедиться, что в EEPROM не помещается ровно 256 пакетов, прежде чем зациклить адрес, иначе последовательность не "разорвется", и вы никогда не узнаете, где была последняя запись после первого зацикливания. .
,

1

Вы можете назначить первый байт (байты) EEPROM в качестве адреса следующего свободного места для хранения GPS-координат и обновить его до того, как Arduino перейдет в спящий режим. При пробуждении получить адрес.

Вы также можете оставить указатель в оперативной памяти; Оперативная память сохраняет свое содержимое во время сна. Но использование EEPROM позволит вам даже выключить Arduino и продолжить работу с того места, на котором вы остановились после сброса при включении питания. (Конечно, другие части вашей программы также должны быть устойчивы к перезапуску; здесь я просто смотрю на хранилище координат).

Кроме того, двух байтов недостаточно для хранения GPS-координат с точностью до четырех знаков после запятой, если их диапазон не ограничен таким образом, что вы можете масштабировать их до [0 - 65535].

,

Использование одних и тех же байтов и запись в одно и то же место часто приводит к тому, что эти байты быстро ломаются. У них ограниченное количество записей., @Avamander


7

Вы можете разделить пространство EEPROM на записи и предоставить каждой записи один "использованный" кусочек. Вы можете использовать отдельный байт для его хранения или повторно использовать бит из байта, который не полностью используется вашими данными.

Предположим, вы начинаете с EEPROM, заполненной нулями, и решаете, что первый байт каждой записи содержит "используемый" бит в LSb. При первом вводе координат вы получите:

 /---"used"
01 51 00 00 04 00 00
00 00 00 00 00 00 00
 \---"free"
...
00 00 00 00 00 00 00

(конечно, вам не нужно хранить GPS-координаты в формате BCD, это просто иллюстрация) .

Обратите внимание, что при добавлении записей очень просто отслеживать последнюю: просто проверяйте записи по порядку, пока не найдете "бесплатную" один и вернуться на один шаг. Также обратите внимание, что первая запись всегда "используется".

Это будет продолжаться до тех пор, пока все ваши записи не будут "использованы":

01 51 00 00 04 00 00
01 52 00 00 05 00 00
...
01 53 00 00 06 00 00

В этот момент (когда вам нужно записать новые данные, но нет «свободных» записей), вы снова начинаете запись с первой записи, инвертируя значение «используемой» записи. бит:

 /---"used"
00 54 00 00 07 00 00
01 02 00 00 05 00 00
 \---"free"
...
01 53 00 00 06 00 00

(помните, что первая запись всегда "используется"? Благодаря этому можно просто поменять местами значения, представляющие "используемые" и "свободные" записи, ничего не удаляя).

Подводя итог, алгоритм таков:

  • прочитайте раздел "подержанный" бит из первой записи
  • просматривать записи до тех пор, пока значение параметра "используется" бит меняется или пока вы не дойдете до конца.
  • чтобы прочитать последние зарегистрированные данные, используйте последний параметр "использованный" запись
  • для записи новых данных используйте первый "бесплатный" вход. Если нет "свободных" записи, начните сначала, инвертируя "используемые" немного.
,

Это кажется лучшим ответом здесь. Однако «грязный» может быть не лучшим словом для действительных на данный момент данных., @endolith

@endolith Спасибо, я заменил «грязный» на «использованный» и «чистый» на «бесплатный»., @Dmitry Grigoryev


0

Вопрос касается конкретно EEPROM (E2), и многие ответы указывают или пытаются устранить основное ограничение E2: ограниченное количество операций записи. Не упоминается медленная скорость E2. Он лучше всего подходит для хранения редко изменяемых данных, таких как встроенные или установочные параметры, такие как данные калибровки устройства и функции внешней операционной среды устройства. Его единственное реальное преимущество перед другими решениями заключается в том, что оно может уже существовать на вашем микроконтроллере — например, на Atmega 328.

Новым продуктом в области энергонезависимого хранения данных является ферроэлектрическая оперативная память (FRAM). Время записи примерно в 30 раз быстрее, 150 нс, а срок службы составляет 10 ^ 12 операций записи, или в 10 миллионов РАЗ больше, чем у E2. Я создал регистратор данных, который использует кольцевой буфер во FRAM для хранения периодических выборок данных и записи их по запросу.

Те же методы, предложенные в ответах для E2, будут одинаково хорошо работать в FRAM с дополнительным преимуществом, заключающимся в том, что вы можете игнорировать сложности, предназначенные для обхода ограниченной стойкости E2 к записи.

И в качестве отказа от ответственности: я не продаю этот материал и не имею к нему никакого другого интереса. Но я им пользуюсь, и он работает так, как написано на коробке.

Adafruit производит их на разделительной плате в нескольких вариациях (размер и тип последовательной шины), которые продаются ими и другими ритейлерами. Ссылка предназначена для платы SPI-bus размером 8 КБ.

,