In response to conversations we’ve had with industrial automation pros, OnLogic has begun carrying a selection of RS485-connected Modbus-compatible data acquisition and digital I/O modules for monitoring and automation. Data Acquisition Modules can be used in a wide range of applications and this guide is intended as a quick primer to installation and setup.
What is a DAQ Module?
The EX9055D-M is a digital I/O module with 8 digital isolated inputs and outputs. The input signals are electrically isolated from the core module circuitry to protect the module; in the event of high voltage or short circuit, this isolation prevents damage to the device. The open-collector outputs each provide the user with one end (the collector) of a transistor to use as a switched power source.
To help get you started, we’ve set up this simple example to demonstrate some of the I/O module functionality and explain how to configure software to communicate with it.
Wiring a DAQ Module
The simplest use for the digital inputs is as monitors for simple switches – in this example we’ll use a few push-buttons. In real world applications, you might use the inputs to monitor anything “digital” – anything that only has two states. You might use a digital input to see if a door is open, or a light is on, or if a system is powered. We use a similar setup as part of OnLogic’s building automation system; it monitors doors, water sensors, and mechanical systems to provide an extra layer of security for sensitive areas.
For a switch-style connection to an input (like the button in this example), the wiring is simple:
Later, when reading the input status, it will show “high” when the switch is open (as pictured) and “low” when the switch is closed.
You will need to make two connections to drive the outputs: one from an external power supply (10-40V), and the other one from the device you’re trying to power. The output circuitry acts as a switch. Depending on your unique requirements, you may or may not use a separate power supply from the one powering the module itself; in this case, we’ll share the power supply across the two power inputs. When the module receives the output “high” command, the load receives power. When it is set “low”, the load is shut off.
Finally, you’ll need to connect a power supply for the module itself (+Vs and GND), and a 2-wire RS485 connection to communicate with. Be sure to note which of your system’s serial ports you’re using; you’ll need to know later on.
Software Setup for DAQ Modules
Each Modbus-compatible module operates in two modes, “Normal” (or ASCII) mode, and “Modbus” mode. By default, Modbus-compatible modules come configured to start in Modbus mode. However, Normal mode can be easier to get off the ground quickly, so we’ll start there.
To run the module in Normal mode, set the switch on the rear of the module to ON while the device is disconnected from power. If your module does not have a switch on the rear, you will need to find the INIT pin and connect it to ground while power is disconnected. When you connect power to the module, it will boot in INIT mode, which allows you to change the module configuration, including its operating mode. While in INIT mode, modules respond to Normal mode (ASCII) commands. Instead of reconfiguring the device, we can just run it in INIT mode and save a little time.
Normal (ASCII) Command Structure
Each ASCII command shares the same basic structure:
Delimiter, Address, Command, [Data], Carriage Return
Unless otherwise specified, the address and data are sent in ASCII hex (ie, address 0 is “00”, address 8 is “08”, and address 90 is “5A”). For example, if we want to ask the module what its name is, we send:
(Delimiter: $, Address: 00, Command: M, Carriage Return: \r)
The module will reply with a packet containing its name. In our case, it looks like: !009055M. Most replies will begin with a success/failure character (usually ! or ?), then the address, then whatever data was requested. When in INIT mode, the module address is always 00.
Since all commands are sent in ASCII and completed with a carriage return, you can actually use a serial console (PuTTY, for example) to communicate with a “Normal-mode” module – it’s not something you’d want to do in a production environment, but it can be useful for troubleshooting. The example code included on each DAQ module product page also has a terminal function you can use from a command prompt (see code documentation for details).
To communicate with the module in the real world, you’ll want to use something a little more efficient than hand-typed commands, of course. We’ll run through a few commands here, and the example code linked above has a short block for each module we distribute.
To use the ASCII commands, in Python (either the interpreter console or a stand-alone program), you’ll first need to open the serial port you connected to the module. In Windows, the port name will be similar to “COM4”; in Linux, it’s usually name something like “/dev/ttyS2”.
from serial import Serial
Port = Serial(“COM4”, baudrate=9600, timeout=0.1)
The default baudrate for the modules is 9600, so we want to make sure that’s set correctly. We set the timeout so that read commands will complete quickly, even if we don’t get the expected amount of data (generally, this will occur if there is an error).
Now, you can send commands as needed and read the reply using the serial functions read and write:
You should see the same reply in the example above (!009055M).
To read the status of the IO, we’ll run:
The reply contains the status of all the outputs and inputs – if no input is connected to ground, the status reply should be !00FF00. ! for success, 00 for output status, FF for the input status, and a trailing 00. Input and output status are both represented as a single-byte hex value describing state. If we look at input status (FF), each of the inputs (DI0 to DI7) correspond to a single bit in the status byte, with DI0 at bit 0, DI1 at bit 1, etc. If you press and hold one of the buttons and run the read command again, you’ll see the returned status change depending on which button you pressed.The same applies to the outputs (except in reverse, 1 is on, 0 is off). If we send the module an output command:
(Delimiter: #, address: 00, channel: 00, state: 01)
We should see DO0 turn on. If we change the state value to “10” (“#000010\r”), we should see DO0 shut off and DO4 turn on, etc.
With a little bit of additional logic, you can set a short loop to watch the inputs and take action when one of them is activated. You’d need a very fast (and very inefficient!) loop to monitor the inputs well, though, so instead of checking input state, you can use the Read Latch Status command “$00L0\r”. When an input is brought “low”, the event is recorded (“latched”) separately so that if you miss the event itself, you can still determine that it occurred and trigger a response. You’ll then clear the latched input to be ready for the next event using the Clear Latched Input command: “$00C\r”.
In this short program, you can see the read/clear latch status in action, monitoring the buttons wired up for this example. In this more complex version, we add a few convenience functions and work a bit more with the outputs.
Modbus Command Structure
Modbus is a communication protocol created by Modicon in the 1970s for use with their devices. Due to its simplicity and robustness, it came to be used more broadly, and is now one of a few major communication protocols in use by the industry.
Each Modbus-enabled module takes a set of standardized Modbus commands as documented on the Modbus website. There is also more device-specific information available from each DAQ module’s own documentation. The Modbus I/O modules available from OnLogic all ship in Modbus mode by default. If you were just in ASCII mode while following this document, you’ll need to switch back to Modbus mode by unplugging the INIT wire or flipping the INIT switch, and then reboot the device.
Commands are sent as raw byte values, so you won’t be able to use a standard serial terminal. However, we have included a Modbus pseudo-terminal in the product page example code for each module so that you can test and troubleshoot (it will automatically calculate the checksum for you as well).
Each modbus command has a single command-code byte and associated data, followed by a two-byte checksum.
Checksum calculation is a many-step process:
- Take 0xFFFF, XOR with the first byte in packet
- If LSB of result is 1, you will need to XOR a second value after performing step 3
- Shift result 1 place right.
- If the LSB at step 2 was 1, XOR the result with 0xA001
- Repeat steps 2-4 7 more times
- Repeat steps 2-5 for all bytes in packet
- The resulting CRC is 2 bytes. When sending the packet, the least significant BYTE is sent first, followed by the most significant BYTE.
For example, to read the status of all inputs, you send the byte values for:
Address, Command code, Starting channel (upper byte), Starting channel (lower byte), Number of channels to read (upper byte), Number of channels to read (lower byte), CRC (lower), CRC (upper)
In practice, that sequence looks like this:
0x01 0x02 0x00 0x00 0x00 0x08 0x79 0xCC
|0x01||0x02||0x00 0x00||0x00 0x08||0x79 0xCC|
|Address||Command Code||Starting channel||# of channels read||Checksum|
When sent as part of a Python program, you can format it as a list:
port.write([0x01, 0x02, 0x00, 0x00, 0x00, 0x08, 0x79, 0xCC])
The response back will be in similar format [Address, Command code, Byte count, Input value, CRC (lower), CRC (upper)]:
0x01 0x02 0x01 0xFF 0xFF 0xC8
You can then recover the input value (0xFF) and further process it as desired. See the Modbus block in the product’s example code for more information.
While this may seem like a complex process, in practice DAQ modules offer a a lot of valuable advantages and flexibility. With a bit of experience, you’ll be analyzing and reacting to data efficiently and effectively.
For help in identifying the right hardware configuration for your specific application, contact one of our solutions specialists.