Configuring Siemens RF1060R on SIMATIC IOT2040 Gateway

David Krause13 min read
Sensor IntegrationSiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Overview

Engineers integrating the SIMATIC RF1060R UHF RFID reader with the SIMATIC IOT2040 gateway frequently encounter two distinct failure modes: USB enumeration succeeds (the device appears as /dev/usb/hiddev0 and is listed by lspci) but no application data is returned, or RS232/RS485 communication appears active at the physical layer yet the reader does not respond to host commands. The root cause in most cases is a mismatch between the host-side driver stack and the embedded Baltech reader module, combined with a missing or misconfigured serial protocol profile inside Node-RED on the IOT2040.

The Windows C# example from the RF1060R documentation works on Win10 because the Baltech USB HID driver is installed and the bundled library transparently converts HID reports into the Baltech command set. The IOT2040 ships with a Yocto/Poky-based image that exposes the device as a generic HID device but does not include the Baltech userspace library, so application data is never decoded. The reliable remediation path is to migrate the integration to the RF1060R's RS232 or RS485 interface and address the reader through a Node-RED serial flow that speaks either the documented SIMATIC ASCII protocol or Modbus RTU.

Safety and ESD notice: Always power down the IOT2040 and the RF1060R before changing cable connections. The RF1060R's USB and serial interfaces share a common ground; do not connect a shielded USB cable with a separate chassis ground while the serial shield is also bonded at the IOT2040 end, or you will create a ground loop that can damage the Baltech module's RS232 transceiver.

IOT2040 Hardware and Interface Inventory

The SIMATIC IOT2040 is an Intel Quark x1020-based IoT gateway in DIN-rail format, designed to bridge field-level devices to IT/cloud endpoints. The relevant interfaces for the RF1060R integration are summarized in the table below.

Interface Quantity Specification Notes
Ethernet 2 10/100 Mbps, RJ45 Independent MACs, switchable
USB 2 USB 2.0 Type A Combined current limit 500 mA
Serial (X21) 1 RS232 / RS422 / RS485 software-selectable DB9 male, non-isolated
Arduino shield 2 20-pin digital/analog headers 3.3 V logic level
Storage 1 microSD slot Used for the Example Image

The single serial port X21 is a multiprotocol transceiver driven by the MAX3160 or equivalent. The protocol is selected through a device-tree overlay shipped with the Siemens Example Image. The default configuration after a fresh image write is RS232, 9600 baud, 8N1, no flow control. This default is not compatible with the RF1060R's ASCII protocol (19200 baud, 8N1) or with its Modbus RTU profile (19200 or 38400 baud, 8E1) without reconfiguration.

RF1060R Hardware and Interface Inventory

The SIMATIC RF1060R is a UHF RFID reader for the 865–928 MHz band, intended for industrial gate and conveyor applications. It exposes three electrical interfaces plus an antenna port. The integration-relevant interfaces are:

Interface Connector Protocol Default Parameters
USB USB 2.0 Type B Baltech HID (vendor-specific) HID reports, 64-byte payload
RS232 DB9 male (DTE) SIMATIC ASCII or Modbus RTU 19200 8N1 / 19200 8E1
RS485 DB9 (4-wire full duplex, optionally 2-wire half) SIMATIC ASCII or Modbus RTU 19200 8E1, address 1

Internally, the RF1060R is implemented around a Baltech reader module. The USB path talks directly to the Baltech command set; the serial path runs a Siemens-firmware converter that maps Baltech frames onto either a framed ASCII transport or Modbus RTU holding/input registers. The two paths are mutually exclusive at any one time; the active path is selected by a DIP switch on the back of the reader or, in firmware revisions 1.2 and later, by an SOPAS command over the serial interface.

USB Path: Why It Enumerates but Does Not Stream

When the RF1060R is connected to the IOT2040's USB-A port, the Linux kernel logs show the device attaching:

[  312.448] usb 1-1: new full-speed USB device number 3 using ohci-pci
[  312.612] usb 1-1: New USB device found, idVendor=13ad, idProduct=9999, bcdDevice= 1.10
[  312.620] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[  312.640] hid-generic 0003:13AD:9999.0001: hiddev0,hidraw0: USB HID v1.10 Device [Baltech RFID Reader] on usb-0000:00:04.0-1/input0

