← Control CANopen de un variador LOVATO VLB3 desde un PLC
Seguidores solares de dos ejesRaspberry PLC 21CANopenControl
Control CANopen de un variador LOVATO VLB3 desde un PLC — ejemplo completo
Controla un variador de frecuencia LOVATO VLB3 por CANopen SDO desde un Raspberry PLC 21 en Python. Marcha, paro, consigna de frecuencia, corriente y errores.
Programa completo y ejecutable para el Raspberry PLC 21 (lovato-vlb3-vfd-canopen-sdo.py): incluye cabecera de conexionado, requisitos y notas de integración.
Descarga el pack completo del proyecto — gratisEste ejemplo + los relacionados + lista de materiales
Vista de solo lectura.
#!/usr/bin/env python3
# -----------------------------------------------------------------------------
# COMPLETE EXAMPLE — LOVATO VLB3 VFD control via CANopen SDO
#
# Device: Raspberry PLC 21 (Industrial Shields), built-in CAN bus (can0)
# Based on: dual-axis solar tracker project
#
# CAN bus / requirements:
# sudo ip link set can0 up type can bitrate 125000
# pip3 install canopen
# EDS file of the LOVATO VLB3 VFD in the same directory (VLB3.eds)
#
# Logic:
# 1. Connect to the can0 bus and register the VFD node (node 3).
# 2. Motor parameterization via SDO: boost, cos φ and nominal
# voltage/frequency, written once at startup.
# 3. Operation via the control word 0x400B sub 1:
# 0x0061 Run Forward · 0x0062 Run Backward · 0x0060 Stop with ramp
# 4. Frequency setpoint in 0x400B sub 3 (tenths of Hz: 250 = 25.0 Hz).
# 5. Monitoring: motor current (0x2D88, tenths of A) and CiA error code
# (0x603F). On error, immediate stop and notification.
# -----------------------------------------------------------------------------
import time
import canopen
CAN_CHANNEL = 'can0'
CAN_BITRATE = 125000
NODE_VFD = 3
EDS_VFD = 'VLB3.eds'
# --- Control word 0x400B sub 1 ------------------------------------------------
CMD_RUN_FWD = 0x0061 # run forward
CMD_RUN_BWD = 0x0062 # run backward
CMD_STOP = 0x0060 # stop with deceleration ramp
# --- Motor parameters (nameplate of the axis motor) ----------------------------
BOOST_PCT = 25 # torque boost at low frequency (%)
COS_PHI_x100 = 76 # cos φ = 0.76
V_NOMINAL_V = 230 # nominal voltage (V)
F_NOMINAL_x10 = 500 # nominal frequency = 50.0 Hz
def connect():
"""Opens the CAN bus and returns (network, VFD node)."""
network = canopen.Network()
network.connect(channel=CAN_CHANNEL, bustype='socketcan',
bitrate=CAN_BITRATE)
driver = network.add_node(NODE_VFD, EDS_VFD)
driver.nmt.state = 'OPERATIONAL'
return network, driver
def parameterize_motor(driver):
"""Writes the motor nameplate parameters via SDO (once at startup)."""
driver.sdo[0x2B12][1].write(BOOST_PCT) # torque boost
driver.sdo[0x2C01][5].write(COS_PHI_x100) # cos φ
driver.sdo[0x2C01][7].write(V_NOMINAL_V) # nominal V
driver.sdo[0x2C01][8].write(F_NOMINAL_x10) # nominal f (x0.1 Hz)
print("VFD parameterized (boost, cos phi, nominal V/f)")
def run(driver, forward=True, frequency_hz=25.0):
"""Starts the motor in the requested direction with the given setpoint."""
driver.sdo[0x400B][3].write(int(frequency_hz * 10)) # setpoint in 0.1 Hz
cmd = CMD_RUN_FWD if forward else CMD_RUN_BWD
driver.sdo[0x400B][1].write(cmd)
direction = "FORWARD" if forward else "BACKWARD"
print(f"Running {direction} at {frequency_hz:.1f} Hz")
def stop(driver):
"""Stop with deceleration ramp."""
driver.sdo[0x400B][1].write(CMD_STOP)
print("Stop with ramp")
def read_current(driver):
"""Motor current in amps (0x2D88 returns tenths of A)."""
return driver.sdo[0x2D88].raw * 0.1
def read_error(driver):
"""CiA 402 error code (0 = no error)."""
return driver.sdo[0x603F].raw
def monitor(driver, seconds):
"""Watches current and error during a maneuver; stops on fault."""
t_end = time.time() + seconds
while time.time() < t_end:
amps = read_current(driver)
err = read_error(driver)
print(f" Motor I = {amps:5.2f} A error = 0x{err:04X}")
if err != 0:
stop(driver)
raise RuntimeError(f"VFD in fault: code 0x{err:04X}")
time.sleep(1)
if __name__ == '__main__':
network, driver = connect()
try:
parameterize_motor(driver)
# Demo maneuver: 10 s forward, stop, 10 s backward, stop.
run(driver, forward=True, frequency_hz=25.0)
monitor(driver, 10)
stop(driver)
time.sleep(3) # wait for the ramp to finish
run(driver, forward=False, frequency_hz=15.0)
monitor(driver, 10)
stop(driver)
finally:
# Whatever happens, the motor ends up stopped and the bus closed.
try:
stop(driver)
except Exception:
pass
network.disconnect()
print("CAN bus closed")
Descarga el pack completo del proyecto — gratisEste ejemplo + los relacionados + lista de materiales