📜 ⬆️ ⬇️

Arduino & OpenHAB

In the previous article, we met with the industry standard Modbus and embedded its support in the Arduino, it remains to connect the device with the platform OpenHAB.

This time we will learn how to configure the plugin and the OpenHAB interface to work with the device, the basics of addressing and debugging the Modbus protocol. The paper presents an experiment with the source code of the plug-in, and on the page vk.com/myremoter you can discuss the open controller of the smart home, which we will use in the following experiments.

But let's see once again, what advantages will the use of the Modbus standard give us?
Modern house - a complex engineering structure, where lighting control is not the most important function. In addition to sensors in the house install air conditioning and ventilation systems, heating control, drainage pumps and wells. Such tasks can be assigned to a special or industrial controller, in this case the Modbus protocol will help to unite all engineering systems into a single network, and a simple and inexpensive controller running on the same bus will add additional control and functionality, saving a lot of money. In favor of this low requirements for equipment, openness of the standard, the mass character of its use, although, perhaps, the main secret of the popularity of Modbus is its flexibility in connecting programs and equipment.
')
Well, it's time to get to work.

Install OpenHAB, configurator and null modem connection emulator
Let's look at the documentation , open the download page and download the Runtime core and Demo setup, unpack them in C: \ openhab, then download the openHAB Designer and unpack it in C: \ openhab \ designer. Check for Java by running java –version, if there is no Java, follow the instructions for installing it.
Launch OpenHAB by running C: \ openhab \ start.bat and open the web interface using the link localhost : 8080 / openhab.app? Sitemap = demo

Now download and install com0com , run Setup from the program menu, we look for what serial ports a virtual pair is created for (I have this COM7 + COM8). We use them to communicate OpenHAB and simulator.

Then install the Modbus Tcp Binding plugin which will allow OpenHAB to interact with modbus devices. Open the download page, download the Addons, unzip org.openhab.binding.modbus-1.6.2.jar to the C: \ openhab \ addons folder.

After this, we configure the connection of the plug-in with the device, for this we will run the OpenHAB configurator and open the openhab_default.cfg file. Find the Modbus Binding section and add the following information to the end of this section, then save the file.

modbus:serial.slave1.connection=COM7 modbus:serial.slave1.id=1 modbus:serial.slave1.start=0 modbus:serial.slave1.length=4 modbus:serial.slave1.type=discrete modbus:serial.slave2.connection=COM7 modbus:serial.slave2.id=1 modbus:serial.slave2.start=16 modbus:serial.slave2.length=4 modbus:serial.slave2.type=coil modbus:serial.slave3.connection=COM7 modbus:serial.slave3.id=1 modbus:serial.slave3.start=2 modbus:serial.slave3.length=3 modbus:serial.slave3.type=input modbus:serial.slave4.connection=COM7 modbus:serial.slave4.id=1 modbus:serial.slave4.start=5 modbus:serial.slave4.length=3 modbus:serial.slave4.type=holding 

The settings contain 4 groups of addresses associated with the registers of the device. Each group contains the serial port number, the modbus controller address, the modbus address of the first register in the group, the number of registers in the group and the type of these registers. Address groups will become the link between the OpenHAB elements and the device.

Now we set up the OpenHAB connection with the device registers. Open the demo.items file in the configurator and add the following code to the end of this file:

 Group FF_Modbus "Modbus" (All) Contact MB_DT0 "DT0 [MAP(en.map):%s]" (FF_Modbus){modbus="slave1:0"} Contact MB_DT1 "DT1 [MAP(en.map):%s]" (FF_Modbus){modbus="slave1:1"} Contact MB_DT2 "DT2 [MAP(en.map):%s]" (FF_Modbus){modbus="slave1:2"} Contact MB_BTN "BTN [MAP(en.map):%s]" (FF_Modbus){modbus="slave1:3"} Switch MB_CL16 "CL16" (FF_Modbus){modbus="slave2:0"} Switch MB_CL17 "CL17" (FF_Modbus){modbus="slave2:1"} Switch MB_CL18 "CL18" (FF_Modbus){modbus="slave2:2"} Switch MB_LED "LED" (FF_Modbus){modbus="slave2:3"} Number MB_INPT2 "INPT2[%d]" (FF_Modbus){modbus="slave3:0"} Number MB_INPT3 "INPT3[%d]" (FF_Modbus){modbus="slave3:1"} Number MB_INPT4 "INPT4[%d]" (FF_Modbus){modbus="slave3:2"} Number MB_HOLD5 "HOLD5[%d]" (FF_Modbus){modbus="slave4:0"} Number MB_HOLD6 "HOLD6[%d]" (FF_Modbus){modbus="slave4:1"} Number MB_HOLD7 "HOLD7[%d]" (FF_Modbus){modbus="slave4:2"} 

