Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Расчёт времени по времени


Расчёт времени по времени

Сообщений 1 страница 15 из 15

1

Не знаю как назвать эту тему, но думаю многим будет интересна как головоломка.
Задача простая. У нас есть часы реального времени, лампочка и время её включения.

При включении лампочки мы запоминаем: Год-Месяц-День-Час-Минута-Секунда
Теперь нам нужно, чтоб лампочка горела 5 минут и отключилась, но вот беда, вырубило везде свет и включили через год )))))
Считываем с часов реального времени типа DS1307 данные и получаем:

Реальное время:  Год-Месяц-День-Час-Минута-Секунда
Время запуска:    Год-Месяц-День-Час-Минута-Секунда
Сколько лампочка работает: ????

Алгоритм из IF просто жесть, вот краткий не законченный кусочек:

Алгоритм на IF
Код:
'========================================== Переменные рассчёта времени
Dim Vrin(6) As Byte                                         'Запомненное время
Dim Vrout As Dword                                          'Выход в минутах
Dim Vrtm3 As Dword                                          'Временная переменная Dword для рассчёта
Dim Vrtm1 As Byte     

....
'================== рассчёт времени
Timeload:
'Массив Vrin(6)
'1-секунды
'2-минуты
'3-часы
'4-день
'5-месяц
'6-год
'Переменные с часов реального времени:
'Seco
'Mine
'Hour
'Dat
'Month
'Year

Vrout = 0
Gosub Clock:
If Year = Vrin(6) Then                                      'Если год равен
   If Month = Vrin(5) Then                                  'Если месяц равен
      If Dat = Vrin(4) Then                                 'Если день равен
                 If Hour = Vrin(3) Then                     'Если час равен
                    If Mine = Vrin(2) Then                  'Если минуты равны то без изменений
                       Vrout = 0
                       Elseif Mine > Vrin(2) Then           'если минуты не равны и секунды больше, то выссчитываем
                                        Vrout = Mine - Vrin(2)
                                        If Seco < Vrin(1) Then Vrout = Vrout - 1


                       'else ERROR - минуты не могут быть меншье если час не изменился и день тоже и месяц тоже и год тоже
                    End If

                    Elseif Hour > Vrin(3) Then              'если час больше и год,месяц,день равен
                        Vrout = Hour - Vrin(3)
                        Vrout = Vrout * 60
                        If Mine => Vrin(2) Then             'Если минуты больше и секунды тоже, то высчитываем ответ
                               Vrtm3 = Mine - Vrin(2)
                               Vrout = Vrout + Vrtm3
                               If Seco < Vrin(1) Then Vrout = Vrout - 1
                               Elseif Mine < Vrin(2) Then   'вычитаем минуты если они меньше чем дано - нужно для перехода из часа в час
                                      Vrtm3 = Vrin(2) - Mine
                                      Vrout = Vrout - Vrtm3
                        End If
                    'else ERROR расчёта времени - час не может быть меньше если дата не изменилась
                 End If
         Elseif Dat > Vrin(4) Then                          'Высчитываем если другой день и при этом равен месяц и год
                Vrout = Dat - Vrin(4)
                Vrout = Vrout * 1440
               If Hour = Vrin(3) Then                       'Если час равен
                    If Mine = Vrin(2) Then                  'Если минуты равны то без изменений
                       Vrout = 0
                       Elseif Mine > Vrin(2) Then           'если минуты не равны и секунды больше, то выссчитываем
                                                 Vrout = Mine - Vrin(2)
                                                 If Seco > Vrin(1) Then Vrout = Vrout - 1
                       'else ERROR - минуты не могут быть меншье если час не изменился и день тоже и месяц тоже и год тоже
                    End If

                    Elseif Hour > Vrin(3) Then              'если час больше и год,месяц,день равен
                        Vrout = Hour - Vrin(3)
                        Vrout = Vrout * 60
                        If Mine => Vrin(2) Then             'Если минуты больше и секунды тоже, то высчитываем ответ
                               Vrtm3 = Mine - Vrin(2)
                               Vrout = Vrout + Vrtm3
                               If Seco < Vrin(1) Then Vrout = Vrout - 1
                               Elseif Mine < Vrin(2) Then   'вычитаем минуты если они меньше чем дано - нужно для перехода из часа в час
                                    Vrtm3 = Vrin(2) - Mine
                                    Vrout = Vrout - Vrtm3
                        End If
                    Elseif Hour < Vrin(3) Then              'убавляем время если час ещё не подошел - нужно с перехода день на день
                           Vrtm3 = Vrin(3) - Hour
                           Vrtm3 = Vrtm3 * 60
                           Vrout = Vrout - Vrtm3
                            If Mine => Vrin(2) Then         'Если минуты больше и секунды тоже, то высчитываем ответ
                                       Vrtm3 = Mine - Vrin(2)
                                       Vrout = Vrout + Vrtm3
                                       If Seco < Vrin(1) Then Vrout = Vrout - 1
                                       Elseif Mine < Vrin(2) Then       'вычитаем минуты если они меньше чем дано - нужно для перехода из часа в час
                                            Vrtm3 = Vrin(2) - Mine
                                            Vrout = Vrout - Vrtm3
                            End If
               End If
      End If
         'else ERROR расчёта времени - месяц не может быть меньше если год равен
   End If

