Contrôler un variateur de vitesse NFLIXIN 9600 Series en Modbus

Bonjour,
Je suis en train d’installer un variateur de vitesse sur ma pompe de piscine 0.8 kW monophasée.
J’utilise le variateur NFLIXIN 9600 Series http://nflixin.com/en/?p=103.

J’arrive à lire les informations en provenance du variateur (tension, fréquence, courant, code erreur, …) en lisant les registres à partir de 7000H, mais je n’ai pas d’informations pour le piloter.

Après tâtonnements, j’ai réussi à envoyer la fréquence demandée en écrivant le registre 000EH.
Exemple: 000EH = 4000 pour faire fonctionner le moteur à 40.00 Hz.
Cependant, je n’arrive pas à piloter la marche et l’arrêt.

La documentation (https://opendevices.ru/wp-content/uploads/2020/01/9600_series__User_manual.pdf) indique:

  • Register 1000H = fréquence demandée (-100% à 100%)
  • Registre 2000H = commandes ?

image

Est-ce que quelqu’un aurait des informations complémentaires ?

Bonjour,

Est-ce que P0-14 qui est la limite basse de fréquence ne correspondrait pas au registre 000E ? 1’ en décimal = E en hexa ?

Pour la section U0 c’est clair mais pour le reste pas vrament
image

l’adresse de base est 0x7000 donc u0-10 prend pour adresse 0x700A

Pour les commandes run stop forward de ce que je comprend il faudrait écrire les paramètres de A7-08 à l’adresse 0x2000

Bonjour,
Je viens de recevoir un VFD 9600 et je souhaite faire exactement la même chose que vous : commander ma pompe de piscine.
Pour info, j’avais un autre VFD (AT2) avant, qui a commandé la pompe pendant plus d’un an sans problème (réduction de vitesse) via ESPHome. Malheureusement, il est mort à cause d’une mauvaise manip. Par ailleurs, j’utilise déjà le MODBUS en liaison avec une chaudière…
Je souhaite utiliser ce VFD en MODBUS pour changer de vitesse et lire le courant (pour évaluer l’encrassement du filtre), or la doc me parait très confuse.
Pouvez-vous m’aider pour me dire par exemple comment vous avez obtenu le courant (YAML ou suite de commandes MODBUS).
Si vous pouvez m’aider, je gagnerai un temps précieux !

Correction : Pour le monitoring, a priori pas de problème. Par contre pour la commande pour faire fonctionner à 40Hz, ne faudrait-il pas utiliser 0008H comme adresse ?

Pour communiquer avec le variateur en Modbus, il faut:

  1. Configurer les paramètres Modbus du variateur:

    • paramètre PD-00 « Baud Rate »
    • paramètre PD-01 « Data Format »
    • paramètre PD-02 « Local Address »
    • paramètre PD-03 « Response Delay »
    • paramètre PD-04 « Communication Timeout »
    • paramètre PD-05 « Protocol Selection » = 1 ‹ Standard Modbus ›
    • paramètre PD-06 « Current Resolution »
  2. Configurer la source des commandes du variateur:

    • paramètre P0-02 « Command Source selection » = 2 ‹ Communication Control (LED blinking) ›
    • paramètre P0-03 « Main Frequency source X selection » = 9 ‹ Communication setting ›
  3. Lire les données du variateur en Modbus:

    • Registre 7000H (paramètre U0-00)
    • Registre 7001H (paramètre U0-01)
  4. Contrôler le variateur en Modbus:

    • Registre 1000H (paramètre A7-06) = -10000 à 100000 (-100.00% à 100.00%)
    • Registre 2000H (paramètre A7-08) = 1 ‹ Forward RUN ›, 2 ‹ Reverse RUN ›, …, 5 ‹ Coast to stop ›, 6 ‹ Decelerate to stop ›, …

Merci beaucoup ! Je bosse aussi la/les doc(s)…
Contrôler le variateur en Modbus : pour contrôler l’entrée fréquence, c’est l’adresse 0008H ? (paramètre P0-08)
Par ailleurs, je ne comprends pas la correspondance entre le paramètre (A7-06 par exemple) et l’adresse (1000H par exemple).

L’adresse 1000H est celle où il faut écrire la fréquence demandée en centièmes de pourcent.
L’adresse 2000H permet d’écrire la commande 1=avant, 2=arrière, …, les valeurs à écrire sont décrites dans le paramètre A7-08

Exemple pour faire fonctionner le variateur en marche avant à 35 Hz (avec P0-10 « Maximum Frequency » = 50 Hz):

  • Registre 1000H = 7000 (70% de P0-10, soit 35 Hz)
  • Registre 2000H = 1 (Forward RUN)

Un grand merci ! J’essaye dès que je peux (car pour l’instant le variateur est loin de moi !).
Je vous tiens au courant…
Cela dit, dans une doc, 1000H correspond à : Communication setup value (-10000 to 10000)( Decimal)…- Extrait de la la doc spécifique MODBUS, WK600 series modbus RS485.DOCX, voir http://www.cnweiken.cn/en/page/56.htm?spm=a2g0s.imconversation.0.0.688d3e5f9rEZlL-.
Par contre, dans la doc principale, comme vous l’indiquez, on lit ce qui suit :
Screenshot_14

Bonne Année 2024 !
J’ai pu jouer avec le convertisseur. Et j’ai pu faire une petite synthèse pour ceux que cela intéresse.
Je rappelle que dans mon cas, je contrôle une pompe de filtration de piscine) et je cherchais à obtenir le courant consommé (pour mesurer le taux d’encrassement) et à pouvoir commander le démarrage, la vitesse et l’arrêt).
Paramétrage WK600 :