The first line defines the FF_Modbus group which will combine the added elements. Each element is defined by its type, name, text format, list of groups in which it is composed and settings for communication with the device. We used elements of three types - Contact, Switch, Number, and in the communication settings we specified the type (modbus), the name of one of the groups specified in the plugin settings (for example, slave1) and the register sequence number in this group.

The following table will help us to visualize the relationship between the registers of the controller, regular and logical addresses of Modbus, groups of registers in the settings of the plugin and OpenHAB elements.



It's time to display our items in the interface. Open the demo.sitemap file in the configurator and add a description of two frames to it:

  Frame { Group item=FF_Modbus icon="attic" } Frame { Text item= MB_DT0 Text item= MB_DT1 Text item= MB_DT2 Text item= MB_BTN Switch item= MB_CL16 Switch item= MB_CL17 Switch item= MB_CL18 Switch item= MB_LED Text item= MB_INPT2 Text item= MB_INPT3 Text item= MB_INPT4 Setpoint item= MB_HOLD5 minValue=0 maxValue=50 step=1 Setpoint item= MB_HOLD6 minValue=0 maxValue=500 step=10 Setpoint item= MB_HOLD7 minValue=0 maxValue=500 step=100 } 

The first frame contains the FF_Modbus group, it will display all the elements included in it.
In the second frame, each element has individual interface settings. The settings indicate the type of the widget, the connection with the element and in some cases additional parameters. You can familiarize yourself with the principles of building an OpenHAB interface in this description .



Let's try to test the created configuration on the simulator.

Download the RSsim 8.19 simulator from the download page and unpack it into the C: \ arduino folder. The program has an interesting feature, it is free, and its source codes are available, but it also requires registration. The instructions say that for registration you need to open the About MOD_RSsim window, click the “Register” button, enter “Completely Free” in the registration name field, and “66840713” in the registration key field.

Run the simulator, perform registration, in the Port field, select MODBUS RS-232, press the button , in the settings dialog of the serial port, we specify the second port of the virtual pair (for example, COM8), the speed is 9600, 1 stop bit, there is no parity.





We launch OpenHAB and open the web interface, click the switches and see how the values ​​in the Coil table of the simulator change, then open the Digital Inputs table in the simulator, change the values ​​in the registers with addresses 10001-10004 and monitor the change in the state of contacts in the web interface. After that, open the Analog Inputs table, enter the values ​​in the registers 30003-30005 and monitor the change of values ​​in the fields INPT2- INPT4. And finally, we set the values ​​in the fields of HOLD5-HOLD7 and check their correspondence in the registers 40006-40008 of the simulator. You have already noticed that logical addressing is used in the simulator. In order that finally not to get confused in registers, addresses and elements use the previously given table.

At first glance, everything worked out, but if you look closely at the OpenHAB console, it is noticeable that with each controller poll, the plugin sends an event to the bus, even if nothing has changed. It seems that to solve this problem will have to study and modify the plugin.

Solution Description
Brief information on the architecture of the OpenHAB plugin can be found here .
The development environment issues for OpenHAB are covered in this tutorial .

In the process of work, the changes touched two ModbusGenericBindingProvider.java and ModbusBinding.java files.

ModbusGenericBindingProvider contains a nested ModbusBindingConfig class that stores the configuration of the element, create a mechanism for saving the current state in it.

