Как сохранить значение перед сбросом

zhuki
Offline
Зарегистрирован: 12.10.2011

Здравствуйте.

Проблема выглядит следующим образом. Есть некая система работающая постоянно. Управляет отоплением. Система работает на базе контроллера (UNO). Более детальные установки и корректировки производяться с компьютера ,который подключается по необходимости. В момент подключения Ардуино сбрасывает все данные в исходные состояния. Данные  меняются часто  и постоянно, сохранять  их в ERPROM не хорошо ресурс ограничен. Данных не много достаточно 10 ячеек ERPROM. Но ,восстановление их системой занимает 3-4 часа.

Можно ли определить в Ардуино ,что сейчас будет сброс ,чтобы выполнить сохранение. Или может есть какой другой вариант. Спасибо.

maksim
Offline
Зарегистрирован: 12.02.2012

Знать что будет сброс может только модуль вкантового  вычисления суперпозиции ресета, экстрасенс, человек из будующего или вы когда открываете сериал соединение. )
Можно задержать сброс и сохранить переменные или вообще отогнуть ногу ресет МК и сброса вообще никогда не будет.

Я не понимаю в чем ваша проблема. Если вы часто что-то коректируете передавая по UART, то в чем проблема сохранять эти данные при изменении? Какая разница, что вы их сохраните в ЕЕПРОМ до сброса или после? ведь количество перезаписей в ЕЕПРОМ от этого не уменьшится. 
Если у вас есть данные, которые быстро меняются, то зачем их вообще сохранять если они быстро меняются? Насколько часто меняются? раз в час? а если так то при ежечасной перезаписи ячейки хватит на 11 лет.

А если вы имеете ввиду под "детальные установки и корректировки производяться с компьютера" перепрошивку МК, то либо мудрите ресет с задержкой, либо дополнительную кнопку по нажатию, которой переменные будут сохраняться в ЕЕПРОМ.

zhuki
Offline
Зарегистрирован: 12.10.2011

Ещё раз попробую описать. Работает система и оптимизирует свои показатели на основе сбора статистики (период 1 мин). Время на сбор статистики (постояно меняющейся) примерно 3-4 часа. Когда статистика собрана ,то система работает в оптимальном режиме. Я решаю, например установить таймер на некое действие или ещё что либо.  Для этого мне надо подключиться к Ардуино с компьютера. При подключении происходит сброс и весь накопленный опыт пропадает.

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

Меня интересует что то вроде события OnShutdown, OnClose ,ну или какое то аппаратное решение. И не надо экстрасенсов предлагать.

zhuki
Offline
Зарегистрирован: 12.10.2011

Вижу ещё один вариант. Подключить SRAM по I2C и загонять туда данные. При инииализации их считывать. Эта память не протрётся ,её и подпитать наверно можно. Если кто с этим работал поделитесь.

Спасибо.

chervyachok
chervyachok аватар
Offline
Зарегистрирован: 22.12.2011

При соединении с компа не обязательно должен быть ресет. Раньше при использовании родного ИДЕ так и было, сейчас использую MS Visual Studio 2010 с установленым плагином для ардуино. Так тут подключайся/отключайся сколько влезет - программа продолжает работать и никакой перегрузки не происходит. 

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

step962
Offline
Зарегистрирован: 23.05.2011

zhuki пишет:

Вижу ещё один вариант. Подключить SRAM по I2C и загонять туда данные. При инииализации их считывать. Эта память не протрётся ,её и подпитать наверно можно.

