Аналоги setTimeout() и clearTimeout() в atmega168 atmega328
- Войдите на сайт для отправки комментариев
Имеется код, в котором кнопками регулируется состояние аналогового пина и периодически производится запись в EEPROM этого состояния. При регулировке, значение изменяется "очень часто" кнопками "+" и "-" и нет надобности записывать значения сразу после изменения, ведь EEPROM, яко бы имеет свой лимит перезаписи.
Возникает задача:
при изменении значения запускать таймер;
через пару секунд после последней корректировки значения записывать его в EEPROM;
соответственно, перезапускать таймер при очередном изменении значения, чтобы в EEPROM писать не через две секунды после первого изменения, а через 2 после последнего.
Как это проще и правильнее сделать?
Или же заиметь один таймер, который раз в ~надчать секунд смотрит, сколько времени назад было последнее изменение переменой и, если он изменялась более пары секунд назад и не равна своему прошлому значению, то записывать новое в EEPROM. Это + 1 таймер и две переменных - времени последнего изменения и прошлого состояния переменной.
Ну, ставите 16-битный таймер в Normal Mode с делителем 1024, и запрещаете прерывание по переполнению.
При каждом нажатии кнопки делаете следующее:
1. разрешаете прерывание по переполнению
2. записываете в регистр счётчика, число соответсвующее Вашему временному интервалу (для 2с это, вроде 34285, но пересчитайте сами, это я в уме посчитал).
Обработчик прерывания такой
1. запрещаете прерывания по переполнению
2. записываете чего надо в EEPROM.
Всё. Будет записываться через 2 с. после последнего нажатия кнопки.
Если потребуются более длительные интервалы (на которые не хватит ондного переполнения) можете устроить счётчик переполнений, например.
Это вовсе не аналог setTimeOut(), а обычное откладывание действий с контролем максимального интервала. setTimeOut() устанавливает процедуру, которая один раз вызовется при истечении интервала, уж тогда setInterval().
Вам необходимо простая проверка, которую можно сделать разными способами. Самое простое, запоминать время последнего нажатия на кнопку и в рабочем цикле постоянно сравнивать с текущим временем, кроме того, сравнивать текущее время со временем последней записи. Если время, после нажатия на кнопку не достигло интервала ожидания, ничего не делать, иначе поставить флаг необходимочти записи. Если время последней записи достигло критичного интервала или есть флаг записи, записать. А можно по таймеру записывать с фиксированным в любом случае, или по флагу, что были нажатия и чего-то записать надо.
Оптимальным решением тут будет несколько иное. Ничего не писать вообще в eeprom, пока есть внешнее питание. При его пропадании, обеспечить бэкап батарейкой или танталовым кондёром, процессором отлавливать пропадание внешнего питания, записывать чего надо и переходить в спящий режим.
Если писать 1 раз в час в eeprom, то 100000/24/365 = более 11 лет... :)
faeton,
Вы не поняли, что ему нужно. Вот смотрите, у меня есть радиоприёмник и он работает так:
1. Если я поменял станцию и слушаю её не меняя в течение 4 минут, то он запоминает ёё, чтобы включить её же при следующем включении питания.
2. Если я поменял громкость и после этого не меняю её в течение 2 минут, он опять же запоминает её, чтобы включить такую же при следующем включении питания.
ТС нужно примерно тоже самое.
А теперь прикиньте: что мне толку от запоминания "раз в час"? Постоянно будет получаться, что я полчаса послушал, выключил, а она не запомнилась.
А с батарейкой или конденсатором, ну не знаю, из-за такой ерунды плодить дополнительный конденсатор или тем более батарейку, которую надо иногда заменять, да ещё и задействовать дефицитную "ногу" контроллера на контроль питания - я Вас умоляю, гораздо проще завести таймер (я описал ТС как это делается) и всего делов-то.
faeton,
Вы не поняли, что ему нужно. Вот смотрите, у меня есть радиоприёмник и он работает так:
1. Если я поменял станцию и слушаю её не меняя в течение 4 минут, то он запоминает ёё, чтобы включить её же при следующем включении питания.
2. Если я поменял громкость и после этого не меняю её в течение 2 минут, он опять же запоминает её, чтобы включить такую же при следующем включении питания.
ТС нужно примерно тоже самое.
А теперь прикиньте: что мне толку от запоминания "раз в час"? Постоянно будет получаться, что я полчаса послушал, выключил, а она не запомнилась.
А с батарейкой или конденсатором, ну не знаю, из-за такой ерунды плодить дополнительный конденсатор или тем более батарейку, которую надо иногда заменять, да ещё и задействовать дефицитную "ногу" контроллера на контроль питания - я Вас умоляю, гораздо проще завести таймер (я описал ТС как это делается) и всего делов-то.
Наверное, мы оба не совсем точно понимаем что человеку надо... Он говорил, что кнопки могут иногда нажиматься часто и не следует их сразу же записывать. Ну, по принципу чиновников: хорошее дело должно вылежаться. :) Если о приёмнике, то тут, наверное, такое уточнение: громкость регулируется кнопкой и не надо писать всю историю вывода громкости на желаемое значение пледовательным нажатием кнопки 10 раз, надо записать то значение, которое устаканилось. Примерно так же я делал при чтении весов.
Кстати, раз в час т.с. надо тоже не писать в любом случае, очевидно, а проверять было ли вообще изменение - я это упустил в своём первом сообщении.
Про батарейку и ноги... Совершенно недостоверно предполагаю каку-то фунцию "что-то там в названии-BDO" или какой-то похожей аббревиатурой, суть которой обнаружение внутри процессором снижение напряжения питания. Что-то в памяти отложилось от изучении даташита в первом чтении т.с., но не задержалось по ненадобности пока. Если потребуется, загляну в даташит ещё раз и найду эту фишку. Может быть, кто-то про это знает достоверно и имеет опыт.
Кстати, запоминать громкость и восстанавливать её при включении - плохой тон? как мне кажется... По крайнемй мере, приличные магнитоллы так не делают. Я иногда домой приезжаю с таким уровнем громкости, что соседи косо поглядывают. Если утром этот уровень громкости восстановится при включении зажигания, будет мягко говоря немного неожиданно. :)
Кстати, запоминать громкость и восстанавливать её при включении - плохой тон? как мне кажется...
Вам так кажется, Вы так не делаете. Мы свободные люди в свободной стране.
Как это проще и правильнее сделать?
Проще и правильнее использовать флаговую логику и блинк без делай. Типа такого:
Всё. И никаких "таймеров", обработчиков ..
Как это проще и правильнее сделать?
Проще и правильнее использовать флаговую логику и блинк без делай. Типа такого:
Всё. И никаких "таймеров", обработчиков ..
Кто-то говорил о хорошем тоне программирования, но зятянул в язык высокого уровня флаги 0/1 :))) Наверное, false и true будет красивее. :)
А вот конструкция everyMilliss(WAIT, {}); меня удивила... Это как так в процедуру отдать кусок кода? Я, очевидно, что-то не знаю в языке С... :) Полез искать arhat.h и курить исходник... :)
Мы свободные люди в свободной стране.
это где это вы такие и там? покажите мне на глобусе России такую страну!
А вот конструкция everyMilliss(WAIT, {}); меня удивила...
Это просто макрос.
А вот по поводу куска кода ...
Это как так в процедуру отдать кусок кода? Я, очевидно, что-то не знаю в языке С... :)
Очевидно, не знаете.
В С++ имеются лямбда-выражения - тот самый случай - отдать в функцию (или присвоить переменной) кусок кода.
Им, конечно, далеко до полноценных лямбда выражений в функциональных языках (убогие они здесь), но как факт - передать кусок кода или присвоить его переменной - как два пальца. Можете MSDN почитать.
Кстати, в среде ArduinoIDE все это отлично работает, только нужно опцию компилятора добавить, а именно прописать "-std=c++11" в опцию compiler.cpp.flags файла
<arduino location>\hardware\arduino\avr\platform.txt
Там было "Я, очевидно, что-то не знаю в языке С..." .. в "С" - нет лямбда-выражений. Там ваще ничего "матерного нет". Простой и удобный язык. недаром Торвальдс отношение к С/С++ применяет как критерий оценки профпригодности.. :)
Там было "Я, очевидно, что-то не знаю в языке С..." .. в "С" - нет лямбда-выражений.
Здесь форум про ардуино и по контексту речь шла о языке, используемом ардуино IDE. О том, что я писал про С++, в моём посте указано явно. Хотите придираться - ищите нормальные поводы, типа деления целочисленных констант в дефайне или незнания имени своего учителя.
Очевидно, не знаете.
В С++ имеются лямбда-выражения - тот самый случай - отдать в функцию (или присвоить переменной) кусок кода.
Им, конечно, далеко до полноценных лямбда выражений в функциональных языках (убогие они здесь), но как факт - передать кусок кода или присвоить его переменной - как два пальца. Можете MSDN почитать.
Кстати, в среде ArduinoIDE все это отлично работает, только нужно опцию компилятора добавить, а именно прописать "-std=c++11" в опцию compiler.cpp.flags файла
<arduino location>\hardware\arduino\avr\platform.txt