Skip to content

ODRFID-485 (Modbus Firmware)

The device accepts commands and sends a reply via RS485 interface using the Modbus RTU protocol

An AT command set recognized by the device follows the CDC device firmware as close as possible.

The device understands a subset of the Modbus RTU protocol. The supported operations are:

  • Read Input Registers (function code 4)
  • Read Holding Registers (function code 3)
  • Preset Single Holding Register (function code 6)
  • Preset Multiple Holding Registers (function code 16)
  • All the other function codes are not supported and will raise an exception

Numbering Convention

According to the MODBUS protocol specification, for example, the holding registers occupy the address space 40001 - 49999. However, the transmitted address is the relative one (0 for the 40001, 1 for the 40002, etc.). Here and throughout this document the relative addresses (starting from zero) are used.

Modbus Registers

Input Registers

  • 0 - Returns the size (in bytes) of the internal data pending to be read
  • 1 - Returns the tag presence indicator:

    • 0 - no tag present
    • any other value - a tag is present
    • supported since v3.1. Previous versions will report a protocol exception.
    • SCAN0 - the register holds the result of the last scan operation (AT+i, AT+n, etc.). Please note that the tag might already be absent - the device does not perform scanning on its own in this mode and has no means to detect the tag presence in real time.
    • SCAN2 - a scanning operation is performed each T milliseconds (ref. to the Device Settings). The register holds the result of the last scan operation (updated each T milliseconds). Please note, that after switching from SCAN0 to SCAN2 the master must wait for at least T milliseconds (2 * T is recommended) before querying this register in order to acquire a reliable value.
  • All the other registers are not supported, an attempt to read them will raise an exception

Holding registers

  • 0-125 (0x00 - 0x7D) - The internal data buffer

    • write: send an AT command to the device. The exact starting address is irrelevant (it is recommended to use zero for consistency), as long as the total number of registers holding the AT command fits into this region.
    • read: returns the requested portion of the internal data buffer. In order to find out the amount of valid data pending to be read, query the first input register (address 0). The valid data starts at address 0 and occupies [1st input register value] bytes (i.e. ceil([1st input register value]/2) registers). The device will not check whether the requested internal data is valid or not and will always return the requested number of bytes. The internal data read operation does not clear the pending data, i.e. the value of the 1st input register will remain the same after the read operation.
  • 126 (0x7E) - write any value to this register in order to drop the pending data (the 1st input register will be set to 0). This command is ignored if an inventory scan is in progress, pending data not dropped.

  • 127 (0x7F) - write any value to this register in order to restart the device
  • 128 (0x80) - write any value to this register in order to restart the device and put it into the DFU mode.

Attention

The DFU protocol is not compatible with the Modbus RTU protocol. You will not be able to update the device firmware without disconnecting it from the Modbus line.

  • 130 (0x82) - starting from v2.1 only! (read-only in v2.1, read-write starting from v2.2)

    • read: the size of the last scanned tag UID
    • write: write any value to this register in order to clear (set to zero) registers 130-141
  • 131-141 (0x83 - 0x8D) - starting from v2.1 only! (read-only)

    • 131 - the type of the last scanned tag (ref. Tag Types)
    • 132 - the first byte of the last scanned tag UID
    • 133 - the second byte of the last scanned tag UID
    • ...

Bug

please consult the p.1 of the Errata

  • 143 (0x8F) - starting from v3.1 (write-only) - write the value 0x4242 (16962) to perform a factory reset (the address, the baud rate, the device settings, etc.) and reboot the device.

  • All the other registers are not supported, an attempt to read/write to them will raise an exception. Registers 130-141 are active only in the SCAN2 mode. They will not be updated in the SCAN0 mode.

Command sequence example 1:

The default device address (Modbus slave ID) is 95 (0x5F)

  1. Drop any pending data (you may want to read it first): write 1 to the holding register 126

    >> 5F06007E0000E4AC

    << 5F06007E0000E4AC

  2. Send the AT command (ex. AT+SCAN0): write AT+SCAN0 to the holding registers 0,1,2,3 (i.e. sizeof(AT+SCAN0)==8 divided by 2. Should the command occupy 7 bytes, it should be padded with 1 zero - 0x00)

    >> 5F10000000040841542B5343414E304A48

    << 5F1000000004CCB4

    The device returned a success code (0x10 instead of 0x90 for an exception), therefore there is no need to check for the \r\nOK\r\n (or \r\nERROR\r\n) response and it is not transmitted by the device.

  3. Check that there is no data pending (there should not be any data, this action is shown here for demonstration purposes only)

    >> 5F04000000013CB4

    << 5F0402000010FD

Command sequence example 2:

  1. Drop any pending data (you may want to read it first): write 1 to the holding register 126

    >> 5F06007E0000E4AC

    << 5F06007E0000E4AC

  2. Send the AT command (ex. AT+G?): write AT+G?\0 to the holding registers 0,1,2 (i.e. sizeof(AT+G?)==5 padded with zero (total count 6) divided by 2)

    >> 5F10000000030641542B473F00A682

    << 5F10000000038D76

    The device returned a success code, now we can query the command result

  3. Check the number of bytes pending to be read: read the value of the first input register

    >> 5F04000000013CB4

    << 5F04020009D0FB

    The device reports 9 bytes pending to be read. We need to read 5 holding registers (ceil(9/2) == 5)

  4. Read the pending internal data: read the corresponding number of holding registers

    >> 5F030000000588B7

    << 5F030A0D0A2B473D33330D0A30F147

    Note the garbage (0x30) at the end of data - we have read one extra byte that must be discarded by the processing software. Meaningful data is 9 bytes (0A0D0A2B473D33330D0A, i.e. \r\n+G=33\r\n)

  5. Important: drop the pending data read (this is the same as the 1st step. Whether to clear the data before or after the command is up to the processing software (as long as the internal buffer does not overflow), but either step 1 or step 4 must be executed)

    >> 5F06007E0000E4AC

    << 5F06007E0000E4AC

