Главная » Статьи » Общая тематика

Работаем с 8:30 до 19:00
Выдалось немного свободного времени, и я решил поделиться своими наработками. Описания устройства я не планировал, скажу кратко. Там есть часы реального времени, микроконтроллер и 4 реле. Одной из задач МК является включать и выключать выбранные пользователем реле (то есть, устройства, подключенные этим же пользователем к этим реле) в определенные интервалы суток. Так называемый автомат включения и выключения нагрузки.
Так вот, с задачей чтения времени и даты я справился, а вот с временем включения и выключения повозился. Искал в сети алгоритм, но не обнаружил подходящего. Предлагаю свой вариант. Возможно, не оригинальный, но все же, кого-то подтолкнет к решению своей задачи.

Итак, имеем время в обычном формате ЧЧ:ММ:СС.
Время в формате ЧЧ:ММ:СС
Для удобства назовем их HH:MM:SS
Это реальное текущее время. Тот же формат имеет и время включения и выключения. Не важно, как мы их получили.

Обозначим их как - HHon:MMon:SSon - время требуемого включения.
И соответственно - HHoff:MMoff:SSoff - время требуемого выключения.

Идея проста: преобразуем этот формат в секунды. Если нужна миллисекундная точность, то в миллисекунды, но число огромное уже получится.
Получаем текущее время: HH*3600 + MM*60 + SS
Таким же макаром получаем и время вкл/выкл.

Дадим имена переменным, которые будут хранить это время: RealTime, OnTime и OffTime.

При секундной точности требуется переменная размерностью в 4 байта, при минутной - достаточно двухбайтной переменной. 

Для примера возьмем реальные цифры.
Текущее время - пусть будет 13:26:07,
время включения 12:20:00,
Время выключения 17:30:00

Я не буду привязываться к какому-то языку, описываю лишь алгоритм.
Итак - RealTime = 13*3600 + 26*60 + 07 = 48367 секунд,
OnTime = 12*3600 + 20*60 + 00 = 44400 секунд,
OffTime = 17*3600 + 30*60 + 00 = 63000 секунд.

Далее создаем алгоритм для определения момента включения нагрузки.
Если текущее время больше или равно времени включения и меньше времени выключения, то включаем нагрузку.

В простом варианте выглядит так:
If (RealTime >= OnTime) And (RealTime < OffTime) Then
Relay = Work 
Else
Relay = NoWork
EndIf 

В общем случае этот вариант работает. И в данном примере можно проверить:
48367 больше, чем 44400, но меньше, чем 63000.
Но давайте представим, что юзеру ни с того ни с сего понадобилось включить, к примеру, вентилятор, в 21:40:00, а выключить - в 00:20:00. Вышеприведенное условие не выполнится.
Как быть в этом случае?

Условие немного усложняется:
If ((RealTime >= OnTime) And (RealTime < OffTime)) Or_
((RealTime > OffTime) And (OffTime < OnTime))Then
           Relay = Work
Else
           Relay = NoWork
EndIf