The kernel creates /dev/usb/hiddev0 and /dev/hidraw0, which is consistent with the symptom reported. The C# example on Windows relies on a vendor DLL (BaltechRF.dll) that issues HID feature reports and decodes input reports through the WinUSB-compatible HID stack. On the IOT2040, no equivalent userspace library is preinstalled. Attempting to read /dev/usb/hiddev0 with cat or with a generic HID client will return only raw interrupt-in transfers but no decoded tag data, because the Baltech command/response protocol requires vendor-specific GET_REPORT and SET_REPORT opcodes that are not exposed by the standard hiddev ioctls.

Three remediation options exist for the USB path:

  1. Port the Baltech library to Yocto and rebuild the IOT2040 image with a Yocto recipe that includes libhidapi-libusb and the Baltech command set. This is the only path that preserves the C# example's logic verbatim and is the recommended approach if you need access to Baltech-specific features such as the air-protocol trace.
  2. Use the SOPAS ETM tool from a Windows host to reflash the RF1060R's USB descriptor so that it enumerates as a CDC-ACM serial device rather than as an HID device. The firmware revision must be at least 1.2 for this to be supported. After the reflash, the IOT2040 will see /dev/ttyACM0 and the Node-RED serial node can be used directly.
  3. Switch to the serial interface and abandon the USB path entirely. This is the simplest and most robust solution and is the focus of the remainder of this article.

Serial Path: RS232 Wiring and DIP Switch Setup

For the serial path, configure the RF1060R DIP switch block S1 to the position corresponding to your chosen interface and protocol. The DIP block has four switches, labeled S1.1 through S1.4:

Switch Function ASCII Protocol Modbus RTU
S1.1 Interface select OFF = RS232, ON = RS485 OFF = RS232, ON = RS485
S1.2 Baud rate OFF = 19200, ON = 9600 OFF = 19200, ON = 38400
S1.3 Parity OFF = None (8N1) ON = Even (8E1)
S1.4 Termination (RS485 only) ON if end of bus ON if end of bus

Wire the IOT2040 X21 DB9 to the RF1060R's DB9 using a straight-through RS232 cable (no crossover). The pinout is:

IOT2040 X21 Pin Signal RF1060R DB9 Pin
2 RXD (out from IOT2040) 2 (TXD from reader)
3 TXD (into IOT2040) 3 (RXD into reader)
5 SGND 5
7 RTS 8 (CTS)
8 CTS 7 (RTS)

If using RS485, wire the IOT2040's X21 pins 4 (TXD+/D+) and 9 (TXD-/D-) to the reader's DB9 pins 4 and 9 respectively. Enable termination (S1.4 = ON) only if the reader is the physical end of the bus. The IOT2040 firmware does not include onboard RS485 termination; add a 120 Ω resistor across pins 4 and 9 at the IOT2040 end if it is the bus end.

IOT2040 Serial Port Configuration

On the IOT2040, the serial port X21 is exposed as /dev/ttyS0 on the Siemens Example Image. The kernel module that drives the multiprotocol transceiver is loaded with a device-tree overlay located in /boot/overlays/. To switch the transceiver to RS485 with even parity, edit /boot/uEnv.txt and set:

dtparam=iocontroller_rs485=on
dtparam=rs485_termination=off

Then reboot. After reboot, verify the transceiver mode with:

dmesg | grep -i max3160

The expected line is:

[    4.221] max3160 spi1.0: MAX3160 configured for RS485 half-duplex

Use stty to configure the line discipline to match the RF1060R's expected parameters. For Modbus RTU at 19200 8E1:

stty -F /dev/ttyS0 19200 cs8 parenb -parodd cstopb -ixon -ixoff -crtscts raw

For ASCII protocol at 19200 8N1, drop the parity settings:

stty -F /dev/ttyS0 19200 cs8 -parenb -cstopb -ixon -ixoff -crtscts raw

Confirm the line settings with stty -F /dev/ttyS0 -a. The reported parenb flag should match the parity you intend; raw mode disables canonical input processing, which is required for binary RTU framing and for ASCII protocol's CR/LF handling.

Node-RED Serial Node Configuration