Port settings

Factory defaults are 115200 baudrate, 8N1 (8 bits, 1 stop bit, no parity), device address 0x5F (95). These settings can be changed via the AT+[ command described below. The new settings are saved in the non-volatile memory and applied after the device reset.

General Frame Format

(This applies to the data send and received via the Preset Holding Registers and Read Holding Registers commands respectively)

  • Host-to-Device data must start with an AT keyword and can end with a carriage-return character (ASCII code 13 decimal, 0x0d hexadecimal, "\r" as C string literal) or zero (0x00) in order to fit data into a number of 16bit registers.

Note

unlike the CDC protocol, the carriage-return character is optional.

Bug

Please consult the p.2 of the Errata

  • Device-to-Host frames start and end with a carriage-return character followed by a line-feed character (ASCII codes 13,10 decimal, 0x0d,0x0a hexadecimal, "\r\n" as C string literal).
  • Device-to-Host response to a Host-to-Device request consists of one or more frames.

    Note: unlike the CDC procotol, the \r\nOK\r\n and \r\nERROR\r\n frames are not transmitted. The success or error code is transmitted in the Modbus reply frame following the Modbus RTU protocol: the MSB of the function code signals the error condition.

  • Do not add any unnecessary white space characters (space, back-space, tab, line-feed, etc.) to the request data, they will not be removed by the command-line parser leading to the "ERROR" response.

For a complete description of the L3 commands, refer to the ODRFID (CDC) API reference. Note that there are no \r\nOK\r\n and \r\nERROR\r\n frames. The differences are listed below.

Inventory scan (all tags)

The command is asynchronous - the scanned tag UIDS will be placed into the buffer (holding registers 0-125) after the scanning process has completed. The device will be unresponsive until while scanning is in progress.

Second LED Control

In addition to the first (green) LED, controlled by the AT+D1... command, this device has the second (red) LED and therefore supports the AT+D2 command.

Syntax:

Request AT+D2=[0|1] Switch the LED
0=off, 1=on
Response Success code as per the Modbus RTU protocol

Output Pin Control

This command controls the state of the output pin OUT2 (open collector, no pull)

Syntax:

Request AT+Y=[0|1] Set the OUT2 state to
0=off (open circuit), 1=on (connected to ground)
Response Success code as per the Modbus RTU protocol

Example

Request AT+Y=1\r OUT2 state is connected to ground
Response Success code as per the Modbus RTU protocol
Request AT+Y=0\r OUT2 state is open circuit
Response Success code as per the Modbus RTU protocol
Request AT+Y?\r Query the OUT2 state
Response +Y=0 OUT2 state is open circuit

Input Pin

(extra command, compared to the CDC variant) This command reports the state of the input pin (if present)

Syntax:

Request AT+y? Request the IN state
Response +y=0 or +y=1 0 - pulled low, 1 - pulled high
OK

UART/RS485 Control

This command queries and sets the UART-related settings (baudrate, bits, parity etc.). The returned values are the ones, saved in the non-volatile memory. They can differ from the actual ones in case they have been altered without a following reboot. The new settings are saved in the non-volatile memory immediately and applied at the next reboot.

Attention

When modifying the UART-related settings using this command, all settings will be written (i.e. internally the AT+P command will be called).

Syntax:

Request AT+[=<a>,<s>,<p>,<b>,<r>,<t>\r write new settings
Response Success code as per the Modbus RTU protocol

The values passed in the request and returned in the reply:

  • <a> - address (1..247), decimal (ATTENTION: hex is not accepted, 95 will be interpreted as 0x5F, not as 0x95)
  • <s> - stop bits
    • 10 - 1 stop bit
    • 15 - 1.5 stop bits
    • 20 - 2 stop bits
  • <p> - parity
    • 0 - none
    • 1 - odd (implemented since v 2.0)
    • 2 - even (implemented since v 2.0)
  • <b> - data bits (only 8 bits mode is supported, any other value will be accepted, but ignored)
  • <r> - baud rate
  • <t> - inter-char timeout

Example:

Request AT+[?\r
Response +[=95,10,0,8,115200,10 115200 8N1, address 0x5F, timeout 10ms

Errata

P.1 Holding registers 131-141

Firmware versions affected v2.1, v2.2
Action Reading any number of holding registers starting from 131
Expected data The tag type and UID
Data received Invalid data
Workaround When reading registers 131 and higher, always issue the Read Holding Registers command (function code 3) with the starting address value 130
Example: Read UID of size 4 from registers 132, 133, 134, 135
WRONG Read 4 holding registers (function code 3, start address 132, number of registers - 4)
CORRECT Read 6 holding registers (function code 3, start address 130, number of registers - 6)

P.2 The CR terminator

Firmware versions affected all versions up to v2.2
Action terminating the AT... command with the \r character
Expected result normal frame processing
Actual result Modbus slave exception
Workaround Do not append the \r character to the frame. If the frame needs padding, pad with one zero byte to make the number of characters even.