Чтение с последней заполненной ячейки EEPROM...

Otto
Offline
Зарегистрирован: 26.06.2016

Здраствуйте. Такой вопрос касаемо записи/чтения EEPROM. Есть один проект в котором будет происходить частая запись и чтение в EEPROM память Arduino (Nano Atmega168). При включенной Ардуинке запись происходит последовательно в каждую ячейку начиная с 0 и до 512, после заполнения EEPROM переходит вначало и перезапись/чтение начинается с нулевой ячейки... Но при выкл. и вкл. питания запись начнётся опять с нулевой ячейки не пройдя всю память, а откл. питания может быть частенько.

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

Часть кода для визуального понимания:

byte E_1;            // переменная для экономии ресурсов ОЗУ EEPROM
int addr = 0;        // Начальный адрес памяти EEPROM
int L;               // переменная для преобразования ручных поворотов через map()

//другой код...

void setup() {
//другой код...

  L = EEPROM.read(addr) * 118;   //умножаем значение из памяти на 118
}


void finction() {
//другой код...
  if (Right_Pin_1 ==  true || Left_Pin_1 ==  true) E_1 = 1;     //если истина хотя бы 1 переменная, присваиваем E_1  единицу
  if (Right_Pin_1 == false &&  Left_Pin_1 == false && E_1 == 1) {    //если все переменные лож и E_1 равна 1, тогда...
    EEPROM.update(addr, L / 118);  //делим на 118 и записываем обновлённые значения в EEPROM в ячейку addr
    addr = addr + 1;     //переходим на следующую ячейку памяти для записи
    if (addr == 512) {   //если дошли до последней ячейки (для Arduino NANO Atmega168)
      addr = 0;          //переходим обратно в первую ячейку и по кругу...
    }
    E_1 = 0;    //меняем значение переменной E_1 на 0
  }

}

void loop() {
//другой код...
//другой код...
//другой код...
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так, вроде, в приведённом коде нет ничего на тему

Otto пишет:

Хочу реализовать, что бы при Откл. и Вкл. питания чтение началось не с нулевой ячейки памяти, а с последней ячейки куда была произведена запись 

Или я что-то пропустил? Как Вы это хотите реализовать?

Otto
Offline
Зарегистрирован: 26.06.2016

смысла нет писать весь код. 

Вопрос в том, что возможно ли такое реализовать или нет?

Может не совсем понятно выразился просто, когда описывал идею :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Простите, так я не понял. В первом посте не было никакого вопроса вообще и я подумал, что у Вас есть идея и Вы хотите ею поделиться. А Вы просто спрашивали можно ли такое сделать? Да, конечно, можно.

Otto
Offline
Зарегистрирован: 26.06.2016

неподкинете пример каким образом реализовать, буду очень благодарен)))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, вариантов много. Общее у них одно: нужно сохранять адрес последней использованной ячейки там где отключение питания не приведёт к потере информации. Можно сохранять адрес после каждого использования EEPROM, а можно предусмотреть какой-нибудь аварийный bac-up питания (на ионисторе, например) и сохранять не постоянно, а только при пропадании внешнего питания. Ионистора хватит на то, чтобы сохранить.

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

Можно придумать миллион вариантов куда именно сохранять. Каждый из вариантов может быть полезным, а может оказаться идиотизмом в зависимости от задачи и множества факторов, которые. кроме Вас никто не знает.

Например:

1. Записывать на SD карту. При включении питания (в setup) считывать с карты номер ячейки  и продолжать от него
2. Выгружать на внешний Web-сервер или файловый сервер, а при включении питания считывать оттуда
 

Я уж не говорю про экзотику типа "сервой поворачиваем вал потенциометра на 1/512 его хода на единицу адреса. Тогда по текущему сопротивлению всегда можно узнать адрес или ещё круче, присобачить роботизированную руку, чтобы она адрес на обоях записывала, а при включении питания его оттуда считывать и распозновать.

Ну, это уже шутки пошли, но в принципе, подумайте. Общую идею я рассказал.

toc
Offline
Зарегистрирован: 09.02.2013

подкину вариант:
у меня в одном проекте в аналогично сохраняются записи фиксированной длины в епром. Одно из полей записи содержит время. Кажется типа time_t, обычное астрономическое киевское время. Перезаписываю запись с минимальным временем.

sergkr1983
Offline
Зарегистрирован: 09.12.2015

Пишите не 512 ячеек памяти, а 511. А в 512-ю посоянно записывайте номер ячейки для записи. Вот Вам и будет от куда брать номер ячейки при потере питания.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sergkr1983 пишет:

А в 512-ю посоянно записывайте номер ячейки для записи.

