Продление срока службы EEPROM

Я работаю над программным обеспечением, использующим Uno (ATmega328P). У меня есть байт стадии, который может принимать одно из 5 значений (0-4) в моем коде, и он будет увеличиваться на 1 каждые 2,5 часа. Если я потеряю питание, мне нужно убедиться, что при пробуждении стадия будет такой же, какой она была на момент потери питания, поэтому каждый раз при обновлении стадии я сохраняю ее в EEPROM.

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

В настоящее время мне не нужно использовать EEPROM для чего-либо еще, поэтому, чтобы продлить срок службы EEPROM, я собираюсь выделить 1 четверть (0-255 байт) для сохранения этого значения. Каждый раз, когда я меняю стадию, я буду записывать 3 байта в EEPROM, что будет:

  • Индексный байт (используется для сдвига адресов, по которым я записываю).
  • Байт стадии (стадия, которую мне нужно сохранить).
  • Байт количества (количество раз, когда я записывал сцену по текущему индексу).

Для начала индекс будет записан в байт 0 в EEPROM, стадия — в байт 1, а количество — в байт 2.

Мой план состоит в том, чтобы разрешить запись этапа в байт 1 250 раз, затем очистить счетчик и сместить индекс на 3. Это, в свою очередь, переместит байты, в которые записываются этап и счетчик, на 4 и 5. Я буду делать это до тех пор, пока индекс не достигнет конца 255 байтов, а затем верну индекс на 0. Таким образом, в общей сложности я должен иметь возможность выполнить сдвиг 85 раз.

Каждый байт имеет 100 000 циклов стирания/записи, так что это означает, что я могу пройти через байты 0-255 400 раз, записывая сцену 250 раз за проход. Так что вместо 100 тыс. записей у меня будет около 8,5 млн записей.

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

, 👍0

Обсуждение

У меня нет большого опыта работы с EEPROM, но, возможно, на одну «страницу» (которая может быть, например, 256 байт) записывается даже один байт, так что вам, возможно, придется принять это во внимание при записи данных., @Michel Keijzers

Еще один совет (если применимо): записывайте байты (или страницу) только тогда, когда значение действительно изменилось (например, проверяйте текущее значение байта и записывайте его только тогда, когда оно не равно новому значению)., @Michel Keijzers

Мне этот метод показался интересным. Раньше я записывала однобайтовое (ненулевое) значение в первую ячейку памяти, которая была нулевой/пустой. Поэтому при каждой записи я перемещала её на один байт. Достигнув конца EEPROM, я обнуляла всю память и начинала с нуля. Чтобы прочитать последнее значение при включении питания, просто продолжайте считывать значения из EEPROM, пока не прочитаете ноль (или не окажетесь в последней ячейке)., @Gerben