The Siemens Example Image includes Node-RED with the node-red-node-serialport package preinstalled. To configure the serial node for the RF1060R:

  1. Open the Node-RED editor at http://<iot2040-ip>:1880.
  2. Drag a serial in node from the palette onto the flow.
  3. Click the pencil icon next to the Serial Port field and add a new configuration:
     a. Serial port: /dev/ttyS0
     b. Baud rate: 19200 (or 38400 for Modbus RTU fast profile)
     c. Data bits: 8
     d. Parity: none (ASCII) or even (RTU)
     e. Stop bits: 1
     f. Flow control: false
     g. Split input on: leave blank for RTU; set to \r\n for ASCII framed mode
     h. Deliver: string (ASCII) or buffer (RTU)
  4. Wire a debug node to the serial-in node's output and click Deploy.
  5. Trigger a tag read on the reader; the debug pane should display the ASCII or RTU response frame.
Race condition warning: If the reader is configured for Modbus RTU and the node delivers string payloads, the binary CRC bytes will be silently corrupted by Node-RED's default UTF-8 string conversion. Always select Deliver: buffer and use a function node with msg.payload.toString('hex') to inspect the raw frame during commissioning.

For an end-to-end inventory read in Modbus RTU, use the node-red-contrib-modbus package. Configure a Modbus Read node with:

  • Unit-ID: 1 (default for RF1060R)
  • FC: 04 (Read Input Registers)
  • Address: 0x0000 (tag EPC word 0)
  • Quantity: 12 (96 bits / 12 words; typical EPC length)
  • Poll rate: 1000 ms minimum to respect FCC duty cycle on the US band

ASCII Protocol Framing

When the RF1060R is set to ASCII protocol (DIP S1.3 = OFF, no parity), each command and response is a CR/LF-delimited ASCII string. A typical inventory command and response is:

Tx: REQA<CR><LF>
Rx: EPC,300833B2DDD9014000000096<CR><LF>OK<CR><LF>

The reader also accepts SOPAS ASCII commands in the form sMN <command>. To read firmware version:

Tx: sMN ReadDeviceIdent<CR><LF>
Rx: sRA ReadDeviceIdent,RF1060R,1.2.3,109747997<CR><LF>

For Node-RED parsing, feed the serial-in output to a function node that splits on \r\n and routes the first token to a switch node for command dispatch.

Modbus RTU Framing

In Modbus RTU mode, the RF1060R uses even parity and exposes the following register map (subset):

Address (hex) Register Access Description
0x0000–0x000B EPC words 0–11 FC 04 96-bit EPC payload
0x0100 RSSI FC 04 Signed dBm, last tag
0x0101 Tag count FC 04 Tags in last inventory
0x0200 Trigger FC 05/06 Coil: start inventory
0x0201 Antenna select FC 05/06 Coil: 1 = Ant 1, 2 = Ant 2

The complete register map is in the RF1060R Operating Instructions under section 5.4 "Modbus interface". Always validate the actual firmware behavior with SOPAS ETM before assuming a register is present, because earlier 1.0.x firmware revisions did not implement the antenna select coil.

Troubleshooting Matrix

Symptom Likely Cause Verification Remediation
/dev/usb/hiddev0 present, no data No Baltech userspace library ls -l /dev/hidraw0; check for Baltech .so Switch to serial or build Baltech userspace
Serial silent, no echo on cat /dev/ttyS0 Wrong DIP switch position LED on reader should blink on TX Re-set S1.1/S1.2 to match protocol
Garbled bytes, CRC errors in RTU Parity mismatch stty -F /dev/ttyS0 -a shows parenb opposite of reader Match parity in stty command
Modbus exception 0x02 (illegal address) Register not implemented in firmware Check reader firmware with SOPAS Update firmware to 1.2+ or use ASCII instead
Modbus exception 0x06 (busy) Inventory in progress Poll rate too high Increase poll interval to ≥1000 ms
CRC error 0x07 in raw RTU RS485 collision, termination missing Oscilloscope: see ring on bus end Enable 120 Ω termination at both ends
Node-RED debug shows empty payload String vs buffer mode Inspect msg.payload type in function node Set serial node to "Deliver: buffer"
Tag reads succeed on bench, fail in field Antenna VSWR or interference SOPAS air-protocol trace Re-tune antenna, check cable length < 6 m