Add a variable to this class.
 private State mb_itemState = UnDefType.NULL; 

Fix the function code
 State getItemState() { return mb_itemState; } 

And add a function
 void setItemState(State state) { mb_itemState = state; } 

The ModbusBinding class contains two methods:
 protected void internalUpdateItem(String slaveName, InputRegister[] registers, String itemName) 
Which sends an update event to the OpenHAB bus for data of type holding.

 protected void internalUpdateItem(String slaveName, BitVector coils, String itemName) 
Which sends an update event to the OpenHAB bus for coil data.

These methods are invoked every time after the slave is polled. We will correct their code so that we can send an event only if the data has changed.
 protected void internalUpdateItem(String slaveName, InputRegister[] registers,String itemName) { for (ModbusBindingProvider provider : providers) { if ( !provider.providesBindingFor(itemName) ) { continue; } ModbusBindingConfig config = provider.getConfig(itemName); if ( !config.slaveName.equals(slaveName)) { continue; } String slaveValueType = modbusSlaves.get(slaveName).getValueType(); double rawDataMultiplier = modbusSlaves.get(slaveName).getRawDataMultiplier(); State newState = extractStateFromRegisters(registers, config.readRegister, slaveValueType); /* receive data manipulation */ if (config.getItem() instanceof SwitchItem) { newState = newState.equals(DecimalType.ZERO) ? OnOffType.OFF : OnOffType.ON; } if (( rawDataMultiplier != 1 ) && (config.getItem() instanceof NumberItem)) { double tmpValue = (double)((DecimalType)newState).doubleValue() * rawDataMultiplier; newState = new DecimalType( String.valueOf(tmpValue) ); } State currentState = config.getItemState(); if (! newState.equals(currentState)) { eventPublisher.postUpdate(itemName, newState); config.setItemState(newState); //!!! } } } protected void internalUpdateItem(String slaveName, BitVector coils, String itemName) { for (ModbusBindingProvider provider : providers) { if (provider.providesBindingFor(itemName)) { ModbusBindingConfig config = provider.getConfig(itemName); if (config.slaveName.equals(slaveName)) { boolean state = coils.getBit(config.readRegister); State currentState = provider.getConfig(itemName).getItemState(); State newState = provider.getConfig(itemName).translateBoolean2State(state); if (!newState.equals(currentState)) { eventPublisher.postUpdate(itemName, newState); config.setItemState(newState); //!!! } } } } } 


The revised plugin, along with the source code, is located in this repository .
Stop OpenHAB, download and copy org.openhab.binding.modbus-1.6.2.jar to the C: \ openhab \ addons folder. We start C: \ openhab \ start.bat, open the web interface and check the work again. Now everything is fine, events appear only when the value of the corresponding register changes.

The only thing that remains is to check OpenHAB's interaction directly with the controller from the previous article .
We connect the controller's USB cable to the computer, look at which port the adapter is on (for example, COM6), stop OpenHAB, open the openhab_default.cfg file in the configurator, in the Modbus Binding section, in the communication parameters for each group of registers, we fix the port number (for example, modbus: serial.slave1.connection = COM6). Save the file, run OpenHAB and open the web interface. Let's try changing the value in the fields HOLD5 ... HOLD7 and L16 ... L18, the value in the corresponding field INPT2..INPT4 and DT0..DT2 should change, then click on the layout button, the value in the BTN field should change, click on the LED field , at the same time the LED should light up or go out.

What we received as a result of our work:
1. docked the modbus device with the OpenHAB platform;
2. got acquainted with the principles of building the interface in OpenHAB;
3. We got acquainted with the internal structure of the plug-in; this made it possible to correct inaccuracies in its work.

Findings:
Based on the Arduino controller and the OpenHAB platform, it is not difficult to create a software and hardware solution for automation, for example, in the Smart Home system. For further practical experiments we will try to determine the main functionality and requirements for the controller and the system as a whole. To discuss this issue, the open project page vk.com/myremoter is created .

Source: https://habr.com/ru/post/252555/


All Articles