Таймер подсчета времени наработки

Pritorius
Offline
Зарегистрирован: 25.10.2015

Доброго времени суток. Передо мной стоит задача написать программу которая на первый взгляд кажется очень тривиальной. Но т.к. дело обстоит с Arduino простая задача завела меня в тупик. Вобщем суть задачи такая: есть порт цифровой на нем в штатном режиме присутсвует 1 (порт притянут резистором к +5в). При появлении сигнала низкого уровня (0 - порт через оптопару притягивается к земле) необходимо запустить таймер который бы считал время наработки. Есще один "камень" в этом, что сигнал может держатся и час и два и сутки. После появления (1 - высокий уровень) таймер должен выключится и значение записаться в ЕЕПРОМ.  Как реализовать таймер подсчета на столь длителльное время?

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

таймер моточасов механический бери и не парь мосг - что бы потом не гадать: сбойнуло-не сбойнуло

Gres
Gres аватар
Offline
Зарегистрирован: 26.03.2013

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

Olm
Offline
Зарегистрирован: 09.10.2014

Настаиваете прерывание по таймеру и в обработчике считаете время когда на пине 0.  Такой проект на тиньке 13 можно реализовать. Информацию о наработке куда выводить планируете?  32х битной переменной будет достаточно на 136 лет, если её инкрементировать раз в секунду

axill
Offline
Зарегистрирован: 05.09.2011

Решение задачи зависит от дополнительных требований. Как то - точность счета и требованиями к адекватности результата при потерях питания

самый простой вариант сделать достаточно точно и достаточно адекватно отработать потерю питания вам уже предложили - использовать модуль часов реального времени с резервной батарейкой. При появлении логического нуля запоминаем в еепром время старта, при появлении логической единицы извлекаем это значение и считаем разницу. Эту разницу плюсуем к накопительному счетчику который тоже храним в еепром. Для расчёта разницы проще всего использовать юниксовский формат времёни, многие библиотеки RTC умеют его считать. В этом формате время представлено одним числом - число секунд от 01.01.1970. Разница считается простой операцией вычитания из времени окончания времени начала.

Кроме того в еепром желательно сохранять сам статус входа. Тогда можно реализовать такой сценарий. При включении ардуино смотрим какой статус в еепром. Если там ноль значит мы потеряли питание когда был ноль. Смотрим какой статус сейчас. Если единица то прошедшее время плюсуем в счётчик. Может получиться больше фактического, но это компромисс между потерей часов работы и некоторым завышением.

Olm
Offline
Зарегистрирован: 09.10.2014

Модуль часов это конечно хорошо. У меня часы на прерываниях идут с погрешностью пару секунд в месяц, а модуль на  DS1307 гуляет на 30 секунд в сутки туда-сюда. Проблему сохранения показаний при отключении питания можно решить установкой конденсатора на 500-1000 микрофарад и диода на питании. Перед диодом подтягиваем к земле 10-50 килоомами и конролируем наличие питания подсоединив  к какому-либо пину. Непрерывно опрашиваем этот пин и как только напруга пропадет, сохраняем переменную  в eeprom. Запись 1 байта eeprom на 16 мгц занимает 4.5мс и на заряде конденсатора успевает всё сохраниться. сам такой метод применял, работает надёжно. Надо только чтоб напруга резко обрывалась, чтоб заряд на конденсаторе оставался, а если питание медленно будет падать из-за других конденсаторов в блоке питания, которые могут быть и большей емкости, то не будет работать такой способ.

 

Pritorius
Offline
Зарегистрирован: 25.10.2015

Отвечу всем и по-порядку.

1. Сам бы не парился с ардуино и поставил бы обычный счетчик но на предприятии решили по-своему. Закупили Ардуино шилды и т.п. поэтому работаем с тем что есть.

2. Информация будет выводиться на 16х2 дисплей. Важны только часы наработки поэтому планирую сохранять в ЕЕПРОМ раз в час, а при пропадании питания считывать сохраненное значение из памяти и к нему плюсовать следующее.

3. Модуль DS3231 есть, гонял его неделю отклонений особых не заметно. Критичность измерения +-минуты и я не думаю что нужна особая точность ведь результат необходим в часа сугубо ориентеровочный.

з.ы. Спс за ответы попробую пошаманить с RTC и Юниксовским форматом времени. Может получится.

Olm
Offline
Зарегистрирован: 09.10.2014

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

axill
Offline
Зарегистрирован: 05.09.2011

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

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

