Календарный таймер как упростить?

d_kin
Offline
Зарегистрирован: 07.12.2016

Здравствуйте!

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

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

Бывает ли какой более простой способ сравнения даты для установки времени включения и выключения?

Вот мой пример на операторе if, здесь подстройка по времени происходит каждые 10 дней, т.е. 3 раза в месяц, но хочется каждый день и как-то попроще.

//Январь
if (mo == 1 && dd >= 1 && dd < 11) // mo - месяц, dd  - день
     {rel1off = 9*60+15
      rel1on = 16*60+6
     }
if (mo == 1 && dd >= 11 && dd < 21)
     {rel1off = 9*60+9
      rel1on = 16*60+21
     }
if (mo == 1 && dd >= 21 && dd <= 31)
     {rel1off = 8*60+56
      rel1on = 16*60+40
     }
 
//Февраль
if (mo == 2 && dd >= 1 && dd < 11)
     {rel1off = 8*60+37
      rel1on = 17*60+4
     }
if (mo == 2 && dd >= 11 && dd < 21)
     {rel1off = 8*60+16
      rel1on = 17*60+27
     }
if (mo == 2 && dd >= 21 && dd <= 31)
     {rel1off = 7*60+53
      rel1on = 17*60+49
     }
 
//Март
if (mo == 3 && dd >= 1 && dd < 11)
     {rel1off = 7*60+30
      rel1on = 18*60+10
     }
if (mo == 3 && dd >= 11 && dd < 21)
     {rel1off = 7*60+3
      rel1on = 18*60+31
     }
if (mo == 3 && dd >= 21 && dd <= 31)
     {rel1off = 6*60+36
      rel1on = 18*60+53
     }
 
//Апрель
if (mo == 4 && dd >= 1 && dd < 11)
     {rel1off = 6*60+6
      rel1on = 19*60+16
     }
if (mo == 4 && dd >= 11 && dd < 21)
     {rel1off = 5*60+39
      rel1on = 19*60+37
     }
if (mo == 4 && dd >= 21 && dd <= 31)
     {rel1off = 5*60+13
      rel1on = 19*60+58
     }
 
//Май
if (mo == 5 && dd >= 1 && dd < 11)
     {rel1off = 4*60+49
      rel1on = 20*60+19
     }
if (mo == 5 && dd >= 11 && dd < 21)
     {rel1off = 4*60+27
      rel1on = 20*60+40
     }
if (mo == 5 && dd >= 21 && dd <= 31)
     {rel1off = 4*60+80
      rel1on = 21*60+0
     }
 
//Июнь
if (mo == 6 && dd >= 1 && dd < 11)
     {rel1off = 3*60+53
      rel1on = 21*60+18
     }
if (mo == 6 && dd >= 11 && dd < 21)
     {rel1off = 3*60+45
      rel1on = 21*60+29
     }
if (mo == 6 && dd >= 21 && dd <= 31)
     {rel1off = 3*60+48
      rel1on = 21*60+33
     }
 
//Июль
if (mo == 7 && dd >= 1 && dd < 11)
     {rel1off = 3*60+59
      rel1on = 21*60+26
     }
if (mo == 7 && dd >= 11 && dd < 21)
     {rel1off = 4*60+16
      rel1on = 21*60+10
     }
if (mo == 7 && dd >= 21 && dd <= 31)
     {rel1off = 4*60+35
      rel1on = 20*60+52
     }
 
//Август
if (mo == 8 && dd >= 1 && dd < 11)
     {rel1off = 4*60+55
      rel1on = 20*60+30
     }
if (mo == 8 && dd >= 11 && dd < 21)
     {rel1off = 5*60+16
      rel1on = 20*60+6
     }
if (mo == 8 && dd >= 21 && dd <= 31)
     {rel1off = 5*60+38
      rel1on = 19*60+37
     }
 
//Сентябрь
if (mo == 9 && dd >= 1 && dd < 11)
     {rel1off = 5*60+59
      rel1on = 19*60+10
     }
if (mo == 9 && dd >= 11 && dd < 21)
     {rel1off = 6*60+19
      rel1on = 18*60+43
     }
if (mo == 9 && dd >= 21 && dd <= 31)
     {rel1off = 6*60+39
      rel1on = 18*60+15
     }
 