Тогда уж что-нибудь вроде Nonvolatile RAM. Подводите сигнал с RESET микроконтроллера к ноге STORE микросхемы и данные пишутся в ее EEPROM (из ее же RAM'а). Цена вопроса - 2-3 доллара.

А еще есть чисто RAM-микрухи, но с интегрированной в них батарейкой и заявленным ресурсом несколько лет.

MAFia
Offline
Зарегистрирован: 26.10.2011

Дуинка резетится от втыкания - вытыкания USB, если она была под внешним питанием. Т.е она работает, работает, втыкнули в нее USB (просто втыкнули в нее и комп, без открытия порта, передачи чего-либо) она резетится (Во всяком случае, у меня так было).

Если топикстартер имеет ввиду именно это, то на мой взгляд самое простое - сделать так, чтобы ПИТАНИЕ на дуину по USB не шло (например, перерезать "+" в USB кабеле). 

zhuki
Offline
Зарегистрирован: 12.10.2011

Нашел решение своей проблемы.

В микросхеме часов DS1307 есть 56 байт энергонезависимой памяти NVRAM. Записывать можно что угодно и сколько угодно раз. Всё сохраняется т.к. есть батарейка.  Сделал так ,при изменении параметров происходит запись в эту память ,ну а при инициализации и сбросе всё восстанавливается.  Теперь при подключении к Ардуино с компьютера или при отключении необходимые данные не пропадают ,а сохраняются . Что то вроде файла ini.

 

Дурачёк
Дурачёк аватар
Offline
Зарегистрирован: 25.11.2012

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

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

zhuki
Offline
Зарегистрирован: 12.10.2011

Обсуждали. Данные меняются 1 раз в минуту ,60 раз в час ,1440 раз в сутки ,43200 раз в месяц. EPROM хватит на 2 с небольшим месяца потом в этих ячейках будет "дырка".

Дурачёк
Дурачёк аватар
Offline
Зарегистрирован: 25.11.2012

Число циклов до первого сбоя около 5647899\43200=130 месяцев и это ещё без ремапа! Кроме того приведено число циклов перезаписи с максимально возможной интенсивностью и даже при таких условиях речь идёт о разовом сбое, а не о прожженой ячейке. Тут знаете-ли четырёхбайтные счётчики, через ноль перекручиваются, так-что.

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

maksim
Offline
Зарегистрирован: 12.02.2012

Откуда вы взяли эту цифру 5647899?

Дурачёк
Дурачёк аватар
Offline
Зарегистрирован: 25.11.2012

Например отсюда:

 while (FuckIn == FuckOut) {
    if (FuckIn == 3){
      FuckIn = 2;  
    }
    else {
      FuckIn = 3;
    } 
    EEPROM.write(2, FuckIn);
    FuckOut = EEPROM.read(2);
    ++Fucks;
    if ((Fucks % 10000)==0) digitalWrite(13,(!digitalRead(13)));
  }
maksim
Offline
Зарегистрирован: 12.02.2012

Из даташита:

7.4 EEPROM Data Memory
The ATmega48PA/88PA/168PA/328P contains 256/512/512/1K bytes of data EEPROM memory. It is organized as a separate data space, in which single bytes can be read and written. The EEPROM has an endurance of at least 100,000 write/erase cycles. The access between theEEPROM and the CPU is described in the following, specifying the EEPROM Address Registers, the EEPROM Data Register, and the EEPROM Control Register. ”Memory Programming” on page 294 contains a detailed description on EEPROM Programming in SPI or Parallel Programming mode.
 
Все-таки думаю не зря производитель пишит эту цифру. И в расчетах нужно использовать именно ее, а тот подход, который предлагаете вы называется "русский авось".
Сейчас запустил этот тест по уничтожению ячейки ради интереса, как встанет отпишусь, но уже перевалило за 200000 перезаписей.
#include <EEPROM.h>

void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);  
  unsigned long Fucks = 0;
  byte FuckIn = 0, FuckOut = 0;
   Serial.println("START");
  while (FuckIn == FuckOut) {
    if (FuckIn == 0) FuckIn = 255; 
    else FuckIn = 0; 
    EEPROM.write(301, FuckIn);
    FuckOut = EEPROM.read(301);
    ++Fucks;
    if ((Fucks % 1000) == 0) {
      Serial.println(Fucks);
      digitalWrite(13,(!digitalRead(13)));
    }
  }
  Serial.println("ERROR");
  Serial.println("ERROR");
  Serial.println("ERROR");
  Serial.println(Fucks);
}

void loop() {}

 

 

zhuki
Offline
Зарегистрирован: 12.10.2011

Я с вами всё равно не согласен ,т.к. написано в даташите 100000 ,значит нарушать не положено. Тем более через 2 с небольшим месяца попадаешь в зону риска. А это отопление моего жилища и впереди зима. 

Ваш кусок кода ничего не доказывает ,да и как у вас такое число получилось тоже не ясно. Записывать в ячейку то 2 то 3  (0010 или 0011  двоичное представление), т.е. переписывать один единственный бит это не серьёзно. Надо записывать ,хотя бы 0 и 255 (0000 и 1111 ). Да и время не плохо бы дать на реакцию после записи. Вам есть ещё поле для эксперементов, если ещё ячейки остались нетронутые.

maksim
Offline
Зарегистрирован: 12.02.2012

zhuki пишет:
Да и время не плохо бы дать на реакцию после записи.
Вы о чем? о какой реакции и времени?

zhuki
Offline
Зарегистрирован: 12.10.2011

Вот две таблицы из даташита на контроллер (стр 22 и 23) ,разве здесь не о времени на реакцию записи.

maksim
Offline
Зарегистрирован: 12.02.2012

