Комментарии
Странно, что готовые модули продаются по 10 баксов штука. Сам FM24CL16 стоит $1 в розницу и $0.5 оптом на али. Он имеет настолько простую схему подключения, что платить в 10-20 раз за модуль это слишком.

P.S. А почему бы в данной ситуации вместо оперативки microsd? Туда же можно писать уже что угодно — хоть GPS хоть коды ODB2 хоть данные гироскопа-акселерометра.
берем breakout ценой примерно ноль, перемыкиваем прямо на внешний контактах, останется только напряжение подтянуть и все.
Да, меня тоже поразила разница в цене микрухи и сборки.
За чип хотят 16р/штука.

SD хорошо, но там слишком много контактов. Это же мотоцикл, более того, эндуро. Там такие вибрации, что контакты противопоказаны.

Ну и жрёт память SD в ардуине и флеш жрёт и быстродействие совсем не то. Здесь же i2c одна на всех, две ножки всего. Никаких файловых систем, просто пиу и готово.
P.S. А почему бы в данной ситуации вместо оперативки microsd?

насколько я понимаю, только промышленные micro sd карты (с соответствующей ценой) сравнимы по циклам записи с eeprom. у дешевых карт — циклов записи меньше.
тут, конечно, может помочь больший размер карты — можно устраивать wear leveling с циклическими буферами.
но в этом случае возникает вопрос про хранение указателя ) или поиска последней записи по сигнатуре )
в принципе, указатель в данном случае:
а. можно хранить в памяти, а записывать только по прерыванию на понижении питания
б. использовать код грея для указателя — чтобы уменьшить износ младших бит в ячейке

недавно был пост про малинку и readonly fs — там обсуждали износостойкость и были ссылки на информацию по картам
https://geektimes.ru/post/283802/
Про беду с хранением указателя я писал выше. Можно писать блоками на sizeof некую структуру и в ней держать байт маркера. О, сейчас напишу в самой статейке.
Написал в тексте статьи два способа организации циклической записи без хранения указателя.
Обмануть судьбу можно, как мне кажется, просто зануляя предыдущее значение. Суммарное снижение ресурса получится в 2 раза или даже чуть меньше.
А моточасы, надо полагать, величина всегда возрастающая, поэтому можно просто писать в следующую ячейку и потом искать наибольшее значение.

Впрочем, попробовать новые штуки — тоже хорошо :]
МЧ и одометры растут конечно, но им тоже нужен сброс. Есть одометр поездки, сбрасывается перед стартом. Есть МЧ после ТО, тоже сбрасываются после того самого ТО.
Хорошо, при сбросе (записи нуля) просто занулить все ячейки.
Я думал занулить в sram, а запишет оно уже по расписанию.

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

Я не понял — надо два занчения хранить при выключении питания? И ради этого сыр бор?
В чем проблема хранить показания одометра в еепроме (не обязательно внутреннем — их на любой плате россыпь обычно, спаял да прикрутил на соплях) по смещению 0x00, отвести на это целых четыре байта, например, а часы хранить в структуре по смещению 0x04???
Там больше. Три одометра, два счётчика МЧ.
Может ещё что-то всплывёт.
Микросхема стоит 16р/ш при покупке от 10 штук. Я её потом напаяю прямо на плату, когда буду разводить. Главное — код мизерный, память не ест, гемора нет.
может хранить в микросхеме часов с батарейкой, и изредка сбрасывать на епром?
вот например, RTC + i2c + 64 bytes RAM backed by battery
http://www.nxp.com/documents/data_sheet/PCF85363A.pdf

батарейки живут долго, там успеешь и имплементировать отслеживание разряда батареии и приглашение её поменять.
А что будет с памятью в pcf85363a, если сядет батарейка или надо просто её поменять?
Батарейка от вибрации (мотоцикл) может и отскочить на ходу. Лишиться часов не так страшно, как одометров и моточасов.
Бакап в епроме будет ээээ сильно устаревшим же.