Почему бы не использовать RTC? Если этап увеличивается каждые 2,5 часа, его можно рассчитать по формуле `((часов с 1970 года) \2.5 ) % 5, @Code Gorilla

Существуют алгоритмы, позволяющие продлить срок службы EEPROM, но будут ли они оправданы с точки зрения затрачиваемой вычислительной мощности, если стоимость замены EEPROM каждый год составляет всего несколько фунтов?, @Code Gorilla

@MichelKeijzers Размер страницы для EEPROM ATMega328Ps составляет 4 байта. Поэтому лучше не использовать байты 1, 2 и 3. Таким образом, первая страница используется только для байта index., @Gerben

@CodeGorilla, в некоторых RTC также есть свободное ОЗУ с питанием от батареи, в которое можно записывать данные. Оно работает так же, как EEPROM, но не портится и сохраняет данные, пока резервная батарея достаточно заряжена., @Gerben

@Gerben, спасибо за информацию... Я играл только со SRAM, у которой страница была 32 байта, если мне не изменяет память. Полагаю, это зависит от типа/марки/модели накопителя., @Michel Keijzers

Часы реального времени (RTC) — лучшее решение. Второй по эффективности вариант — избежать отключения питания Arduino. В качестве алгоритма я бы не считал до 250, а использовал бы EEPROM как кольцевой буфер и непрерывно записывал бы данные в следующую ячейку. Arduino можно было бы отключить во время записи в EEPROM, возможно, переменная должна была бы записываться дважды, возможно, с контрольной суммой. Нужно запомнить всего два бита... кто-то более креативный, чем я, сможет что-то с этим сделать (например, протокол для хранения или запомнить каким-то другим способом)., @Jot

Также задавался вопрос по адресу: http://forum.arduino.cc/index.php?topic=523223 Если вы собираетесь сделать это, пожалуйста, будьте внимательны и добавьте ссылки на другие ресурсы, где вы делаете кросспосты. Это позволит нам избежать траты времени на дублирование, а также поможет другим, у кого возникнут те же вопросы, найти ваш пост и найти всю необходимую информацию., @per1234

Всем привет! Большое спасибо за ваши комментарии. @Gerben Если я осуществлю свою идею, то обязательно обнулю свою EEPROM, как только достигну последнего используемого байта. Даже не думал об этом., @user1649972

@CodeGorilla Я использую технику RTC в других местах своего кода, но в данном случае использование RTC не подходит, поскольку мне нужно, чтобы процесс продолжился именно с того места, где он остановился, независимо от того, как долго он был выключен., @user1649972

@Jot, кольцевой буфер — отличная идея, он ещё больше продлит срок службы EEPROM. Я, честно говоря, переусложнил всё с подсчётом, спасибо., @user1649972

@per1234, извините, что не упомянул о кросспостинге. Проект ограничен по времени, и я, честно говоря, не думал, что получу такой ценный совет так быстро. В будущем, если буду кросспостить, буду давать ссылку., @user1649972

@user1649972 — разве обнуление EEPROM не будет пустой тратой цикла записи? Хотя я не представляю, как вы бы следовали совету gerban, не сделав этого. (Понимаю, что вы имеете в виду, говоря, что идея с RTC в данном случае не подходит), @Code Gorilla

@CodeGorilla, это как бы тратит один цикл впустую, но при этом немного упрощает код. Использование всего 1 КБ памяти, но запись его дважды, всё равно увеличит количество циклов записи в 500 раз (без учёта размера страницы). Если этого достаточно для жизненного цикла продукта..., @Gerben

@CodeGorilla Пытался придумать способ обойти это, так как это будет означать, что я буду записывать дважды на каждую запись в каждом цикле. К сожалению, мне придётся удалить старые данные перед возвращением в исходную точку. Мой план заключается в том, чтобы, достигнув конца EEPROM, я просканировал все элементы и вернул их к значению 0xFF (значение по умолчанию). Это нужно, чтобы найти последний индекс при пробуждении после отключения питания. При пробуждении я буду сканировать все индексы, пока не достигну индекса со значением 0xFF, а затем вернусь к предыдущему индексу, который будет последним сохранённым индексом. Пока не могу придумать способ обойти это., @user1649972


3 ответа


1

Вы можете загрузить спред, сохранив текущее значение ИЛИ 0x80 или 0x00.

При записи вы записываете в следующую ячейку памяти, а когда она переходит на следующую ячейку, вы берете другое значение и выполняете с ним операцию ИЛИ.

Значения в EEPROM будут

[{0x00|value},{0x00|value},{0x00|value},...,{0x00|value},{0x00|value},{0x00|value},{0x80|value},{0x80|value},{0x80|value},...,{0x80|value},{0x80|value}]

или

[{0x80|value},{0x80|value},{0x80|value},...,{0x80|value},{0x80|value},{0x80|value},{0x00|value},{0x00|value},{0x00|value},...,{0x00|value},{0x00|value}]

Затем вы считываете первый и последний байт, и если старший бит равен, вы берете последнее значение.

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

,

0

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

Для каждых 16 бит я бы использовал 13 для счетчика и 3 для значения. Счетчик, будучи 13 битами, может считать от 0 до 2^13-1 или от 0 до 8191. 3 бита значения могут хранить 0 - 2^3-1 или от 0 до 7, что вполне подходит для вашего значения 0-4.

Размер счетчика важен, так как он более чем вдвое превышает количество 16-битных пар в EEPROM. Если предположить, что EEPROM объемом 1 кБ содержит 512 16-битных значений, то вам нужно, чтобы в вашем счетчике было доступно более 1024 значений (если вы хотите изменить разделение для хранения большего числа...).

Алгоритм прост:

  1. Прочитать EEPROM, просматривая следующее значение счетчика. Если счет увеличивается более чем на 1, то последнее прочитанное значение является текущим.
  2. Если счет идет от 8191 до 0, то продолжайте, вы просто зациклились, вот и все.
  3. Увеличьте счетчик на 1 и запишите в EEPROM адреса, где счетчик увеличился более чем на 1.

Например, если у вас есть:

78 1
79 2
80 3
8191 7
8191 7
8191 7

Вы знаете, что пространство после 80 не используется (0xFFFF разделено на 0x1FFF и 0x7), поэтому вы записываете в него «81 4».

Другой:

8190 2
8191 3
0 4
1 0
2 1
7283 3
7284 4
7285 0

Переход от 8191 к 0 — это просто циклический переход, который можно считать последовательным. Однако переход от 2 к 7283 не является последовательным, поэтому вы можете перезаписать запись 7283 на «3 2».

Если при записи вы выходите за пределы области памяти EEPROM, вы просто снова возвращаетесь к началу.

Это дает вам 512 * 100 000 записей или 51,2 млн записей.

,

Это превосходно, и я на 100% воспользуюсь этой идеей в другом проекте, над которым работаю, с использованием EEPROM большего объёма. Я буду использовать только 2 байта, как и предлагалось, откажусь от счёта, связанного только со стадией и индексом, и буду перемещать индекс после каждой записи в EEPROM. Поскольку я планирую использовать только 256 байт, мне не понадобится такой большой индекс, чтобы охватить их все, — достаточно одного байта. Ещё раз спасибо, это ценно и будет использовано. Исходя из моей базовой идеи, у меня было 28 лет, идея, которую я опубликовал здесь, дала бы мне 2425 лет, а теперь, используя пары байтов, я получу до 3652 лет, так что я полностью защищён., @user1649972


0

Также проверьте, что значения, которые вы хотите записать, действительно меняются. Нет смысла стирать и записывать значение, которое уже есть. И вы экономите 3,3 мс, не выполняя запись.

,

Привет, Эдгар, спасибо за ответ. Значение меняется на 100% каждый раз, когда я пытаюсь записать, и именно изменение значения инициирует запись в EEPROM. Отличный совет, ещё раз спасибо., @user1649972