En Yaml esphome, un extrait du code :

  id: mod_bus
  tx_pin: TX
  rx_pin: RX
  baud_rate: 9600
    
modbus:
  id: mod_bus_inverter
  
modbus_controller:
  id: inverter
  address: 1
  modbus_id: mod_bus_inverter
  update_interval: 5s
  command_throttle: 1000ms

sensor:
  - platform: modbus_controller
    modbus_controller_id: inverter
    id: inverter_current
    name: "Courant pompe"
    address: 0x7004
    register_type: holding
    value_type: S_WORD
    unit_of_measurement: "mA"
    filters:
      multiply: 100

output:
  - id: low_speed_output
    platform: gpio
    inverted: true
    pin: GPIO32
    
  - platform: modbus_controller
    modbus_controller_id: inverter
    id: pump_stop
    write_lambda: |-
      payload.push_back(6);
      return x ;
    address: 0x2000
    value_type: U_WORD

  - platform: modbus_controller
    modbus_controller_id: inverter
    id: pump_start
    write_lambda: |-
      payload.push_back(1);
      return x ;
    address: 0x2000
    value_type: U_WORD

  - platform: modbus_controller
    modbus_controller_id: inverter
    id: low_speed
    write_lambda: |-
      payload.push_back(6000);
      return x ;
    address: 0x1000
    value_type: U_WORD

  - platform: modbus_controller
    modbus_controller_id: inverter
    id: high_speed
    write_lambda: |-
      payload.push_back(10000);
      return x ;
    address: 0x1000
    value_type: U_WORD
1 « J'aime »