Опять гемор, зачем, если есть fram?
У EEPROM время жизни скажем ~100 тысяч циклов, если обновлять одну и ту же ячейку раз в секунду, то хватит примерно на сутки. Идея заключается в том, чтобы использовать новую позицию для записи каждый раз, 1К памяти хватит на 3 года.

Простейший алгоритм реализации — это ввести некий счетчик, который увеличивается каждый раз при сохранении структуры (содержащей данные и сообственно счетчик). Если счетчик дошел до 100.000 — инкрементируется позиция структуры (которую можно хранить по фиксированному адресу, т.к. запись туда происходит редко).
Как раз примерно такое я описал только что в статье по просьбе комментирующего.
У EEPROM время жизни скажем ~100 тысяч циклов

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

если мы просто инкременитируем байт — то каждый раз младший бит мигает. и в конце концов умирает, а старшие разряды живы.
в итоге, добавив минимальную логику на преобразование gray-binary мы можем растянуть срок жизни еще в 8 раз )

Википедия — Код Грея
Это понятно.
Но использование fram добавляет 16р к цене устройства и позволяет не париться с проблемами еепрома навсегда.
Идея заключается в том, чтобы использовать новую позицию для записи каждый раз, 1К памяти хватит на 3 года.

Всё хорошо, если стирание/запись не постраничная, как это часто бывает. Но на таких размерах это обычно не так.

Даже три года — это очень очень мало.
Вы видели автомобиль с электронным одометром, который дохнет через три года? Я нет.
Три года = это расчетное значение при непрерывной эксплуатации 24/7, если так эксплуатировать автомобиль, то не одометр, а он сам сдохнет раньше 3 лет.
Причины сыра-бора описаны во втором абзаце — ограниченный ресурс еепрома. Если в мегу писать раз в 10 секунд, то гарантированно проработает она только ~11 дней(100 000 циклов/ячейку / 3600 / 24 * 10) и даже установка внешней еепромки увеличит ресурс всего в 10 раз (для первой загуглившейся AT24C16B). Так что проблему это не решит.
Хотя всё же проще кольцевой буфер или, ИМХО, правильнее детектировать отключение питания и тогда всё сохранять, например, как тут http://radiokot.ru/forum/viewtopic.php?p=1120034#p1120034
Писать по пропаданию питания — хорошая идея, но… ненадёжно.
Я это планирую сделать, но с FRAM как-то заметно проще получается.
Сначала я хотел обмануть судьбу записывая структурку данных в разные места 1К памяти чипа по кругу. Упёрся в то, что указатель надо где-то хранить тоже, а данные достаточно случайные, чтобы использовать какой-то маркер для последовательного поиска.

Можно было, наверное, два кольцевых буфера завести, один с указателем (увеличивается равномерно, при поиске искать самое большое число, которое не FF), а второй собственно с данными.
Есть средство лучше. Описал в статейке, посмотри обновление.
Я делаю примерно так. Два однобайтовых каунтера — глобальный в ячейке 0 и локальный в самой структуре (которую будем двигать по eeprom). Глобальный задает номер блока в который пишем наши данные (ну то есть смещение блока данных). После каждой записи увеличиваем локальный счетчик и перезаписываем его в месте с данными. Как только дошли до 256 увеличиваем глобальный счетчик и переходим к следующему блоку сбросив локальный счетчик в 0. Дошли до конца памяти — глобальный счетчик в 0 и дальше по циклу. Глобальный счетчик перезаписывается только 1 раз на 256 записей. Локальный каждый раз, но он после каждых 256 записей переезжает на новое место.
Из личного опыта FRAM память довольно чувствительна к помехам по напряжению питания. Если использовать для установки на мотоцикл, это необходимо учесть.
Я на входе ставлю стабилизатор (китайский импульсный понижатель постоянного напряжения с ШИМ) и толстый конденсатор для дополнительного сглаживания и питания в случае чего. На вход, где 12В, через делитель подключаю ногу ардуины. Если на ней пропало напряжение, значит у нас есть несколько миллисекунд на запись состояния и самоубийство. Экранчик питается отдельно. Думаю как лучше сделать.
НЛО прилетело и опубликовало эту надпись здесь
Хорошая мысль, кстати.
Добавлю в проект, спасибо.
Тогда надо писать в циклический буфер как минимум на две структурки таких. Для бакапа.
Обновил статью. Добавил ссылки на алиекспресс и примеры решения с EEPROM или Flash.
Зачем постоянно в EEPROM писать — при включении прочитали последнее значение, при выключении записали.
Нужно только реализовать «реакцию» на отключение питания, и схему на поддержание питания Ардуины, что бы успела скинуть последнее значение в EEPROM.
Если бы было плевать на потерю этих данных, я бы так и сделал. Вероятность потери же весьма велика. Права на ошибку нет, что-то сглючило с еепромом и прощай. Это всё-таки не микроволновка, а мотоцикл.
И Ваш способ не избавляет от вероятности потери данных:
...«что-то сглючило с FRAM и прощай»...