End If
Return

Почему такая сложность? Дело в том, что если будет другой месяц - то и число в дате может быть меньше чем число даты запуска и это ещё без учёта кол-ва дней в месяце.

Наверно будет проще сделать на FOR ))))

Задача тут простая, кидаем в подпрограмму "дату и время" запуска, а та смотрит настоящую дату и время и выдаёт сколько минут прошло от присланной даты с учётом секунд.

Отредактировано Ev3658 (2018-02-28 11:02:52)

0

2

Очень интересная статья - Расчёт времени по времени

Решения в статье:

Свернутый текст
Код:
Dim D As Word                            'количество пройденных дней

Dim Ds As Word                           'вспомогательные переменные
Dim Dd As Word
Dim Dt As Byte
Dim Dy As Byte
Dim Dx As Byte
Dim Nn As Byte
Dim Dn As Word
Dim Dm As Word

Dim D0 As Byte                           'число пуска
Dim M0 As Byte                           'месяц пуска
Dim Y0 As Byte                           'год пуска

Dim D1 As Byte                           'число проверки
Dim M1 As Byte                           'месяц проверки
Dim Y1 As Byte                           'год проверки


'значения переменных в качестве примера
'число/месяц/год запуска счетчика
D0 = 1
M0 = 8
Y0 = 16

'число/месяц/год просмотра
D1 = 2
M1 = 10
Y1 = 51


'///начало вычислений

'В цикле идет вычисление двух величин:
'Ds-оставшееся кол-во дней в году с момента запуска счетчика
'Dd-оставшееся кол-во дней в году от момента просмотра

Do
 Incr Nn
  If Nn = 1 Then
   Dy = Y0 / 4                           'вычисляем високосный год
   Dn = D0
   Dm = M0
  Elseif Nn = 2 Then
   Dy = Y1 / 4
   Dn = D1
   Dm = M1
  End If

    Dy = Dy * 4                          'если год поделился без остатка тогда он високосный

  If Dm = 1 Then
    Dd = 31 - Dn
     If Dy = Y1 Then                     'если год високосный
      Dd = Dd + 335
     Else
      Dd = Dd + 334
     End If
  Elseif Dm = 2 Then
     If Dy = Y1 Then
      Dd = 29 - Dn
     Else
      Dd = 28 - Dn
     End If
      Dd = Dd + 306
  Elseif Dm = 3 Then
    Dd = 31 - Dn
    Dd = Dd + 275
  Elseif Dm = 4 Then
    Dd = 30 - Dn
    Dd = Dd + 245
  Elseif Dm = 5 Then
    Dd = 31 - Dn
    Dd = Dd + 214
  Elseif Dm = 6 Then
    Dd = 30 - Dn
    Dd = Dd + 184
  Elseif Dm = 7 Then
    Dd = 31 - Dn
    Dd = Dd + 153
  Elseif Dm = 8 Then
    Dd = 31 - Dn
    Dd = Dd + 122
  Elseif Dm = 9 Then
    Dd = 30 - Dn
    Dd = Dd + 92
  Elseif Dm = 10 Then
    Dd = 31 - Dn
    Dd = Dd + 61
  Elseif Dm = 11 Then
    Dd = 30 - Dn
    Dd = Dd + 31
  Elseif Dm = 12 Then
    Dd = 31 - Dn
  End If

   If Nn = 1 Then
    Ds = Dd
   End If


Loop Until Nn = 2
Nn = 0

'вычисляем пройденные дни
Dt = Y1 - Y0                             'считаем сколько лет между запуском и проверкой
If Dt = 0 Then                           'если старт счетчика и проверка в одном году
  D = Ds - Dd
Elseif Dt = 1 Then                       'если разница один год

  If Dy = Y1 Then                        'если год проверки високосный
   Dd = 366 - Dd
  Else
   Dd = 365 - Dd
  End If
  D = Ds + Dd