2 remarques :

  • la première est que pour lire les données sur les adresses 7000H, il faut mettre le type de registre en « holding ». Avec le type « read », cela ne fonctionne pas.
  • la seconde est que pour activer le modbus en écriture, j’avais utilisé les components « light » et « output », mais je trouvais cela compliqué. J’ai essayé en passant pas des « switch », mais, les switchs Modbus étaient rafraichis au rythme de la lecture des sensors. Du coup en final, j’ai écrit directement avec l’UART. Le code est beaucoup plus simple et lisible.
  - platform: template
    id: high_speed
    name: "high_speed"
    optimistic: True
    turn_on_action:
      - uart.write: [0x01 , 0x06, 0x10, 0x00, 0x27, 0x10, 0x97, 0x36] # vitesse 50Hz
    turn_off_action:
      - uart.write: [0x01 , 0x06, 0x10, 0x00, 0x17, 0x70, 0x83, 0x1E] # vitesse 30 Hz

  - platform: template
    name: "pump_activation"
    id: pump_activation
    optimistic: True
    restore_mode: ALWAYS_OFF
    turn_on_action:
        - switch.turn_on: inverter_supply                               # convertisseur on
        - delay: 5s
        - switch.turn_on: high_speed
        - delay: 2s
        - uart.write: [0x01 , 0x06, 0x20, 0x00, 0x0, 0x01, 0x43, 0xCA]  # Start
        - delay: 2s
        - switch.turn_off: high_speed
  
    turn_off_action:
        - uart.write: [0x01 , 0x06, 0x20, 0x00, 0x0, 0x06, 0x02, 0x08]  # Stop
        - delay: 1s 
        - switch.turn_on: high_speed
        - delay: 5s
        - switch.turn_off: inverter_supply                              # convertisseur off

I did in phython and it worked good, maybe can be useful for someone:

import tkinter as tk
from tkinter import ttk
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
import threading
import time
import serial.tools.list_ports

client = None
conectado = False
thread_running = False

# Contadores
total_requisicoes = 0
total_respostas = 0
total_erros = 0
total_reenviados = 0

root = tk.Tk()
root.title("Monitoramento e Controle da Bomba")

labels = {}
campos = {}

registros = [
    ("Status (Hz)", 0x3000, 1, ""),
    ("Frequência Atual (Hz)", 0x7000, 0.01, "Hz"),
    ("Frequência Configurada (Hz)", 0x7001, 0.01, "Hz"),
    ("Tensão do Barramento DC (V)", 0x7002, 0.1, "V"),
    ("Tensão de Saída Motor (V)", 0x7003, 1, "V"),
    ("Corrente de Saída (A)", 0x7004, 0.1, "A"),
    ("Potência de Saída (kW)", 0x7005, 0.01, "kW"),
    ("Carga (%)", 0x7006, 0.1, "%"),
    ("X state", 0x7007, 1, ""),
    ("DO state", 0x7008, 1, ""),
    ("Tensão AI1 (V)", 0x7009, 0.01, "V"),
    ("Entrada AI2 (V/mA)", 0x700A, 0.01, "V/mA"),
    ("Tensão AI2 (V)", 0x700B, 0.01, "V"),
    ("Count value", 0x700C, 1, ""),
    ("Length value", 0x700D, 1, ""),
    ("Load speed", 0x700E, 1, ""),
    ("PID setting", 0x700F, 1, ""),
    ("PID feedback", 0x7010, 1, ""),
    ("PLC stage", 0x7011, 1, ""),
    ("Input pulse frequency", 0x7012, 0.01, "kHz"),
    ("Feedback speed (Hz)", 0x7013, 0.01, "Hz"),
    ("Tempo de Operação (min)", 0x7014, 0.1, "min"),
    ("Tensão A1 antes da correção (V)", 0x7015, 0.001, "V"),
    ("Saída AO1 (V/mA)", 0x7016, 0.01, "V/mA"),
    ("Tensão AI3 (V)", 0x7017, 0.001, "V"),
    ("Velocidade linear (m/min)", 0x7018, 1, "m/min"),
    ("Tempo Inversor Ligado (min)", 0x7019, 1, "min"),
    ("Tempo Motor Ligado (min)", 0x701A, 0.1, "min"),
    ("Frequência AI3 (Hz)", 0x701B, 1, "Hz"),
    ("Communication setting value (%)", 0x701C, 0.01, "%"),
    ("Encoder feedback speed (%)", 0x701D, 0.01, "%"),
    ("Main frequency X (%)", 0x701E, 0.01, "%"),
    ("Auxiliary frequency Y (%)", 0x701F, 0.01, "%"),
    ("Temperatura Motor (°C)", 0x7022, 1, "°C"),
    ("Target Torque (%)", 0x7023, 0.1, "%"),
    ("Target voltage upon V/F separation (V)", 0x7027, 1, "V"),
    ("Output voltage upon V/F separation (V)", 0x7028, 1, "V"),
    ("X function state visual display 1", 0x702B, 1, ""),
    ("X function state visual display 2", 0x702C, 1, ""),
    ("Fault information", 0x702D, 1, ""),
    ("Phaze Z counting", 0x703A, 1, ""),
    ("Current set frequency (%)", 0x703B, 0.01, "%"),
    ("Current running frequency (%)", 0x703C, 0.01, "%")
]

