Как записать в свободное место на внешнем EEPROM?
Я хочу записывать координаты GPS во внешнюю EEPROM через I2C.
Например: Широта: 51.0000 Долгота: 4.0000
Если я удалю десятичный разряд, каждый из этих адресов будет занимать до двух байтов каждый.
Мой вопрос: Как мне каждый раз регистрировать каждый новый набор данных GPS по новому адресу памяти в EEPROM?
Принимая во внимание, что Arduino может быть выключен между записями.
@blarg, 👍3
4 ответа
Лучший ответ:
Трюк, который вы хотите реализовать здесь, заключается в возможности просмотреть 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 последовательность прерывается, поэтому вы знаете, где была последняя запись.
Здесь есть только пара небольших замечаний:
- Вы можете использовать только 5*n ячеек в EEPROM, так как последний 5-байтовый пакет данных может не поместиться в последний бит EEPROM (скажем, это 1024-байтовая EEPROM, у вас будет место для 204,8 пакетов, поэтому 204 пакета и осталось 4 байта).
- Вы должны убедиться, что в EEPROM не помещается ровно 256 пакетов, прежде чем зациклить адрес, иначе последовательность не "разорвется", и вы никогда не узнаете, где была последняя запись после первого зацикливания. .
Вы можете назначить первый байт (байты) EEPROM в качестве адреса следующего свободного места для хранения GPS-координат и обновить его до того, как Arduino перейдет в спящий режим. При пробуждении получить адрес.
Вы также можете оставить указатель в оперативной памяти; Оперативная память сохраняет свое содержимое во время сна. Но использование EEPROM позволит вам даже выключить Arduino и продолжить работу с того места, на котором вы остановились после сброса при включении питания. (Конечно, другие части вашей программы также должны быть устойчивы к перезапуску; здесь я просто смотрю на хранилище координат).
Кроме того, двух байтов недостаточно для хранения GPS-координат с точностью до четырех знаков после запятой, если их диапазон не ограничен таким образом, что вы можете масштабировать их до [0 - 65535].
Вы можете разделить пространство 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
Вопрос касается конкретно EEPROM (E2), и многие ответы указывают или пытаются устранить основное ограничение E2: ограниченное количество операций записи. Не упоминается медленная скорость E2. Он лучше всего подходит для хранения редко изменяемых данных, таких как встроенные или установочные параметры, такие как данные калибровки устройства и функции внешней операционной среды устройства. Его единственное реальное преимущество перед другими решениями заключается в том, что оно может уже существовать на вашем микроконтроллере — например, на Atmega 328.
Новым продуктом в области энергонезависимого хранения данных является ферроэлектрическая оперативная память (FRAM). Время записи примерно в 30 раз быстрее, 150 нс, а срок службы составляет 10 ^ 12 операций записи, или в 10 миллионов РАЗ больше, чем у E2. Я создал регистратор данных, который использует кольцевой буфер во FRAM для хранения периодических выборок данных и записи их по запросу.
Те же методы, предложенные в ответах для E2, будут одинаково хорошо работать в FRAM с дополнительным преимуществом, заключающимся в том, что вы можете игнорировать сложности, предназначенные для обхода ограниченной стойкости E2 к записи.
И в качестве отказа от ответственности: я не продаю этот материал и не имею к нему никакого другого интереса. Но я им пользуюсь, и он работает так, как написано на коробке.
Adafruit производит их на разделительной плате в нескольких вариациях (размер и тип последовательной шины), которые продаются ими и другими ритейлерами. Ссылка предназначена для платы SPI-bus размером 8 КБ.
- Является ли использование malloc() и free() действительно плохой идеей для Arduino?
- Как читать и записывать EEPROM в ESP8266
- Какой реальный срок службы EEPROM?
- Как запомнить значения переменных после перезагрузки платы Arduino Uno R3
- Получить доступ к EEPROM ATtiny с помощью кода Arduino?
- Очистка EEPROM
- Как сохранить переменную с плавающей запятой в EEPROM
- Spiffs против Eeprom на esp8266
Использование одних и тех же байтов и запись в одно и то же место часто приводит к тому, что эти байты быстро ломаются. У них ограниченное количество записей., @Avamander