//Октябрь
if (mo == 10 && dd >= 1 && dd < 11)
     {rel1on = 7*60+0
      rel1off = 17*60+48
     }
if (mo == 10 && dd >= 11 && dd < 21)
     {rel1on = 7*60+21
      rel1off = 17*60+23
     }
if (mo == 10 && dd >= 21 && dd <= 31)
     {rel1on = 7*60+45
      rel1off = 16*60+56
     }
 
//Ноябрь
if (mo == 11 && dd >= 1 && dd < 11)
     {rel1off = 8*60+08
      rel1on = 16*60+35
     }
if (mo == 11 && dd >= 11 && dd < 21)
     {rel1off = 8*60+29
      rel1on = 16*60+17
     }
if (
     }
 
//Декабрь
if (mo == 12 && dd >= 1 && dd < 11)
     {rel1off = 9*60+3
      rel1on = 15*60+57
     }
if (mo == 12 && dd >= 11 && dd < 21)
     {rel1off = 9*60+13
      rel1on = 15*60+56
     }
if (mo == 12 && dd >= 21 && dd <= 31)
     {rel1off = 9*60+15
      rel1on = 15*60+57
     }
 
 
timenow = hh*60 + mm
if (timenow > rel1off && timenow < rel1on)
     {rel1 = 0
     }
elese
     {rel1 =1
     }
 
 
bwn
Offline
Зарегистрирован: 25.08.2014

Берем календарь, смотрим восход - закат на каждый день для своей местности. Прописываем зависимость, вводим поправку от количества прошедших  дней  от 22 декабря в +, с 22 июня в -.

d_kin
Offline
Зарегистрирован: 07.12.2016

Эта поправка нелинейная, бывает за 10 дней на 5 минут разница, или  за 3 дн на полчаса в зависимости от времени года.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Господи, а что прям такая точность нужна?

Ну заведите массив из 366 элементов, забейте туда время восхода и берите готовое время из массива по дню года в качестве индекса (только не спрашивайте, где взять день года, когда есть дата, а то я не люблю материться).

А что, ручками вбивать 366 значений времени не лень? Если лень, то сделайте ещё проще, добавьте к ардуине какой-никакой вай-фай и тупо спрашивайте время восхода для текущей даты у какого-нибудь астрономического сайта.

d_kin
Offline
Зарегистрирован: 07.12.2016

Отлично! Время восхода и захода солнца у меня для каждого дня есть.

Вопрос в том, как уйти от оператора if, как работать в моем случае с массивами (я не работал с ними).

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

d_kin пишет:

Вопрос в том, как уйти от оператора if, как работать в моем случае с массивами (я не работал с ними).

А чего с ним работать?

ну, допустим. что мы считаем 1-ое января нулевым днём года, второе - первsм и т.п.

Пишем массив

int sunRise [] = {
   xxx, //время для 1 января
   yyy, //время для 2 января
   ...
   zzz  //время для 31 декабря
};

Ну а теперь, когда нам нжуно время восхода для n-го дня года, просто пишем

int srTime = sunRise[n];

d_kin
Offline
Зарегистрирован: 07.12.2016

Если я получил дату 22.12 с часов реального времени, то как к ней обратиться в массив, как точно посчитать какой она будет в массиве?

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

Забейте поправку в епром с интервалом 1 минута (тот же массив, только память не жрет) и берите требуемые ячейки в зависимости от количества дней прошедших с 22 декабря. Вангую, что потребуется только на 187 дней, только знак менять.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

d_kin пишет:

Если я получил дату 22.12 с часов реального времени, то как к ней обратиться в массив, как точно посчитать какой она будет в массиве?

Так, ну я же говорил, в массиве она будет находиться по индексу, равному номеру дня в году. 

для 01.01 - sunRise[0]
для 02.01 - sunRise[1]
..
для 31.12 - sunRise[365] // для вискокосного года или 364 для невисокосного.

Забиваете массив для текущего года и не паритесь.

Через год забиваете новый массив для нового года (если там что-то меняется, я не знаю).

d_kin
Offline
Зарегистрирован: 07.12.2016

Это я понял. Но с модуля часов я получу dd=22, mm=12,

а в массиве конкретно например 322 день, как стыковать массив с месяцем и днем из часов?

d_kin
Offline
Зарегистрирован: 07.12.2016

bwn пишет:

Забейте поправку в епром с интервалом 1 минута (тот же массив, только память не жрет) и берите требуемые ячейки в зависимости от количества дней прошедших с 22 декабря. Вангую, что потребуется только на 187 дней, только знак менять.

спасибо, пока сложно, попробую разобраться с массивом впринципе 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

d_kin пишет:

Это я понял. Но с модуля часов я получу dd=22, mm=12,

а в массиве конкретно например 322 день, как стыковать массив с месяцем и днем из часов?

Т.е. у Вас есть номер дня в месяце и номер года, а Вы не можете посчитать номер дня в году? 

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

d_kin
Offline
Зарегистрирован: 07.12.2016

Получается их надо перемножать как-то, в каждом месяце разное число дней и февраль меняется

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

ЕвгенийП пишет:

Т.е. у Вас есть номер дня в месяце и номер года, а Вы не можете посчитать номер дня в году? 

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

Евгений, просьба отклонена!!! У меня с математикой, так себе. Я бы просто просуммировал по месяцам. Как тоже самое, но проще?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Когда-то я даже формулу рожал, сейчас найду - не проще. но прикольнее, тупо формула и всё, только год надо знать, чтобы учесть високосность. Ща. поищу. где-то валялось.

a5021
Offline
Зарегистрирован: 07.07.2013

Почтенная публика в курсе, что время восхода и заката для одной и той же даты каждый год разные?

d_kin
Offline
Зарегистрирован: 07.12.2016

я посмотрел по астрономическим сайтам разница в 1-2 минуты за 50 лет

d_kin
Offline
Зарегистрирован: 07.12.2016

я посмотрел по астрономическим сайтам разница в 1-2 минуты за 50 лет

d_kin
Offline
Зарегистрирован: 07.12.2016

Подскажите, если я сделаю 365-366 дней на операторе if ардуино не зависнет, или по часу думать будет?

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

d_kin пишет:

Подскажите, если я сделаю 365-366 дней на операторе if ардуино не зависнет, или по часу думать будет?

С ума сошли? Да и памяти то хватит?
Дальше ведь смешнее. Астрономические данные верны для равнины, в лесу, горах, городах это будут другие значения. Освещение ведь предназначенно для комфорта населения, а не солнышко приветствовать.))))

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

Либо я не в курсе, но думаю, А5021 имел в виду наш високосный цикл. Допускаю, что в корне не прав.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Нашёл формулу!

Это маленький задачник с пояснениями, котрый я писал для своих студентов почти 20 лет назад (в 1997, я тогда преподавал в двух универах сразу :))))

В общем, всё, что нужно знать о календаре и о том, как его программировать, содержится в первой главе. Там и формулы и пояснения и куски программ.

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

ЕвгенийП пишет:

Нашёл формулу!

Это маленький задачник с пояснениями, котрый я писал для своих студентов почти 20 лет назад (в 1997, я тогда преподавал в двух универах сразу :))))

В общем, всё, что нужно знать о календаре и о том, как его программировать, содержится в первой главе. Там и формулы и пояснения и куски программ.

Пасибки, весьма познавательно. Но, на мой взгляд, проще ссуммировать месяца и учесть високосный (для данной задачи).))))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, енто ж скучно :)

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

ЕвгенийП пишет:

Ну, енто ж скучно :)

Не отрицаю, для того, у кого мозг в правильном направлении заточен.))) У меня вот только алгоритмика получается (разложить задачу на минимальные составляющие).

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Бляха муха, а подоткнуть к ардуине на вход ацп фотодатчик...или не айс?

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

Евгений, надеюсь ТС не обидится за оффтоп, с младости (проффесиональной) мучал вопрос, есть ли способ замены метода последовательного приближения (простых иттераций) при расчетах в металлургии, например:
Дано - общая масса 12000кг,
хрома содержится 8,5%, требуется 12,5%
Содержание Cr в феррохроме 70%. (это простой пример, сложный содержит 6-8 элементов)
Расчет идет исключительно на логарифмической линейке ( калькулятор на большом кол-ве элементов пустой номер), плюсовую поправку даю сам интуитивно.
Когда добрался до EC-ки просто крутил цикл 1000 раз.
Есть ли более простые варианты? С точки зрения математика?

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

Что-то мне кажется, что время рассвета и заката на протяжении года меняется по синусоиде.