def atualizar_qualidade():
    lbl_total.config(text=f"Requisições: {total_requisicoes}")
    lbl_sucesso.config(text=f"Recebidas: {total_respostas}")
    lbl_erros.config(text=f"Erros: {total_erros}")
    lbl_reenviados.config(text=f"Reenviadas: {total_reenviados}")

def interpretar_status(valor):
    return {
        0x0001: "RUN FORWARD",
        0x0002: "RUN REVERSE",
        0x0003: "STOP"
    }.get(valor, f"DESCONHECIDO (0x{valor:04X})")

def tentativa_leitura_registro(endereco, tentativas=3, delay=0.3):
    global total_requisicoes, total_respostas, total_erros, total_reenviados
    for i in range(tentativas):
        total_requisicoes += 1
        resposta = client.read_holding_registers(endereco, 1, unit=1)
        if hasattr(resposta, 'registers'):
            total_respostas += 1
            if i > 0:
                total_reenviados += i
            return resposta.registers[0]
        total_erros += 1
        time.sleep(delay)
    return None

def tentativa_leitura_bloco(inicio, tamanho, tentativas=3, delay=0.3):
    global total_requisicoes, total_respostas, total_erros, total_reenviados
    for i in range(tentativas):
        total_requisicoes += 1
        resposta = client.read_holding_registers(inicio, tamanho, unit=1)
        if hasattr(resposta, 'registers'):
            total_respostas += 1
            if i > 0:
                total_reenviados += i
            return resposta.registers
        total_erros += 1
        time.sleep(delay)
    return None

def atualizar_dados():
    global conectado, thread_running
    bloco_inicio = 0x7000
    bloco_fim = 0x703C
    bloco_tamanho = bloco_fim - bloco_inicio + 1

    while conectado:
        try:
            bruto = tentativa_leitura_registro(0x3000)
            if bruto is not None:
                campos["Status (Hz)"].config(text=interpretar_status(bruto))
            else:
                campos["Status (Hz)"].config(text="Erro")

            blocos = tentativa_leitura_bloco(bloco_inicio, bloco_tamanho)
            for nome, endereco, fator, unidade in registros:
                if endereco == 0x3000:
                    continue
                if blocos:
                    try:
                        bruto = blocos[endereco - bloco_inicio]
                        valor = round(bruto * fator, 2)
                        texto = f"{valor} {unidade}".strip()
                    except:
                        texto = "Erro"
                else:
                    texto = "Erro"
                campos[nome].config(text=texto)
                time.sleep(0.02)

            atualizar_qualidade()
            time.sleep(1.0)
        except Exception as e:
            print(f"Erro geral durante leitura: {e}")
            time.sleep(2)
    thread_running = False

def conectar():
    global client, conectado, thread_running
    porta = combo_portas.get()
    client = ModbusClient(method='rtu', port=porta, baudrate=9600, timeout=3, stopbits=1, bytesize=8, parity='N')
    if client.connect():
        conectado = True
        btn_conectar.config(state="disabled")
        btn_desconectar.config(state="normal")
        if not thread_running:
            threading.Thread(target=atualizar_dados, daemon=True).start()
            thread_running = True

