Страница 1 из 2 12 ПоследняяПоследняя
Показано с 1 по 10 из 16

Тема: СТГ 3 и modbus

  1. #1

    По умолчанию СТГ 3 и modbus

    Пытаюсь считать с СТГ 3 текущие измеренное значение, Нажмите на изображение для увеличения. 

Название:	1.png 
Просмотров:	31 
Размер:	91.7 Кб 
ID:	78530Нажмите на изображение для увеличения. 

Название:	2.png 
Просмотров:	29 
Размер:	74.8 Кб 
ID:	78531


    Пример запроса данных:
    01; 03; 00; 00; 00; 02; sum 0; sum 1,
    где N номер сигнализатора в сети. Устанавливается пользователем в
    диапазоне от 1 до 31;
    sum 0; sum 1 контрольная сумма (CRC), рассчитывается в соответствии
    с протоколом «MODBUS-RTU».


    # Извлечение данных из регистров
    reg0 = registers[0]
    reg1 = registers[1]

    # Разбиение регистров на байты
    byte1 = (reg0 >> 8) & 0xFF
    byte2 = reg0 & 0xFF
    byte3 = (reg1 >> 8) & 0xFF
    byte4 = reg1 & 0xFF

    # Извлечение состояния сигнализации и знака
    sign_bit = (byte1 >> 7) & 0x01
    p1 = (byte1 >> 3) & 0x01
    p2 = (byte1 >> 4) & 0x01
    comma_position = (byte1 & 0x07)

    # Определение знака
    sign = '-' if sign_bit else '+'

    # Чтение значений
    integer_part = byte2 * 100 + byte3 * 10 + (byte4 >> 4)
    decimal_part = (byte4 & 0x0F) * 100

    # Формирование значения
    value = integer_part + decimal_part / 10000
    if sign_bit:
    value = -value

    # Сдвиг запятой
    value /= 10 ** comma_position

    # Форматирование результата
    print(f"Значение: {value:.{comma_position}f}")
    print(f"Состояние сигнализации: П1={p1}, П2={p2}")

    def main():
    # Параметры запроса
    unit_id = 1
    address = 0x00 # Начальный адрес
    count = 2 # Количество регистров

    while True:
    # Чтение данных
    data = read_modbus_data(client, unit_id, address, count)
    if data:
    interpret_data(data.registers)




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

    Значение: 0.02120
    Состояние сигнализации: П1=0, П2=0
    Значение: 0.02423
    Состояние сигнализации: П1=0, П2=0
    Значение: 0.01677
    Состояние сигнализации: П1=0, П2=0
    Значение: 0.015674
    Состояние сигнализации: П1=0, П2=0
    Значение: 0.016387


    Хотя в официальной программе значение Нажмите на изображение для увеличения. 