Помехи обмена по I2C, блокирующая реализация Wire библиотеки…
i2c с подтверждением работает. Я в библиотеке верю в качество передачи, но надо убеждаться. Это в ближайшее время пофиксю.
Всё глючит, потом бакап в eeprom — это хорошо, но только как бакап.

Я в своём проекте ambox.me делаю именно так как предложенной выше. Плюс еже простейшая схема из электролита и диода на входечтобы питание не пропадало неожиданно. АЦП и источник опорного в Ардуине, благо есть. Пр правильной организации кольцевого буфера можно не только повысить ресурс eeprom на 2.5 порядка, но и гарантировать откат на предыдущее значение, если что.

Да, я всё это уже и сам придумал, когда статью написал. Я просто не стал бороться с еепромом, а решил проблему тупо железкой, с которой биться не нужно. :)
Вот, рекомендую.
Любопытная память, спасибо. Хотя раз уж тут речь о микроконтроллере, то это десятки миллиампер потребляемого тока, а значит, если добавить хороший емкий конденсатор в цепь питания, то при выключении внешнего питания у вас будет несколько секунд на то, чтобы разобрать все данные в SRAM и записать в EEPROM. При таком подходе срок её жизни существенно увеличится.
Нескольких секунд не будет, будут миллисекунды. Писать надо по прерыванию так как до чтения ноги питания может не дойти. Прерываний внешних всего два, оба заняты.
Способ с FRAM надёжнее заметно. Конечно же, намного проще.
Одно другое не исключает, даже наоборот. :) Я собираюсь писать и туда и туда. Просто fram на i2c и шина тоже может сглючить даже на 100кГц.
по поводу «Прерываний внешних всего два, оба заняты.» не совсем верно ))
прерываний больше, просто их на одну строчку кода сложнее обрабатывать))))
не ограничивайте себя int0 & int1
ловите pin change на порт и просто проверяйте нужную ногу

для атмеги328
4 Pin Change Interrupt Request 0 (pins D8 to D13) (PCINT0_vect)
5 Pin Change Interrupt Request 1 (pins A0 to A5) (PCINT1_vect)
6 Pin Change Interrupt Request 2 (pins D0 to D7) (PCINT2_vect)

тут есть прекрасный саммари http://gammon.com.au/interrupts, чтобы толстый даташит не перекапывать
Я в курсе про пинченч и векторы.
Я к тому, что те два без всякого вектора, хардкорного программирования, группирования, разбора в функции, с какой ноги пришло оно.
Если нет фрама, то да, надо упарываться со схемотехникой и ломать голову над живучестью еепрома. А если есть, то не надо :)
Это какой конденсатор поставите. На 33000 микрофарад Ардуина живет больше 5 секунд. Вполне достаточно для сохранения, можно даже и меньше конденсатор поставить.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.