def desconectar():
    global conectado, client
    conectado = False
    if client:
        client.close()
    btn_conectar.config(state="normal")
    btn_desconectar.config(state="disabled")

def listar_portas():
    return [p.device for p in serial.tools.list_ports.comports()]

# UI
coluna = 0
for i, (nome, *_rest) in enumerate(registros):
    linha = i % 20
    if i > 0 and linha == 0:
        coluna += 2
    tk.Label(root, text=nome).grid(row=linha, column=coluna, sticky="w")
    campo = tk.Label(root, text="---", width=20, anchor="w")
    campo.grid(row=linha, column=coluna + 1, sticky="w")
    campos[nome] = campo

# CONTROLE
frame_controle = tk.Frame(root)
frame_controle.grid(row=len(registros)+1, column=0, columnspan=6, pady=10)

btn_on = tk.Button(frame_controle, text="Ligar Bomba", bg="green", fg="white", command=lambda: client.write_register(0x2000, 1, unit=1))
btn_on.pack(side="left", padx=5)

btn_off = tk.Button(frame_controle, text="Desligar Bomba", command=lambda: client.write_register(0x2000, 6, unit=1), bg="red", fg="white")
btn_off.pack(side="left", padx=5)

btn_off = tk.Button(frame_controle, text="Fault Reset", command=lambda: client.write_register(0x2000, 7, unit=1), bg="blue", fg="white")
btn_off.pack(side="left", padx=5)

slide_freq = tk.Scale(frame_controle, from_=10, to=60, label="Frequência (Hz)", orient="horizontal")
slide_freq.pack(side="left", padx=5)

btn_set_freq = tk.Button(frame_controle, text="Enviar Frequência", command=lambda: client.write_register(0x1000, int(slide_freq.get() * (10000 / 60)), unit=1))
btn_set_freq.pack(side="left", padx=5)

combo_portas = ttk.Combobox(frame_controle, values=listar_portas(), width=10)
combo_portas.pack(side="left", padx=5)
combo_portas.set("COM10")

btn_conectar = tk.Button(frame_controle, text="Conectar", command=conectar)
btn_conectar.pack(side="left", padx=5)

btn_desconectar = tk.Button(frame_controle, text="Desconectar", command=desconectar, state="disabled")
btn_desconectar.pack(side="left", padx=5)

# QUALIDADE
frame_qualidade = tk.Frame(root)
frame_qualidade.grid(row=len(registros)+2, column=0, columnspan=6, pady=5)
lbl_total = tk.Label(frame_qualidade, text="Requisições: 0")
lbl_total.pack(side="left", padx=10)
lbl_sucesso = tk.Label(frame_qualidade, text="Recebidas: 0")
lbl_sucesso.pack(side="left", padx=10)
lbl_erros = tk.Label(frame_qualidade, text="Erros: 0")
lbl_erros.pack(side="left", padx=10)
lbl_reenviados = tk.Label(frame_qualidade, text="Reenviadas: 0")
lbl_reenviados.pack(side="left", padx=10)

def on_closing():
    desconectar()
    root.destroy()

root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop()

Le lien initial étant mort, je ne trouve que des NFLIXIN 9600 avec sortie triphasée (probablement comme “tous” les variateurs industriels). Tu es sur de l’avoir utilisé avec une pompe monophasée ?

Bonjour à tous,
Dans l’idée de domotiser mon système de filtration piscine j’ai fait l’acquisition d’un NFLIXIN 9600D-1T-00220M (qui au démarrage indique 9600E) pour remplacer un AT2-1500X qui fonctionne bien (mais n’est pas pilotable en RS485 et n’a pas ses bornier TA/TB/TC peuplés).