Verification Procedure

  1. With the IOT2040 booted and the reader connected, confirm the device tree overlay is loaded: ls /sys/firmware/devicetree/base/soc/spi@1a00/spi_master/spi1/spi1.0/ should show compatible containing maxim,max3160.
  2. Confirm the line settings: stty -F /dev/ttyS0 -a. Verify baud and parity against the DIP switch table above.
  3. Send a query via raw terminal: printf 'REQA\r\n' > /dev/ttyS0; sleep 0.2; xxd < /dev/ttyS0. A 9600 8N1 ASCII reader should reply with a CR/LF-terminated string; an RTU reader will be silent because the host has not sent a CRC-bearing frame.
  4. For RTU, use a Modbus CLI tool such as mbpoll on the IOT2040: mbpoll -m rtu -b 19200 -P even -s 1 -a 1 -r 1 -c 4 -t 4 /dev/ttyS0. A valid response returns four 16-bit words; an exception returns a single byte whose MSB is set.
  5. In Node-RED, deploy a flow with serial-in → debug and confirm the debug pane receives frames at the expected rate when a tag is presented.
  6. End-to-end check: write a tag EPC to a CSV file on the IOT2040 (/home/root/tags.csv) by appending on each inventory hit. Verify the file grows.

Firmware Update Path

If the reader's firmware is below 1.1, the Modbus interface and the CDC-ACM reflash option are not available. Upgrade using SOPAS ETM from a Windows host connected via the serial port at 57600 8N1 in service mode. The service-mode entry is the SOPAS command sMN SetServiceMode 1 followed by a power cycle. The firmware file is distributed by Siemens as part of the RF1060R Service Pack. Always keep the reader on a stable 24 V supply during the update; a brown-out mid-flash bricks the Baltech module and requires a factory return.

Field-Commissioning Checklist

  • Confirm the IOT2040 is at firmware ≥ V2.1.3 of the Example Image; earlier images shipped with Node-RED 0.18, which has known node-red-node-serialport issues on Yocto Quark.
  • Confirm the reader firmware is ≥ 1.2 if Modbus is in use.
  • Verify the antenna VSWR is < 1.5 at the operating frequency using the SOPAS tuning screen; a high VSWR is the single most common cause of intermittent read success in field reports.
  • Set the poll rate to comply with regional UHF regulations: 4 s dwell in the FCC band (US), 0.5 s dwell in the ETSI band (EU).
  • Back up the working configuration with the SOPAS Save to file command after commissioning, and store the file in the IOT2040's /home/root/config/ directory for rapid re-deployment.

Why does the RF1060R enumerate on the IOT2040 USB port but return no data?

The RF1060R exposes a Baltech HID device that the Linux kernel binds to /dev/usb/hiddev0 and /dev/hidraw0. The IOT2040 image does not include the Baltech userspace library that decodes HID reports into tag data, so the application layer sees no payload. The fix is to switch to the serial interface (RS232 or RS485) and address the reader through a Node-RED serial or Modbus flow.

Which serial protocol should I use, ASCII or Modbus RTU?

Use ASCII for human-readable commissioning and for the SOPAS command set. Use Modbus RTU when integrating the IOT2040 into a PLC/SCADA landscape that already speaks Modbus, because it allows register-based access (FC 04 read input registers, FC 05/06 write coils) without parsing variable-length strings. ASCII is 19200 8N1; RTU is 19200 8E1 on unit-ID 1.

What are the default serial parameters after a fresh image write?

The Siemens Example Image leaves X21 at RS232, 9600 baud, 8N1, no flow control. The RF1060R's ASCII protocol uses 19200 8N1 and RTU uses 19200 8E1, so you must reconfigure the port with stty -F /dev/ttyS0 19200 cs8 -parenb -cstopb raw (ASCII) or add parenb (RTU), and adjust the device-tree overlay to select RS485 if applicable.

How do I read multiple Modbus registers without losing bytes in Node-RED?

Set the serial-in node to Deliver: buffer rather than string, otherwise UTF-8 conversion corrupts binary CRC bytes. Use the node-red-contrib-modbus package's Modbus Read node with FC 04 and a quantity of 12 to read a 96-bit EPC; poll at ≥ 1000 ms to avoid Modbus exception 0x06 (slave busy) on slow Quark hardware.

Can the IOT2040 reflash the RF1060R?

Yes, through the serial service mode, but only with a Windows host running SOPAS ETM. The IOT2040 itself cannot host the SOPAS Windows-only flash tool. Switch the reader to service mode with sMN SetServiceMode 1 via a terminal on /dev/ttyS0, cycle power, and perform the flash from a separate PC connected to the reader's serial port.

Back to blog