не совсем понимаю как это сделать, устройств у меня 10 штук , у каждого свой сетевой адрес и у каждого свои 2 регистраВложение 81739
или вот так?изображение_2025-02-04_131549646.png
Последний раз редактировалось atomo2; 04.02.2025 в 09:16.
МихаилГл kondor3000 Да спасибо все получилось. Единственное теперь нужно , как то значения преобразовать , в моем скрипте на пк было 2 преобразования. Где мы разбирали 2 регистра по байтам, вычисляли позицию запятой и знак числа и преобразовывали биты в десятичное число и вставляли точку куда нужно
def display_concentration(registers):
if len(registers) < 2:
print("Недостаточно данных для отображения концентрации")
return
byte1 = (registers[0] >> 8) & 0xFF # Старший байт первого регистра
byte2 = registers[0] & 0xFF # Младший байт первого регистра
byte3 = (registers[1] >> 8) & 0xFF # Старший байт второго регистра
byte4 = registers[1] & 0xFF # Младший байт второго регистра
sign_bit = (byte1 >> 7) & 0x01 # Определяем знак (бит 7 в первом байте)
comma_position = byte1 & 0x07 # Определяем позицию запятой (биты 0-2 в первом байте)
sign = '-' if sign_bit else '+'
integer_part = byte2 * 10000 + byte3 * 10 + (byte4 >> 4) # Вычисление целой части
decimal_part = (byte4 & 0x0F) * 100 # Десятичная часть
value = integer_part + decimal_part / 10000 # Собираем число
value = -value if sign_bit else value # Добавляем знак
value /= 10 ** comma_position # Учитываем запятую
value = round(value, 2) # Округляем до двух знаков
print(f"Значение концентрации: {value:.2f}")
и так же Объединяли два регистра в одно 32-битное число, преобразовывали его в строку шестнадцатеричного представления и разделяли число на целую и дробную часть с учетом положения запятой.
def format_value_with_comma(hex_value, comma_position):
value_str = f"{hex_value:08X}" # Преобразует число в строку из 8 шестнадцатеричных символов
integer_part = value_str[2:-comma_position] if comma_position < len(value_str) else '0'
decimal_part = value_str[-comma_position:] if comma_position > 0 else '0'
formatted_value = f"{integer_part},{decimal_part}".lstrip('0') or '0'
return f"{formatted_value[:formatted_value.index(',') + 3]}" if ',' in formatted_value else formatted_value
Я могу теперь написать функциональный блок?) или есть готовые решения?
Если у вас в регистрах нестандартные числа (не real, word и т.п.), то придется писать код преобразования. А если стандартные, но в итоге число не то, что в действительности, то надо пробовать менять местами слова в регистрах. В кодесисе в библиотеках овен есть готовые блоки для этого.
Я бы попробовал для начала считать FLOAT, если не правильное отображение, то поменять местами регистры (потом байты) и проверить.
МихаилГл kondor3000 capzap Значения концентрации и порогов я сейчас получаю в 10 тичной системе , концентрация 1536, порог 1 1040 и порог 2 1056 , если в 16-ричную переводить то 0,0 10 и 20 . Простите ошибся. Получается нужно писать преобразователь, блок или функцию я не нашел
Код:from pymodbus.client.sync import ModbusSerialClient as ModbusClient import time # Параметры подключения PORT = 'COM17' BAUDRATE = 9600 client = ModbusClient( method='rtu', port=PORT, baudrate=BAUDRATE, stopbits=1, parity='N', timeout=1 ) def read_modbus_data(client, unit_id, address, count): if not client.connect(): print("Не удалось подключиться к Modbus серверу") return None result = client.read_holding_registers(address, count, unit=unit_id) client.close() if result.isError(): print("Ошибка чтения данных: ", result) return None return result.registers def format_value_with_comma(hex_value, comma_position): value_str = f"{hex_value:08X}" integer_part = value_str[2:-comma_position] if comma_position < len(value_str) else '0' decimal_part = value_str[-comma_position:] if comma_position > 0 else '0' formatted_value = f"{integer_part},{decimal_part}".lstrip('0') or '0' return f"{formatted_value[:formatted_value.index(',') + 3]}" if ',' in formatted_value else formatted_value def display_registers(registers): if len(registers) < 2: print("Недостаточно данных для отображения") return combined_hex = (registers[0] << 16) | registers[1] comma_position = (registers[0] >> 8) & 0xFF formatted_value = format_value_with_comma(combined_hex, comma_position) print(f"Значение: {formatted_value}") def display_concentration(registers): if len(registers) < 2: print("Недостаточно данных для отображения концентрации") return byte1 = (registers[0] >> 8) & 0xFF byte2 = registers[0] & 0xFF byte3 = (registers[1] >> 8) & 0xFF byte4 = registers[1] & 0xFF sign_bit = (byte1 >> 7) & 0x01 comma_position = byte1 & 0x07 sign = '-' if sign_bit else '+' integer_part = byte2 * 10000 + byte3 * 10 + (byte4 >> 4) decimal_part = (byte4 & 0x0F) * 100 value = integer_part + decimal_part / 10000 value = -value if sign_bit else value value /= 10 ** comma_position value = round(value, 2) print(f"Значение концентрации: {value:.2f}") def main(): unit_id = 1 count = 2 threshold1_address = 0x02 threshold2_address = 0x04 concentration_address = 0x00 while True: p1_data = read_modbus_data(client, unit_id, threshold1_address, count) if p1_data: print("Установленное значение порога 1:") display_registers(p1_data) p2_data = read_modbus_data(client, unit_id, threshold2_address, count) if p2_data: print("Установленное значение порога 2:") display_registers(p2_data) conc_data = read_modbus_data(client, unit_id, concentration_address, count) if conc_data: print("Измеренное значение концентрации:") display_concentration(conc_data) time.sleep(3) if __name__ == "__main__": main()
Последний раз редактировалось atomo2; 04.02.2025 в 11:36.
Это разработчики СТГ-3 так постарались)) Если я любым методом буду считывать концентрацию и пороги, то буду получать значения , что я выше написал, а потом их приходится конвертировать и получать уже , то что нужно...ппц какой то
Снимок экрана 2025-02-04 163745.png
изображение_2025-02-04_163816263.png