From e524190581396a9c3dad0f693ad528530daf3551 Mon Sep 17 00:00:00 2001 From: "Sergey A. Glukhov" Date: Thu, 12 Jun 2025 14:03:04 +0300 Subject: [PATCH 1/6] Add files via upload --- AnjLabCodeBox.xml | 3231 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3231 insertions(+) create mode 100644 AnjLabCodeBox.xml diff --git a/AnjLabCodeBox.xml b/AnjLabCodeBox.xml new file mode 100644 index 0000000..3c303da --- /dev/null +++ b/AnjLabCodeBox.xml @@ -0,0 +1,3231 @@ + + + + + Helpful ST blocks and functions + + + + + + + + + + + + + + + Sergey A Glukhov + true + Anjlab + ACB + Helpful ST blocks and functions + reStructuredText + 888cbf53-45a1-47de-9a2a-fbd72e84a196 + false + qualified-access-only + AnjlabCodeBox + AnjLabCodeBox + true + false + Anjlab Code Box + 3.5.17.1 + + + + + + + + + + + + + + + + + Входной сигнал + + + + + + + + + + Выходной сигнал + + + + + + + + + Время начала + + + + + + + + Память сигнала + + + + + Сглаживание дискретного сигнала + + + + + IF input AND NOT memory THEN + startTime := TIME(); +END_IF; +memory := input; +output := input AND ((TIME() - startTime) > T#100ms); + + + + + 95ddd795-0967-4fd1-b39a-104236a6cda9 + + + + + + + + + + + + Входной сигнал + + + + + + + + + + Выходной сигнал + + + + + + + + + Время начала + + + + + + + + Память сигнала + + + + + Сглаживание дискретного сигнала + + + + + IF (NOT input AND memory) OR (input AND NOT memory) THEN + startTime := TIME(); +END_IF; +memory := input; +output := input; +IF ((TIME() - startTime) < T#100ms) THEN + output := NOT input; +END_IF + + + + + 55ebab12-5437-4033-a731-b42ecbacfe06 + + + + + + + + + + + + Входной сигнал + + + + + + + + + + Выходной сигнал + + + + + + + + + Время начала + + + + + + + + Память сигнала + + + + + Сглаживание дискретного сигнала + + + + + IF NOT input AND memory THEN + startTime := TIME(); +END_IF; +memory := input; +output := input; +IF NOT input AND ((TIME() - startTime) < T#100ms) THEN + output := TRUE; +END_IF + + + + + 30d49b21-1ce3-4ef8-883d-665f4a788870 + + + + + + + + + + + + Входной сигнал + + + + + + + + + + Передний фронт + + + + + + + + Задний фронт + + + + + + + + + + + + + + + Отфильтрованный вход + + + + + + + + + + выделяет передний и задний фронт с фильтром на 100 миллисекунд + + + + + fbDio1(input := input, output => filteredInput); +raise := fall := FALSE; +IF filteredInput AND NOT memory THEN + raise := TRUE; +ELSIF NOT filteredInput AND memory THEN + fall := TRUE; +END_IF +memory := filteredInput; + + + + + 576b0ef3-7dfb-44b9-9d4d-f7a2f2158045 + + + + + + + + + + + + Входной сигнал + + + + + + + + + + Выходной сигнал + + + + + + + + + Время начала + + + + + + + + Память сигнала + + + + + Двойной клик + + + + + output := FALSE; +IF input AND NOT memory THEN + IF (TIME() - startTime) > T#100MS AND (TIME() - startTime) < T#800MS THEN + output := TRUE; + END_IF; + startTime := TIME(); +END_IF; +memory := input; + + + + + d3ac0715-866a-45c1-a900-b774b7c5c01c + + + + + + + + + + + + Входное значение + + + + + + + + Размер буфера минимум 32 максимум 1000 + + + + + + + + Сброс буфера + + + + + + + + + + Выходное отфильтрованное значение + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Эта функция хранит до 32-х значений в буфере и выдает среднее значение. Вы сами можете решить, сколько значений сохранить для получения среднего числа. + + + + + (* ограничим bufferSize в размер буфера *) +bufferSize := MIN(MAX(bufferSize, 1000), 32); +(* Инициализация *) +IF NOT isInitialized OR reset THEN + isInitialized := TRUE; + FOR counter := 1 TO bufferSize DO + buffer[counter] := input; + END_FOR; + sum := input * bufferSize; + output := input; + RETURN; +END_IF; + +IF counter >= bufferSize THEN + counter := 1; +ELSE + counter := counter + 1; +END_IF + +sum := sum + input - buffer[counter]; +{warning disable C0195} +output := DWORD_TO_WORD(sum / bufferSize); +buffer[counter] := input; + + + + + 23da4515-91ff-492f-bd6c-a924c27cb1b0 + + + + + + + + + + + + Входное значение + + + + + + + Временной интервал + + + + + + + + + + Выходное отфильтрованное значение + + + + + + + + + + + + + + + + + + + + + + + + + + + возвращает среднее значение за определенный промежуток времени. + + + + + (* Получаем текущее время *) +currentTime := TIME_TO_DWORD(TIME()); +(* Инициализация *) +IF NOT isInitialized OR timeInterval = T#0s THEN + isInitialized := TRUE; + lastTime := currentTime; + output := input; +ELSIF output = input THEN + lastTime := currentTime; +ELSE + tempTime := WORD_TO_DWORD(input - output) * (currentTime - lastTime) / + TIME_TO_DWORD(timeInterval); + IF tempTime <> 0 THEN + output := DINT_TO_WORD(WORD_TO_DINT(output) + DWORD_TO_DINT(tempTime)); + lastTime := currentTime; + END_IF; +END_IF; + + + + + cc4d134d-f449-4f06-8605-2d943310a473 + + + + + + + + + + + + Входной сигнал + + + + + + + Время нажатия + + + + + + + + + + Выходной сигнал + + + + + + + + + Время начала + + + + + + + + Память сигнала + + + + + Долгий клик + + + + + IF input AND NOT memory THEN + startTime := TIME(); +END_IF; +memory := input; +output := input AND ((TIME() - startTime) > pressTime); + + + + + e847a08d-2858-49e0-b6fb-cbe441c3349b + + + + + + + + + + + + Запуск генератора + + + + + + + + + + Время импульсов + + + + + + + + + + Выходной сигнал + + + + + + + + + + + + + + + + + + + + создает импульсы с заданной частотой + CLK_PWM(EN := TRUE, PT := T#5ms); На выходе Q будет импульс в один цикл ПЛК, раз в 5 миллисекунд. + + + + + currentTime := TIME(); +IF enable AND NOT memory THEN + lastTime := currentTime - pulseTime; +END_IF; +memory := enable; +output := currentTime - lastTime >= pulseTime; +IF output THEN lastTime := currentTime; END_IF; + + + + + e2565834-4fd9-4a85-b9e7-a4c45a2b4e0b + + + + + + + + + + + + Частота, раз в секунду (Гц) + + + + + + + + Соотношение + + + + + + + + + + Выходной сигнал + + + + + + + + + + + + + + + + + + + + + + создает ШИМ-сигнал заданной частоты со смещением соотношения. Каждый цик ШИМ можно разделить на 2 фазы: Ton (время включения) и Toff (время выключения). + Соотношение задается от 0 до 1. Например, соотношение 0.5 разделит время каждого цикла шим на 50% на Ton и 50% на Toff . + + + + + (* Если частота ШИМ 0, то прерываем исполнение ФБ *) +IF frequency <= 0.0 THEN + output := FALSE; + RETURN; +END_IF; +(* Вычисляем сколько миллисекунд требуется на один цикл ШИМ *) +tempValue := 1000.0 / frequency; +(* Запускаем генератор сигналов *) +clock(pulseTime := REAL_TO_TIME(tempValue)); +(* Создаем выдержанный пульс на нужное время *) +pulseTimer(in := clock.output, pt := REAL_TO_TIME(tempValue * dutyCycle), Q => output); + + + + + 55fa2adc-b14d-4d49-a0d3-ee6618946ede + + + + + + + + + + + + Частота, раз в секунду (Гц) + + + + + + + Длина фазы Ton + + + + + + + + + + Выходной сигнал + + + + + + + + + + + + + + + + + Создает ШИМ-сигнал с заданным временем фазы Ton . Например, мы можем установить F на 100 раз в секунду. Это значит, один цикл ШИМ будет 10 + миллисекунд. Теперь поставим PW в T#5ms и получим равное время для фазы Ton и Toff по 50%. + + + + + (* Если частота ШИМ 0 или время одного цикла меньше, +чем время для фазы Ton, то прерываем исполнение ФБ *) +IF frequency <= 0.0 OR (REAL_TO_TIME(1000.0 / frequency) < pulseWidth) THEN + output := FALSE; + RETURN; +END_IF; +(* Запускаем генератор сигналов *) +clock(pulseTime := REAL_TO_TIME(1000.0 / frequency)); +(* Создаем выдержанный пульс на нужное время *) +pulseTimer(in := clock.output, PT := pulseWidth, Q => output); + + + + + ff93b01a-c5fb-4d17-a425-8e834ffc249d + + + + + + + + + + + + Широта + + + + + + + + Долгота + + + + + + + + Текущее время в UTC + + + + + + + + + + + Градус над горизонтом, при котором уже считается наступление заката или восхода + + + + + + + + + + Время дня солнцестояния + + + + + + + + Время восхода + + + + + + + + Время заката + + + + + + + + Угол наклона солнца в солнцестояние в градусах + + + + + + + + + + Угол наклона солнца в полдень в радианах + + + + + + + Дельта от солнцестояния до восхода или заката + + + + + + + + + + расчет времени заката и восхода + + + + + MIDDAY := SunMidday(longitude, utc); +b := latitude * 0.0174532925199433; +dk := 0.40954 * SIN(0.0172 * (UINT_TO_REAL(DayOfYear(utc)) - 79.35)); +SUN_DECLINATION := DegreesToRadians(DK); +IF SUN_DECLINATION > 180.0 THEN + SUN_DECLINATION := SUN_DECLINATION - 360.0; +END_IF; +SUN_DECLINATION := 90.0 - LATITUDE + SUN_DECLINATION; +delta := HourToTime(REAL_TO_INT(ACOS((SIN(RadiansToDegrees(H)) - SIN(B) * SIN(DK)) / (COS(B) * COS(DK))) * 3.819718632)); +SUN_RISE := MIDDAY - delta; +SUN_SET := MIDDAY + delta; + + + + + c0162500-a121-4d9a-a1ba-5801e54027bc + + + + + + + + + + + + + + + IP-адрес как строка, например, '192.168.1.2' + + + + + + + + + + + + Преобразование в шестнадцатеричный формат для записи IP + + + + + position := FIND(ipStr, '.'); +WHILE position > 0 DO + IpDecode := SHL(IpDecode, 8) OR + STRING_TO_DWORD(LEFT(ipStr, position - 1)); + ipStr := DELETE(ipStr, position, 1); + position := FIND(ipStr, '.'); +END_WHILE; +IpDecode := SHL(IpDecode, 8) OR STRING_TO_DWORD(ipStr); + + + + + 370b1e33-b130-432d-82c0-d0ff7d197d76 + + + + + + + + + + + + + + + Входное значение + + + + + Округляет значение и возвращает ближайшее целое значение, которое больше или равно X. + ceil(3.14) = 4 ceil(-3.14) = -3 + + + + + Ceil := REAL_TO_DINT(input); + +IF DINT_TO_REAL(Ceil) < input THEN + Ceil := Ceil + 1; +END_IF; + + + + + 7e9d7ee0-507a-40bb-a5cb-1802edf09ecc + + + + + + + + + + + + + + + Входное значение + + + + + Вычисляет с основанием степени 10. + exp10(2) = 100 exp10(3) = 1000 + + + + + Exp10 := EXP(input * 2.30258509299405); + + + + + f6121561-6e17-4f2f-aa33-883772fb1cdc + + + + + + + + + + + + + + + Входное значение + + + + + + + + Степень + + + + + + + + + + + + Возведение в степень X^N. Хотя в стандарте есть оператор EXPT, по заявлению OSCAT, данный алгоритм работает в 30 раз быстрее в CoDeSys. + + + + + sign := power.15; +power := ABS(power); +IF power.0 THEN ExpN := input; ELSE ExpN := 1.0; END_IF; +power := SHR(power, 1); + +WHILE power > 0 DO + input := input * input; + IF power.0 THEN ExpN := ExpN * input; END_IF; + power := SHR(power, 1); +END_WHILE; + +IF sign THEN ExpN := 1.0 / ExpN; END_IF; + + + + + 9bf63bfe-fe54-48dc-8f90-261ea50d788f + + + + + + + + + + + + + + + Входное значение + + + + + Округляет значение и возвращает ближайшее целое значение, которое меньше или равно X. + floor(3.14) = 3 floor(-3.14) = -4 + + + + + FLOOR := REAL_TO_DINT(input); +IF DINT_TO_REAL(FLOOR) > input THEN + FLOOR := FLOOR - 1; +END_IF; + + + + + 24fdd6dd-18c7-494b-9be5-85e1efccd187 + + + + + + + + + + + + + + + Входное значение + + + + + Эта функция возвращает дробную часть числа с плавающей точкой. + fract(3.14) = 0.14 + + + + + IF ABS(input) < 2.0E9 THEN + FRACT := input - DINT_TO_REAL(DTrunc(input)); +ELSE + FRACT := 0.0; +END_IF; + + + + + 645754da-c783-41eb-83c4-3246b516ea8a + + + + + + + + + + + + + + + Делимое + + + + + + + + Делитель + + + + + Вычисляет остаток от деления для чисел с плавающей запятой. + modr(5.5, 2.5) = 0.5 + + + + + IF divisor = 0.0 THEN + MODR := 0.0; +ELSE + MODR := input - DINT_TO_REAL(FLOOR(input / divisor)) * divisor; +END_IF; + + + + + + eb5f423f-4ff8-4594-96fb-e59f6014738a + + + + + + + + + + + + + + + Число для обработки + + + + + + + + Точность после запятой + + + + + Округляет число с плавающей точкой до указанного количества знаков после запятой. + round(12.23456789, 2) = 12.23 + + + + + Round := DWORD_TO_REAL(REAL_TO_DWORD(input * Exp10(precision))) / Exp10(precision); + + + + + + 43eb8e9c-7822-492d-a6d3-b21875b9c65d + + + + + + + + + + + + + + + Входное значение в Цельсиях + + + + + Преобразование температуры из Цельсия в Фаренгейт + + + + + CelciusToFarenheit := celsiusTemp * 1.8 + 32.0; + + + + + f38a7a17-3c95-415a-9d89-4d5e214e7d67 + + + + + + + + + + + + + + + Входное значение в Цельсиях + + + + + + + + + + + + + 0°C в кельвинах + + + + + Преобразование температуры из Цельсия в Кельвин + + + + + CelciusToKelvin := celsiusTemp + physT0; + + + + + c9722344-c925-4350-b9db-68400010e960 + + + + + + + + + + + + + + + Входное значение в радианах + + + + + Конвертирует радианы в градусы. + + + + + DegreesToRadians := ModR(57.29577951308232 * radians, 360.0); + + + + + 00741b76-d02e-4841-9218-cf4e51799c29 + + + + + + + + + + + + + + + Входное значение в Фаренгейтах + + + + + Преобразование температуры из Фаренгейт в Цельсий + + + + + FarenheitToCelcius := (fahrenheitTemp - 32.0) * 0.5555555555555; + + + + + 1c8099aa-563e-4039-baa6-55b2d26aae82 + + + + + + + + + + + + + + + Входное значение в Кельвнах + + + + + + + + + + + + + 0°C в кельвинах + + + + + Преобразование температуры из Кельвина в Цельсий + + + + + KelvinToCelcius := kelvinTemp - phys_T0; + + + + + e6d47c81-1b52-487e-bf16-0f77ef5ec08d + + + + + + + + + + + + + + + Входное значение в Км/ч + + + + + Преобразование скорости: км/ч в м/с + + + + + KmhToMs := kmhSpeed * 0.2777777777777; + + + + + 2027f9e1-f77f-4afa-a939-a7875cdc7b46 + + + + + + + + + + + + + + + Входное значение в м/с + + + + + Преобразование скорости: м/с в км/ч + + + + + MsToKmh := msSpeed * 3.6; + + + + + 89576b24-8a23-496b-abf0-27109c81d84e + + + + + + + + + + + + + + + Входное значение в градусах + + + + + + + + + + + + + + + + + + + + + + + + + + + конвертирует градусы в радианы + + + + + RadiansToDegrees := ModR(0.0174532925199433 * degrees, pi*2); + + + + + 4b9ad742-ef31-4574-92c8-257046749aee + + + + + + + + + + + + + + + Входное значение + + + + + + + + Входное минимальное + + + + + + + + Входное максимальное + + + + + + + + Выходное минимальное + + + + + + + + Выходное максимальное + + + + + линейное масштабирование числа с плавающей запятой + + + + + IF inputLow = inputHigh THEN + ScaleReal := outputLow; +ELSE + ScaleReal := (outputHigh - outputLow) / (inputHigh - inputLow) * (LIMIT(inputLow, input, inputHigh) - inputLow) + outputLow; +END_IF; + + + + + 6196bfc8-2183-4935-bc2e-5406080c7841 + + + + + + + + + + + + + + + Строка + + + + + + + + Символ для подсчета + + + + + + + + + + + + + + Указатель на символ + + + + + + + + Длина строки + + + + + + + + Текущая позиция строки для прохода + + + + + считает, как много указанных символов содержится в строке + + + + + charPointer := ADR(inputString); +length := LEN(inputString); +CountChar := 0; +FOR position := 1 TO length DO + IF charPointer^ = charToCount THEN + CountChar := CountChar + 1; + END_IF; + charPointer := charPointer + 1; +END_FOR; + + + + + 5aa298bd-a611-423a-87e1-7a0a808f20a1 + + + + + + + + + + + + + + + Входная строка + + + + + + + + Что удалить + + + + + + + + + + Для временной строки + + + + + + + + Позиция найденного символа + + + + + Удаление символа из строки + + + + + tempString := inputString; +REPEAT + position := FIND(tempString, substringToRemove); + IF position <> 0 THEN + tempString := DELETE(tempString, LEN(substringToRemove), position); + END_IF; +UNTIL (position = 0) +END_REPEAT; +RemoveSubString := tempString; + + + + + 0b8ea8fb-1139-4800-98db-52a469579462 + + + + + + + + + + + + + + + Входная строка + + + + + + + + Значение setup.EXTENDED_ASCII может быть или TRUE или FALSE, в зависимости от символьной таблицы, которая поддерживается ПЛК. Обычно стоит в TRUE. + + + + + Изменить регистр символа с маленькой буквы на заглавную. Работает только с латинскими буквами формата ASCII. + + + + + IF input > 96 AND input < 123 THEN + ToUpper := input AND 16#DF; +ELSIF input > 223 AND input <> 247 AND input <> 255 AND useExtendedASCII THEN + ToUpper := input AND 16#DF; +ELSE + ToUpper := input; +END_IF; + + + + + 698221f0-adfb-47db-abeb-4a75818c8180 + + + + + + + + + + + + + + + Входная дата + + + + + + + + + + Год + + + + + + + + Месяц + + + + + + + + День + + + + + + + + + + + + Извлечение года, месяца и дня из DATE + + + + + (* Получаем дату строкой 'D#2000-01-01' *) +sTemp := DATE_TO_STRING(input); +year := STRING_TO_UINT(MID(sTemp, 3, 4)); +month := STRING_TO_UINT(MID(sTemp, 8, 2)); +day := STRING_TO_UINT(MID(sTemp, 11, 2)); + +DateToElements := true; + + + + + 6db1ca07-0a85-498a-b97a-6a21380eb6fc + + + + + + + + + + + + + + + Входная дата + + + + + + + + + + + + Определение дня недели + + + + + NumOfDay := DATE_TO_DWORD(input) / 86400; +NumOfDay := NumOfDay + 3; +DayOfWeek := DWORD_TO_UINT(NumOfDay MOD 7); + + + + + c2ffe08f-5940-4c7a-9f94-7b20fd25a5b5 + + + + + + + + + + + + + + + Входная дата в формате DATE + + + + + + + + + + + + + + + + + + + + + + Вычисление порядкового дня в году + + + + + DateToElements(input := input, year => year, month => month, day => day); + +DayOfYear := DaysTillMonth(year, month) + day; + + + + + f45877af-d8f3-4c70-8245-f5113a02d7b2 + + + + + + + + + + + + + + + Год + + + + + Вычисление количества дней в году + + + + + IF IsLeapYear(year) THEN + DaysInYear := 366; +ELSE + DaysInYear := 365; +END_IF; + + + + + 0cb6fbcb-04a1-492a-bc99-f7d781171e05 + + + + + + + + + + + + + + + Год + + + + + + + + Месяц + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + функция, чтобы определить количество дней от начала года до указанного месяца. + + + + + DaysTillMonth := days[month] + BOOL_TO_UINT(month > 2 AND IsLeapYear(year)); + + + + + 998fa9fe-8a9c-4caf-85f6-9d4d58758e09 + + + + + + + + + + + + + + + Год + + + + + считает сколько прошло дней до указанного года + + + + + (* Получаем количество лет прошло с 1970го года *) +year := year - 1970; +DaysTillYear := year * 365 + ((year + 1) / 4) - ((year + 69) / 100) + ((year + 369) / 400); + + + + + 3fd03899-b6a1-4d1d-bd61-e17642c4a73b + + + + + + + + + + + + + + Часы + + + + + + + + Минуты + + + + + + + + Секунды + + + + + + + + Миллисекунды + + + + + Упаковка часов, минут, секунд и миллисекунд в TIME + + + + + HmsToTime := DWORD_TO_TIME(((h * 60 + m) * 60 + sec) * 1000 + ms); + + + + + 3968a562-7bfd-47a8-a79a-14053b959297 + + + + + + + + + + + + + + Часы (0..23) + + + + + Преобразовать часы (в виде INT) в TIME + + + + + HourToTime := T#1H * hours; + + + + + 6f15ae17-53ff-4aec-ba86-f5a3d4193b82 + + + + + + + + + + + + + + + Часы (0..23) + + + + + Преобразовать количество часов (INT) во значение типа TOD (время суток). + + + + + HourToTod := TOD#00:00:00 + T#1h * hours; + + + + + fe41eacd-9f55-4e06-b2b7-479808977dfb + + + + + + + + + + + + + + + Год + + + + + Определение високосного года + + + + + IsLeapYear := year MOD 400 = 0 OR year MOD 4 = 0 AND year MOD 100 <> 0; + + + + + 2da9dfda-5b1d-454a-bcdd-873266c15f56 + + + + + + + + + + + + + + + Широта + + + + + + + + Дата в UTC + + + + + + + + + + + + + + + + + время солнцестояния на заданной широте в заданное время + + + + + T := UINT_TO_REAL(DayOfYear(utc)); +OFFSET := -0.1752 * SIN(0.033430 * T + 0.5474) - 0.1340 * SIN(0.018234 * T - 0.1939); +SunMidday := HourToTod(REAL_TO_INT(12.0 - OFFSET - lon * 0.0666666666666)); + + + + + 8af2c015-46ea-475d-acc8-627981e9c1d4 + + + + + + + + + + + + + + Входное время + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Извлечение часов, минут, секунд и миллисекунд из TIME + + + + + (* Теперь время имеет строку типа 'TOD#12:12:59' *) +sTemp := TOD_TO_STRING(TIME_TO_TOD(input)); +h := STRING_TO_UINT(MID(sTemp, 5, 2)); +m := STRING_TO_UINT(MID(sTemp, 8, 2)); +sec := STRING_TO_UINT(MID(sTemp, 11, 2)); +TimeToElements := TRUE; + + + + + d8de33e6-87c6-4733-b78a-ba4d754deb93 + + + + + + + + + + + + + + + текущее время + + + + + + + + нижняя граница + + + + + + + + верхняя граница + + + + + функция определения, что текущее время находится в промежутке между двумя отметками времени TIME_OF_DAY. + + + + + TodBetween := ( + FromTime > ToTime AND (CurrTime > FromTime OR CurrTime < ToTime) + ) OR (FromTime < ToTime AND (CurrTime < ToTime AND CurrTime > FromTime) +); + + + + + + c23200b5-1781-4c39-9b57-f0e0e966370c + + + + + + + + + + + + + + нижняя граница + + + + + + + + верхняя граница + + + + + Вычисление разницы отметок времени + + + + + IF ToTime < FromTime THEN + TodDiff := T#24H - TOD_TO_TIME(FromTime) + TOD_TO_TIME(ToTime); +ELSE + TodDiff := ToTime - FromTime; +END_IF + + + + + 68ceaa4e-735c-48a4-a936-c6b5da48a973 + + + + + + + + + + + + + + + Текущая дата + + + + + Вычисления порядкового номера недели в году + + + + + WeekOfYear := ((DayOfYear(currentDate) + 6) / 7); +IF DayOfWeek(currentDate) < DayOfWeek(YearStarts(currentDate)) THEN + WeekOfYear := WeekOfYear + 1; +END_IF; + + + + + 70448faa-ac59-425b-8d39-299263f17006 + + + + + + + + + + + + + + + Текущая дата + + + + + + + + + + Временная строка + + + + + Вычисления с какого дня недели начинается год + + + + + str := DATE_TO_STRING(currentDate); (* получаем строку `D#2000-12-30` *) +YearStarts := STRING_TO_DATE(CONCAT(CONCAT('D#', MID(str, 3, 4)), '-01-01')); + + + + + 395f1cd0-ef8e-4840-af88-1cc7e4bc199f + + + + + + +
+ + + + + + + + Год + + + + + + + + Месяц + + + + + + + + День + + + + + + + + Час + + + + + + + + Минуты + + + + + + + + Секунды + + + + + + + + Миллисекунды + + + + + + + + + + + + Упаковка года, месяца, дня, часов, минут, секунд и миллисекунд в DT + + + + + sTemp := CONCAT('DT#', UINT_TO_STRING(y)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(mn)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(d)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(h)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(m)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(sec)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(ms)); +YmdhmsTodt := STRING_TO_DT(sTemp); + + + + + 22b5f20f-f8ae-477a-af67-7efa962518d0 + + + + + + + + + + + + + + + Год + + + + + + + + Месяц + + + + + + + + День + + + + + + + + + + + + Gеревод год, месяц и день в формат DATE. + + + + + sTemp := CONCAT('D#', UINT_TO_STRING(y)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(m)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(d)); +YmdToDate := STRING_TO_DATE(sTemp); + + + + + 5c9ab7aa-35fb-49a0-b541-53a3c59037e8 + + + + + + + + + + + + + + + Входное число + + + + + Cчитает количество бит, равных TRUE в DWORD. + Пример: bit_count(3) = 2 Потому что 2 бита равны 1, а остальные равны 0. + + + + + WHILE input > 0 DO + IF input.0 THEN + BitCount := BitCount + 1; + END_IF + input := SHR(input, 1); +END_WHILE; + + + + + 35c5d0b0-50b6-48ad-8ade-487398968ef5 + + + + + + + + + + + + + + + Байт, в котором нужно произвести операцию + + + + + + + + Присваиваемое значение + + + + + + + + Какому по номеру биту + + + + + + + + + + + + + + + Загружает значение одного бита в байт. + bit_load_b(2#0000_0000, 1, 2) = 2#0000_0010 + + + + + IF value THEN + BitLoadB := input OR SHL(dat, position); +ELSE + BitLoadB := input AND (NOT SHL(dat, position)); +END_IF; + + + + + 0ee4e802-faae-426e-a4d7-a5fbb5c81186 + + + + + + + + + + + + + + + Входное число + + + + + + + + номер бита + + + + + Вычисляем значение единичного бита в переменной типа DWORD. + + + + + BitOfDword := (SHR(input, n) AND 16#00000001) > 0; + + + + + 7c67bd8a-5ab5-43d1-9cc5-4957da9e0079 + + + + + + + + + + + + + + + Входное значение + + + + + + + + Номер инвертируемого бита + + + + + Инвертируем указанный бит в DWORD + + + + + BitToggleDword := SHL(DWORD#1, position) XOR input; + + + + + fbbd32ea-a489-45b8-af81-580307e6eaa4 + + + + + + + + + + + + + + + Входное значение X + + + + + + + + Входное значение Y + + + + + + + + Количество сравниваемых разрядов + + + + + + + + + + + + Сравнивает 2 входных числовых переменных, совпадают ли их первые разрады. + Количество сравниваемых разрядов передается в параметре N. + cmp(3.141516, 3.141517, 6) вернет TRUE. + + + + + tmp := ABS(x); +IF tmp > 0.0 THEN + tmp := Exp10(DINT_TO_REAL(FLOOR(LOG(tmp))-n+1)); +ELSE + tmp := Exp10(tmp); +END_IF; + +CompareReals := ABS(x - y) < tmp; + + + + + 95639908-aef5-4ad0-9463-00d7f35e4750 + + + + + + + + + + + + + + + Входное значение + + + + + Усекает число с плавающей запятой в целое число DINT. 1.5 станет 1, а -1.5 станет -1. + Данная функция необходима, потому что REAL_TO_DINT на разных системах может вернуть разный результат. + + + + + DTrunc := REAL_TO_DINT(input); + +IF input > 0.0 THEN + IF DINT_TO_REAL(DTrunc) > input THEN + DTrunc := DTrunc - 1; + END_IF; +ELSE + IF DINT_TO_REAL(DTrunc) < input THEN + DTrunc := DTrunc + 1; + END_IF; +END_IF; + + + + + e81c8fd1-e716-4f15-a950-9242e8801c85 + + + + + + + + + + + + + + + Входное значение + + + + + Вычисляет, является ли число четным или нет. Если четное, то вернет TRUE, а если нет - вернет FALSE. + + + + + Even := NOT input.0; + + + + + dd31efa8-aa78-41e1-be66-269920045c5c + + + + + + + + + + + + + + + Предыдущее значение + + + + + + + + + + + + + + + + + + + + + + + + + константа Эйлера + + + + + Вычисляет псевдо-случайное число. Чтобы сгенерировать число, функция + считывает таймер ПЛК и создает число с плавающей точкой от 0 до 1. Чтобы + использовать эту функцию больше, чем один раз, в одном цикле ПЛК, нужно ее + вызывать с разным значением входного параметра last. В него проще внести + прошлое число, чтобы исключить повторения. + + + + + tn := TIME_TO_DWORD(TIME()); +tc := BitCount(tn); +tn.31 := tn.2; +tn.30 := tn.5; +tn.29 := tn.4; +tn.28 := tn.1; +tn.27 := tn.0; +tn.26 := tn.7; +tn.25 := tn.6; +tn.24 := tn.3; +tn := ROL(tn, BitCount(tn)) OR 16#80000001; +tn := tn MOD 71474513 + INT_TO_DWORD(tc + 77); +Random := FRACT(DWORD_TO_REAL(tn) / 10000000.0 * +(E - LIMIT(0.0, last, 1.0)) +); + + + + + 8d60497f-9b6b-4c61-877a-775acbca0520 + + + + + + + + + + + + + + + Входное значение + + + + + Поменять байт местами в DWORD + + + + + SwapDwordBytes := (ROR(input, 8) AND 16#FF00FF00) OR (ROL(input, 8) AND 16#00FF00FF); + + + + + 2cf34bc5-a910-4ad8-9cd5-2ccbbf01ed02 + + + + + + + + + + + + + + + Входное значение + + + + + Поменять байт местами в WORD + + + + + SwapWordBytes := ROL(input, 8); + + + + + 683a7031-edb1-4113-9c5d-4519805b2f16 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 3598da81558aa160e0cff6e84d8753167b084a21 Mon Sep 17 00:00:00 2001 From: "Sergey A. Glukhov" Date: Thu, 12 Jun 2025 14:06:13 +0300 Subject: [PATCH 2/6] Update AnjLabCodeBox.xml --- AnjLabCodeBox.xml | 544 +++++++++++++++++++++++----------------------- 1 file changed, 278 insertions(+), 266 deletions(-) diff --git a/AnjLabCodeBox.xml b/AnjLabCodeBox.xml index 3c303da..062605b 100644 --- a/AnjLabCodeBox.xml +++ b/AnjLabCodeBox.xml @@ -1,6 +1,6 @@ - + - + Helpful ST blocks and functions @@ -86,10 +86,10 @@ - IF input AND NOT memory THEN - startTime := TIME(); -END_IF; -memory := input; + IF input AND NOT memory THEN + startTime := TIME(); +END_IF; +memory := input; output := input AND ((TIME() - startTime) > T#100ms); @@ -145,13 +145,13 @@ output := input AND ((TIME() - startTime) > T#100ms); - IF (NOT input AND memory) OR (input AND NOT memory) THEN - startTime := TIME(); -END_IF; -memory := input; -output := input; -IF ((TIME() - startTime) < T#100ms) THEN - output := NOT input; + IF (NOT input AND memory) OR (input AND NOT memory) THEN + startTime := TIME(); +END_IF; +memory := input; +output := input; +IF ((TIME() - startTime) < T#100ms) THEN + output := NOT input; END_IF @@ -207,13 +207,13 @@ END_IF - IF NOT input AND memory THEN - startTime := TIME(); -END_IF; -memory := input; -output := input; -IF NOT input AND ((TIME() - startTime) < T#100ms) THEN - output := TRUE; + IF NOT input AND memory THEN + startTime := TIME(); +END_IF; +memory := input; +output := input; +IF NOT input AND ((TIME() - startTime) < T#100ms) THEN + output := TRUE; END_IF @@ -279,13 +279,13 @@ END_IF - fbDio1(input := input, output => filteredInput); -raise := fall := FALSE; -IF filteredInput AND NOT memory THEN - raise := TRUE; -ELSIF NOT filteredInput AND memory THEN - fall := TRUE; -END_IF + fbDio1(input := input, output => filteredInput); +raise := fall := FALSE; +IF filteredInput AND NOT memory THEN + raise := TRUE; +ELSIF NOT filteredInput AND memory THEN + fall := TRUE; +END_IF memory := filteredInput; @@ -341,13 +341,13 @@ memory := filteredInput; - output := FALSE; -IF input AND NOT memory THEN - IF (TIME() - startTime) > T#100MS AND (TIME() - startTime) < T#800MS THEN - output := TRUE; - END_IF; - startTime := TIME(); -END_IF; + output := FALSE; +IF input AND NOT memory THEN + IF (TIME() - startTime) > T#100MS AND (TIME() - startTime) < T#800MS THEN + output := TRUE; + END_IF; + startTime := TIME(); +END_IF; memory := input; @@ -428,28 +428,28 @@ memory := input; - (* ограничим bufferSize в размер буфера *) -bufferSize := MIN(MAX(bufferSize, 1000), 32); -(* Инициализация *) -IF NOT isInitialized OR reset THEN - isInitialized := TRUE; - FOR counter := 1 TO bufferSize DO - buffer[counter] := input; - END_FOR; - sum := input * bufferSize; - output := input; - RETURN; -END_IF; - -IF counter >= bufferSize THEN - counter := 1; -ELSE - counter := counter + 1; -END_IF - -sum := sum + input - buffer[counter]; -{warning disable C0195} -output := DWORD_TO_WORD(sum / bufferSize); + (* ограничим bufferSize в размер буфера *) +bufferSize := MIN(MAX(bufferSize, 1000), 32); +(* Инициализация *) +IF NOT isInitialized OR reset THEN + isInitialized := TRUE; + FOR counter := 1 TO bufferSize DO + buffer[counter] := input; + END_FOR; + sum := input * bufferSize; + output := input; + RETURN; +END_IF; + +IF counter >= bufferSize THEN + counter := 1; +ELSE + counter := counter + 1; +END_IF + +sum := sum + input - buffer[counter]; +{warning disable C0195} +output := DWORD_TO_WORD(sum / bufferSize); buffer[counter] := input; @@ -517,22 +517,22 @@ buffer[counter] := input; - (* Получаем текущее время *) -currentTime := TIME_TO_DWORD(TIME()); -(* Инициализация *) -IF NOT isInitialized OR timeInterval = T#0s THEN - isInitialized := TRUE; - lastTime := currentTime; - output := input; -ELSIF output = input THEN - lastTime := currentTime; -ELSE - tempTime := WORD_TO_DWORD(input - output) * (currentTime - lastTime) / - TIME_TO_DWORD(timeInterval); - IF tempTime <> 0 THEN - output := DINT_TO_WORD(WORD_TO_DINT(output) + DWORD_TO_DINT(tempTime)); - lastTime := currentTime; - END_IF; + (* Получаем текущее время *) +currentTime := TIME_TO_DWORD(TIME()); +(* Инициализация *) +IF NOT isInitialized OR timeInterval = T#0s THEN + isInitialized := TRUE; + lastTime := currentTime; + output := input; +ELSIF output = input THEN + lastTime := currentTime; +ELSE + tempTime := WORD_TO_DWORD(input - output) * (currentTime - lastTime) / + TIME_TO_DWORD(timeInterval); + IF tempTime <> 0 THEN + output := DINT_TO_WORD(WORD_TO_DINT(output) + DWORD_TO_DINT(tempTime)); + lastTime := currentTime; + END_IF; END_IF; @@ -596,10 +596,10 @@ END_IF; - IF input AND NOT memory THEN - startTime := TIME(); -END_IF; -memory := input; + IF input AND NOT memory THEN + startTime := TIME(); +END_IF; +memory := input; output := input AND ((TIME() - startTime) > pressTime); @@ -666,12 +666,12 @@ output := input AND ((TIME() - startTime) > pressTime); - currentTime := TIME(); -IF enable AND NOT memory THEN - lastTime := currentTime - pulseTime; -END_IF; -memory := enable; -output := currentTime - lastTime >= pulseTime; + currentTime := TIME(); +IF enable AND NOT memory THEN + lastTime := currentTime - pulseTime; +END_IF; +memory := enable; +output := currentTime - lastTime >= pulseTime; IF output THEN lastTime := currentTime; END_IF; @@ -735,16 +735,16 @@ IF output THEN lastTime := currentTime; END_IF; - (* Если частота ШИМ 0, то прерываем исполнение ФБ *) -IF frequency <= 0.0 THEN - output := FALSE; - RETURN; -END_IF; -(* Вычисляем сколько миллисекунд требуется на один цикл ШИМ *) -tempValue := 1000.0 / frequency; -(* Запускаем генератор сигналов *) -clock(pulseTime := REAL_TO_TIME(tempValue)); -(* Создаем выдержанный пульс на нужное время *) + (* Если частота ШИМ 0, то прерываем исполнение ФБ *) +IF frequency <= 0.0 THEN + output := FALSE; + RETURN; +END_IF; +(* Вычисляем сколько миллисекунд требуется на один цикл ШИМ *) +tempValue := 1000.0 / frequency; +(* Запускаем генератор сигналов *) +clock(pulseTime := REAL_TO_TIME(tempValue)); +(* Создаем выдержанный пульс на нужное время *) pulseTimer(in := clock.output, pt := REAL_TO_TIME(tempValue * dutyCycle), Q => output); @@ -803,15 +803,15 @@ pulseTimer(in := clock.output, pt := REAL_TO_TIME(tempValue * dutyCycle), Q => - (* Если частота ШИМ 0 или время одного цикла меньше, -чем время для фазы Ton, то прерываем исполнение ФБ *) -IF frequency <= 0.0 OR (REAL_TO_TIME(1000.0 / frequency) < pulseWidth) THEN - output := FALSE; - RETURN; -END_IF; -(* Запускаем генератор сигналов *) -clock(pulseTime := REAL_TO_TIME(1000.0 / frequency)); -(* Создаем выдержанный пульс на нужное время *) + (* Если частота ШИМ 0 или время одного цикла меньше, +чем время для фазы Ton, то прерываем исполнение ФБ *) +IF frequency <= 0.0 OR (REAL_TO_TIME(1000.0 / frequency) < pulseWidth) THEN + output := FALSE; + RETURN; +END_IF; +(* Запускаем генератор сигналов *) +clock(pulseTime := REAL_TO_TIME(1000.0 / frequency)); +(* Создаем выдержанный пульс на нужное время *) pulseTimer(in := clock.output, PT := pulseWidth, Q => output); @@ -923,16 +923,16 @@ pulseTimer(in := clock.output, PT := pulseWidth, Q => output); - MIDDAY := SunMidday(longitude, utc); -b := latitude * 0.0174532925199433; -dk := 0.40954 * SIN(0.0172 * (UINT_TO_REAL(DayOfYear(utc)) - 79.35)); -SUN_DECLINATION := DegreesToRadians(DK); -IF SUN_DECLINATION > 180.0 THEN - SUN_DECLINATION := SUN_DECLINATION - 360.0; -END_IF; -SUN_DECLINATION := 90.0 - LATITUDE + SUN_DECLINATION; -delta := HourToTime(REAL_TO_INT(ACOS((SIN(RadiansToDegrees(H)) - SIN(B) * SIN(DK)) / (COS(B) * COS(DK))) * 3.819718632)); -SUN_RISE := MIDDAY - delta; + MIDDAY := SunMidday(longitude, utc); +b := latitude * 0.0174532925199433; +dk := 0.40954 * SIN(0.0172 * (UINT_TO_REAL(DayOfYear(utc)) - 79.35)); +SUN_DECLINATION := DegreesToRadians(DK); +IF SUN_DECLINATION > 180.0 THEN + SUN_DECLINATION := SUN_DECLINATION - 360.0; +END_IF; +SUN_DECLINATION := 90.0 - LATITUDE + SUN_DECLINATION; +delta := HourToTime(REAL_TO_INT(ACOS((SIN(RadiansToDegrees(H)) - SIN(B) * SIN(DK)) / (COS(B) * COS(DK))) * 3.819718632)); +SUN_RISE := MIDDAY - delta; SUN_SET := MIDDAY + delta; @@ -970,13 +970,13 @@ SUN_SET := MIDDAY + delta; - position := FIND(ipStr, '.'); -WHILE position > 0 DO - IpDecode := SHL(IpDecode, 8) OR - STRING_TO_DWORD(LEFT(ipStr, position - 1)); - ipStr := DELETE(ipStr, position, 1); - position := FIND(ipStr, '.'); -END_WHILE; + position := FIND(ipStr, '.'); +WHILE position > 0 DO + IpDecode := SHL(IpDecode, 8) OR + STRING_TO_DWORD(LEFT(ipStr, position - 1)); + ipStr := DELETE(ipStr, position, 1); + position := FIND(ipStr, '.'); +END_WHILE; IpDecode := SHL(IpDecode, 8) OR STRING_TO_DWORD(ipStr); @@ -1008,10 +1008,10 @@ IpDecode := SHL(IpDecode, 8) OR STRING_TO_DWORD(ipStr); - Ceil := REAL_TO_DINT(input); - -IF DINT_TO_REAL(Ceil) < input THEN - Ceil := Ceil + 1; + Ceil := REAL_TO_DINT(input); + +IF DINT_TO_REAL(Ceil) < input THEN + Ceil := Ceil + 1; END_IF; @@ -1088,17 +1088,17 @@ END_IF; - sign := power.15; -power := ABS(power); -IF power.0 THEN ExpN := input; ELSE ExpN := 1.0; END_IF; -power := SHR(power, 1); - -WHILE power > 0 DO - input := input * input; - IF power.0 THEN ExpN := ExpN * input; END_IF; - power := SHR(power, 1); -END_WHILE; - + sign := power.15; +power := ABS(power); +IF power.0 THEN ExpN := input; ELSE ExpN := 1.0; END_IF; +power := SHR(power, 1); + +WHILE power > 0 DO + input := input * input; + IF power.0 THEN ExpN := ExpN * input; END_IF; + power := SHR(power, 1); +END_WHILE; + IF sign THEN ExpN := 1.0 / ExpN; END_IF; @@ -1130,9 +1130,9 @@ IF sign THEN ExpN := 1.0 / ExpN; END_IF; - FLOOR := REAL_TO_DINT(input); -IF DINT_TO_REAL(FLOOR) > input THEN - FLOOR := FLOOR - 1; + FLOOR := REAL_TO_DINT(input); +IF DINT_TO_REAL(FLOOR) > input THEN + FLOOR := FLOOR - 1; END_IF; @@ -1164,10 +1164,10 @@ END_IF; - IF ABS(input) < 2.0E9 THEN - FRACT := input - DINT_TO_REAL(DTrunc(input)); -ELSE - FRACT := 0.0; + IF ABS(input) < 2.0E9 THEN + FRACT := input - DINT_TO_REAL(DTrunc(input)); +ELSE + FRACT := 0.0; END_IF; @@ -1207,11 +1207,11 @@ END_IF; - IF divisor = 0.0 THEN - MODR := 0.0; -ELSE - MODR := input - DINT_TO_REAL(FLOOR(input / divisor)) * divisor; -END_IF; + IF divisor = 0.0 THEN + MODR := 0.0; +ELSE + MODR := input - DINT_TO_REAL(FLOOR(input / divisor)) * divisor; +END_IF; @@ -1251,7 +1251,7 @@ END_IF; - Round := DWORD_TO_REAL(REAL_TO_DWORD(input * Exp10(precision))) / Exp10(precision); + Round := DWORD_TO_REAL(REAL_TO_DWORD(input * Exp10(precision))) / Exp10(precision); @@ -1602,10 +1602,10 @@ END_IF; - IF inputLow = inputHigh THEN - ScaleReal := outputLow; -ELSE - ScaleReal := (outputHigh - outputLow) / (inputHigh - inputLow) * (LIMIT(inputLow, input, inputHigh) - inputLow) + outputLow; + IF inputLow = inputHigh THEN + ScaleReal := outputLow; +ELSE + ScaleReal := (outputHigh - outputLow) / (inputHigh - inputLow) * (LIMIT(inputLow, input, inputHigh) - inputLow) + outputLow; END_IF; @@ -1674,14 +1674,14 @@ END_IF; - charPointer := ADR(inputString); -length := LEN(inputString); -CountChar := 0; -FOR position := 1 TO length DO - IF charPointer^ = charToCount THEN - CountChar := CountChar + 1; - END_IF; - charPointer := charPointer + 1; + charPointer := ADR(inputString); +length := LEN(inputString); +CountChar := 0; +FOR position := 1 TO length DO + IF charPointer^ = charToCount THEN + CountChar := CountChar + 1; + END_IF; + charPointer := charPointer + 1; END_FOR; @@ -1738,14 +1738,14 @@ END_FOR; - tempString := inputString; -REPEAT - position := FIND(tempString, substringToRemove); - IF position <> 0 THEN - tempString := DELETE(tempString, LEN(substringToRemove), position); - END_IF; -UNTIL (position = 0) -END_REPEAT; + tempString := inputString; +REPEAT + position := FIND(tempString, substringToRemove); + IF position <> 0 THEN + tempString := DELETE(tempString, LEN(substringToRemove), position); + END_IF; +UNTIL (position = 0) +END_REPEAT; RemoveSubString := tempString; @@ -1784,12 +1784,12 @@ RemoveSubString := tempString; - IF input > 96 AND input < 123 THEN - ToUpper := input AND 16#DF; -ELSIF input > 223 AND input <> 247 AND input <> 255 AND useExtendedASCII THEN - ToUpper := input AND 16#DF; -ELSE - ToUpper := input; + IF input > 96 AND input < 123 THEN + ToUpper := input AND 16#DF; +ELSIF input > 223 AND input <> 247 AND input <> 255 AND useExtendedASCII THEN + ToUpper := input AND 16#DF; +ELSE + ToUpper := input; END_IF; @@ -1853,12 +1853,12 @@ END_IF; - (* Получаем дату строкой 'D#2000-01-01' *) -sTemp := DATE_TO_STRING(input); -year := STRING_TO_UINT(MID(sTemp, 3, 4)); -month := STRING_TO_UINT(MID(sTemp, 8, 2)); -day := STRING_TO_UINT(MID(sTemp, 11, 2)); - + (* Получаем дату строкой 'D#2000-01-01' *) +sTemp := DATE_TO_STRING(input); +year := STRING_TO_UINT(MID(sTemp, 3, 4)); +month := STRING_TO_UINT(MID(sTemp, 8, 2)); +day := STRING_TO_UINT(MID(sTemp, 11, 2)); + DateToElements := true; @@ -1896,8 +1896,8 @@ DateToElements := true; - NumOfDay := DATE_TO_DWORD(input) / 86400; -NumOfDay := NumOfDay + 3; + NumOfDay := DATE_TO_DWORD(input) / 86400; +NumOfDay := NumOfDay + 3; DayOfWeek := DWORD_TO_UINT(NumOfDay MOD 7); @@ -1945,8 +1945,8 @@ DayOfWeek := DWORD_TO_UINT(NumOfDay MOD 7); - DateToElements(input := input, year => year, month => month, day => day); - + DateToElements(input := input, year => year, month => month, day => day); + DayOfYear := DaysTillMonth(year, month) + day; @@ -1977,10 +1977,10 @@ DayOfYear := DaysTillMonth(year, month) + day; - IF IsLeapYear(year) THEN - DaysInYear := 366; -ELSE - DaysInYear := 365; + IF IsLeapYear(year) THEN + DaysInYear := 366; +ELSE + DaysInYear := 365; END_IF; @@ -2101,8 +2101,8 @@ END_IF; - (* Получаем количество лет прошло с 1970го года *) -year := year - 1970; + (* Получаем количество лет прошло с 1970го года *) +year := year - 1970; DaysTillYear := year * 365 + ((year + 1) / 4) - ((year + 69) / 100) + ((year + 369) / 400); @@ -2297,8 +2297,8 @@ DaysTillYear := year * 365 + ((year + 1) / 4) - ((year + 69) / 100) + ((year + 3 - T := UINT_TO_REAL(DayOfYear(utc)); -OFFSET := -0.1752 * SIN(0.033430 * T + 0.5474) - 0.1340 * SIN(0.018234 * T - 0.1939); + T := UINT_TO_REAL(DayOfYear(utc)); +OFFSET := -0.1752 * SIN(0.033430 * T + 0.5474) - 0.1340 * SIN(0.018234 * T - 0.1939); SunMidday := HourToTod(REAL_TO_INT(12.0 - OFFSET - lon * 0.0666666666666)); @@ -2358,11 +2358,11 @@ SunMidday := HourToTod(REAL_TO_INT(12.0 - OFFSET - lon * 0.0666666666666)); - (* Теперь время имеет строку типа 'TOD#12:12:59' *) -sTemp := TOD_TO_STRING(TIME_TO_TOD(input)); -h := STRING_TO_UINT(MID(sTemp, 5, 2)); -m := STRING_TO_UINT(MID(sTemp, 8, 2)); -sec := STRING_TO_UINT(MID(sTemp, 11, 2)); + (* Теперь время имеет строку типа 'TOD#12:12:59' *) +sTemp := TOD_TO_STRING(TIME_TO_TOD(input)); +h := STRING_TO_UINT(MID(sTemp, 5, 2)); +m := STRING_TO_UINT(MID(sTemp, 8, 2)); +sec := STRING_TO_UINT(MID(sTemp, 11, 2)); TimeToElements := TRUE; @@ -2409,10 +2409,10 @@ TimeToElements := TRUE; - TodBetween := ( - FromTime > ToTime AND (CurrTime > FromTime OR CurrTime < ToTime) - ) OR (FromTime < ToTime AND (CurrTime < ToTime AND CurrTime > FromTime) -); + TodBetween := ( + FromTime > ToTime AND (CurrTime > FromTime OR CurrTime < ToTime) + ) OR (FromTime < ToTime AND (CurrTime < ToTime AND CurrTime > FromTime) +); @@ -2451,10 +2451,10 @@ TimeToElements := TRUE; - IF ToTime < FromTime THEN - TodDiff := T#24H - TOD_TO_TIME(FromTime) + TOD_TO_TIME(ToTime); -ELSE - TodDiff := ToTime - FromTime; + IF ToTime < FromTime THEN + TodDiff := T#24H - TOD_TO_TIME(FromTime) + TOD_TO_TIME(ToTime); +ELSE + TodDiff := ToTime - FromTime; END_IF @@ -2485,9 +2485,9 @@ END_IF - WeekOfYear := ((DayOfYear(currentDate) + 6) / 7); -IF DayOfWeek(currentDate) < DayOfWeek(YearStarts(currentDate)) THEN - WeekOfYear := WeekOfYear + 1; + WeekOfYear := ((DayOfYear(currentDate) + 6) / 7); +IF DayOfWeek(currentDate) < DayOfWeek(YearStarts(currentDate)) THEN + WeekOfYear := WeekOfYear + 1; END_IF; @@ -2528,7 +2528,7 @@ END_IF; - str := DATE_TO_STRING(currentDate); (* получаем строку `D#2000-12-30` *) + str := DATE_TO_STRING(currentDate); (* получаем строку `D#2000-12-30` *) YearStarts := STRING_TO_DATE(CONCAT(CONCAT('D#', MID(str, 3, 4)), '-01-01')); @@ -2614,19 +2614,19 @@ YearStarts := STRING_TO_DATE(CONCAT(CONCAT('D#', MID(str, 3, 4)), '-01-01')); - sTemp := CONCAT('DT#', UINT_TO_STRING(y)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(mn)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(d)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(h)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(m)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(sec)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(ms)); + sTemp := CONCAT('DT#', UINT_TO_STRING(y)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(mn)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(d)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(h)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(m)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(sec)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(ms)); YmdhmsTodt := STRING_TO_DT(sTemp); @@ -2680,11 +2680,11 @@ YmdhmsTodt := STRING_TO_DT(sTemp); - sTemp := CONCAT('D#', UINT_TO_STRING(y)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(m)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(d)); + sTemp := CONCAT('D#', UINT_TO_STRING(y)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(m)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(d)); YmdToDate := STRING_TO_DATE(sTemp); @@ -2716,11 +2716,11 @@ YmdToDate := STRING_TO_DATE(sTemp); - WHILE input > 0 DO - IF input.0 THEN - BitCount := BitCount + 1; - END_IF - input := SHR(input, 1); + WHILE input > 0 DO + IF input.0 THEN + BitCount := BitCount + 1; + END_IF + input := SHR(input, 1); END_WHILE; @@ -2778,10 +2778,10 @@ END_WHILE; - IF value THEN - BitLoadB := input OR SHL(dat, position); -ELSE - BitLoadB := input AND (NOT SHL(dat, position)); + IF value THEN + BitLoadB := input OR SHL(dat, position); +ELSE + BitLoadB := input AND (NOT SHL(dat, position)); END_IF; @@ -2913,13 +2913,13 @@ END_IF; - tmp := ABS(x); -IF tmp > 0.0 THEN - tmp := Exp10(DINT_TO_REAL(FLOOR(LOG(tmp))-n+1)); -ELSE - tmp := Exp10(tmp); -END_IF; - + tmp := ABS(x); +IF tmp > 0.0 THEN + tmp := Exp10(DINT_TO_REAL(FLOOR(LOG(tmp))-n+1)); +ELSE + tmp := Exp10(tmp); +END_IF; + CompareReals := ABS(x - y) < tmp; @@ -2951,16 +2951,16 @@ CompareReals := ABS(x - y) < tmp; - DTrunc := REAL_TO_DINT(input); - -IF input > 0.0 THEN - IF DINT_TO_REAL(DTrunc) > input THEN - DTrunc := DTrunc - 1; - END_IF; -ELSE - IF DINT_TO_REAL(DTrunc) < input THEN - DTrunc := DTrunc + 1; - END_IF; + DTrunc := REAL_TO_DINT(input); + +IF input > 0.0 THEN + IF DINT_TO_REAL(DTrunc) > input THEN + DTrunc := DTrunc - 1; + END_IF; +ELSE + IF DINT_TO_REAL(DTrunc) < input THEN + DTrunc := DTrunc + 1; + END_IF; END_IF; @@ -3050,20 +3050,20 @@ END_IF; - tn := TIME_TO_DWORD(TIME()); -tc := BitCount(tn); -tn.31 := tn.2; -tn.30 := tn.5; -tn.29 := tn.4; -tn.28 := tn.1; -tn.27 := tn.0; -tn.26 := tn.7; -tn.25 := tn.6; -tn.24 := tn.3; -tn := ROL(tn, BitCount(tn)) OR 16#80000001; -tn := tn MOD 71474513 + INT_TO_DWORD(tc + 77); -Random := FRACT(DWORD_TO_REAL(tn) / 10000000.0 * -(E - LIMIT(0.0, last, 1.0)) + tn := TIME_TO_DWORD(TIME()); +tc := BitCount(tn); +tn.31 := tn.2; +tn.30 := tn.5; +tn.29 := tn.4; +tn.28 := tn.1; +tn.27 := tn.0; +tn.26 := tn.7; +tn.25 := tn.6; +tn.24 := tn.3; +tn := ROL(tn, BitCount(tn)) OR 16#80000001; +tn := tn MOD 71474513 + INT_TO_DWORD(tc + 77); +Random := FRACT(DWORD_TO_REAL(tn) / 10000000.0 * +(E - LIMIT(0.0, last, 1.0)) ); @@ -3139,6 +3139,16 @@ Random := FRACT(DWORD_TO_REAL(tn) / 10000000.0 * + + + + + + 8c1463b5-02f2-427d-bd06-9e39d42fcbff + + + + @@ -3225,7 +3235,9 @@ Random := FRACT(DWORD_TO_REAL(tn) / 10000000.0 * + + - \ No newline at end of file + From 5e5a3a6bf8a10f08552188863b1a1763b476fb75 Mon Sep 17 00:00:00 2001 From: "sergey.glukhov" Date: Thu, 12 Jun 2025 14:10:28 +0300 Subject: [PATCH 3/6] test --- AnjLabCodeBox.xml | 530 +++++++++++++++++++++++----------------------- 1 file changed, 265 insertions(+), 265 deletions(-) diff --git a/AnjLabCodeBox.xml b/AnjLabCodeBox.xml index 062605b..e0d3192 100644 --- a/AnjLabCodeBox.xml +++ b/AnjLabCodeBox.xml @@ -1,4 +1,4 @@ - + @@ -86,10 +86,10 @@ - IF input AND NOT memory THEN - startTime := TIME(); -END_IF; -memory := input; + IF input AND NOT memory THEN + startTime := TIME(); +END_IF; +memory := input; output := input AND ((TIME() - startTime) > T#100ms); @@ -145,13 +145,13 @@ output := input AND ((TIME() - startTime) > T#100ms); - IF (NOT input AND memory) OR (input AND NOT memory) THEN - startTime := TIME(); -END_IF; -memory := input; -output := input; -IF ((TIME() - startTime) < T#100ms) THEN - output := NOT input; + IF (NOT input AND memory) OR (input AND NOT memory) THEN + startTime := TIME(); +END_IF; +memory := input; +output := input; +IF ((TIME() - startTime) < T#100ms) THEN + output := NOT input; END_IF @@ -207,13 +207,13 @@ END_IF - IF NOT input AND memory THEN - startTime := TIME(); -END_IF; -memory := input; -output := input; -IF NOT input AND ((TIME() - startTime) < T#100ms) THEN - output := TRUE; + IF NOT input AND memory THEN + startTime := TIME(); +END_IF; +memory := input; +output := input; +IF NOT input AND ((TIME() - startTime) < T#100ms) THEN + output := TRUE; END_IF @@ -279,13 +279,13 @@ END_IF - fbDio1(input := input, output => filteredInput); -raise := fall := FALSE; -IF filteredInput AND NOT memory THEN - raise := TRUE; -ELSIF NOT filteredInput AND memory THEN - fall := TRUE; -END_IF + fbDio1(input := input, output => filteredInput); +raise := fall := FALSE; +IF filteredInput AND NOT memory THEN + raise := TRUE; +ELSIF NOT filteredInput AND memory THEN + fall := TRUE; +END_IF memory := filteredInput; @@ -341,13 +341,13 @@ memory := filteredInput; - output := FALSE; -IF input AND NOT memory THEN - IF (TIME() - startTime) > T#100MS AND (TIME() - startTime) < T#800MS THEN - output := TRUE; - END_IF; - startTime := TIME(); -END_IF; + output := FALSE; +IF input AND NOT memory THEN + IF (TIME() - startTime) > T#100MS AND (TIME() - startTime) < T#800MS THEN + output := TRUE; + END_IF; + startTime := TIME(); +END_IF; memory := input; @@ -428,28 +428,28 @@ memory := input; - (* ограничим bufferSize в размер буфера *) -bufferSize := MIN(MAX(bufferSize, 1000), 32); -(* Инициализация *) -IF NOT isInitialized OR reset THEN - isInitialized := TRUE; - FOR counter := 1 TO bufferSize DO - buffer[counter] := input; - END_FOR; - sum := input * bufferSize; - output := input; - RETURN; -END_IF; - -IF counter >= bufferSize THEN - counter := 1; -ELSE - counter := counter + 1; -END_IF - -sum := sum + input - buffer[counter]; -{warning disable C0195} -output := DWORD_TO_WORD(sum / bufferSize); + (* ограничим bufferSize в размер буфера *) +bufferSize := MIN(MAX(bufferSize, 1000), 32); +(* Инициализация *) +IF NOT isInitialized OR reset THEN + isInitialized := TRUE; + FOR counter := 1 TO bufferSize DO + buffer[counter] := input; + END_FOR; + sum := input * bufferSize; + output := input; + RETURN; +END_IF; + +IF counter >= bufferSize THEN + counter := 1; +ELSE + counter := counter + 1; +END_IF + +sum := sum + input - buffer[counter]; +{warning disable C0195} +output := DWORD_TO_WORD(sum / bufferSize); buffer[counter] := input; @@ -517,22 +517,22 @@ buffer[counter] := input; - (* Получаем текущее время *) -currentTime := TIME_TO_DWORD(TIME()); -(* Инициализация *) -IF NOT isInitialized OR timeInterval = T#0s THEN - isInitialized := TRUE; - lastTime := currentTime; - output := input; -ELSIF output = input THEN - lastTime := currentTime; -ELSE - tempTime := WORD_TO_DWORD(input - output) * (currentTime - lastTime) / - TIME_TO_DWORD(timeInterval); - IF tempTime <> 0 THEN - output := DINT_TO_WORD(WORD_TO_DINT(output) + DWORD_TO_DINT(tempTime)); - lastTime := currentTime; - END_IF; + (* Получаем текущее время *) +currentTime := TIME_TO_DWORD(TIME()); +(* Инициализация *) +IF NOT isInitialized OR timeInterval = T#0s THEN + isInitialized := TRUE; + lastTime := currentTime; + output := input; +ELSIF output = input THEN + lastTime := currentTime; +ELSE + tempTime := WORD_TO_DWORD(input - output) * (currentTime - lastTime) / + TIME_TO_DWORD(timeInterval); + IF tempTime <> 0 THEN + output := DINT_TO_WORD(WORD_TO_DINT(output) + DWORD_TO_DINT(tempTime)); + lastTime := currentTime; + END_IF; END_IF; @@ -596,10 +596,10 @@ END_IF; - IF input AND NOT memory THEN - startTime := TIME(); -END_IF; -memory := input; + IF input AND NOT memory THEN + startTime := TIME(); +END_IF; +memory := input; output := input AND ((TIME() - startTime) > pressTime); @@ -666,12 +666,12 @@ output := input AND ((TIME() - startTime) > pressTime); - currentTime := TIME(); -IF enable AND NOT memory THEN - lastTime := currentTime - pulseTime; -END_IF; -memory := enable; -output := currentTime - lastTime >= pulseTime; + currentTime := TIME(); +IF enable AND NOT memory THEN + lastTime := currentTime - pulseTime; +END_IF; +memory := enable; +output := currentTime - lastTime >= pulseTime; IF output THEN lastTime := currentTime; END_IF; @@ -735,16 +735,16 @@ IF output THEN lastTime := currentTime; END_IF; - (* Если частота ШИМ 0, то прерываем исполнение ФБ *) -IF frequency <= 0.0 THEN - output := FALSE; - RETURN; -END_IF; -(* Вычисляем сколько миллисекунд требуется на один цикл ШИМ *) -tempValue := 1000.0 / frequency; -(* Запускаем генератор сигналов *) -clock(pulseTime := REAL_TO_TIME(tempValue)); -(* Создаем выдержанный пульс на нужное время *) + (* Если частота ШИМ 0, то прерываем исполнение ФБ *) +IF frequency <= 0.0 THEN + output := FALSE; + RETURN; +END_IF; +(* Вычисляем сколько миллисекунд требуется на один цикл ШИМ *) +tempValue := 1000.0 / frequency; +(* Запускаем генератор сигналов *) +clock(pulseTime := REAL_TO_TIME(tempValue)); +(* Создаем выдержанный пульс на нужное время *) pulseTimer(in := clock.output, pt := REAL_TO_TIME(tempValue * dutyCycle), Q => output); @@ -803,15 +803,15 @@ pulseTimer(in := clock.output, pt := REAL_TO_TIME(tempValue * dutyCycle), Q => - (* Если частота ШИМ 0 или время одного цикла меньше, -чем время для фазы Ton, то прерываем исполнение ФБ *) -IF frequency <= 0.0 OR (REAL_TO_TIME(1000.0 / frequency) < pulseWidth) THEN - output := FALSE; - RETURN; -END_IF; -(* Запускаем генератор сигналов *) -clock(pulseTime := REAL_TO_TIME(1000.0 / frequency)); -(* Создаем выдержанный пульс на нужное время *) + (* Если частота ШИМ 0 или время одного цикла меньше, +чем время для фазы Ton, то прерываем исполнение ФБ *) +IF frequency <= 0.0 OR (REAL_TO_TIME(1000.0 / frequency) < pulseWidth) THEN + output := FALSE; + RETURN; +END_IF; +(* Запускаем генератор сигналов *) +clock(pulseTime := REAL_TO_TIME(1000.0 / frequency)); +(* Создаем выдержанный пульс на нужное время *) pulseTimer(in := clock.output, PT := pulseWidth, Q => output); @@ -923,16 +923,16 @@ pulseTimer(in := clock.output, PT := pulseWidth, Q => output); - MIDDAY := SunMidday(longitude, utc); -b := latitude * 0.0174532925199433; -dk := 0.40954 * SIN(0.0172 * (UINT_TO_REAL(DayOfYear(utc)) - 79.35)); -SUN_DECLINATION := DegreesToRadians(DK); -IF SUN_DECLINATION > 180.0 THEN - SUN_DECLINATION := SUN_DECLINATION - 360.0; -END_IF; -SUN_DECLINATION := 90.0 - LATITUDE + SUN_DECLINATION; -delta := HourToTime(REAL_TO_INT(ACOS((SIN(RadiansToDegrees(H)) - SIN(B) * SIN(DK)) / (COS(B) * COS(DK))) * 3.819718632)); -SUN_RISE := MIDDAY - delta; + MIDDAY := SunMidday(longitude, utc); +b := latitude * 0.0174532925199433; +dk := 0.40954 * SIN(0.0172 * (UINT_TO_REAL(DayOfYear(utc)) - 79.35)); +SUN_DECLINATION := DegreesToRadians(DK); +IF SUN_DECLINATION > 180.0 THEN + SUN_DECLINATION := SUN_DECLINATION - 360.0; +END_IF; +SUN_DECLINATION := 90.0 - LATITUDE + SUN_DECLINATION; +delta := HourToTime(REAL_TO_INT(ACOS((SIN(RadiansToDegrees(H)) - SIN(B) * SIN(DK)) / (COS(B) * COS(DK))) * 3.819718632)); +SUN_RISE := MIDDAY - delta; SUN_SET := MIDDAY + delta; @@ -970,13 +970,13 @@ SUN_SET := MIDDAY + delta; - position := FIND(ipStr, '.'); -WHILE position > 0 DO - IpDecode := SHL(IpDecode, 8) OR - STRING_TO_DWORD(LEFT(ipStr, position - 1)); - ipStr := DELETE(ipStr, position, 1); - position := FIND(ipStr, '.'); -END_WHILE; + position := FIND(ipStr, '.'); +WHILE position > 0 DO + IpDecode := SHL(IpDecode, 8) OR + STRING_TO_DWORD(LEFT(ipStr, position - 1)); + ipStr := DELETE(ipStr, position, 1); + position := FIND(ipStr, '.'); +END_WHILE; IpDecode := SHL(IpDecode, 8) OR STRING_TO_DWORD(ipStr); @@ -1008,10 +1008,10 @@ IpDecode := SHL(IpDecode, 8) OR STRING_TO_DWORD(ipStr); - Ceil := REAL_TO_DINT(input); - -IF DINT_TO_REAL(Ceil) < input THEN - Ceil := Ceil + 1; + Ceil := REAL_TO_DINT(input); + +IF DINT_TO_REAL(Ceil) < input THEN + Ceil := Ceil + 1; END_IF; @@ -1088,17 +1088,17 @@ END_IF; - sign := power.15; -power := ABS(power); -IF power.0 THEN ExpN := input; ELSE ExpN := 1.0; END_IF; -power := SHR(power, 1); - -WHILE power > 0 DO - input := input * input; - IF power.0 THEN ExpN := ExpN * input; END_IF; - power := SHR(power, 1); -END_WHILE; - + sign := power.15; +power := ABS(power); +IF power.0 THEN ExpN := input; ELSE ExpN := 1.0; END_IF; +power := SHR(power, 1); + +WHILE power > 0 DO + input := input * input; + IF power.0 THEN ExpN := ExpN * input; END_IF; + power := SHR(power, 1); +END_WHILE; + IF sign THEN ExpN := 1.0 / ExpN; END_IF; @@ -1130,9 +1130,9 @@ IF sign THEN ExpN := 1.0 / ExpN; END_IF; - FLOOR := REAL_TO_DINT(input); -IF DINT_TO_REAL(FLOOR) > input THEN - FLOOR := FLOOR - 1; + FLOOR := REAL_TO_DINT(input); +IF DINT_TO_REAL(FLOOR) > input THEN + FLOOR := FLOOR - 1; END_IF; @@ -1164,10 +1164,10 @@ END_IF; - IF ABS(input) < 2.0E9 THEN - FRACT := input - DINT_TO_REAL(DTrunc(input)); -ELSE - FRACT := 0.0; + IF ABS(input) < 2.0E9 THEN + FRACT := input - DINT_TO_REAL(DTrunc(input)); +ELSE + FRACT := 0.0; END_IF; @@ -1207,11 +1207,11 @@ END_IF; - IF divisor = 0.0 THEN - MODR := 0.0; -ELSE - MODR := input - DINT_TO_REAL(FLOOR(input / divisor)) * divisor; -END_IF; + IF divisor = 0.0 THEN + MODR := 0.0; +ELSE + MODR := input - DINT_TO_REAL(FLOOR(input / divisor)) * divisor; +END_IF; @@ -1251,7 +1251,7 @@ END_IF; - Round := DWORD_TO_REAL(REAL_TO_DWORD(input * Exp10(precision))) / Exp10(precision); + Round := DWORD_TO_REAL(REAL_TO_DWORD(input * Exp10(precision))) / Exp10(precision); @@ -1602,10 +1602,10 @@ END_IF; - IF inputLow = inputHigh THEN - ScaleReal := outputLow; -ELSE - ScaleReal := (outputHigh - outputLow) / (inputHigh - inputLow) * (LIMIT(inputLow, input, inputHigh) - inputLow) + outputLow; + IF inputLow = inputHigh THEN + ScaleReal := outputLow; +ELSE + ScaleReal := (outputHigh - outputLow) / (inputHigh - inputLow) * (LIMIT(inputLow, input, inputHigh) - inputLow) + outputLow; END_IF; @@ -1674,14 +1674,14 @@ END_IF; - charPointer := ADR(inputString); -length := LEN(inputString); -CountChar := 0; -FOR position := 1 TO length DO - IF charPointer^ = charToCount THEN - CountChar := CountChar + 1; - END_IF; - charPointer := charPointer + 1; + charPointer := ADR(inputString); +length := LEN(inputString); +CountChar := 0; +FOR position := 1 TO length DO + IF charPointer^ = charToCount THEN + CountChar := CountChar + 1; + END_IF; + charPointer := charPointer + 1; END_FOR; @@ -1738,14 +1738,14 @@ END_FOR; - tempString := inputString; -REPEAT - position := FIND(tempString, substringToRemove); - IF position <> 0 THEN - tempString := DELETE(tempString, LEN(substringToRemove), position); - END_IF; -UNTIL (position = 0) -END_REPEAT; + tempString := inputString; +REPEAT + position := FIND(tempString, substringToRemove); + IF position <> 0 THEN + tempString := DELETE(tempString, LEN(substringToRemove), position); + END_IF; +UNTIL (position = 0) +END_REPEAT; RemoveSubString := tempString; @@ -1784,12 +1784,12 @@ RemoveSubString := tempString; - IF input > 96 AND input < 123 THEN - ToUpper := input AND 16#DF; -ELSIF input > 223 AND input <> 247 AND input <> 255 AND useExtendedASCII THEN - ToUpper := input AND 16#DF; -ELSE - ToUpper := input; + IF input > 96 AND input < 123 THEN + ToUpper := input AND 16#DF; +ELSIF input > 223 AND input <> 247 AND input <> 255 AND useExtendedASCII THEN + ToUpper := input AND 16#DF; +ELSE + ToUpper := input; END_IF; @@ -1853,12 +1853,12 @@ END_IF; - (* Получаем дату строкой 'D#2000-01-01' *) -sTemp := DATE_TO_STRING(input); -year := STRING_TO_UINT(MID(sTemp, 3, 4)); -month := STRING_TO_UINT(MID(sTemp, 8, 2)); -day := STRING_TO_UINT(MID(sTemp, 11, 2)); - + (* Получаем дату строкой 'D#2000-01-01' *) +sTemp := DATE_TO_STRING(input); +year := STRING_TO_UINT(MID(sTemp, 3, 4)); +month := STRING_TO_UINT(MID(sTemp, 8, 2)); +day := STRING_TO_UINT(MID(sTemp, 11, 2)); + DateToElements := true; @@ -1896,8 +1896,8 @@ DateToElements := true; - NumOfDay := DATE_TO_DWORD(input) / 86400; -NumOfDay := NumOfDay + 3; + NumOfDay := DATE_TO_DWORD(input) / 86400; +NumOfDay := NumOfDay + 3; DayOfWeek := DWORD_TO_UINT(NumOfDay MOD 7); @@ -1945,8 +1945,8 @@ DayOfWeek := DWORD_TO_UINT(NumOfDay MOD 7); - DateToElements(input := input, year => year, month => month, day => day); - + DateToElements(input := input, year => year, month => month, day => day); + DayOfYear := DaysTillMonth(year, month) + day; @@ -1977,10 +1977,10 @@ DayOfYear := DaysTillMonth(year, month) + day; - IF IsLeapYear(year) THEN - DaysInYear := 366; -ELSE - DaysInYear := 365; + IF IsLeapYear(year) THEN + DaysInYear := 366; +ELSE + DaysInYear := 365; END_IF; @@ -2101,8 +2101,8 @@ END_IF; - (* Получаем количество лет прошло с 1970го года *) -year := year - 1970; + (* Получаем количество лет прошло с 1970го года *) +year := year - 1970; DaysTillYear := year * 365 + ((year + 1) / 4) - ((year + 69) / 100) + ((year + 369) / 400); @@ -2297,8 +2297,8 @@ DaysTillYear := year * 365 + ((year + 1) / 4) - ((year + 69) / 100) + ((year + 3 - T := UINT_TO_REAL(DayOfYear(utc)); -OFFSET := -0.1752 * SIN(0.033430 * T + 0.5474) - 0.1340 * SIN(0.018234 * T - 0.1939); + T := UINT_TO_REAL(DayOfYear(utc)); +OFFSET := -0.1752 * SIN(0.033430 * T + 0.5474) - 0.1340 * SIN(0.018234 * T - 0.1939); SunMidday := HourToTod(REAL_TO_INT(12.0 - OFFSET - lon * 0.0666666666666)); @@ -2358,11 +2358,11 @@ SunMidday := HourToTod(REAL_TO_INT(12.0 - OFFSET - lon * 0.0666666666666)); - (* Теперь время имеет строку типа 'TOD#12:12:59' *) -sTemp := TOD_TO_STRING(TIME_TO_TOD(input)); -h := STRING_TO_UINT(MID(sTemp, 5, 2)); -m := STRING_TO_UINT(MID(sTemp, 8, 2)); -sec := STRING_TO_UINT(MID(sTemp, 11, 2)); + (* Теперь время имеет строку типа 'TOD#12:12:59' *) +sTemp := TOD_TO_STRING(TIME_TO_TOD(input)); +h := STRING_TO_UINT(MID(sTemp, 5, 2)); +m := STRING_TO_UINT(MID(sTemp, 8, 2)); +sec := STRING_TO_UINT(MID(sTemp, 11, 2)); TimeToElements := TRUE; @@ -2409,10 +2409,10 @@ TimeToElements := TRUE; - TodBetween := ( - FromTime > ToTime AND (CurrTime > FromTime OR CurrTime < ToTime) - ) OR (FromTime < ToTime AND (CurrTime < ToTime AND CurrTime > FromTime) -); + TodBetween := ( + FromTime > ToTime AND (CurrTime > FromTime OR CurrTime < ToTime) + ) OR (FromTime < ToTime AND (CurrTime < ToTime AND CurrTime > FromTime) +); @@ -2451,10 +2451,10 @@ TimeToElements := TRUE; - IF ToTime < FromTime THEN - TodDiff := T#24H - TOD_TO_TIME(FromTime) + TOD_TO_TIME(ToTime); -ELSE - TodDiff := ToTime - FromTime; + IF ToTime < FromTime THEN + TodDiff := T#24H - TOD_TO_TIME(FromTime) + TOD_TO_TIME(ToTime); +ELSE + TodDiff := ToTime - FromTime; END_IF @@ -2485,9 +2485,9 @@ END_IF - WeekOfYear := ((DayOfYear(currentDate) + 6) / 7); -IF DayOfWeek(currentDate) < DayOfWeek(YearStarts(currentDate)) THEN - WeekOfYear := WeekOfYear + 1; + WeekOfYear := ((DayOfYear(currentDate) + 6) / 7); +IF DayOfWeek(currentDate) < DayOfWeek(YearStarts(currentDate)) THEN + WeekOfYear := WeekOfYear + 1; END_IF; @@ -2528,7 +2528,7 @@ END_IF; - str := DATE_TO_STRING(currentDate); (* получаем строку `D#2000-12-30` *) + str := DATE_TO_STRING(currentDate); (* получаем строку `D#2000-12-30` *) YearStarts := STRING_TO_DATE(CONCAT(CONCAT('D#', MID(str, 3, 4)), '-01-01')); @@ -2614,19 +2614,19 @@ YearStarts := STRING_TO_DATE(CONCAT(CONCAT('D#', MID(str, 3, 4)), '-01-01')); - sTemp := CONCAT('DT#', UINT_TO_STRING(y)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(mn)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(d)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(h)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(m)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(sec)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(ms)); + sTemp := CONCAT('DT#', UINT_TO_STRING(y)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(mn)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(d)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(h)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(m)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(sec)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(ms)); YmdhmsTodt := STRING_TO_DT(sTemp); @@ -2680,11 +2680,11 @@ YmdhmsTodt := STRING_TO_DT(sTemp); - sTemp := CONCAT('D#', UINT_TO_STRING(y)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(m)); -sTemp := CONCAT(sTemp, '-'); -sTemp := CONCAT(sTemp, UINT_TO_STRING(d)); + sTemp := CONCAT('D#', UINT_TO_STRING(y)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(m)); +sTemp := CONCAT(sTemp, '-'); +sTemp := CONCAT(sTemp, UINT_TO_STRING(d)); YmdToDate := STRING_TO_DATE(sTemp); @@ -2716,11 +2716,11 @@ YmdToDate := STRING_TO_DATE(sTemp); - WHILE input > 0 DO - IF input.0 THEN - BitCount := BitCount + 1; - END_IF - input := SHR(input, 1); + WHILE input > 0 DO + IF input.0 THEN + BitCount := BitCount + 1; + END_IF + input := SHR(input, 1); END_WHILE; @@ -2778,10 +2778,10 @@ END_WHILE; - IF value THEN - BitLoadB := input OR SHL(dat, position); -ELSE - BitLoadB := input AND (NOT SHL(dat, position)); + IF value THEN + BitLoadB := input OR SHL(dat, position); +ELSE + BitLoadB := input AND (NOT SHL(dat, position)); END_IF; @@ -2913,13 +2913,13 @@ END_IF; - tmp := ABS(x); -IF tmp > 0.0 THEN - tmp := Exp10(DINT_TO_REAL(FLOOR(LOG(tmp))-n+1)); -ELSE - tmp := Exp10(tmp); -END_IF; - + tmp := ABS(x); +IF tmp > 0.0 THEN + tmp := Exp10(DINT_TO_REAL(FLOOR(LOG(tmp))-n+1)); +ELSE + tmp := Exp10(tmp); +END_IF; + CompareReals := ABS(x - y) < tmp; @@ -2951,16 +2951,16 @@ CompareReals := ABS(x - y) < tmp; - DTrunc := REAL_TO_DINT(input); - -IF input > 0.0 THEN - IF DINT_TO_REAL(DTrunc) > input THEN - DTrunc := DTrunc - 1; - END_IF; -ELSE - IF DINT_TO_REAL(DTrunc) < input THEN - DTrunc := DTrunc + 1; - END_IF; + DTrunc := REAL_TO_DINT(input); + +IF input > 0.0 THEN + IF DINT_TO_REAL(DTrunc) > input THEN + DTrunc := DTrunc - 1; + END_IF; +ELSE + IF DINT_TO_REAL(DTrunc) < input THEN + DTrunc := DTrunc + 1; + END_IF; END_IF; @@ -3050,20 +3050,20 @@ END_IF; - tn := TIME_TO_DWORD(TIME()); -tc := BitCount(tn); -tn.31 := tn.2; -tn.30 := tn.5; -tn.29 := tn.4; -tn.28 := tn.1; -tn.27 := tn.0; -tn.26 := tn.7; -tn.25 := tn.6; -tn.24 := tn.3; -tn := ROL(tn, BitCount(tn)) OR 16#80000001; -tn := tn MOD 71474513 + INT_TO_DWORD(tc + 77); -Random := FRACT(DWORD_TO_REAL(tn) / 10000000.0 * -(E - LIMIT(0.0, last, 1.0)) + tn := TIME_TO_DWORD(TIME()); +tc := BitCount(tn); +tn.31 := tn.2; +tn.30 := tn.5; +tn.29 := tn.4; +tn.28 := tn.1; +tn.27 := tn.0; +tn.26 := tn.7; +tn.25 := tn.6; +tn.24 := tn.3; +tn := ROL(tn, BitCount(tn)) OR 16#80000001; +tn := tn MOD 71474513 + INT_TO_DWORD(tc + 77); +Random := FRACT(DWORD_TO_REAL(tn) / 10000000.0 * +(E - LIMIT(0.0, last, 1.0)) ); @@ -3240,4 +3240,4 @@ Random := FRACT(DWORD_TO_REAL(tn) / 10000000.0 * - + \ No newline at end of file From cd01f3d222a58ede97c6518c5ded2d4bc0ea815f Mon Sep 17 00:00:00 2001 From: "sergey.glukhov" Date: Thu, 12 Jun 2025 14:13:58 +0300 Subject: [PATCH 4/6] test --- AnjLabCodeBox.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AnjLabCodeBox.xml b/AnjLabCodeBox.xml index e0d3192..fe32fdf 100644 --- a/AnjLabCodeBox.xml +++ b/AnjLabCodeBox.xml @@ -1,7 +1,7 @@  - - + + Helpful ST blocks and functions @@ -1597,7 +1597,7 @@ END_IF; - линейное масштабирование числа с плавающей запятой + Линейное масштабирование числа с плавающей запятой From df164cb3572c19fd9c294be6ee14837b96d9229c Mon Sep 17 00:00:00 2001 From: "sergey.glukhov" Date: Thu, 12 Jun 2025 17:22:02 +0300 Subject: [PATCH 5/6] update --- .gitignore | 1 + AnjLabCodeBox.xml | 773 +++++++++++++++++++++++----------------------- 2 files changed, 387 insertions(+), 387 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae0f2e6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +._AnjlabCodeBox.xml \ No newline at end of file diff --git a/AnjLabCodeBox.xml b/AnjLabCodeBox.xml index fe32fdf..eb119c9 100644 --- a/AnjLabCodeBox.xml +++ b/AnjLabCodeBox.xml @@ -1,8 +1,8 @@  - - - Helpful ST blocks and functions + + + Comprehensive PLC Utility Library for CoDeSys @@ -21,14 +21,15 @@ true Anjlab ACB - Helpful ST blocks and functions + Comprehensive PLC Utility Library for CoDeSys reStructuredText 888cbf53-45a1-47de-9a2a-fbd72e84a196 false qualified-access-only AnjlabCodeBox AnjLabCodeBox - true + false + https://github.com/anjlab/codebox false Anjlab Code Box 3.5.17.1 @@ -48,7 +49,7 @@ - Входной сигнал + Input signal @@ -58,7 +59,7 @@ - Выходной сигнал + Output signal @@ -68,7 +69,7 @@