Название:	3.png 
Просмотров:	12 
Размер:	3.6 Кб 
ID:	78532 что я делаю не так?
    Последний раз редактировалось atomo2; 09.09.2024 в 12:46.

  2. #2

    По умолчанию

    Все код рабочий, ошибка была тут integer_part = byte2 * 10000 + byte3 * 10 + (byte4 >> 4) на 10000 умножать надо было

  3. #3

    По умолчанию

    А вот пороги не получается считать , если я устанавливаю пороги 20 и 40 , то у меня считывается 32 и 64


    Параметры запроса
    unit_id = 1
    address = 0x00 # Начальный адрес для измеренного значения
    count = 2 # Количество регистров для измеренного значения
    threshold1_address = 0x02 # Адрес порога 1
    threshold2_address = 0x04 # Адрес порога 2
    while True:
    # Чтение данных измеренного значения
    data = read_modbus_data(client, unit_id, address, count)
    if data:
    print("Текущее значение концентрации:")
    interpret_data(data.registers)

    # Чтение порога 1
    p1_data = read_modbus_data(client, unit_id, threshold1_address, count)
    if p1_data:
    print("Установленное значение порога 1:")
    interpret_data(p1_data.registers)
    # Чтение порога 2
    p2_data = read_modbus_data(client, unit_id, threshold2_address, count)
    if p2_data:
    print("Установленное значение порога 2:")
    interpret_data(p2_data.registers)
    Последний раз редактировалось atomo2; 10.09.2024 в 17:49.

  4. #4

    По умолчанию

    Цитата Сообщение от atomo2 Посмотреть сообщение
    А вот пороги не получается считать , если я устанавливаю пороги 20 и 40 , то у меня считывается 32 и 64
    ...
    Примечательно, что это одинаковые значения, только в шестнадцатеричной и десятичной системе

  5. #5

    По умолчанию

    Цитата Сообщение от 1exan Посмотреть сообщение
    Примечательно, что это одинаковые значения, только в шестнадцатеричной и десятичной системе
    Так то оно так) Но ведь у меня выводится то в десятичной системе , значит в 16 ричной что то другое считывается?


    Откинем все лишние и сделаем только чтение 2х порогов

    from pymodbus.client.sync import ModbusSerialClient as ModbusClient

    # Конфигурация клиента Modbus
    client = ModbusClient(
    method='rtu', # Протокол RTU
    port='/dev/ttyS6', # COM-порт (например, /dev/ttyS6 для Linux или COM6 для Windows)
    baudrate=9600, # Скорость передачи данных
    stopbits=1, # Стоп-биты
    parity='N', # Четность (None)
    bytesize=8 # Размер байта
    )

    # Подключение к клиенту
    client.connect()

    # Чтение значений порога 1 и порога 2
    # Чтение регистров 0002 и 0003 для порога 1
    result_threshold_1 = client.read_holding_registers(0x0002, 2, unit=1)
    threshold_1 = result_threshold_1.registers

    # Чтение регистров 0004 и 0005 для порога 2
    result_threshold_2 = client.read_holding_registers(0x0004, 2, unit=1)
    threshold_2 = result_threshold_2.registers

    # Закрытие соединения
    client.close()

    # Вывод значений порогов
    print(f"Установленное значение порога 1: {threshold_1[0]}, {threshold_1[1]}")
    print(f"Установленное значение порога 2: {threshold_2[0]}, {threshold_2[1]}")

    И получаем

    Установленное значение порога 1: 1056, 0
    Установленное значение порога 2: 1088, 0


    Разобрался , нужно было выводить младший байт , позже подробнее напишу
    Последний раз редактировалось atomo2; 11.09.2024 в 04:49.

  6. #6

    По умолчанию

    Изменил код считываю в 16 ричной системе

    from pymodbus.client.sync import ModbusSerialClient as ModbusClient
    import time

    # Параметры подключения
    port = 'COM6'
    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)
    if result.isError():
    print("Ошибка чтения данных: ", result)
    return None

    # Закрытие соединения
    client.close()
    return result

    def interpret_data(registers, is_threshold=False):
    if len(registers) < 2:
    print("Недостаточно данных для интерпретации")
    return

    # Инициализация переменной value
    value = None

    # Извлечение данных из регистров
    reg0 = registers[0]
    reg1 = registers[1]

    if is_threshold:
    # Для порога младший и старший байты используются напрямую
    byte1 = reg0 & 0xFF
    byte2 = (reg0 >> 8) & 0xFF
    byte3 = reg1 & 0xFF
    byte4 = (reg1 >> 8) & 0xFF

    # Интерпретация данных
    hex_value = f"{reg0:04X} {reg1:04X}"
    print(f"Значение порога (16-ричное): {hex_value}")

    else:
    # Разбиение регистров на байты
    byte1 = (reg0 >> 8) & 0xFF
    byte2 = reg0 & 0xFF
    byte3 = (reg1 >> 8) & 0xFF
    byte4 = reg1 & 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
    if sign_bit:
    value = -value

    # Сдвиг запятой
    value /= 10 ** comma_position

    # Форматирование результата с округлением до 2 знаков после запятой
    value = round(value, 2)

    print(f"Значение концентрации: {value:.2f}")

    return value

    def main():
    # Параметры запроса
    unit_id = 1
    address = 0x00 # Начальный адрес для измеренного значения
    count = 2 # Количество регистров для измеренного значения

    threshold1_address = 0x02 # Адрес порога 1
    threshold2_address = 0x04 # Адрес порога 2

    while True:
    # Чтение данных измеренного значения
    data = read_modbus_data(client, unit_id, address, count)
    if data:
    print("Текущее значение концентрации:")
    interpret_data(data.registers)

    # Чтение порога 1
    p1_data = read_modbus_data(client, unit_id, threshold1_address, count)
    if p1_data:
    print("Установленное значение порога 1:")
    interpret_data(p1_data.registers, is_threshold=True)

    # Чтение порога 2
    p2_data = read_modbus_data(client, unit_id, threshold2_address, count)
    if p2_data:
    print("Установленное значение порога 2:")
    interpret_data(p2_data.registers, is_threshold=True)

    # Задержка 1 секунда
    time.sleep(1)

    if __name__ == "__main__":
    main()


    И получаю

    Текущее значение концентрации:
    Значение концентрации: 0.09
    Установленное значение порога 1:
    Значение порога (16-ричное): 0587 0000
    Установленное значение порога 2:
    Значение порога (16-ричное): 0414 5000

    Все верно , но как теперь сделать из значения 0587 0000 число 8.7 , а из значения 0414 5000 число 14.5 . Понятно, что тут это младший байт первого регистра число 8 , но и в нем же 7. (как правильно запятую расставлять?) Во втором пороге младший байт 14 первого регистра и старший второго регистра 50
    Последний раз редактировалось atomo2; 11.09.2024 в 06:32.

  7. #7
    Супер Модератор Аватар для Евгений Кислов
    Регистрация
    27.01.2015
    Адрес
    Москва
    Сообщений
    13,595

    По умолчанию

    (как правильно запятую расставлять?)
    Это описано на втором скриншоте из вашего первого поста.

    У вас есть HEX-строка, содержащее сырое значение: 05 87 00 00

    Три младших байта нужно интерпретировать как целое беззнаковое (870000).

    Старший байт - это битовое поле.

    05 = 0b00000101

    Для наглядности визуально выделим отдельные наборы бит: 0b0_00_00_101

    0 - знак значения (1 - минус, 0 - плюс)
    00 - не используются
    00 - состояния сигнализации двух порогов (0 - не сработала, 1 - сработала); каждый бит из двух бит соответствует одному из двух порогов
    101 - положение точки в значении (0b101 = 5)

    Теперь мы знаем, что реальное значение - это 870000 / 10^5 = 8.7
    Если бы бит знака соответствовал минусу - то нужно было бы домножить на -1.0.

    В общем, для начала стоит погуглить, как в Python работать с битами - проверить заданный бит целого числа, извлечь порцию бит в отдельную переменную и т. д.

  8. #8

    По умолчанию

    Цитата Сообщение от Евгений Кислов Посмотреть сообщение
    Это описано на втором скриншоте из вашего первого поста.

    У вас есть HEX-строка, содержащее сырое значение: 05 87 00 00

    Три младших байта нужно интерпретировать как целое беззнаковое (870000).

    Старший байт - это битовое поле.

    05 = 0b00000101

    Для наглядности визуально выделим отдельные наборы бит: 0b0_00_00_101

    0 - знак значения (1 - минус, 0 - плюс)
    00 - не используются
    00 - состояния сигнализации двух порогов (0 - не сработала, 1 - сработала); каждый бит из двух бит соответствует одному из двух порогов
    101 - положение точки в значении (0b101 = 5)

    Теперь мы знаем, что реальное значение - это 870000 / 10^5 = 8.7
    Если бы бит знака соответствовал минусу - то нужно было бы домножить на -1.0.

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

    Вот если берем HEX-строку 0414 5000

    Три младших байта нужно интерпретировать как целое беззнаковое (145000)

    Старший байт - это битовое поле.

    04 = 0b00000100 положение запятой 4

    но у меня получается 0x1450 = 5200 (в десятичной системе) 145000 / 10^4 = 52

    А должно быть 14.5 , где я опять туплю?)
    Последний раз редактировалось atomo2; 11.09.2024 в 08:03.

  9. #9

    По умолчанию

    Цитата Сообщение от atomo2 Посмотреть сообщение
    Спасибо, буду пробовать

    Вот если берем HEX-строку 0414 5000

    Три младших байта нужно интерпретировать как целое беззнаковое (145000)

    Старший байт - это битовое поле.

    04 = 0b00000100 положение запятой 4

    но у меня получается 0x1450 = 5200 (в десятичной системе) 145000 / 10^4 = 52

    А должно быть 14.5 , где я опять туплю?)
    Не переводите в десятичную - вы же сами пишете: 145000 / 10^4 = 14.5

  10. #10
    Пользователь
    Регистрация
    23.09.2008
    Адрес
    Центророссийск
    Сообщений
    3,053

    По умолчанию

    Это не hex, это bcd
    Последний раз редактировалось Валенок; 22.09.2024 в 12:50.

Страница 1 из 2 12 ПоследняяПоследняя

Похожие темы

  1. Ответов: 26
    Последнее сообщение: 31.01.2023, 17:42
  2. Ответов: 2
    Последнее сообщение: 04.06.2019, 16:55
  3. Ответов: 10
    Последнее сообщение: 10.06.2018, 16:36
  4. Ответов: 2
    Последнее сообщение: 17.03.2016, 08:47
  5. Ответов: 5
    Последнее сообщение: 14.10.2010, 13:42

Ваши права

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