This is a HAL (Hardware Abstraction Layer) driver for LinuxCNC that implements a Modbus TCP slave, allowing external systems to read and write LinuxCNC HAL pins via Modbus protocol.
- Modbus TCP Server: Listens on configurable TCP ports
- Multiple Data Types: Supports various Modbus register types:
- Holding Registers (read/write): 16-bit signed/unsigned, 32-bit signed/unsigned, float
- Input Registers (read-only): 16-bit signed/unsigned, 32-bit signed/unsigned, float
- Coils (read/write): Digital outputs
- Discrete Inputs (read-only): Digital inputs
- Bit Mapping: Individual bits within registers can be mapped to separate HAL pins
- Byte/Word Swapping: Configurable endianness handling
- XML Configuration: Easy setup through XML configuration files
- LinuxCNC installed and configured
- Development packages:
libexpat1-dev,linuxcnc-dev(or equivalent) - GCC compiler
- Make build system
-
Clone or download the source code
git clone <repository-url> cd linuxcnc-mbslave
-
Build the driver
make
-
Install the driver
sudo make install
This installs the
mbslavebinary to your LinuxCNC installation directory (typically/usr/binor~/linuxcnc-dev/bin).
If available, you can install using:
sudo dpkg -i linuxcnc-mbslave_*.deb
sudo apt-get install -f # Install dependencies if neededThe XML configuration file should be placed in one of these standard locations:
~/linuxcnc/configs/your-machine-name/mbslave-config.xml
Examples:
~/linuxcnc/configs/mill/mbslave-config.xml~/linuxcnc/configs/lathe/mbslave-config.xml
/etc/linuxcnc/mbslave-config.xml
~/linuxcnc/configs/your-machine-name/modbus/mbslave-config.xml
Copy the provided example:
cp examples/mbslave-conf.xml ~/linuxcnc/configs/your-machine-name/mbslave-config.xmlCreate an XML configuration file (e.g., mbslave-config.xml) to define your Modbus slave setup:
<modbusSlaves>
<modbusSlave name="mbslave">
<tcpListener port="1502"/>
<!-- Holding Registers (Read/Write) starting at address 3000 -->
<holdingRegisters start="3000">
<pin name="spindle-speed" type="s16"/>
<pin name="feed-rate" type="u16"/>
<pin name="position-x" type="float"/>
<pin name="control-word" type="u32"/>
<!-- Bit-mapped register -->
<bitRegister>
<pin name="enable-bit" bit="0"/>
<pin name="ready-bit" bit="1"/>
<pin name="alarm-bit" bit="2"/>
</bitRegister>
</holdingRegisters>
<!-- Input Registers (Read-Only) starting at address 5000 -->
<inputRegisters start="5000">
<pin name="actual-position" type="float"/>
<pin name="status-word" type="u16"/>
</inputRegisters>
<!-- Digital Inputs starting at address 1000 -->
<inputs start="1000">
<pin name="home-switch"/>
<pin name="limit-switch"/>
</inputs>
<!-- Digital Outputs (Coils) starting at address 2000 -->
<coils start="2000">
<pin name="coolant-on"/>
<pin name="spindle-enable"/>
</coils>
</modbusSlave>
</modbusSlaves>- s16: 16-bit signed integer (-32768 to 32767)
- u16: 16-bit unsigned integer (0 to 65535)
- s32: 32-bit signed integer (uses 2 Modbus registers)
- u32: 32-bit unsigned integer (uses 2 Modbus registers)
- float: 32-bit floating point (uses 2 Modbus registers)
- byteswap: Swap bytes within each 16-bit word (
byteswap="true") - wordswap: Swap word order for 32-bit values (
wordswap="true")
-
Load in HAL configuration file (
.halfile):# Load the Modbus slave component loadusr -W mbslave ~/linuxcnc/configs/your-machine-name/mbslave-config.xml -
Connect HAL pins in your HAL file:
# Connect Modbus pins to your LinuxCNC HAL pins net spindle-speed-cmd mbslave.mbslave.spindle-speed => spindle.0.speed-in net coolant-enable mbslave.mbslave.coolant-on => iocontrol.0.coolant-flood
You can also run the driver manually for testing:
mbslave ~/linuxcnc/configs/your-machine-name/mbslave-config.xmlHAL pins are named using the pattern: mbslave.<slave-name>.<pin-name>
For the example configuration above:
mbslave.mbslave.spindle-speedmbslave.mbslave.feed-ratembslave.mbslave.enable-bit- etc.
You can test the Modbus connection using various tools:
# Read holding registers starting at address 3000
mbpoll -a 1 -r 3000 -c 5 -t 4 127.0.0.1:1502
# Write to holding register
mbpoll -a 1 -r 3000 -t 4:int16 127.0.0.1:1502 1234from pymodbus.client.sync import ModbusTcpClient
client = ModbusTcpClient('127.0.0.1', port=1502)
result = client.read_holding_registers(3000, 5, unit=1)
print(result.registers)
client.close()Basic configuration for machine status monitoring:
<modbusSlaves>
<modbusSlave name="status">
<tcpListener port="1502"/>
<inputRegisters start="0">
<pin name="x-pos" type="float"/>
<pin name="y-pos" type="float"/>
<pin name="z-pos" type="float"/>
</inputRegisters>
<inputs start="0">
<pin name="machine-on"/>
<pin name="program-running"/>
</inputs>
</modbusSlave>
</modbusSlaves>Configuration with control capabilities:
<modbusSlaves>
<modbusSlave name="control">
<tcpListener port="1502"/>
<holdingRegisters start="100">
<pin name="jog-speed" type="float"/>
<pin name="spindle-override" type="u16"/>
</holdingRegisters>
<coils start="0">
<pin name="estop-reset"/>
<pin name="cycle-start"/>
<pin name="feed-hold"/>
</coils>
</modbusSlave>
</modbusSlaves>-
Port already in use
- Check if another process is using the configured port
- Use
netstat -tln | grep 1502to check
-
HAL component fails to load
- Verify LinuxCNC is running and HAL is available
- Check XML configuration syntax
- Ensure all required dependencies are installed
-
Cannot connect from Modbus client
- Verify firewall settings
- Test with local connection first (
127.0.0.1) - Check if the port is accessible:
telnet 127.0.0.1 1502
Add debug output by running with verbose logging (if implemented) or check system logs:
dmesg | grep mbslave
journalctl -fThe project uses a standard Make build system:
# Configure the build (detects LinuxCNC installation)
make configure
# Build all components
make all
# Clean build artifacts
make clean
# Install to system
make installsrc/- Source code filesexamples/- Example configuration filesdebian/- Debian packaging filesMakefile- Main build configurationconfigure.mk- Build system configuration
This software is released under the terms specified in the LICENSE file.
- Current version: 0.9.0 (Initial release)
- See TODO file for planned improvements
- See ChangeLog for version history
- Review the ChangeLog for version history
- Check the TODO file for known limitations
- File issues or questions with the project maintainers