Она накроется первой и весь епром выбросите :(

TD27T
Offline
Зарегистрирован: 08.04.2016

ЕвгенийП пишет:

sergkr1983 пишет:

А в 512-ю посоянно записывайте номер ячейки для записи.

Она накроется первой и весь епром выбросите :(

Как вариант - в нулевую писать указатель на ячейу, в которую пишется номер ячейки для записи. Этот указатель менять когда пройдёт один полный цикл. Память будет изнашиваться равномерно.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

как вариант делать как в файловой системе

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

как вариант делать как в файловой системе

Угу.

Секторами по 512 байт.

Logik
Offline
Зарегистрирован: 05.08.2014

Если считаем что другой энергонезависимой памяти в системе нет, то правильных пути 3

1. Присмотрется к диапазону значений сохраняемой переменной. Если он не 0-255, то одно из неиспользуемых значений использовать как маркер свободной ячейки. После записи в эту ячейку маркер переписываем в следующую по порядку. Если же диапазон занят полностью то можна делать искуственное исключение значения переходя к 2-х байтовому. Т.е. исключаем например 0xff заменив на пару 0xff,0xff, а маркер свободной станет 0xff,0xfe. Другие варианты от 0xff,0x00 до 0xff,0xfd можно применять еще для чего полезного.

2. Как выше намекалось, по адресу 0 храним адрес указателя на свободную. Указатель на свободную ячейку после каждой записи увеличиваем. При некоторой ситуации не сильно часто (раз в месяц, по завершению цикла прохода памяти, просто при включении и т.д.),  меняем положение указателя перезаписывая его по адресу 0.

3. Аппаратно фиксируем отключение. Никаких ионисторов и пр. там не надо, хватит электролита на плате. Те 10мсек он обеспечит с запасом.  Надо только быстро, в идеале по прерыванию , реагировать на исчезновение  внешнего питания на входе. Через резистор с самого входа, до диода и стабилизатора завести сигнал на пин контроллера. Ну и в прерывании записывать указатель на свободную ячейку по адресу 0.

ПС. все методы предполагают выведение 1-2 ячеек из пространства для сохранения данных. Это очень просто делается прямо при записи и чтении.

TD27T
Offline
Зарегистрирован: 08.04.2016

Кстати, раз уж зашла речь про епром - спрошу здесь, чтоб тему не создавать, если автор не против.

Везде пишут про ресурс памяти в циклах чтение/запись. Следует ли это понимать так, что чтение так же старит ячейку, как и запись? Ну, то есть, нет смысла прочитать значение из памяти, и если оно такое же как нужно, то не записывать его заново? А то вот бродят такие мысли когда сохраняю структуру с настройками - порядка 30 байт, а меняется там, в основном, одно-два поля, т.е. пару байт всего.

Logik
Offline
Зарегистрирован: 05.08.2014

//то чтение так же старит ячейку, как и запись? 

Нет конечно.

//Ну, то есть, нет смысла прочитать значение из памяти, и если оно такое же как нужно, то не записывать его заново? 

Есть смысл. Именно надо предварительно читать и не переписывать такое же.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andriano пишет:

ua6em пишет:

как вариант делать как в файловой системе

Угу.

Секторами по 512 байт.

Пишите байтами, я о таблице говорю, сама идеология решения, правда потеряем ровно половину, как минимум, но это лучше чем совсем ничего, есть правда еще решение реализовать алгоритм SSD как функция, в них это работает безупречно )))

Logik
Offline
Зарегистрирован: 05.08.2014

//реализовать алгоритм SSD как функция

???

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Контроллер SSD

Главной задачей контроллера является обеспечение операций чтения/записи, и управление структурой размещения данных. Основываясь на матрице размещения, в какие ячейки уже проводилась запись, а в какие еще нет.

 

Otto
Offline
Зарегистрирован: 26.06.2016

Всем спасибо за достаточно большое количество нужной информации, кое что полезное уяснил для себя помимо вопроса :)

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

andriano пишет:

ua6em пишет:

как вариант делать как в файловой системе

Угу.

Секторами по 512 байт.

Пишите байтами, я о таблице говорю, сама идеология решения...

Идеология решения ФС опирается на то, что в минимальном элементе данных (секторе) можно разместить достаточно много записей элементов каталога.

Сколько элементов записей каталога поместится в одном байте?

Morroc
Offline
Зарегистрирован: 24.10.2016

TD27T пишет:

Кстати, раз уж зашла речь про епром - спрошу здесь, чтоб тему не создавать, если автор не против.

Везде пишут про ресурс памяти в циклах чтение/запись. Следует ли это понимать так, что чтение так же старит ячейку, как и запись? Ну, то есть, нет смысла прочитать значение из памяти, и если оно такое же как нужно, то не записывать его заново? А то вот бродят такие мысли когда сохраняю структуру с настройками - порядка 30 байт, а меняется там, в основном, одно-два поля, т.е. пару байт всего.

Если писать eeprom.put() то оно вроде так и реализовано уже в ардуине.