Else                                     'если прошло больше одного года
 Dt = Y0
 Incr Dt
 Do
  Dx = Dt / 4                            'проверка високосного года
  Dx = Dx * 4
   If Dx = Dt Then                       'если високосный прибавим 366 дней
    D = D + 366
   Else
    D = D + 365
   End If
  Incr Dt
 Loop Until Dt = Y1                      'не учитываем год проверки, выходим

 If Dy = Y1 Then                         'если год проверки високосный
   Dd = 366 - Dd
  Else
   Dd = 365 - Dd
  End If

  D = D + Ds
  D = D + Dd

End If

 Print D                                 'печатаем количество пройденных дней

End
А вот алгоритм Mrshilov, использующий в качестве опорной даты 2000й год и занимающий всего 1 кб памяти.
Код:
Dim Dd As Long , Temp_long As Long , Temp_word As Word , Temp1_word As Word
Dim Month As Byte , Dat As Byte , Year As Byte

'-------------------------------------------------------------------------------
Dat = 1
Month = 8
Year = 16
Gosub Days_since                                            'первая дата
Dd = Temp_long

Dat = 2
Month = 10
Year = 51
Gosub Days_since                                            'вторая дата

Dd = Temp_long - Dd
Print Dd                                                    'результат

End
'-------------------------------------------------------------------------------
Days_since:
Temp_word = Year + 2000                                     'дней от 2000 года
Temp_long = Temp_word * 367
Temp1_word = Month + 9
Temp1_word = Temp1_word / 12
Temp1_word = Temp_word + Temp1_word
Temp1_word = Temp1_word * 7
Temp1_word = Temp1_word / 4
Temp_long = Temp_long - Temp1_word
Temp1_word = Month * 275
Temp1_word = Temp1_word / 9
Temp_long = Temp_long + Temp1_word
Temp_long = Temp_long + Dat
Temp_long = Temp_long - 730530
Return

Отредактировано Ev3658 (2018-02-28 13:12:34)

0

3

Вообще, в VB эта вся свистопляска делается легко как в вычислениях, так и в сравнениях, просто указываешь дату/время (до/после) и всё. А работает это всё так просто потому, что там всё сводится к секундам. Т.ч. пока проще варианта не придумать.
Правда тут сразу автоматом возникает проблема с "вечным календарём" (всякая высокосная фигня). Можно правда в конкретном случае сделать как раз только секунды и из них получать точно или приблизительное время.

зы: кстати я тут потихоньку начал изучать АЦП в хмеге (если тебе эта тема ещё интересна), один идейку задумал, надо шустрый АЦП.

Отредактировано RDW (2018-02-28 11:41:28)

0

4

RDW написал(а):

....один идейку задумал, надо шустрый АЦП.

Это уже отдельная тема ))) Если получится сделать значение АЦП в нормальный ноль и регулировать переменником от 0 до значения 12 бит, буду раз узнать как смог ))))

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

0

5

Ev3658 написал(а):

Очень интересная статья - Расчёт времени по времени:

Статья, наверное, очень интересная, но ссылка ведет к началу темы.

0

6

max написал(а):

Статья, наверное, очень интересная, но ссылка ведет к началу темы.

Исправил! Даже сам не понял как такое получилось.

0

7

Ev3658 написал(а):

А зачем високосный год

Ну сам сказал, что тебе надо потом показать сколько сек/лет светила лампочка. :)

Ev3658 написал(а):

Если получится сделать значение АЦП в нормальный ноль и регулировать переменником от 0 до значения 12 бит, буду раз узнать как смог

Обязательно отпишу, если получится. Два одновременно работающих АЦП возбуждают мозг.  :crazyfun: Но мне пока надо режим тот что Vcc/1.6В, т.е. 2В размах. Правда сейчас немного поглазел в инете и у многих там проблемы из-за корявостей ревизий камней, т.е. если будет результат или нет - это не значит, что он повторим другими.  :sceptic:

0

8

RDW написал(а):

...это не значит, что он повторим другими.

Опорное напряжение как не старался, но больше 1,6 вольта не получается и это в режиме обычного замера. Хуже того, абсолютный ноль получить не получается.
Вот, горячая тема про ADC, сам скоро буду родственнице протез руки пытаться сделать, хотелось бы на Xmega - Xmega ADC

0

9

Вот, если кому пригодится, кусочек когда для расчёта в небольшом интервале времени, то-есть переход с месяца на месяц и не более, то-есть если за два месяца будет - алгоритм бесполезен. Високосный год учтён.
Вроде как работает.