Je voulais dans un premier temps le faire fonctionner avec le panneau de controle en façade.

Malheureusement la doc papier que j’ai ne semble pas correspondre exactement à mon model notament le paramètre P1-00 “Motor Type Selection” est censé selon la doc aller de 0 à 2, mais mon modèle est réglé sur 3 par défaut et peut aller de 1 à 4. Ou encore le paramètre P0-20 est absent de mon manuel mais présent sur le variateur (souvent indiqué sur internet comme étant la fréquence min).
Au final j’ai essayé différents paramètres mais rien n’y fait, le panneau affiche un 50.0 clignotant (je ne sais pas pourquoi il clignote), le potard ne règle pas grand chose. Quand je selectionne run la fréquence indiquée monte mais jamais à 50 (j’arrive à configurer/réduire le temps d’accélération avec P0-17, mais visiblement pas la fréquence visée), le moteur de la pompe siffle aigu, la pompe de s’amorce pas.

Est-ce que l’un d’entre vous dispose d’un manuel qui pourrait correspondre à mon model? Ou aurait une idée de quoi vérifier? (je passe sur la configuration des paramètres P1- 01 à 05 pour s’aligner avec ceux de ma pompe).

Merci d’avance :slight_smile:

Guys. Thank you!
I was almost giving up on this

make shure these are also set:

  • P0-02 = 2 (Command source: Modbus)
  • P0-03 = 9 (Frequency source: Modbus)
  • Pd-00 = 6005 (Data format (8-N-1))
  • Pd-01 = 3 Baud rate (9600 bps)
  • Pd-02 = 1 (Broadcast address to 1)
  • PD-03 = 20 (Response delay)
  • Pd-05 = 1 (Standard Modbus protocol)
uart:
  id: mod_bus_uart
  tx_pin: 17
  rx_pin: 16
  baud_rate: 9600
  stop_bits: 1

modbus:
  id: mod_bus_inverter
  uart_id: mod_bus_uart
  send_wait_time: 200ms
  flow_control_pin: 4 # RS485 module enable pin

modbus_controller:
  - id: inverter
    address: 1
    modbus_id: mod_bus_inverter
    update_interval: 5s
    command_throttle: 100ms

