Two-axis solar trackersRaspberry PLC 21CANopenControl
Driving a LOVATO VLB3 inverter over CANopen SDO with Python
Moving a heavy solar tracker axis means commanding a motor drive with ramps, direction changes and constant supervision. This example shows CANopen VFD control of a LOVATO VLB3 inverter from the integrated CAN bus of a Raspberry PLC 21, written in Python with the canopen library. Taken from a real two-axis solar tracker deployment, it covers motor parameterization by SDO, run forward, run backward, stop with ramp, frequency setpoints, and live readout of motor current and error codes.
One control word, three commands
The VLB3 exposes its command interface at object 0x400B. Writing 0x0061 to subindex 1 starts the motor forward, 0x0062 reverses it and 0x0060 stops with the configured deceleration ramp. The frequency setpoint goes to subindex 3 in tenths of a hertz, so 250 means 25.0 Hz. Three SDO writes replace an entire relay-and-potentiometer cabinet, and every command travels on the same two wires as the feedback.
Motor parameterization over the bus
Boost, cos phi and nominal voltage/frequency are written once at startup through SDO, straight from the motor nameplate values in the script header. This makes drive replacement trivial: swap the hardware, power up, and the PLC pushes the full motor configuration automatically — no keypad menus and no parameters lost in a cabinet somewhere in the field. The script header becomes the single source of truth for the motor data.
Supervision with current and error readout
During every maneuver the script polls object 0x2D88 for motor current (tenths of an ampere) and 0x603F for the CiA error code. Any non-zero error triggers an immediate stop and raises an exception with the code, so a stalled axis or an undervoltage trip never goes unnoticed. A finally block guarantees the motor is stopped and the bus closed even on a crash.
A snippet from the implementation
Straight from the example as deployed on the Raspberry PLC 21 — copy it freely:
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, driverThe full example is a complete program — wiring header, setup and main loop — ready to adapt to your application.
Frequently asked questions
What CAN bitrate does this setup use?
The example brings up can0 at 125 kbit/s with ip link, which is a robust choice for the cable lengths found inside a tracker. The drive, encoders and PLC must all share the same bitrate.
Do I need the EDS file of the LOVATO VLB3?
Yes. The canopen library loads the drive's object dictionary from the EDS, which lets you address objects like 0x400B by index. LOVATO provides the EDS for the VLB3 series on its website.
Can the Raspberry PLC talk to the drive and the encoders on the same bus?
Yes. CANopen is multi-drop, so the VLB3 (node 3) and the two encoders (nodes 4 and 5) share the same twisted pair, each with a unique node ID and proper termination at both ends.