В массив Vrin(6) запихиваете дату в формате:
'1-сек
'2-мин
'3-час
'4-день
'5-месяц
'6-год
Вызываете подпрограмму Timeload, та вызывает стандартную библиотеку часов и использует переменные:
'Seco
'Mine
'Hour
'Dat
'Month
'Year
ответ в минутах получаете в переменной типа Dword - Vrout

Код:
'========================================== Переменные рассчёта времени
Dim Vrin(6) As Byte                                         'Запомненное время
Dim Vrout As Dword                                          'Выход в минутах
Dim Vrtm3 As Dword                                          'Временная переменная Dword для рассчёта
Dim Vrtm1 As Byte                                           'Временная переменная Byte для рассчёта


...
...
...
...

'================== рассчёт времени
Timeload:




'Массив Vrin(6)
'1-секунды
'2-минуты
'3-часы
'4-день
'5-месяц
'6-год
'Переменные с часов реального времени:
'Seco
'Mine
'Hour
'Dat
'Month
'Year




Gosub Clock:
Vrtm3 = 0
If Month <> Vrin(5) Then
   Select Case Vrin(5)
     Case 1:
     Vrtm3 = 44640
     Case 2:
        Vrtm1 = Year Mod 4
        If Vrtm1 = 0 Then
           Vrtm3 = 41760
           Else
           Vrtm3 = 40320
        End If
     Case 3:
     Vrtm3 = 44640
     Case 4:
     Vrtm3 = 43200
     Case 5:
     Vrtm3 = 44640
     Case 6:
     Vrtm3 = 43200
     Case 7:
     Vrtm3 = 44640
     Case 8:
     Vrtm3 = 43200
     Case 9:
     Vrtm3 = 44640
     Case 10:
     Vrtm3 = 44640
     Case 11:
     Vrtm3 = 43200
     Case 12:
     Vrtm3 = 44640
   End Select
End If
Vrout = Vrtm3
      If Dat => Vrin(4) Then                                'Высчитываем если другой день и при этом равен месяц и год
                Vrtm3 = Dat - Vrin(4)
                Vrtm3 = Vrtm3 * 1440
                Vrout = Vrout + Vrtm3
                Else
                Vrtm3 = Vrin(4) - Dat
                Vrtm3 = Vrtm3 * 1440
                Vrout = Vrout - Vrtm3
      End If

      If Hour => Vrin(3) Then                               'если час больше и год,месяц,день равен
            Vrtm3 = Hour - Vrin(3)
            Vrtm3 = Vrtm3 * 60
            Vrout = Vrout + Vrtm3
            Else
               Vrtm3 = Vrin(3) - Hour
               Vrtm3 = Vrtm3 * 60
               Vrout = Vrout - Vrtm3
      End If

      If Mine => Vrin(2) Then                               'Если минуты больше и секунды тоже, то высчитываем ответ
         Vrtm3 = Mine - Vrin(2)
         Vrout = Vrout + Vrtm3
          Else                                              'вычитаем минуты если они меньше чем дано - нужно для перехода из часа в час
              Vrtm3 = Vrin(2) - Mine
              Vrout = Vrout - Vrtm3
      End If

       If Seco < Vrin(1) And Vrout > 0 Then Vrout = Vrout - 1
Return


Для чего это может пригодится, ну к примеру определить через какое время вырубить то или это или восстановиться после внезапного выключения.
Максимальное получаемое время между реальным и запомненным - 92160 минут. (два месяца по 31 дню).

Отредактировано Ev3658 (2018-03-01 00:30:46)

0

10

Непонятно зачем такие свистопляски. В BASCOM есть прекрасная библиотека по работе с датой и временем. Все эти вопросы решаются очень просто. Только нужно внимательно прочесть раздел DATE and TIME в справке.

0

11

sva-don написал(а):

Непонятно зачем такие свистопляски. ...


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

0

12

Ev3658 написал(а):

sva-don написал(а):Непонятно зачем такие свистопляски. ...Есть устройство, которое обслуживает двигателя. Если вдруг пропадёт питание или чего либо, то при включении надо узнать сколько времени прошло.То-есть разница в минутах от запомненного времени.

Простои считать ?
Так не проще ли ограничиться периодом от 00:00 до 23:59 и считать только время работы ?
Затем банальная арифметика даст время простоя.
И переход в другие сутки просто даст нужное время (работа или простой) в учет уже следующих суток.

У нес так время работы оборудования в шахте уже годами считается... ;)

0

13

Эта тема уже обсуждалась, надо просто контролировать пропадание питания и успевать записывать нужные данные в ЕЕПРОМ.

0

14

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

0

15

Ev3658 написал(а):

По опыту активное использование энергонезависимой памяти в контроллере снижает надёжность устройства

Нужно использовать FRAM.

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Расчёт времени по времени