# --- MONITORING (U0 parameter group read from 0x7000) ---
sensor:
  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Running Frequency"
    address: 0x7000
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "Hz"
    filters:
      - multiply: 0.01
    accuracy_decimals: 2

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Set Frequency"
    address: 0x7001
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "Hz"
    filters:
      - multiply: 0.01
    accuracy_decimals: 2

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD DC Bus Voltage"
    address: 0x7002
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "V"
    filters:
      - multiply: 0.1
    accuracy_decimals: 1

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Output Voltage"
    address: 0x7003
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "V"
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "Pump Current"
    address: 0x7004
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "A"
    filters:
      - multiply: 0.01
    accuracy_decimals: 2

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Output Power"
    address: 0x7005
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "kW"
    filters:
      - multiply: 0.1
    accuracy_decimals: 1

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Output Torque"
    address: 0x7006
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "%"
    filters:
      - multiply: 0.1
    accuracy_decimals: 1

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD X State"
    address: 0x7007
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD DO State"
    address: 0x7008
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD AI1 Voltage"
    address: 0x7009
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "V"
    filters:
      - multiply: 0.01
    accuracy_decimals: 2

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD AI2 Voltage or Current"
    address: 0x700A
    register_type: holding
    value_type: U_WORD
    filters:
      - multiply: 0.01
    accuracy_decimals: 2

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD AI3 Voltage"
    address: 0x700B
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "V"
    filters:
      - multiply: 0.01
    accuracy_decimals: 2

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Count Value"
    address: 0x700C
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Length Value"
    address: 0x700D
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Load Speed"
    address: 0x700E
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD PID Setting"
    address: 0x700F
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD PID Feedback"
    address: 0x7010
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD PLC Stage"
    address: 0x7011
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Input Pulse Frequency"
    address: 0x7012
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "kHz"
    filters:
      - multiply: 0.01
    accuracy_decimals: 2

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Feedback Speed"
    address: 0x7013
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "Hz"
    filters:
      - multiply: 0.01
    accuracy_decimals: 2

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Remaining Running Time"
    address: 0x7014
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "min"
    filters:
      - multiply: 0.1
    accuracy_decimals: 1

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD AI1 Voltage Before Correction"
    address: 0x7015
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "V"
    filters:
      - multiply: 0.001
    accuracy_decimals: 3

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD AI2 Before Correction"
    address: 0x7016
    register_type: holding
    value_type: U_WORD
    filters:
      - multiply: 0.01
    accuracy_decimals: 2

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD AI3 Voltage Before Correction"
    address: 0x7017
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "V"
    filters:
      - multiply: 0.001
    accuracy_decimals: 3

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Linear Speed"
    address: 0x7018
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "m/min"
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Accumulative Power On Time"
    address: 0x7019
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "min"
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Accumulative Running Time"
    address: 0x701A
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "min"
    filters:
      - multiply: 0.1
    accuracy_decimals: 1

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Pulse Input Frequency"
    address: 0x701B
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "Hz"
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Communication Setting Value"
    address: 0x701C
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "%"
    filters:
      - multiply: 0.01
    accuracy_decimals: 2

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Encoder Feedback Speed"
    address: 0x701D
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "Hz"
    filters:
      - multiply: 0.01
    accuracy_decimals: 2

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Main Frequency X"
    address: 0x701E
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "Hz"
    filters:
      - multiply: 0.01
    accuracy_decimals: 2

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Auxiliary Frequency Y"
    address: 0x701F
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "Hz"
    filters:
      - multiply: 0.01
    accuracy_decimals: 2

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD View Register Value"
    address: 0x7020
    register_type: holding
    value_type: U_WORD
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Rotor Position"
    address: 0x7021
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "°"
    filters:
      - multiply: 0.1
    accuracy_decimals: 1

  - platform: modbus_controller
    modbus_controller_id: inverter
    name: "VFD Motor Temperature"
    address: 0x7022
    register_type: holding
    value_type: U_WORD
    unit_of_measurement: "°C"
    accuracy_decimals: 0

# --- MODBUS CONTROL (output platform for commands) ---
output:
  - platform: modbus_controller
    modbus_controller_id: inverter
    id: output_pump_start
    address: 0x2000
    register_type: holding
    value_type: U_WORD
    write_lambda: |-
      payload.push_back(0x0001); // 1 = Forward Run
      return x;

  - platform: modbus_controller
    modbus_controller_id: inverter
    id: output_pump_stop
    address: 0x2000
    register_type: holding
    value_type: U_WORD
    write_lambda: |-
      payload.push_back(0x0006); // 6 = Stop
      return x;

# --- HOME ASSISTANT ENTITIES ---
switch:
  - platform: template
    name: "Pump Operation"
    id: pump_switch
    optimistic: true
    icon: "mdi:pump"
    turn_on_action:
      - output.turn_on: output_pump_start
    turn_off_action:
      - output.turn_on: output_pump_stop

number:
  - platform: template
    name: "Target Frequency"
    id: target_freq
    min_value: 35.0
    max_value: 50.0
    step: 0.1
    unit_of_measurement: "Hz"
    initial_value: 35.0
    optimistic: true
    set_action:
      - lambda: |-
          esphome::modbus_controller::ModbusController *controller = id(inverter);
          uint16_t value = static_cast<uint16_t>((x / ${vfd_max_frequency_hz}) * 10000.0f);
          auto command = esphome::modbus_controller::ModbusCommandItem::create_write_single_command(controller, 0x1000, value);
          controller->queue_command(command);
      - logger.log:
          format: "Target frequency set to %.2f Hz"
          args: [ 'x' ]