Период - можно считать известен.

Фаза - тоже известна.

Амплитуда - зависит от географической широты.

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

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

andriano, пп. 1, 2.

a5021
Offline
Зарегистрирован: 07.07.2013

ua6em пишет:
Бляха муха, а подоткнуть к ардуине на вход ацп фотодатчик...или не айс?

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

a5021 пишет:

ua6em пишет:
Бляха муха, а подоткнуть к ардуине на вход ацп фотодатчик...или не айс?

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

Ну не знаю, делал аналоговое реле, 8 лет проработало...потом я уволился )))
Ничего кроме единожды не калибровалось

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

bwn пишет:

andriano, пп. 1, 2.

И на что мы здесь ссылаемся? На Конституцию РФ?

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

andriano пишет:

bwn пишет:

andriano, пп. 1, 2.

И на что мы здесь ссылаемся? На Конституцию РФ?

На функцию, возможно она и синусоида.

d_kin
Offline
Зарегистрирован: 07.12.2016

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

a5021
Offline
Зарегистрирован: 07.07.2013

ua6em пишет:
Ну не знаю, делал аналоговое реле, 8 лет проработало...потом я уволился )))
Ничего кроме единожды не калибровалось

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

msng
Offline
Зарегистрирован: 07.06.2012

я бы так считал: дней в году 361

в месяце - дней 30

ну и получается N=30*mm+dd-30

ну и массив с временем восхода/ заката в eeprom

как то так...

будет конечно погрешность, но вам же не самолеты сажать...

 

d_kin
Offline
Зарегистрирован: 07.12.2016

Отлчино, по Вашей формуле получается погрешность максимум в 1-2 дня на протяжении всего года.

Потянет ли ардуино нано 2 массива по 366 чисел (восход и закат) и несколько строк работы с часами и сравнения времени?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

bwn пишет:

Евгений, надеюсь ТС не обидится за оффтоп, с младости (проффесиональной) мучал вопрос, есть ли способ замены метода последовательного приближения (простых иттераций) при расчетах в металлургии, например:
Дано - общая масса 12000кг,
хрома содержится 8,5%, требуется 12,5%
Содержание Cr в феррохроме 70%. (это простой пример, сложный содержит 6-8 элементов)
Расчет идет исключительно на логарифмической линейке ( калькулятор на большом кол-ве элементов пустой номер), плюсовую поправку даю сам интуитивно.
Когда добрался до EC-ки просто крутил цикл 1000 раз.
Есть ли более простые варианты? С точки зрения математика?

Простите, а что нужно сделать? Определить сколько добавить феррохрома, чтобы получить 12,5% хроме в результате?

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