Здесь о времени записи, EEPROM.h написана так что пока запись не окончена при последующей записи программа ждет. А попытка записи/чтения в/из ячейку, которая еще записывается скорее всего приведет к искажению данных.

zhuki
Offline
Зарегистрирован: 12.10.2011

Т.е. в EEPROM.h есть задержка времени? Не знал. Странно, но там нет такого. И как это пока запись не окончена программа ждет.

В моём представлении процессор,регистры ,RAM намного быстрее ,чем EEPROM и Flash. Даже если всё это в одном корпусе.

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

zhuki, таблица показывает минимальное время записи, которое меньше сделать нельзя. (Я читал и смотрел примеры).

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

Удачи!

 

maksim
Offline
Зарегистрирован: 12.02.2012

Если быть точнее то это происходит в библиотеке avr/eeprom.h, которая обернута в EEPROM.h, это бит EEWE и пока он взведен нельзя ни читать ни писать. Но этой задержки естественно не будет, если записывать/читать ЕЕПРОМ с интервалом больше чем 1,8мс (3,6мс).
Вот строка из примера работы с ЕЕПРОМ на С:

while(EECR & (1<<EEWE));//ждем установки бита EEWE

вот на асме:

SBIC    EECR,EEWE       ; Ждем готовности памяти к записи. Крутимся в цикле
RJMP    EEWrite         ; до тех пор пока не очистится флаг EEWE

Тоесть если вы попытаетесь записать/прочитать сразу после предыдущей записи, то программа будет крутиться в цикле и ждать сброса EEWE.

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

maksim
Offline
Зарегистрирован: 12.02.2012

Итак результат. Первый сбой произошел на 6321455 цикле перезаписи! Очень не плохо! Последующие после 12477, 1129, 2891, 6257. Можно считать, что ячейка сносилась.

В принципе если данные не так важны, то можно смело писать/стирать и не париться.
Еще можно организовать дублирование данных и проверку, то есть копировать каждый байт например 3 раза и записывать в 3 ячейки ЕЕПРОМ, а при чтении сравнивать эти копии и если 1 из 3 байт не равен оставшимся двум, то за верное значение принять то что в этих двух байтах. Вероятность того, что две ячейки дадут сбой одновременно и (или), при котором байты одинакого покоцаются стремится к нулю. 

Тогда для задачи поставленной выше ЕЕПРОМ хватит на ~10 лет.

 
Borland
Offline
Зарегистрирован: 17.05.2012

Жалко ячейку то ! сносу не было , 10 лет могла работать, а максим за сутки угробил ))

step962
Offline
Зарегистрирован: 23.05.2011

"Все что должен знать схемотехник о долговечности EEPROM" (с точки зрения MICROCHIP):

максимальное количество циклов стирания/записи - "а кто ж его знает"

порог массового нарастания сбоев - 2.000.000

порог надежного стирания/записи - 1.000.000 (здесь схемы коррекции ошибок еще успевают справляться с нарастающим количеством сбоев)

Ну, а гарантированные (гарантируемые?) пороги - см. даташиты на ИС.

 

zhuki
Offline
Зарегистрирован: 12.10.2011

Спасибо всем .Дискуссия получилась интерестная и познавательная.
Что же касается дела,то имея на борту NVRAM ,я все таки предпочитаю использовать ее. Всем спасибо.

Дурачёк
Дурачёк аватар
Offline
Зарегистрирован: 25.11.2012

zhuki пишет:

Ваш кусок кода ничего не доказывает ,да и как у вас такое число получилось тоже не ясно. Записывать в ячейку то 2 то 3  (0010 или 0011  двоичное представление), т.е. переписывать один единственный бит это не серьёзно. Надо записывать ,хотя бы 0 и 255 (0000 и 1111 ). Да и время не плохо бы дать на реакцию после записи. Вам есть ещё поле для эксперементов, если ещё ячейки остались нетронутые.

Имеющий ум, да сочтит :-) А экпериментов, была проведена масса, разных, это я для вас, ардуринщиков, накалякал, и у кого-то оно даже заработало :-) 2-3 или 0-255 для атмеги не принципиально. Не в коем случае, не пытаюсь Вас в чём то переубедить, ибо изначальная задача Ваша, решалась не памятью, но лёгким движением ножа, или демонтажем перемычки.

А тем кто умеет считать, и логически мыслить, тема действительно пригодится. Главное в ней то, что ресурс перезаписи больше чем количество ячеек. И обходится самыми примитивными алгоритмама ремап-а, увеличивающими и без того не малый ресурс.

PS. Кому интересно, вставьте задержку в цикл, получите другую цифру, но не скоро :-) Цифра так-же зависит от качества питания меги, которая весьма прожорлива в режиме программирования.