Работа с энергонезависимой памятью EEPROM

Ardfun
Offline
Зарегистрирован: 22.05.2016

Здравствуйте, возник вопрос как используя енергонезависимую память запоминать параметры нажатия экрана 

вопрос как запоминать параметр m чтоб при последующем включении отображался экран который был нажат до выключения питания


void loop()
 {
   if (m==0)                                                          
     {
myGLCD.clrScr();
myGLCD.setFont(SmallFont);
myGLCD.print("0", CENTER, 20);
}
   if (m==1)                                                          
     {
myGLCD.clrScr();
myGLCD.setFont(SmallFont);
myGLCD.print("1", CENTER, 20);
 }
   }

 

5N62V
Offline
Зарегистрирован: 25.02.2016

Скорее всего так:

-Подключаете библиотеку EEPROM

-переменную m объявляете глобально

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

-Если m объялена как многобайтовая переменная, то и записываете по-байтно

-в setup()  прописываете считывание этой переменной м, так же по-байтно, что будет происходить при каждом включении/перегрузке

-наслаждаетесь прекрасно работающим кодом.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Открываешь Arduino IDE, идёшь в пункт меню "Файл->Примеры->EEPROM" - и наслаждаешься примерами работы с EEPROM, по мере изучения дописываешь свой код так, чтобы всё, что тебе нужно - сохранялось/вычитывалось в/из EEPROM, profit.

Ardfun
Offline
Зарегистрирован: 22.05.2016

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


#include <EEPROM.h>

boolean f_nextPin = 0; 
unsigned long previousMillis = 0;

byte nextPin = 9;

byte led_1 = 10;
byte led_2 = 11;

int m = 0; 

int addr = 0;
byte value;

/////////////////////////////////////////////////////////////////////////
{

  
   pinMode(nextPin, INPUT);
    
   pinMode(led_1, OUTPUT); 
   pinMode(led_2, OUTPUT);
}
//////////////////////////////////////////////////////////////////////////
   void loop()
 {
   int val = digitalRead(nextPin) == HIGH;
       
   EEPROM.write(addr, val);
   
   m = EEPROM.read(addr);
   
////////////////////////////////////////////////////////////////////////// 
   if (digitalRead(nextPin) == HIGH && f_nextPin == 0)//Фиксируем нажатие и запоминаем время
  {
    previousMillis = millis();
    f_nextPin = 1;
  }
  else if (digitalRead(nextPin) == LOW) //Если отпустили кнопку - сбрасуем флаг
  { 
  f_nextPin = 0;
  }
  if (f_nextPin == 1 && millis() - previousMillis >= 1000) //контроль прошествия времени 1с
  {
        m++;
f_nextPin = 0;// и сбрасуем флаг
    
   if (m > 1) //если уровень больше 1
    {
      m = 0; // то вернуться к началу
    }
   }
//////////////////////////////////////////////////////////////////////
   if (m==0)                                                          
     {
digitalWrite(led_2, HIGH);
 }
   if (m==1)                                                          
     {
digitalWrite(led_1, HIGH);
 }
     }

 

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

Не пишите EEPROM при каждом проходе loop! У EEPROM ограниченое кол-во циклов записи, убете за день.

Ardfun
Offline
Зарегистрирован: 22.05.2016

Write должен в setap быть ?

kalapanga
Offline
Зарегистрирован: 23.10.2016

Ardfun пишет:
Write должен в setap быть ?

Ну а setup-то тут причём? Используйте EEPROM.update()

Ardfun
Offline
Зарегистрирован: 22.05.2016

почему пишет при компиляции 'class EEPROMClass' has no member named 'update'

другую библиотеку нужно подключать?

а то в примерах не сомсем ясно как применить к моей задаче

b707
Offline
Зарегистрирован: 26.05.2017

Ardfun пишет:

почему пишет при компиляции 'class EEPROMClass' has no member named 'update'

а контроллер у вас какой?

И версия ИДЕ...

На старых версиях ИДЕ в ЕПРОМе не было функции update(). Потом для некоторых контроллеров ее написали, а для некоторых так и нет.

Ardfun
Offline
Зарегистрирован: 22.05.2016

контролер Arduino Pro-mini

версия 1.6.2

sadman41
Offline
Зарегистрирован: 19.10.2016

Moжете свой аналог этой функции написать: считали ячейку EEPROM, посмотрели - если там уже лежит то значение, которое вы собираетесь писать, то ничего не делаете. В том случае, если оно иное - пишете новое.

Ardfun
Offline
Зарегистрирован: 22.05.2016

так если скачать новую библиотеку то заработает?

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Есть два варианта...

5N62V
Offline
Зарегистрирован: 25.02.2016

Ardfun пишет:

так если скачать новую библиотеку то заработает?

 

Если последуете совету печального человека, то будете понимать как эта функция работает. А это куда полезнее , чем тупо поставить последнюю идешку и подключить библиотек поновее.

Ardfun
Offline
Зарегистрирован: 22.05.2016

пока не могу разобратся и скачевать новое тоже не хочу )

5N62V
Offline
Зарегистрирован: 25.02.2016

Ardfun пишет:

пока не могу разобратся и скачевать новое тоже не хочу )

ну например Вам надо сохранить изменившуюся переменную aaa

