Таймер подсчета времени наработки
- Войдите на сайт для отправки комментариев
Вс, 25/10/2015 - 08:54
Доброго времени суток. Передо мной стоит задача написать программу которая на первый взгляд кажется очень тривиальной. Но т.к. дело обстоит с Arduino простая задача завела меня в тупик. Вобщем суть задачи такая: есть порт цифровой на нем в штатном режиме присутсвует 1 (порт притянут резистором к +5в). При появлении сигнала низкого уровня (0 - порт через оптопару притягивается к земле) необходимо запустить таймер который бы считал время наработки. Есще один "камень" в этом, что сигнал может держатся и час и два и сутки. После появления (1 - высокий уровень) таймер должен выключится и значение записаться в ЕЕПРОМ. Как реализовать таймер подсчета на столь длителльное время?
таймер моточасов механический бери и не парь мосг - что бы потом не гадать: сбойнуло-не сбойнуло
Можно использовать модуль часов. По событию, считали время старта и сохранили, по следующему событию, считали время остановки, высчитали время наработки и сохранили результат. В следующем цикле результаты суммируете.
Настаиваете прерывание по таймеру и в обработчике считаете время когда на пине 0. Такой проект на тиньке 13 можно реализовать. Информацию о наработке куда выводить планируете? 32х битной переменной будет достаточно на 136 лет, если её инкрементировать раз в секунду
Решение задачи зависит от дополнительных требований. Как то - точность счета и требованиями к адекватности результата при потерях питания
самый простой вариант сделать достаточно точно и достаточно адекватно отработать потерю питания вам уже предложили - использовать модуль часов реального времени с резервной батарейкой. При появлении логического нуля запоминаем в еепром время старта, при появлении логической единицы извлекаем это значение и считаем разницу. Эту разницу плюсуем к накопительному счетчику который тоже храним в еепром. Для расчёта разницы проще всего использовать юниксовский формат времёни, многие библиотеки RTC умеют его считать. В этом формате время представлено одним числом - число секунд от 01.01.1970. Разница считается простой операцией вычитания из времени окончания времени начала.
Кроме того в еепром желательно сохранять сам статус входа. Тогда можно реализовать такой сценарий. При включении ардуино смотрим какой статус в еепром. Если там ноль значит мы потеряли питание когда был ноль. Смотрим какой статус сейчас. Если единица то прошедшее время плюсуем в счётчик. Может получиться больше фактического, но это компромисс между потерей часов работы и некоторым завышением.
Модуль часов это конечно хорошо. У меня часы на прерываниях идут с погрешностью пару секунд в месяц, а модуль на DS1307 гуляет на 30 секунд в сутки туда-сюда. Проблему сохранения показаний при отключении питания можно решить установкой конденсатора на 500-1000 микрофарад и диода на питании. Перед диодом подтягиваем к земле 10-50 килоомами и конролируем наличие питания подсоединив к какому-либо пину. Непрерывно опрашиваем этот пин и как только напруга пропадет, сохраняем переменную в eeprom. Запись 1 байта eeprom на 16 мгц занимает 4.5мс и на заряде конденсатора успевает всё сохраниться. сам такой метод применял, работает надёжно. Надо только чтоб напруга резко обрывалась, чтоб заряд на конденсаторе оставался, а если питание медленно будет падать из-за других конденсаторов в блоке питания, которые могут быть и большей емкости, то не будет работать такой способ.
Отвечу всем и по-порядку.
1. Сам бы не парился с ардуино и поставил бы обычный счетчик но на предприятии решили по-своему. Закупили Ардуино шилды и т.п. поэтому работаем с тем что есть.
2. Информация будет выводиться на 16х2 дисплей. Важны только часы наработки поэтому планирую сохранять в ЕЕПРОМ раз в час, а при пропадании питания считывать сохраненное значение из памяти и к нему плюсовать следующее.
3. Модуль DS3231 есть, гонял его неделю отклонений особых не заметно. Критичность измерения +-минуты и я не думаю что нужна особая точность ведь результат необходим в часа сугубо ориентеровочный.
з.ы. Спс за ответы попробую пошаманить с RTC и Юниксовским форматом времени. Может получится.
Попробуйте всетаки на прерываниях инкрементировать счетчик. Точность достаточная, не надо заморачиваться юниксовским временем, пересчетом. тупо считать время по моему проще, если другой задачи нет. И сохранять по исчезновению питания можно как я выше написал.
Если точность большая не нужна можно и без модуля часов, считать по встроенному в ардуину кварцевому генератору
можно самому настроить прерывание, но проще использовать встроенный механизм, в ардуино уже предусмотрен счётчик времени, онисчитает время от включения ардуино в миллисекундах. Доступ к счетчику через функцию millis(). Нужно только учесть возможность переполнения этого счетчика (ситуация когда сохранённое ранее время больше чем текущее). Математически это легко решается
При появлении логического нуля сохраняем значение millis(). При появлении единицы вычитаем его из текущего millis() получаем время
В ардуино 1 миллисекунда по моему равна 1024 микросекунд, отсюда погрешность, надо поправку делать. а считает ардуина время точно. у меня пара секунд в месяц погрешность с учетом поправки. Если я не ошибаюсь в ардуино таймер 0 настроен на прерывание по переполнению, а там 1 миллисекунда никак не будет.
Вроде как 1 мс = 1024 мкс, но 43 мс = 43008 мкс. Микросекунды идут не совсем равномерно - с пропусками каждую 42-ю.
В ардуино 1 миллисекунда по моему равна 1024 микросекунд, отсюда погрешность, надо поправку делать. а считает ардуина время точно. у меня пара секунд в месяц погрешность с учетом поправки. Если я не ошибаюсь в ардуино таймер 0 настроен на прерывание по переполнению, а там 1 миллисекунда никак не будет.
С чего вы это взяли? В оригинальной документации не ничего подобного https://www.arduino.cc/en/Reference/Millis
Не смотрел как в ардуино реализована эта функция, но сам легко могу получить интервал 1мсек при тактировании от кварца 16мгц - достаточно поделить на 16000. На таймер1 это можно сделать в режиме CTC на железе, а на двух других таймерах используя комбинацию железного и программного счёта
Вроде как 1 мс = 1024 мкс, но 43 мс = 43008 мкс. Микросекунды идут не совсем равномерно - с пропусками каждую 42-ю.
да, а 1000 = 1024 в дуино - отсюда все беды
В ардуино 1 миллисекунда по моему равна 1024 микросекунд, отсюда погрешность, надо поправку делать.
Вроде как 1 мс = 1024 мкс, но 43 мс = 43008 мкс. Микросекунды идут не совсем равномерно - с пропусками каждую 42-ю.
ШТА?
1 с = 1000 мс = 1000000 мкс
ШТА?
1 с = 1000 мс = 1000000 мкс
немогёт такого быть в 8-ми битной дуино
немогёт такого быть в 8-ми битной дуино
А, ну да! Совсем забыл: в дуино же время течёт по-другому :D Оно подчиняется Великому 8-ми битному Закону течения времени в архитектуре AVR.
А, ну да! Совсем забыл: в дуино же время течёт по-другому :D Оно подчиняется Великому 8-ми битному Закону течения времени в архитектуре AVR.
помни, неофит, - 1000 = 1024 !
помни, неофит, - 1000 = 1024 !
Спсибо, учитель, я достиг просветления. А ещё поговаривают, что ёмкость жётских дисков тоже считают как 1000мб/1гб (т.е. 1000 = 1024). Это правда? Мой мир больше не будет прежним...
Спсибо, учитель, я достиг просветления. А ещё поговаривают, что ёмкость жётских дисков тоже считают как 1000мб/1гб (т.е. 1000 = 1024). Это правда? Мой мир больше не будет прежним...
верно - массоны потребителю цифр недокладывают
помни, неофит, - 1000 = 1024 !
уточнение - 1000 г = 1 кило = 1 килобайт = 1024 байт, итого 1000 / 1024 = 0.976 грамм / байт
уточнение - 1000 г = 1 кило = 1 килобайт = 1024 байт, итого 1000 / 1024 = 0.976 грамм / байт
уточнение уточнения - кг. колбасы
уточнение уточнения - кг. колбасы
ВОС сегодня издала отчет согласно которому колбаса вредно. Предлагаю поменять на кило мороженного
уточнение уточнения - кг. колбасы
ВОС сегодня издала отчет согласно которому колбаса вредно. Предлагаю поменять на кило мороженного
Молокопродукты из пальмового масла. Только кило "огненной воды".