Как правильо написать макрос?

Работа с панелями оператора Weintek - подключение, программирование, совмещение с ПЛК

Модераторы: kiv, 8bit, VanMo

Как правильо написать макрос?

Сообщение atomo2 » 18 сен 2024, 13:17

Добрый день. есть код на питоне , который считывает по modbus c газоанализатора СТГ3 , текущую концентрацию и пороги. Теперь я подключил на прямую к входу modbus панели, газоанализатор , помогите с макросом для считывания регистров. Нашел пример , но не совсем понимаю Изображение




Код: Выделить всё
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(1)

if __name__ == "__main__":
    main()
atomo2
 
Сообщения: 4
Зарегистрирован: 26 янв 2024, 09:05

Re: Как правильо написать макрос?

Сообщение dimensy » 18 сен 2024, 23:09

Вот, наваял я вам конвертер
Код: Выделить всё
sub float Convert_Data(unsigned int A)

bool Znak
unsigned int Point
float result, p

GETBIT(A, Znak, 31) //Определяем знак
Point = A & 0x7000000 //Определяем количество знаков после запятой
Point = Point >> 24
POW(10, Point, Point)
p = Point
A = A & 0xFFFFFF//Определяем значение
BCD2BIN(A, A)
result = A
result = result / p
if Znak then
   result = -1 * result
end if

return result

end sub


Создавать его нужно тут
Изображение

Далее, макрос для чтения
Код: Выделить всё
macro_command main()
unsigned int A

float Concentracia, Porog1, Porog2

GetData(A, "MODBUS RTU (HEX Addressing)", 4x_Double, 0, 1)
Concentracia = Convert_Data(A)
SetData(Concentracia, "Local HMI", LW, 0, 1)

GetData(A, "MODBUS RTU (HEX Addressing)", 4x_Double, 2, 1)
Porog1 = Convert_Data(A)
SetData(Porog1, "Local HMI", LW, 2, 1)

GetData(A, "MODBUS RTU (HEX Addressing)", 4x_Double, 4, 1)
Porog2 = Convert_Data(A)
SetData(Porog2, "Local HMI", LW, 4, 1)

end macro_command


На панели выводить в формате float

И, еще, скорее всего в настройках драйвера надо галочки поставить вот тут
Изображение

результат
Изображение
dimensy
 
Сообщения: 207
Зарегистрирован: 14 мар 2018, 17:54

Re: Как правильо написать макрос?

Сообщение 8bit » 19 сен 2024, 11:02

а удобно это они придумали .....

Изображение
Хороший вопрос содержит половину ответа - A good question contains half the answer
Аватара пользователя
8bit
 
Сообщения: 1180
Зарегистрирован: 20 апр 2020, 19:07

Re: Как правильо написать макрос?

Сообщение atomo2 » 19 сен 2024, 15:11

dimensy
Спасибо большое, все работает


8bit
Ну да , так я и написал на питоне скрипт, а с панелью завис чего то(
atomo2
 
Сообщения: 4
Зарегистрирован: 26 янв 2024, 09:05

Re: Как правильо написать макрос?

Сообщение atomo2 » 01 окт 2024, 05:40

dimensy а подскажите пожалуйста как в easy builder преобразовать значения BOOL в Int ?
atomo2
 
Сообщения: 4
Зарегистрирован: 26 янв 2024, 09:05

Re: Как правильо написать макрос?

Сообщение dimensy » 01 окт 2024, 07:06

Просто присвоить один другому
dimensy
 
Сообщения: 207
Зарегистрирован: 14 мар 2018, 17:54


Вернуться в Weintek

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 13