Да, убрав все промежуточные приближения. Молодежь висла минут на 10-15 (допустимо 3-4), с опытом делаешь за 3-5 пересчетов. И чуял, что есть какая то зависимость, но сформулировать не смог.((((
Эт дела давние, так что если неинтересно, забейте.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

bwn пишет:

Евгений, надеюсь ТС не обидится за оффтоп, с младости (проффесиональной) мучал вопрос, есть ли способ замены метода последовательного приближения (простых иттераций) при расчетах в металлургии, например:
Дано - общая масса 12000кг,
хрома содержится 8,5%, требуется 12,5%
Содержание Cr в феррохроме 70%. (это простой пример, сложный содержит 6-8 элементов)
Расчет идет исключительно на логарифмической линейке ( калькулятор на большом кол-ве элементов пустой номер), плюсовую поправку даю сам интуитивно.
Когда добрался до EC-ки просто крутил цикл 1000 раз.
Есть ли более простые варианты? С точки зрения математика?

Простите, а что нужно сделать? Определить сколько добавить феррохрома, чтобы получить 12,5% хроме в результате?

задача класса курса химии за 8 класс однако, решать надо в молях

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

ua6em пишет:

ЕвгенийП пишет:

bwn пишет:

Евгений, надеюсь ТС не обидится за оффтоп, с младости (проффесиональной) мучал вопрос, есть ли способ замены метода последовательного приближения (простых иттераций) при расчетах в металлургии, например:
Дано - общая масса 12000кг,
хрома содержится 8,5%, требуется 12,5%
Содержание Cr в феррохроме 70%. (это простой пример, сложный содержит 6-8 элементов)
Расчет идет исключительно на логарифмической линейке ( калькулятор на большом кол-ве элементов пустой номер), плюсовую поправку даю сам интуитивно.
Когда добрался до EC-ки просто крутил цикл 1000 раз.
Есть ли более простые варианты? С точки зрения математика?

Простите, а что нужно сделать? Определить сколько добавить феррохрома, чтобы получить 12,5% хроме в результате?

задача класса курса химии за 8 класс однако, решать надо в молях

Увы, решать надо в килограммах и тоннах. Для молей весов не придумали.

msng
Offline
Зарегистрирован: 07.06.2012

массив нужно записать в еепром (атмега328 - 1024 байта) тоже нехитрыми формулами можно прописать восход с 4 до 9 утра и закат с 17 до 23 часов. т.е. получается на закат 6 часов, придется обойтись точность около двух минут (плюс погрешность от моей формулы, той что выше) т.е. прибавка в одно значение переменной в массиве  увеличивает время заката на две минуты.

 

d_kin
Offline
Зарегистрирован: 07.12.2016

Вот примерный код, прошу проверить:

---------------------------------------------------

// Управление освещением по времени заката и восхода солнца по массиву данных
// До использования настроить в модуле RTC текущее время: Примеры->DS1307RTC->SetTime
 
#include <Time.h> // время и текущая дата
#include <DS1307RTC.h> // библиотека RTC возвращает time как time_t, работает как с DS1307 так и с DS3231
 
#define REL1 11 // выход управления реле1 на 11 порт (улица)
#define REL2 12 // выход управления реле2 на 12 порт (внутр)
#define DEBUG 1 // 1 включает сообщения отладки в монитор серийного порта. Скорость 115200
 
int minNow, minLast = -1, hourNow, hourLast = -1, minOfDay; // -1 отрабатывает при первом запуске
int mSunrise1, mSunset1, mSunrise2, mSunset2; //время рассвета и заката в минутах от начала дня (0-1439) для реле1 реле2
int tekDay; //номер текущего дня по счету
 
// массив данных рассвета для 365 дней (по порядку с 01.01 по 31.12) в минутах
int voshod [] = {
0, // значание не используется
555, // 01.01
554, // 02.01
554, // ...
553,
553,
552,
552,
551,
550,
549,
549,
548,
547,
545,
544,
543,
542,
541,
539,
538,
536,
535,
533,
532,
530,
528,
527,
525,
523,
521,
519,
517,
515,
513,
511,
509,
507,
505,
503,
501,
498,
496,
494,
492,
489,
487,
485,
482,
480,
477,
475,
473,
470,
468,
465,
463,
460,
457,
455,
452,
450,
447,
444,
442,
439,
436,
434,
431,
428,
426,
423,
420,
418,
415,
412,
410,
407,
404,
401,
399,
396,
393,
390,
388,
385,
382,
379,
377,
374,
371,
369,
366,
363,
360,
358,
355,
352,
350,
347,
344,
342,
339,
336,
334,
331,
328,
326,
323,
321,
318,
316,
313,
311,
308,
306,
303,
301,
298,
296,
294,
291,
289,
286,
284,
282,
280,
277,
275,
273,
271,
269,
267,
265,
263,
261,
259,
257,
255,
253,
252,
250,
248,
246,
245,
243,
242,
240,
239,
238,
236,
235,
234,
233,
232,
231,
230,
229,
228,
227,
226,
226,
225,
225,
224,
224,
223,
223,
223,
223,
223,
223,
223,
223,
224,
224,
224,
225,
225,
226,
226,
227,
228,
229,
230,
231,
232,
233,
234,
235,
236,
238,
239,
240,
242,
243,
245,
246,
248,
249,
251,
253,
255,
256,
258,
260,
262,
264,
265,
267,
269,
271,
273,
275,
277,
279,
281,
283,
285,
287,
289,
291,
293,
295,
297,
299,
301,
303,
305,
307,
309,
312,
314,
316,
318,
320,
322,
324,
326,
328,
330,
332,
334,
336,
338,
340,
342,
344,
346,
348,
350,
352,
354,
356,
358,
360,
362,
364,
366,
368,
370,
372,
375,
377,
379,
381,
383,
385,
387,
389,
391,
393,
395,
397,
399,
401,
403,
405,
407,
409,
411,
413,
415,
418,
420,
422,
424,
426,
428,
430,
432,
435,
437,
439,
441,
443,
445,
448,
450,
452,
454,
456,
459,
461,
463,
465,
468,
470,
472,
474,
476,
479,
481,
483,
485,
488,
490,
492,
494,
496,
498,
501,
503,
505,
507,
509,
511,
513,
515,
517,
519,
521,
523,
525,
526,
528,
530,
532,
533,
535,
536,
538,
539,
541,
542,
543,
545,
546,
547,
548,
549,
550,
551,
551,
552,
553,
553,
554,
554,
554,
555,
555,
555,
555,
555,
555,
555 
};
 
// массив данных заката для 365 дней (по порядку с 01.01 по 31.12) в минутах
int zakat [] = {
0, // значение не испльзуется
966, // 01.01
967, // 02.01
968, // ...
970,
971,
973,
974,
976,
977,
979,
981,
982,
984,
986,
988,
990,
992,
994,
996,
998,
1000,
1002,
1004,
1006,
1008,
1010,
1013,
1015,
1017,
1019,
1022,
1024,
1026,
1028,
1031,
1033,
1035,
1037,
1040,
1042,
1044,
1047,
1049,
1051,
1054,
1056,
1058,
1060,
1063,
1065,
1067,
1069,
1072,
1074,
1076,
1078,
1081,
1083,
1085,
1087,
1090,
1092,
1094,
1096,
1098,
1100,
1103,
1105,
1107,
1109,
1111,
1113,
1116,
1118,
1120,
1122,
1124,
1126,
1128,
1130,
1133,
1135,
1137,
1139,
1141,
1143,
1145,
1147,
1149,
1151,
1154,
1156,
1158,
1160,
1162,
1164,
1166,
1168,
1170,
1173,
1175,
1177,
1179,
1181,
1183,
1185,
1187,
1190,
1192,
1194,
1196,
1198,
1200,
1202,
1204,
1207,
1209,
1211,
1213,
1215,
1217,
1219,
1221,
1224,
1226,
1228,
1230,
1232,
1234,
1236,
1238,
1240,
1242,
1244,
1246,
1248,
1250,
1252,
1254,
1256,
1258,
1260,
1261,
1263,
1265,
1267,
1268,
1270,
1272,
1273,
1275,
1276,
1278,
1279,
1280,
1282,
1283,
1284,
1285,
1286,
1287,
1288,
1289,
1290,
1291,
1292,
1292,
1293,
1293,
1294,
1294,
1294,
1295,
1295,
1295,
1295,
1295,
1295,
1294,
1294,
1294,
1293,
1293,
1292,
1292,
1291,
1290,
1290,
1289,
1288,
1287,
1286,
1285,
1283,
1282,
1281,
1280,
1278,
1277,
1275,
1274,
1272,
1270,
1269,
1267,
1265,
1263,
1262,
1260,
1258,
1256,
1254,
1252,
1250,
1248,
1246,
1243,
1241,
1239,
1237,
1234,
1232,
1230,
1228,
1225,
1223,
1220,
1218,
1216,
1213,
1211,
1208,
1206,
1203,
1201,
1198,
1195,
1193,
1190,
1188,
1185,
1182,
1180,
1177,
1174,
1172,
1169,
1166,
1164,
1161,
1158,
1155,
1153,
1150,
1147,
1145,
1142,
1139,
1136,
1134,
1131,
1128,
1125,
1123,
1120,
1117,
1114,
1112,
1109,
1106,
1103,
1101,
1098,
1095,
1092,
1090,
1087,
1084,
1082,
1079,
1076,
1073,
1071,
1068,
1066,
1063,
1060,
1058,
1055,
1053,
1050,
1047,
1045,
1042,
1040,
1037,
1035,
1033,
1030,
1028,
1025,
1023,
1021,
1018,
1016,
1014,
1012,
1009,
1007,
1005,
1003,
1001,
999,
997,
995,
993,
991,
989,
987,
985,
984,
982,
980,
979,
977,
975,
974,
972,
971,
970,
968,
967,
966,
965,
964,
963,
962,
961,
960,
960,
959,
958,
958,
957,
957,
957,
956,
956,
956,
956,
956,
956,
956,
957,
957,
957,
958,
958,
959,
960,
961,
961,
962,
963,
964,
966
};
 
// настройка
void setup() 
{
Serial.begin(115200); // старт соединенияи и установка скорости
pinMode(REL1, OUTPUT); // инициализируем порт для канала реле1 как выход
pinMode(REL2, OUTPUT); // инициализируем порт для канала реле2 как выход
digitalWrite(REL1 ,HIGH); // устанавливаем на входе релейного модуля1 высокий уровень — реле выключено
digitalWrite(REL2 ,HIGH); // устанавливаем на входе релейного модуля2 высокий уровень — реле выключено
 
 
setSyncProvider(RTC.get); // синхронизация времени с RTC
if (timeStatus() != timeSet) 
Serial.println(«Unable to sync, load time to RTC»);
else
Serial.println(«RTC has set the system time»);
}
 
// основной цикл
void loop()
if (timeStatus()!= timeNotSet) 
{
minNow = minute();
if (minNow != minLast) 
{
minLast = minNow;
hourNow = hour();
minOfDay = hourNow * 60 + minNow; //текущая минута дня 0-1439
 
#if DEBUG == 1
Serial.print(«TimeNow: „);
Serial.print(hourNow);
Serial.print(“-»);
Serial.print(minNow);
Serial.print(" minOfDay:");
Serial.print(minOfDay);
Serial.print(" minLast:");
Serial.print(minLast);
Serial.print(" hourLast:");
Serial.print(hourLast);
Serial.println();
#endif
 
if (hourNow != hourLast) // расчет времени рассвета и заката при изменении часа (раз в час)
//Время рассвета и заката в минутах от начала дня
tekDay = 30,4*month()+day()-30,4; // текущий день по счету с начала года
mSunrise1 = voshod[tekDay] + 15; // где "+15" задержка выключения реле1 утром в минутах после восхода
mSunset1 = zakat[tekDay] - 15; //  где "-15" задержка включения реле1 вечером перед закатом
 
mSunrise2 = voshod[tekDay] + 30; // где "+30" задержка выключения реле2 утром в минутах после восхода
mSunset2 = zakat[tekDay] - 30; //  где "-30" задержка включения реле2 вечером перед закатом
 
#if DEBUG == 1
Serial.print(«DATE: „);
Serial.print(" SUNRISE OFF:");
Serial.print(mSunrise1);
Serial.print(mSunrise2);
Serial.print(" SUNSET ON:");
Serial.print(mSunset1);
Serial.print(mSunset2);
Serial.println();
#endif
hourLast = hourNow;
}
//управляем реле
if (minOfDay < mSunrise1 || minOfDay >= mSunset1) // если минут с начала суток меньше, чем время рассвета или больше чем 
 
время заката
digitalWrite(REL1,LOW); // то устанавливаем на входе реле1 низкий уровень уровень — реле срабатывает
else // во всех остальных случаях
digitalWrite(REL1,HIGH); // устанавливаем на входе реле1 высокий уровень — реле выключается
 
if (minOfDay < mSunrise2 || minOfDay >= mSunset2) // если минут с начала суток меньше, чем время рассвета или больше, чем 
 
время заката
digitalWrite(REL2,LOW); // то устанавливаем на входе реле2 низкий уровень уровень — реле срабатывает
else // во всех остальных случаях
digitalWrite(REL2,HIGH); // устанавливаем на входе реле2 высокий уровень — реле выключается
 
#if DEBUG == 1
Serial.print(«RELE:»);
Serial.print(minOfDay < mSunrise1 || minOfDay >= mSunset1);
Serial.print(minOfDay < mSunrise2 || minOfDay >= mSunset2);
Serial.println();
#endif
 
} // End: if (minNow != minLast)
} // End: if (timeStatus()!= timeNotSet)
} // End loop()
 
byte decToBcd(byte val){
return ( (val/10*16) + (val%10) );}
-------------------------------------------------------
 
Писал на основе других примеров,
еще не пойму зачем последние 2 строки
bwn
Offline
Зарегистрирован: 25.08.2014

А что здесь проверять, в EEPROM уже не лезет, почти везде 2-х байтовое значение: 365*2*2 = 1460 байт. Притом, что на вскидку у Вас действительно синусоида. Попробуйте график построить, может получится просто формулой синуса обойтись. И начинайте все таки от солнцестояния.

d_kin
Offline
Зарегистрирован: 07.12.2016

 А если ее в таком виде залить, будет работать?

Я еще только жду ардуино и раньше не видел ее, поэтому задаю такие вопросы.

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

Оно и не поместится в EEPROM. В моём проекте астротаймера эта информация находится во флеше, как и в других подобных, объявляется как const byte data[12][31] PROGMEM={{/*jan*/},{/*feb*/},.....};, выводится из флеша назад в ОЗУ командой byte time=pgm_read_byte(&(data[hour-1][min-1]));, инклуд (библиотека с pgm_read_byte()) называется avr/pgmspace.h

Посмотреть можно тут. Там сейчас забита конкретная широта 50.8 или что-то такое, короче таблица считается на Амурскую область, г. Благовещенск. Эта функция - встроенная PHP, можно просто подставить другую широту в формулу и считать для себя. Но речь не о функции, по ссылке можно посмотреть полный пример массивов (у меня их два, один на часы другой на минуты). Только закаты, но не суть.

Если охота ещё упростить, надо уже думать в ту сторону, в которую думают создатели архиваторов. Видно что в первом массиве часы часто повторяются, от 17 до 21 и обратно. Если назад преобразовать массив в одномерный (без координат месяц/день), то легко будет забить другой массив, в котором будут тупо индексы, с которых меняется час. Итого надо знать цифру 17, единицу, 32 (второе февраля, когда из 17 впервые станет 18) и ещё 7 подобных цифр и 7, итого получаем в идеале 12 байт информации против 372 исходных, ну реально ещё некоторый байт-код скомпилированного wiring с нужными действиями, получающими из этих 12 байт остальные 360.

В массиве минут этот номер не проходит т. к. цифры заметно меняются, однако видно, что меняются незначительно. Точно так же, считаем разницу между ними, и вот уже таблица разниц поддаётся такому же сжатию как часы. Там их будет просто больше, среди них будут отрицательные, но опять же, всю таблицу реально запихать в те же десятки байт, т. к. 2/-2, 1/-1 будет повторяться часто но бывют редкие 3/-3, 5/-5, но они настолько редки что записывать их в общую очередь нет никакого смысла, потеряем больше постоянно возвращаясь на 2/-2, 1/-1. Просто запоминаем их абсолютные координаты и запишем уже на втором проходе, когда вся таблица будет ещё состоять из 1/-1, 2/-2. После, затолкав туда все разницы, берем исходное число (в моем случае так же 17), получаем из таблицы разниц нормальную таблицу с минутами и можно подставлять в условие.

Более короткие данные в EEPROM/флеше не значат однако, более простой код. Смотрите как вам будет меньше работы, в моём случае астротаймер норм живёт с таблицей во флеше, её можно обновлять (да-да, на другой год таблица уже будет отличаться, незначительно но отличаться), и флеша не жалко, плюс находясь там, таблица не жрёт ОЗУ - вместе с ней спокойно уживаются меню с экраном, кнопки которые можно нажимать кратко, длинно и прям ваще длинно, работа с EEPROM типа будильника и всяких настроек и т. п.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

d_kin пишет:

 А если ее в таком виде залить, будет работать?

1. Взял эмулятор (хоть тот же proteus)
2. Залил
3. Посмотрел
4. Рассказал нам

d_kin пишет:

поэтому задаю такие вопросы.

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

d_kin
Offline
Зарегистрирован: 07.12.2016

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

 

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

msng пишет:

массив нужно записать в еепром

Вы всерьез думаете, что параметры земеной орбиты за время жизни прибора изменятся настолько существенно, что придется неоднократно их перепрограммировать?

dimax
dimax аватар
Онлайн
Зарегистрирован: 25.12.2013

d_kin, вы для себя это колхозите? Если для организации, то лучше купить готовый промышленный астротаймер. В них используют GPS модуль, можно один раз запрограммировать и больше никогда не знать забот. Ну а если самому собирать "велосипед", то опять же удобнее на GPS.

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

d_kin пишет:

...ардуино потянет эту программу или нет. Все, что нужно мне в этом приборе я написал...

Что-то я не нашел, где Вы пишете о требуемой точности установки времени восхода/захода. А без этого ответить на вопрос "потянет или не потянет" невозможно, не говоря уже о конкретном алгоритме.