При появлении логического нуля сохраняем значение millis(). При появлении единицы вычитаем его из текущего millis() получаем время

 

Olm
Offline
Зарегистрирован: 09.10.2014

В ардуино 1 миллисекунда по моему равна 1024 микросекунд, отсюда погрешность, надо поправку делать. а считает ардуина время точно. у меня пара секунд в месяц погрешность с учетом поправки. Если я не ошибаюсь в ардуино таймер 0 настроен на прерывание по переполнению, а там 1 миллисекунда никак не будет.

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

Вроде как 1 мс = 1024 мкс, но 43 мс = 43008 мкс. Микросекунды идут не совсем равномерно - с пропусками каждую 42-ю.

axill
Offline
Зарегистрирован: 05.09.2011

Olm пишет:

В ардуино 1 миллисекунда по моему равна 1024 микросекунд, отсюда погрешность, надо поправку делать. а считает ардуина время точно. у меня пара секунд в месяц погрешность с учетом поправки. Если я не ошибаюсь в ардуино таймер 0 настроен на прерывание по переполнению, а там 1 миллисекунда никак не будет.

С чего вы это взяли? В оригинальной документации не ничего подобного https://www.arduino.cc/en/Reference/Millis

Не смотрел как в ардуино реализована эта функция, но сам легко могу получить интервал 1мсек при тактировании от кварца 16мгц - достаточно поделить на 16000. На таймер1 это можно сделать в режиме CTC на железе, а на двух других таймерах используя комбинацию железного и программного счёта 

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

andriano пишет:

Вроде как 1 мс = 1024 мкс, но 43 мс = 43008 мкс. Микросекунды идут не совсем равномерно - с пропусками каждую 42-ю.

да, а 1000 = 1024 в дуино - отсюда все беды

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Olm пишет:

В ардуино 1 миллисекунда по моему равна 1024 микросекунд, отсюда погрешность, надо поправку делать.

andriano пишет:

Вроде как 1 мс = 1024 мкс, но 43 мс = 43008 мкс. Микросекунды идут не совсем равномерно - с пропусками каждую 42-ю.

ШТА?

1 с = 1000 мс = 1000000 мкс

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

Jeka_M пишет:

ШТА?

1 с = 1000 мс = 1000000 мкс

немогёт такого быть в 8-ми битной дуино

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Клапауций 911 пишет:

немогёт такого быть в 8-ми битной дуино

А, ну да! Совсем забыл: в дуино же время течёт по-другому :D Оно подчиняется Великому 8-ми битному Закону течения времени в архитектуре AVR.

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

Jeka_M пишет:

А, ну да! Совсем забыл: в дуино же время течёт по-другому :D Оно подчиняется Великому 8-ми битному Закону течения времени в архитектуре AVR.

помни, неофит, - 1000 = 1024 !

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Клапауций 911 пишет:

помни, неофит, - 1000 = 1024 !

Спсибо, учитель, я достиг просветления. А ещё поговаривают, что ёмкость жётских дисков тоже считают как 1000мб/1гб (т.е. 1000 = 1024). Это правда? Мой мир больше не будет прежним...

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

Jeka_M пишет:

Спсибо, учитель, я достиг просветления. А ещё поговаривают, что ёмкость жётских дисков тоже считают как 1000мб/1гб (т.е. 1000 = 1024). Это правда? Мой мир больше не будет прежним...

верно - массоны потребителю цифр недокладывают

axill
Offline
Зарегистрирован: 05.09.2011

Клапауций 911 пишет:

помни, неофит, - 1000 = 1024 !

уточнение - 1000 г = 1 кило = 1 килобайт = 1024 байт, итого 1000 / 1024 = 0.976 грамм / байт

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

axill пишет:

уточнение - 1000 г = 1 кило = 1 килобайт = 1024 байт, итого 1000 / 1024 = 0.976 грамм / байт

уточнение уточнения - кг. колбасы

axill
Offline
Зарегистрирован: 05.09.2011

Клапауций 911 пишет:

уточнение уточнения - кг. колбасы

ВОС сегодня издала отчет согласно которому колбаса вредно. Предлагаю поменять на кило мороженного

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

axill пишет:

Клапауций 911 пишет:

уточнение уточнения - кг. колбасы

ВОС сегодня издала отчет согласно которому колбаса вредно. Предлагаю поменять на кило мороженного

Молокопродукты из пальмового масла. Только кило "огненной воды".