Вход

Просмотр полной версии : Вопрос на алгоритмы: правильный подсчёт числа импульсов с модуля Mx110 (переполнение)



Cs-Cs
30.01.2023, 23:16
Камрады!
У меня тупой вопрос на математику и алгоритмы, так как я снова туплю и запутался с простыми вещами.
Мне надо считать импульсы на входе модулей Mx110 (подсчёт расхода, цена одного импульса известна, импульсы поступают редко) с учётом переполнения WORD, в котором модуль их хранит и по их изменению что-то делать.
Примечания:
а) Это НЕ реакция на нажатия кнопок по счётчику импульсов - такое я уже писал. Там было не важно количество импульсов, а тут важно.
б) Пишу на CodeSys 3.5, где медленный Modbus, поэтому вариант считать импульсы самому по R_TRIG не подходит.
в) Внутри программы я могу взять даже 32-битный тип данных, с этим проблем нет. Но штатно модуль считает в типе WORD.

Вопрос-тупняк:
Сейчас я написал простой алгоритм:
* Сохраняем предыдущее значение импульсов с модуля
* Вычисляем по модулю разницу с текущим считанным
* Если разница больше нуля - что-то делаем и текущее значение запоминаем как предыдущее.

Косяк будет в том, когда у нас будет такая ерунда:
Предыдущее = 65534, Текущее = 65535 ===> ОК, разница будет равна 1, и всё будет верно
Предыдущее = 65535, Текущее = 0 ===X, Жесть! Разница будет 65535, что будет ошибкой

Как вы решали такую задачу? Как правильно отреагировать на переполнение WORD в модулей Мх110?
Если вас не затруднит - поясните мне для совсем тупых, так как я очень затупил на простой вещи.

Евгений Кислов
31.01.2023, 06:21
Но штатно модуль считает в типе WORD.


Косяк будет в том, когда у нас будет такая ерунда:
Предыдущее = 65535, Текущее = 0 ===X, Жесть! Разница будет 65535, что будет ошибкой

См. скриншот:

65586

Cs-Cs
31.01.2023, 07:17
Евгений Кислов Хммм... то есть разницу стоит считать именно в том типе, который даёт модуль IO?
Я-то её в LINT переводил и потом считал! А вычитать WORD из WORD и использовать штатную фишку переполнения - гениальная идея! Вау!
Сегодня внесу в код!! СПАСИБО!

Cs-Cs
31.01.2023, 09:09
Евгений Кислов Спасибо! Переписал, заработало!
Сделал FBшку универсальной под Mx110 (WORD) и Mx210 (UDINT).

Валенок
31.01.2023, 13:35
Добавлю (для прогулявших 1-4й класс, хотя сейчас это видимо кандидатская)

Предыдущее = 65534, Текущее = 65535 ===> ОК, разница будет равна 1, и всё будет верно
да, удивительно. Текущее минус предыдущее => 1


Предыдущее = 65535, Текущее = 0 ===X, Жесть! Разница будет 65535, что будет ошибкой
С какого 65535 ? Вот тута Вам надо учить арихметику
Текущее(0) минус предыдущее(65535) => -(минус, знак такой)65535

А как выглядит -65535 в 16-битном формате показали выше. Видимо как чудо.


Я-то её в LINT

LINT_ := LINT_ + LINT_TO_WORD(current - prev);
prev := currrent;

melky
31.01.2023, 13:47
предыдущее 65500, текущее 100 ???

Cs-Cs
31.01.2023, 13:54
Валенок Я первый класс не прогуливал, а честно и открыто сказал, что затупил над простой вещью.
С математикой у меня всегда был ровный стабильный кол: я из тех, кто 10-7.5 будет на калькуляторе подбирать сложением в виде "Так... это вроде много... это недобор".

Просьба пояснить, почему разница будет минусом, если я её считаю по модулю ABS(), а тип подсчёта изначально был больше чем WORD - DWORD. Всё это указано в начале поста.
У меня получалось так: 0 - 65535 = 65535 (по модулю). А так как тип был DWORD, то он бы не переполнился бы.

При чём тут дополнительный код для минуса-то в беззнаковом типе? Если его рассматривать как unsigned и 16 бит, то он так и будет переполняться: 0x0000 => 0xFFFE => 0xFFFF => 0x0000

Я ещё больше затупил.

Валенок
31.01.2023, 13:58
предыдущее 65500, текущее 100 ???
Неповерите - тоже самое.
Открываете win-калькулятор.
Вычитаете из 100 65500. Причем видите отрицательное число. Удивительно.
Не стирая это число делаете вид hex
Запоминаете последние 4 знака (магическое действие)
Пишите только эти загадочные последние 4 знака
Делаете вид dec
И о чудо !!!

melky
31.01.2023, 14:09
Валенок а если разница будет больше, чем в 4-х знаках?, скажем в 8-ми знаках ?, блин... тоже торможу :)
Cs-Cs при использовании ABS надо по другому формулу делать... так как ABS(-65400) будет 65400, то потом еще надо 65535 (или 6) минус ваше ABS и получится ветвление в коде, типа если число отрицательное то то-то, если положительное то то-то

Cs-Cs
31.01.2023, 14:23
Cs-Cs при использовании ABS надо по другому формулу делать... так как ABS(-65400) будет 65400, то потом еще надо 65535 (или 6) минус ваше ABS и получится ветвление в коде, типа если число отрицательное то то-то, если положительное то то-то
Блин, у меня заработало с таким кодом вот:
65596

melky
31.01.2023, 14:25
ох, не суйте мне свой ST, все равно не понимаю :)

Валенок
31.01.2023, 14:31
почему разница будет минусом, если я её считаю по модулю ABS(),.
Потому что ABS к unsigned неприменим без явных приведений типов

melky
31.01.2023, 14:57
не будет если исходный счетчик 16 бит

Валенок да я понял, просто калькулятор был открыт в QWORD :)

Валенок
31.01.2023, 17:49
Валенок да я понял, просто калькулятор был открыт в QWORD :)
Да хоть в QQQWORD.
Разницу больше емкости исходного счетчика Вы не получите в принципе.

Cs-Cs
31.01.2023, 18:29
Достаточно только под под Mx110.
А при Мx210 читать только младшее слово. Вот ничего не изменится.
О, спасибо! Это крутая идея.
Я чаще всего использую Мх100, а Мх210 использовал ровно 1 раз.