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

Тема в разделе "Arduino & Shields", создана пользователем Otto, 10 янв 2017.

  1. Otto

    Otto Нерд

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

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

    Часть кода для визуального понимания:
    Код (C++):
    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() {
    //другой код...
    //другой код...
    //другой код...
    }
     
  2. Unixon

    Unixon Оракул Модератор

    Поскольку у вас используются не все значения байта, выберите одно для значения - маркера и записывайте его в следующую ячейку после данных. Точнее, (maddr=addr+1)%512. При старте программы ищите это значение в EEPROM и начинайте записывать новые данные с его адреса. Сначала записывайте новый маркер, потом новые данные.
     
  3. Otto

    Otto Нерд

    Идея понятна, не поможете пожалуйста с реализацией, недогоняю каким образом подставить переменные
     
  4. Unixon

    Unixon Оракул Модератор

    Значит не до конца понятна. Напишите хотя бы неправильно, а там посмотрим.
     
    Otto нравится это.
  5. Otto

    Otto Нерд

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

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

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

      maddr = EEPROM.read(addr);
      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
        (maddr=addr+1)%512;
        if (addr == 512) {   //если дошли до последней ячейки (для Arduino NANO Atmega168)
          addr = 0;          //переходим обратно в первую ячейку и по кругу...
        }
        E_1 = 0;    //меняем значение переменной E_1 на 0
      }

    }

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

    Unixon Оракул Модератор

    Код (C++):

    #define EEPROM_SIZE 512
    #define EEPROM_EMPTY 0xFF
    #define EEPROM_MARKER 0xFE
    int E_1 = 0;
    int addr = 0;
    int L;

    void setup()
    {
      bool init = true;
      for (int i=0; i<EEPROM_SIZE; i++)
      {
       if (EEPROM.read(i)==EEPROM_MARKER)
       {
        addr = (i-1+EEPROM_SIZE)%EEPROM_SIZE;
        init = false;
        break;
       }
      }
      if (init) L = 0;
      else 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, тогда...
        int maddr = (addr+1)%EEPROM_SIZE;
        EEPROM.write(maddr,EEPROM_MARKER);
        EEPROM.update(addr, L / 118);  //делим на 118 и записываем обновлённые значения в EEPROM в ячейку addr
        addr++;
        if (addr>=EEPROM_SIZE)
        {   //если дошли до последней ячейки (для Arduino NANO Atmega168)
          addr = 0;          //переходим обратно в первую ячейку и по кругу...
        }
        E_1 = 0;    //меняем значение переменной E_1 на 0
      }
    }

    void loop() {
    //другой код...
    //другой код...
    //другой код...
    }
     
    Otto нравится это.
  7. Otto

    Otto Нерд


    Сложнее, чем думал. Спасибо! Сначала сам поразбираюсь в вашем коде, что бы понять его принцип для себя.
     
  8. qwone

    qwone Гик

    Вот я не понимаю зачем городить огород. Проще отвести 2 ячейки памяти . Вот вам и будет адрес. Ну не будет 512, будет 510. Опять же при заливке скетча ЕЕПРОМ перешивается.Знаю что 1 ячейка 0xFF . Так что если 1 ячейка 0xFF, то ЕЕПРОМ пуста. Вот отведите первые ячейки под адресс след своб ячейки. А дальше алгоритм простой. Записали данные и изменили адресс. Дошли до конца, и начали с 0х02 заново. Ведь 0х00 и 0х01 у вас адресс. Простой алгоритм без наворотов.
     
  9. Tomasina

    Tomasina Сушитель лампочек Модератор

    Когда 0х00 или 0х01 испортятся, вся логика полетит к чертям.
     
    neyasbltb_88 нравится это.
  10. Unixon

    Unixon Оракул Модератор

    Для выравнивания количества циклов перезаписи по ячейкам. https://en.wikipedia.org/wiki/Wear_leveling
     
  11. qwone

    qwone Гик

    И у вас часто портится? Вот подсчитай-те сколько раз надо переписать, что бы испортилось окончательно.
    http://arduino.ru/forum/apparatnye-voprosy/resurs-eeprom-atmega-bolee-milliona-perezapisei
    более миллиона. А это в самоделках дохрена.
     
  12. Otto

    Otto Нерд

    Не думаю, что все Микросхемы памяти EEPROM выдерживают такое кол-во перезаписи, риск брака всегда возможен, да и тем более если брать в расчёт, что делается проект не на год, а лет на 5, возможно и более - более качественная продумка защиты кодом лишней не будет)
     
    neyasbltb_88 нравится это.
  13. qwone

    qwone Гик

    Многие проекты нацеленные на века не доживают простой реализации, Но случайные небольшие проекты , могут прожить дольше. Или по простому, не надо хвататься за сложные задачи. Ну что вы собираетесть туда писать? шпоры. Флешки из той памяти не получится.
     
  14. Otto

    Otto Нерд

    Если есть возможность как физически, так и по объёму памяти добавить код и сделать более долгую службу микроконтроллера - почему бы и нет??? Для меня в данном проекте важна долгая и стабильная работа! Тема закрыта!
     
    neyasbltb_88 нравится это.