Прочитаем это условие по-русски:
Если текущее время в данный момент больше или равно времени включения, но пока еще меньше времени выключения, а также, если оно больше времени включения, и при этом время выключения меньше времени включения, то разрешаем работу.
Вторая часть условия проверяет, если время выключения меньше времени включения, то значит интервал нужного нам времени переходит через ноль часов. И таким образом, пока текущее время меньше времени выключения - работаем.
Но опять же, мы можем оказаться сразу при включении в этом интервале, который не будет охватываться условием. 
Поэтому добавим еще одно:
If ((RealTime >= OnTimeAnd (RealTime OffTime)) Or_
((RealTime OffTimeAnd (OffTime OnTime)) Or_
(RealTime < OffTimeAnd (RealTime OnTimeAnd (OnTime OffTimeThen
           Relay = Work
Else
           Relay = NoWork
EndIf

 Добавилась следующая проверка:
Если, независимо от первых двух условий, текущее время 
меньше и времени включения и времени выключения, и при этом время включения больше времени выключения,то также разрешаем работу.
Дабы не писать монструозную проверку в одно условие, я делаю так:

Dim a As Bit
Dim b As Bit
Dim c As Bit

If ((RealTime >= OnTimeAnd (RealTime OffTime)) Then
          a = 1
else
          a = 0
EndIf

И так далее...
В конце проверяю:
If (a = 1 Or b = 1 Or с = 1) Then
           Relay = Work
Else

           Relay = NoWork
EndIf

Мое устройство находится на стадии завершения разработки ПО, но данная часть работает.
Если у кого-то есть замечания - прошу!


Категория: Общая тематика | Добавил: ADMIN (16.09.2015)
Просмотров: 4536 | Комментарии: 13 | Теги: интервал времени, Автомат включения, нагрузка | Рейтинг: 5.0/3
Всего комментариев: 13
1 Matrix252005   (17.09.2015 08:06) [Материал]
Приятного времени суток!!!

Хорошая статья, Максим!!!!

Я что то похожее делал давно, только такой точности до секунды мне не нужно было... Я делал так:

Код
.....
' MinsOff, HrsOff                       - время отключения сенсорного датчика.
' MinsOn, HrsOn                         - время включения сенсорного датчика.
.....
Dim T_VAL1        As Word                    ' текущее время (HRS * 60 + Mins)
Dim T_VAL2        As Word                    ' время откл датч дв-я
Dim T_VAL3        As Word                    ' время вкл датч дв-я
......
T_VAL1 = (Hrs * 60) + Mins
T_VAL2 = (HrsOff * 60) + MinsOff
T_VAL3 = (HrsOn * 60) + MinsOn
.....
' ---------------- Контроль за временем для датчика дв-я ---------------

If S_Off = 0 Then
    If T_VAL1 >= T_VAL2 Or T_VAL1 < T_VAL3 Then  
       SOff = 1
       L_Home = 0
       Sensor = 0
       Podsv = 1
       S_DV_TMP = 1
    Else
       SOff = 0
       Sensor = 1
    EndIf
EndIf

Этот кусок кода из программы для управления светом(датчиком движения и подсветкой пола) в прихожей для "умного дома"... Сейчас переделываю его под более мощный МК.

0
2 ADMIN   (17.09.2015 08:45) [Материал]
Спасибо. Да, то же самое и у меня. Секунды я там не учитываю.
Вот все жду, когда свой дом будет. Там буду уже реализовывать умный дом.

3 MiXaS   (17.09.2015 09:31) [Материал]
Спасибо! Тоже был опыт такого рада. Делал как Matrix252005

4 xvovanx   (20.09.2015 11:26) [Материал]
Спасибо, отличная идея считать все в секундах! Как сам не допёр... surprised Делал проект с 4 таймерами вкл/выкл, так замучился с кучей переменных (отдельно часы, минуты, секунды), а про условия сравнений вообще молчу - были "трехэтажные".

0
5 ivan_fd   (20.09.2015 15:21) [Материал]
Что то последнее условие и описание не сходится.
Или это мне кажется.

6 xvovanx   (20.09.2015 15:25) [Материал]
Чтобы оставить возможность ручного управления (выключить устройство во время действия таймера) "сташное" условие

If ((RealTime >= OnTime) And (RealTime < OffTime)) Or_
((RealTime > OffTime) And (OffTime < OnTime)) Then
Relay = Work
Else
Relay = NoWork
EndIf

упрощается

If ((RealTime = OnTime) Then
Relay = Work
EndIf
If (RealTime = OffTime) Then
Relay = NoWork
EndIf

0
7 ivan_fd   (21.09.2015 10:57) [Материал]
Цитата
упрощается

А если прибор включить когда время включения уже прошло?

Работать не будет ни то, ни то.

0
8 ADMIN   (21.09.2015 17:58) [Материал]
Да, кстати, сейчас борюсь с этим вопросом. Если питание пропало, прибор оказывается в неизвестном состоянии. Помню давным давно решал уже такой вопрос. Постараюсь вспомнить, чем кончилось...

9 xvovanx   (21.09.2015 18:07) [Материал]
Я борюсь с пропаданием питания записью флага смены состояния таймера в память

0
10 ADMIN   (21.09.2015 18:29) [Материал]
Здесь вопрос в определении того места во времени, где ты оказался при включении питания. Вот нужно правильно определить отрезок, на котором находится текущее время. Вроде определил. проверю сегодня-завтра...

11 mikhail09p   (27.09.2015 13:34) [Материал]
А я делаю сейчас иначе. Полностью отказался от отдельных микросхем реального времени, ПИК прекрасно с этим справляется. Потребление около 14 микроампер. Заодно нету проблем с пропаданием питания. Программа всегда исполняется (та часть, которая нужна в данном режиме).
А для того, чтобы можно было изменить параметр (или флаг) во время выполнения условия делаю так:

         If SECONDS>=60 Then     ;
         SECONDS=0
         If HOUR = HOURr[0] And MINUTES = MINUTESr[0] Then SetTemp = TEMPUST[1]
         If HOUR = HOURr[1] And MINUTES = MINUTESr[1] Then SetTemp = TEMPUST[2]
         If HOUR = HOURr[2] And MINUTES = MINUTESr[2] Then SetTemp = TEMPUST[3]
         If HOUR = HOURr[3] And MINUTES = MINUTESr[3] Then SetTemp = TEMPUST[0]

         Inc MINUTES            ;
               GoSub Sr
               If MINUTES=60 Then
               MINUTES=0
               'SECONDS=K
               Inc HOUR               ;
                    If HOUR=24 Then
                    HOUR=0                        
                    EndIf
              EndIf
        EndIf

В результате я делаю проверку раз в минуту ( можно и раз в секунду, если нужно) и могу в работе изменить параметр безболезнено.
Если пропадёт питание, программа, выйдя из сна по прерыванию секундному сделает всё-равно проверку и при совпадении, присвоит нужнве значения SetTemp = TEMPUST.

0
12 ADMIN   (01.10.2015 08:43) [Материал]
Статью дополнил

13 Ingvar   (06.10.2015 19:47) [Материал]
Нормальное решение вопроса. Скорректировать под себя всегда можно. Я хорошие идеи всегда в тумбочку складываю, и эту положу, пригодится когда-нить... Спасибо!

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]