Пишите:

#define ADDR 10// например адрес = 10

int temp;// объявляете временную переменную такого же типа, как и ааа
EEPROM.get(temp, ADDR);//считываете в нее содержимое еепром
if(aaa!=temp) EEPROM.put(aaa, ADDR);// если данные отличаются, записываете ааа в еепром

 

bwn
Offline
Зарегистрирован: 25.08.2014

Я где то пропустил? У меня на старых версиях было только read, write, а там где put, get уже и update появилось.

5N62V
Offline
Зарегистрирован: 25.02.2016

ага, я тоже так думал. А оно вон как! :)

Клапауций 298
Клапауций 298 аватар
Offline
Зарегистрирован: 25.01.2018

bwn пишет:

Я где то пропустил? У меня на старых версиях было только read, write, а там где put, get уже и update появилось.

да - всё стало более лучше.

Ardfun
Offline
Зарегистрирован: 22.05.2016

Вот по такой схеме подключал все работает и записивается но начала как по мне глючить память, как болие грамотно записать, вроде ж использование update как я понял производит перезапесь ячейки тодько при изменении значения?

 int R;
 void setup(void)
{
R = EEPROM.read(0);
}
void loop()
{
  EEPROM.update(0, R);
}

 

И симптомы такие что сбрасивается  R==0 и не записывает новое значение хотя R было другое

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

Честно говоря, есть опыт только использования внешней EEPROM, но вдруг окажется полезным.

EEPROM требуется некоторое время, чтобы "привести себя в порядок". Для внешней - 5 мс, что в тысячи раз больше времени прохождения пустого loop(). Не следует обращаться к ней так часто.

Код выше - он по логике неверен.

И, кстати, такими экспериментами Вы могли уже успеть убить EEPROM.

Ardfun
Offline
Зарегистрирован: 22.05.2016

andriano пишет:

И, кстати, такими экспериментами Вы могли уже успеть убить EEPROM.

так для этого я и мучаю свой девайс чтобы определить что значит мертвая память и как ведет себя устройство

все никак не могу разобратся как грамотно запоминать чтобы ресурса хватило по моим подсчетам на лет 10

при том что в устройстве будут менятся значения после включения в лучшем случаи пару раз на месяц

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

Вот только пару раз в месяц и нужно писать в EEPROM. Тогда вопрос "А что будет по исчерпании ресурса?" отпадет сам собой.

А "мертвая память" в данном случае означает, что считываешь из нее не то, что записал. (точнее "не всегда то")

Ardfun
Offline
Зарегистрирован: 22.05.2016
 int R;
 void setup(void)
{
R = EEPROM.read(0);
}
void loop()
{
if ( R != EEPROM.read(0 )
{
  EEPROM.update(0, R);
}
}

 

типа так надо?

sadman41
Offline
Зарегистрирован: 19.10.2016

Типа надо или ловить момент отключения питания и, вися, на конденсаторе, писать в EEPROM быстренько. Или писать через N сек после того, как параметр прекратил меняться (например - не писать, пока пользователь не оставит в покое энкодер на пять сек). Или поставить FRAM и успокоиться.

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

Ardfun пишет:

 int R;
 void setup(void)
{
R = EEPROM.read(0);
}
void loop()
{
if ( R != EEPROM.read(0 )
{
  EEPROM.update(0, R);
}
}

 

типа так надо?

Как раз так - не надо.

Вы читаете EEPROM сразу после команды записи, что при этом вернет .read(), неизвестно, а если вернет что-нибудь не то, условие окажется верным, выполнится запись - и дальше по кругу.

Зачем Вам читать из EEPROM, если то, что там записано, должно храниться в ячейке оперативной памяти. Читать из EEPROM в loop() не нужно. Совсем.

Ну а что нужно - согласен с sadman41.

Ardfun
Offline
Зарегистрирован: 22.05.2016

andriano пишет:

}

 

типа так надо?

Как раз так - не надо.

Вы читаете EEPROM сразу после команды записи, что при этом вернет .read(), неизвестно, а если вернет что-нибудь не то, условие окажется верным, выполнится запись - и дальше по кругу.

Зачем Вам читать из EEPROM, если то, что там записано, должно храниться в ячейке оперативной памяти. Читать из EEPROM в loop() не нужно. Совсем.

Ну а что нужно - согласен с sadman41.

[/quote]

уже понял что так не надо ;)

Ardfun
Offline
Зарегистрирован: 22.05.2016
 void setup(void)
{
  R = EEPROM.read(10);
}

void loop()
{
 if (Z == 1)
  {
      
       myGLCD.setFont(SmallFont);
       myGLCD.print("*", RIGHT, 0);
  }
  if (digitalRead(K) == HIGH && f_K == 0)
  {
    previousMillis = millis();
    f_K = 1;
  }
  else if (digitalRead(K) == LOW) 
  {
    f_K = 0;
  }
  if (f_K == 1 && millis() - previousMillis >= 1000) 
  {
    Z++;
    f_K = 0;
EEPROM.update(10, R);
if (Z > 1) 

{ Z = 0; 

} } }

 

 

Вот вроде работает, условия таковы сделал что при нажатии и удержании 1с запоминает режим R и на экране засвечивается * что сигнализирует о запоминании режима. Подправте если что то неправильно