Страница 2 из 2 ПерваяПервая 12
Показано с 11 по 18 из 18

Тема: Как получить "День недели" на ST из get_date_time()?

  1. #11
    Пользователь
    Регистрация
    09.12.2013
    Адрес
    Ставрополь
    Сообщений
    1,908

    По умолчанию

    Цитата Сообщение от Shiryaevo Посмотреть сообщение
    б) при каждом ОТКЛ/ВКЛ на входе ENABLE происходит пересчет "Год, Месяц, День". Рекомендуется оценивать целесообразность изменения значения входа ENABLE в коде управляющей программы.
    а это зачем?

  2. #12

    По умолчанию

    Практическая задача
    Классическая КИС-задача, Ротация: переключение работы исполнительных устройств по недельному графику.
    В проекте я использовал библиотечный недельный таймер.
    Однако у него есть особенность: если в момент когда таймер должен сработать на объекте не было электроэнергии, то библиотечный таймер "пропускает" день / момент когда нужно сработать (или я плохо умею выполнять copy/paste).

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

    Второй вариант явился триггером в конкретном случае который меня попросили до-SMART-ить

    Решение задачи принял такое:
    - запоминаем дату (и время) когда должно переключится (в энергонезависимой/RETAIN переменной)
    - мониторим часы и если после ре-старта (по питанию) время "прошло", то выставляем флаг: "уже все было".

    Для решения задачи нужно
    - вычислять день недели, текущий
    - вычислять день недели, следующий
    - посадить "сторожевого пса" (WhatchDog), который будет сидеть и лаять.

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

    Первое с чем столкнулся - написал выше: "как получить текущий день недели"?
    Задачу решил, выше, в сообщениях, и ниже, в этом сообщении, увидите .
    Вычислить значение следующего дня недели (какое значение возвратит get_date_time()), зная текущий день недели) - это простая формула

    Второе с чем столкнулся, это с тем что в функциональных блоках на ST нет типа энергонезависимая переменная.
    Это не проблема, решение понятное - использовать переменную в МАКРОСЕ (возможно что причина в продуктовом маркетинге, но для себя объясняю длинной LOG-а - чего еще запланировано сделать).

    Ниже привожу что у меня получилось (картинки не из проекта, но из отладки)

    Верхний уровень (листа)

    Верхний лист.png

    МАКРОС "Сторожевой пес" (макрос - потому что нужна энергонезависимая переменная)
    Сторожевой пёс.png

    И функциональный блок на ST для вычисления "следующего Дня недели", проверки входных параметров (на ST удобнее проверять значения входных параметров)

    В коде FB я намеренно внёс ошибку. Четыре ошибки. Сделал небольшой тест для тех, кто будет использовать этот код при сдаче проекта преподавателям
    Одна найдется быстро - ее подсветит компилятор
    Две - найдутся если разобраться в алгоритме (подсказка: нет ли лишних переменных в формулах)
    Ну а 4-ая - возможно Вы получите эстетическое удовлетворение когда вы ее найдете ну или скажите "тоже мне ошибка, это же элементарно"

    ///<Description>Вычисляет значение (в секундах), которое будет возращенно функцией get_date_time() в СЛЕДУЮЩИЙ день недели (час, минуту, секунду). Может быть использовано для энергонезависимой логики управления в запланированное время (час, минута, секунда) в запланированный день недели.</Description>
    ///<GroupName>Дата и время</GroupName>

    (*

    ПРИМЕР ИСПОЛЬЗОВАНИЯ

    РАБОЧИЙ ЦИКЛ
    - установить на входы номер дня недели и время. Например: "SET_WeekDay = 1, SET_HOUR = 10, SET_HOUR =15, SET_SECOND = 45" / Понедельник в 10 часов 15 минут 45 секунд.
    - сохранить значение выхода GET_NextWeekTime в энергонезависимой переменной T (значение Т - это значение (секунды) системной функции get_date_time() в следующий Понедельник в 10 часов 15 минут 45 секунд)
    - в каждом цикле управляющей программы сравнивать значение T и текущее значение, возвращаемое GET_DateTime / системной функцией get_date_time()
    - когда значение GET_DateTime станет равно значению энергонезависимой переменной T, выполнить управление по событию: "Понедельник - 10:15:45 - НАСТУПИЛ"

    ПЕРЕЗАПУСК управляющей программы после восстановления электропитания (возобновлении работы управляющей программы)
    - в "первом цикле" управляющей программы исключить перезапись значения Т новым значением GET_NextWeekTime
    - в "первом цикле" управляющей программы сравнить значение энергонезависимой переменной T и текущее значение, возвращенное GET_DateTime / системной функцией get_date_time()
    - если значение GET_DateTime больше или равно значению Т, выполнить управление по событию: "Понедельник - 10:15:45 - ПРОШЕЛ/ПРОПУЩЕН"

    ОБРАТИТЬ ВНИМАНИЕ
    Если на входы установить день недели совпадающий с СЕГОДНЯ (со значением системных часов реального времени), но задаваемый Час и/или Минута и/или Секунда больше чем текущее время, то значение GET_NextWeekTime будет установлена на СЕГОДНЯ, на указанные час, минута, секунда.
    *)

    function_block fbGetNextWeekDayInSecond
    var_input
    ///<Description>Допустимые значения: TRUE - ВКЛючена FALSE - ОТКЛючена </Description>
    ENABLE : bool ;
    ///<Description>День недели. Допустимые значения от 1 (ПН) до 7 (ВС)</Description>
    SET_WeekDay : udint;
    ///<Description>Час. Допустимые значения от 0 до 23</Description>
    SET_HOUR : udint;
    ///<Description>Минута. Допустимые значения от 0 до 59</Description>
    SET_MINUTE : udint ;
    ///<Description>Минута. Допустимые значения от 0 до 59</Description>
    SET_SECOND : udint ;
    end_var

    var_output //объявление выходных переменных
    ///<Description>Значение следующего дня недели и времени. Значение в секундах, возвращаемых системной функцией get_date_time(). При ошибке во входных параметрах и в ОТКЛюченном состоянии - 0.</Description>
    GET_NextWeekTime: udint;
    ///<Description>Значение, возвращенное системной функции get_date_time(). При ошибке во входных параметрах и в ОТКЛюченном состоянии - 4294967295 (максимальное значение для типа данных).</Description>
    GET_DateTime: udint;
    end_var

    var //объявление локальных переменных
    ucSecondPerDay : udint; // константа, число секунд в сутках
    ucSecondPerHour : udint; // константа, число секунд в часе
    ucSecondPerMinute : udint; // константа, число секунд в часе
    ucDaysPerWeek : udint; // константа, число дней в неделе
    ucSYSYear : udint; // константа, год начала работы счетчика секунд системной функции get_date_time() / 01.01.2000
    ucSYSWeekDay : udint; // константа, день недели начала работы счетчика секунд системной функции get_date_time() / 01.01.2000

    uWeekDay_TODAY : udint; // вычисляемый текущий день недели
    uHour : udint; // вычисляемый текущий час
    uMinute :udint; // вычисляемая текущая минута
    uSecond :udint; // вычисляемая текущая секунда

    end_var

    // Выход если вычисления не требуются или ошибка во входных параметрах.
    if not ENABLE
    or ( SET_WeekDay < 1 or SET_WeekDay > 7 )
    or ( SET_HOUR < 0 or SET_HOUR > 24 )
    or ( SET_MINUTE < 0 or SET_MINUTE > 59 )
    or ( SET_SECOND < 0 or SET_SECOND > 59 )
    then
    GET_NextWeekTime:= 0;
    GET_DateTime := 4294967295; // максимальное значение для типа данных
    RETURN;
    end_if


    // Устанавливаем константы
    ucSecondPerDay := 24*60*60; // число секунд в одних сутках
    ucSecondPerHour := 60*60; // число секунд в одном часе
    ucSecondPerMinute := 60; // число секунд в одной минтуе
    ucDaysPerWeek := 7; // число дней в неделе
    ucSYSYear := 2000; // год начала работы счетчика секунд системной функции get_date_time() / 01.01.2000
    ucSYSWeekDay := 6; // день недели начала работы счетчика секунд системной функции get_date_time() / 01.01.2000 / Суббота

    // Устанавливаем значение выхода: значение системной функции get_date_time() в секундах
    GET_DateTime := dt_to_udint(get_date_time());

    // конвертируем в номер текущего дня недели значение (в секундах) системной функции get_date_time() и значение константы (день недели начала работы начала работы счетчика секунд системной функции get_date_time())
    // результат на шкале: 0 - ВС ... 6 - СБ
    uWeekDay_TODAY := ( ( GET_DateTime / ucSecondPerDay) + ucSYSWeekDay) mod ucDaysPerWeek; // последовательность номеров дней недели не нарушается в високосный год
    // конвертируем в шкалу: 1 - ПН ... 7- ВС
    if uWeekDay_TODAY = 0 then uWeekDay_TODAY := 7; end_if;

    // конвертируем в текущий час, минуту, секунду значение (в секундах) системной функции get_date_time()
    uHour := ( GET_DateTime mod ucSecondPerDay ) / ucSecondPerHour; //Час системых часов реального времени
    uMinute := ( ( GET_DateTime mod ucSecondPerDay ) mod ucSecondPerHour ) / ucSecondPerMinute; //Минута системых часов реального времени
    uSecond := ( ( GET_DateTime mod ucSecondPerDay ) mod ucSecondPerHour ) mod ucSecondPerMinute; //Секунда системых часов реального времени

    // расчитываем значение (в секундах) системной функции get_date_time() для запрошенного "следующего" дня недели, часа, минуты, секунды
    if (uWeekDay_TODAY = SET_WeekDay)
    and
    (
    (
    SET_HOUR ??? uHour // маленький тест На какое подходящий оператор сравнения нужно заменить "???". Это может быть ">", "<", "=". Какой правильный ответ?
    )
    or
    (
    SET_HOUR = uHour and SET_MINUTE > uMinute
    )
    or
    (
    SET_HOUR = uHour and SET_MINUTE = uMinute and SET_SECOND > uSecond
    )
    )
    then
    // значение для текущего дня недели
    GET_NextWeekTime := ( ( GET_DateTime / ucSecondPerDay ) * ucSecondPerDay) + (SET_HOUR * ucSecondPerHour) + (SET_MINUTE * ucSecondPerMinute) + SET_SECOND / ucSYSYear;
    else
    // значение для следующего дня недели
    GET_NextWeekTime := ( ( ( GET_DateTime / ucSecondPerDay) + ucDaysPerWeek - uWeekDay_TODAY + SET_WeekDay) * ucSecondPerDay) + (SET_HOUR * ucSecondPerHour) + (SET_MINUTE * ucSecondPerMinute) + SET_SECOND * ucSecondPerDay;
    end_if

    end_function_block
    Последний раз редактировалось Shiryaevo; 22.08.2024 в 21:10.

  3. #13

    По умолчанию

    Согласитесь, что, вот так
    <cat>
    выглядит намного приятнее глазу
    У меня нет никаких причин с Вами спорить.
    Последний раз редактировалось Shiryaevo; 22.08.2024 в 21:20.

  4. #14

    По умолчанию

    Цитата Сообщение от Dimensy Посмотреть сообщение
    а это зачем?
    ... по причинам, описанным в коде.

  5. #15
    Пользователь Аватар для petera
    Регистрация
    06.05.2011
    Адрес
    Минск
    Сообщений
    4,108

    По умолчанию

    День недели для любой даты, а не только для сегодня т.е не использую функцию get_date_time() https://owen.ru/forum/showthread.php...l=1#post441126
    Код:
    FUNCTION dayOfWeek : UDINT;     // (c)  PeterA
    VAR_INPUT
        year: udint;
        mounth: udint;
        day:udint;
        Sun_7:bool; //если 1, то воскресенье 7 день, иначе 0
    END_VAR
    VAR
        MM: ARRAY [1..12] OF udint := [5,1,1,4,6,2,4,0,3,5,1,3];
        dayOfWeekTMP: udint;
    END_VAR
    
    IF udint_to_bool(year MOD 4 ) THEN
        MM[1]:= 5; MM[2]:= 1;
    ELSE
        MM[1]:= 4; MM[2]:= 0;
    END_IF
    dayOfWeekTMP:= (year+year/4+ MM[mounth] + day) MOD 7;
    
    dayOfWeek:= dayOfWeekTMP + bool_to_udint(Sun_7 AND dayOfWeekTMP=0) * 7;
        
    end_function
    Мой канал на ютубе
    https://www.youtube.com/c/ПетрАртюков
    Мой канал на РУТУБЕ
    https://rutube.ru/channel/23641433/
    Библиотека ГМ для СП300
    https://disk.yandex.com/d/gHLMhLi8x1_HBg

  6. #16

    По умолчанию

    А ПР-ки уже могут в ARRAY?

  7. #17

    По умолчанию

    Цитата Сообщение от iAlien Посмотреть сообщение
    А ПР-ки уже могут в ARRAY?
    Пока только внутри блоков на ST

  8. #18

    По умолчанию

    Цитата Сообщение от 1exan Посмотреть сообщение
    Пока только внутри блоков на ST
    И только одномерный

Страница 2 из 2 ПерваяПервая 12

Похожие темы

  1. Ответов: 2
    Последнее сообщение: 29.12.2022, 19:02
  2. Март 2020. Свежая подборка статей на "Дзене" от "Датчиков ОВЕН"!
    от Алексей Сидорцев в разделе Трёп (Курилка)
    Ответов: 1
    Последнее сообщение: 18.04.2020, 17:32
  3. Ответов: 0
    Последнее сообщение: 02.02.2020, 21:44
  4. как гарантированно получить "тики" меньше секунды
    от Keldish в разделе Среда программирования OWEN Logic
    Ответов: 14
    Последнее сообщение: 12.04.2018, 09:35
  5. Ответов: 16
    Последнее сообщение: 15.02.2017, 11:39

Метки этой темы

Ваши права

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