通过RF24Network通过Modbus的OpenHAB无线家用空调控制器


我写了第一篇关于用控制器控制空调的文章之后,仅仅两年多了。在这段时间里,远程控制空调的想法并没有让我离开,而是多次重生。主要条件是空调没有电线。

即,控制器的控制必须是无线的。

背景


第一个原型是Arduino UNO。她接受了UART上的团队,并且知道如何打开和关闭空调。因为连接到工作计算机的arduinka几乎没有实际意义,负责人一直在寻找将后者连接到家庭服务器的机会。从服务器到所有难题的罪魁祸首都没有直接可见性。最大的是在所有同一台工作计算机上都带有LAN的插槽-因为它几乎与空调相对。以太网屏蔽不可用。但是请记住,在zashashnik中的某个地方有一个d-link DSL-2500U dsl调制解调器,该调制解调器已经使用很长时间了,板上只有一个端口。赋予铁杆第二次生命的愿望导致了谷歌搜索,这反过来又奇迹般地导致了一篇文章,将ADSL调制解调器变成Arduino / CraftDuino的以太网屏蔽

向前跳过了创建自定义固件的有趣过程,我仍然设法使调制解调器侦听所需的端口并通过它“转发” UART。因此,在家庭服务器上,我可以发送命令打开/关闭端口到本地调制解调器地址,该地址将转到与其连接的arduino。

但是这篇文章不是关于这个的。最终的解决方案使用Modbus协议和RF24Network无线网络一切都在OpenHAB中控制。


在过去的两年中,我设法从中国订购了许多nishtyak,其中大多数都在等待中。该清单包括NRF24L01 +模块,由少数人购买以进行试验。如果有一天我没有偶然发现一系列文章,他将在壁橱里闲散的走得更远:

博里奇谢谢你!

多亏了他们,我才熟悉Modbus协议。但最重要的是,我为自己找到了OpenHAB-我已经寻找了很长时间。这促使我开始实施长期的想法。

在浏览了文章中的示例之后,我决定尝试使用以太网屏蔽与上述调制解调器分离控制器和服务器。该解决方案使我们能够完成摆在您面前的任务-防护罩和控制器位于台式机上,而无需使用工作计算机,同时,防护罩始终连接到本地网络,并且可以从家庭服务器进行访问。

但是这个决定注定要失败。
ModbusRtu over TCP . modpoll, Arduino & Modbus . — 192.168.1.110 3000 !

OpenHAB. , , Modbus Binding «RTU over TCP». — ModbusRtu c TCP. OpenHAB-(ethernet)--(UART)-.

, ? Item . 1 Item . — . , , TCP Modbus Binding. .. .

Modbus Binding Item' host-port-slaveID .

, . . , .


理念


然后,我终于确定自己需要制造一个可以通过空中操作的控制器。NRF24L01 +模块不应消失!。的确,这至少需要两个控制器-一个起直接作用,第二个起路由器的作用。第二个应该连接到服务器,并通过它与其他服务器进行无线通信。连接到它时,我们指定该包要使用的下级的ID。事实证明,一个串行端口上有许多从设备。是的-这是基于Modbus的无线网络。

顺便说一句,Modbus允许一个主机建立一个网络-许多下属。以及RF24Network-使一切变得无线,甚至在网络节点之间自动路由。

Arduino的库开发


为了实现这样的解决方案,需要花很多时间来修改Modbus-Master-Slave-for-Arduino,以便能够从中继承并重载一些方法。我的实现也已更新(已添加library.properties,库文件分为标头和正文)以适用于最新的Arduino IDE 1.6.5。Arduino

Modbus-over-RF24Network-for-Arduino允许您实现两种可能的行为-代理和从属。示例ModbusRF24Proxy实际上是“路由器”的实现,除了设置必要的引脚外,不需要进行任何修改。
Modbus示例RF24Proxy
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#include <ModbusRtu.h>
#include <ModbusRtuRF24.h>

#define stlPin  13  //     (   Arduino)

// nRF24L01(+) radio attached using Getting Started board 
RF24 radio(9, 10);

// Network uses that radio
RF24Network network(radio);

// Address of our node
const uint16_t this_node = 0;

//  ,   TX
ModbusRF24 proxy(network, 0, 0);
int8_t state = 0;
unsigned long tempus;

void setup() {
    //    
    io_setup();
    //    

    proxy.begin(57600);

    SPI.begin();
    radio.begin();
    network.begin(/*channel*/ 90, /*node address*/ this_node);

    //    100 
    tempus = millis() + 100;
    digitalWrite(stlPin, HIGH);
}

void io_setup() {
    digitalWrite(stlPin, HIGH);
    pinMode(stlPin, OUTPUT);
}

void loop() {

    // Pump the network regularly
    network.update();

    //  
    state = proxy.proxy();

    //      -    50  
    if (state > 4) {
        tempus = millis() + 50;
        digitalWrite(stlPin, HIGH);
    }
    if (millis() > tempus) digitalWrite(stlPin, LOW);
}


路由器或代理使用特殊的构造函数格式:
//  ,   TX
ModbusRF24 proxy(network, 0, 0);

和功能
proxy.proxy();

处理串行端口上的传入数据包,将其发送到RF24Network,从网络接收响应,然后将结果发送回串行端口。

在此实现中,代理的RF24Network地址为零:
// Address of our node
const uint16_t this_node = 0;

-即 这是网络的根设备。如有必要,可以更改代理控制器拓扑中的位置。

Modbus示例RF24从站
Arduino & Modbus:
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#include <ModbusRtu.h>
#include <ModbusRtuRF24.h>

#define ID   1      //  
#define btnPin  2   //  ,   
#define ledPin  7  //   

// nRF24L01(+) radio attached using Getting Started board 
RF24 radio(9, 10);

// Network uses that radio
RF24Network network(radio);

// Address of our node
const uint16_t this_node = ID;

//  
ModbusRF24 slave(network, ID);

//   modbus
uint16_t au16data[11];

void io_setup() {
    digitalWrite(ledPin, LOW);
    pinMode(ledPin, OUTPUT);
    pinMode(btnPin, INPUT);
}

void io_poll() {
    // Coil[1]  Discrete[0]
    au16data[0] = au16data[1];
    //   1.3   
    digitalWrite(ledPin, bitRead(au16data[1], 3));
    //     0.3
    bitWrite(au16data[0], 3, digitalRead(btnPin));
    // Holding[5,6,7]  Input[2,3,4]
    au16data[2] = au16data[5];
    au16data[3] = au16data[6];
    au16data[4] = au16data[7];
    //    
    au16data[8] = slave.getInCnt();
    au16data[9] = slave.getOutCnt();
    au16data[10] = slave.getErrCnt();
}

void setup() {
    //    
    io_setup();

    Serial.begin(57600);
    Serial.println("RF24Network/examples/modbus_slave/");

    SPI.begin();
    radio.begin();
    network.begin(/*channel*/ 90, /*node address*/ this_node);
}

void loop() {

    // Pump the network regularly
    network.update();

    if (network.available()) {
        slave.poll(au16data, 11);
    }
    //    Modbus    
    io_poll();
}



在这种情况下,构造函数已经不同:
//  
ModbusRF24 slave(network, ID);


Modbus寄存器结构


在第一次成功地尝试控制空调的能力之后,我的食欲却增加了。现在这还不够,并且由于我的移动应用程序中具有OpenHAB功能,因此它至少应具有本机控制面板的所有功能。
这意味着这里至少是功能列表:
  • 当前状态指示
  • 打开和关闭空调,各种模式(O 2,电离,静音模式);
  • 当前模式的选择(自动,加热,冷却,排水,风扇);
  • 指示每种模式的温度和风扇速度。对于风扇模式,只有速度;
  • 垂直窗帘设置(自动,0°,15°,30°,45°,60°);
  • 水平窗帘设置(自动,“ | |”,“ / /”,“ / |”,“ | \”,“ \ \”);
  • 时间设置(小时,分钟);
  • 在计时器设置上;
  • 关机定时器设置;
  • 准时设置(小时,分钟);
  • 关机时间设置(小时,分钟);

在开发过程中,寄存器的结构对我来说已经改变了很多次。当前版本在扰流板下方。
Modbus寄存器
TypeByteBitName
Bit RO00CFG_OXYGEN1 —
Bit RO1CFG_ION1 —
Bit RO2CFG_QUIET1 —
Bit RO3CFG_TIMER1 — /
Bit RO4CFG_DELAY1 — /
Bit RO5CFG_SWING1 —
Bit RO6CFG_SWINGH1 —
Bit RO7CFG_SWINGV1 —
Bit RO8CFG_CLOCK1 —
Bit RO9
Bit RO10
Bit RO11CFG_AUTO1 — AUTO
Bit RO12CFG_COOL1 — COOL
Bit RO13CFG_HEAT1 — HEAT
Bit RO14CFG_DRY1 — DRY
Bit RO15CFG_FAN1 — FAN
Integer RO1CFG_TEMP. . : Min + Max*256
Integer RO2CFG_FAN_SPEEDFAN
Bit RO30STATE_POWER:0 — , 1 —
Bit RO1STATE_OXYGEN:0 — , 1 —
Bit RO2STATE_ION:0 — , 1 —
Bit RO3STATE_QUIET:0 — , 1 —
Bit RO4STATE_TIMER:0 — , 1 —
Bit RW8CONTROL_POWER
Bit RW9CONTROL_OXYGEN
Bit RW10CONTROL_ION
Bit RW11CONTROL_QUIET
Integer RO4RTC_HR_MI0x1308
Integer RW5RTCW_HR_MI0x1308
Integer RO6TEMPERATURE1. INT16,
Integer RO7TEMPERATURE2. INT16,
Bit RW80MODE_AUTO
Bit RW1MODE_COOL
Bit RW2MODE_HEAT
Bit RW3MODE_DRY
Bit RW4MODE_FAN
Integer RW9TEMP_AUTOAUTO
Integer RW10TEMP_COOLCOOL
Integer RW11TEMP_HEATHEAT
Integer RW12TEMP_DRYDRY
Integer RW13FAN_AUTOAUTO. 0: Auto
Integer RW14FAN_COOLCOOL. 0: Auto
Integer RW15FAN_HEATHEAT. 0: Auto
Integer RW16FAN_DRYDRY. 0: Auto
Integer RW17FAN_SPEEDFAN. 0: Auto
Bit RW180SWING_AUTO
Bit RW1SWINGV_0
Bit RW2SWINGV_1515°
Bit RW3SWINGV_3030°
Bit RW4SWINGV_4545°
Bit RW5SWINGV_6060°
Bit RW190SWINGH_AUTO
Bit RW1SWINGH_VV|  |
Bit RW2SWINGH_LL/  /
Bit RW3SWINGH_LV/  |
Bit RW4SWINGH_VR|  \
Bit RW5SWINGH_RR\  \
Bit RW200TIMER_ON
Bit RW1TIMER_OFF
Integer RW21TIME_ON_HOUR
Integer RW22TIME_ON_MINUTE
Integer RW23TIME_OFF_HOUR
Integer RW24TIME_OFF_MINUTE
Integer RW25DS18B20_ENV.
Integer RW26DS18B20_NOZ.


寄存器的组织方式是,当控制器启动时,整个数据阵列从EEPROM初始化。
前三个寄存器(CFG_ *)包含功能的配置,它们永不更改,并由EEPROM固件初始化。
寄存器3-7始终显示控制器的当前状态。寄存器3的高位用于改变状态。他们的更改启动了空调的开/关和特殊模式。执行该命令后,该寄存器的低位复制到高位。
寄存器4包含当前控制器时间,可从RTC读取。该值以BCD格式保存,因此当该寄存器以十六进制表示时,将按原样读取时间-12:34为0x1234。
寄存器5用于更改RTC时间。
寄存器6-7包含DS18B20传感器的温度。该值包含一个有符号整数,等于T * 100,即 25.67°C = 2567。最多提供2个传感器,但是通过扩展寄存器表以存储传感器的地址及其温度可以轻松更改数量。
传感器地址的最后2个字节存储在寄存器25-26中。更换传感器时,请重置相应的地址寄存器。当检测到新传感器时,将检查其地址是否在寄存器25-26中。如果地址在表中,则传感器的温度值输入到相应的寄存器6-7中。如果该地址不在表中,并且该表具有零个单元格,则将当前传感器地址写入空闲单元格中。
用户修改后的寄存器8-26将保存在EEPROM中。

腺体


硬件包括以下组件:
  1. Arduino Pro迷你版。
    Arduino Pro Mini NEW
  2. NRF24L01+ — 2.4
  3. LM1117-3.3 — 3.3 NRF24L01+
  4. DS1302 — RTC
  5. 32768 RTC
  6. DS18B20 — . 2
  7. — , ,











通过将光耦合器连接到相应的LED来实现空调的反馈。因此,确保了与空调的电路的电流隔离。通过使用电阻器实验性地选择了光耦合器输入的电流,以使光耦合器的输出打开,并且空调上的主LED的亮度不会降低。

在空调的红外接收器旁边安装了一个红外LED。

该控制器由来自中国奇迹的mini-USB充电供电。从充电盒中移除了中国市电电压触点,并移除了电线。充电本身落在空调机外壳的肠道内,并与输入端220并联。控制器使用常规USB AB电缆连接至充电。

«» Arduino Mega2560 NRF24L01+ LM1117-3.3. 3.3 ( 470*16) . 2560 3.3 , . .
2560 USB 10 .

OpenHAB


Arduino & OpenHAB Modbus Binding, , , . .

Modbus Binding
#
modbus:serial.ac_hall_state.connection=/dev/ttyACM0:57600:8:none:1:rtu
modbus:serial.ac_hall_state.id=1
modbus:serial.ac_hall_state.start=48
modbus:serial.ac_hall_state.length=5
modbus:serial.ac_hall_state.type=discrete

#
modbus:serial.ac_hall_power.connection=/dev/ttyACM0:57600:8:none:1:rtu
modbus:serial.ac_hall_power.id=1
modbus:serial.ac_hall_power.start=56
modbus:serial.ac_hall_power.length=4
modbus:serial.ac_hall_power.type=coil

#
modbus:serial.ac_hall_rtc.connection=/dev/ttyACM0:57600:8:none:1:rtu
modbus:serial.ac_hall_rtc.id=1
modbus:serial.ac_hall_rtc.start=4
modbus:serial.ac_hall_rtc.length=1
modbus:serial.ac_hall_rtc.type=holding

#
modbus:serial.ac_hall_temperature.connection=/dev/ttyACM0:57600:8:none:1:rtu
modbus:serial.ac_hall_temperature.id=1
modbus:serial.ac_hall_temperature.start=6
modbus:serial.ac_hall_temperature.length=2
modbus:serial.ac_hall_temperature.type=holding
modbus:serial.ac_hall_temperature.valuetype=int16

#
modbus:serial.ac_hall_mode.connection=/dev/ttyACM0:57600:8:none:1:rtu
modbus:serial.ac_hall_mode.id=1
modbus:serial.ac_hall_mode.start=8
modbus:serial.ac_hall_mode.length=1
modbus:serial.ac_hall_mode.type=holding

#
modbus:serial.ac_hall_temp.connection=/dev/ttyACM0:57600:8:none:1:rtu
modbus:serial.ac_hall_temp.id=1
modbus:serial.ac_hall_temp.start=9
modbus:serial.ac_hall_temp.length=4
modbus:serial.ac_hall_temp.type=holding

#
modbus:serial.ac_hall_fan.connection=/dev/ttyACM0:57600:8:none:1:rtu
modbus:serial.ac_hall_fan.id=1
modbus:serial.ac_hall_fan.start=13
modbus:serial.ac_hall_fan.length=5
modbus:serial.ac_hall_fan.type=holding

#
modbus:serial.ac_hall_swing.connection=/dev/ttyACM0:57600:8:none:1:rtu
modbus:serial.ac_hall_swing.id=1
modbus:serial.ac_hall_swing.start=18
modbus:serial.ac_hall_swing.length=2
modbus:serial.ac_hall_swing.type=holding

#
modbus:serial.ac_hall_timer.connection=/dev/ttyACM0:57600:8:none:1:rtu
modbus:serial.ac_hall_timer.id=1
modbus:serial.ac_hall_timer.start=320
modbus:serial.ac_hall_timer.length=2
modbus:serial.ac_hall_timer.type=coil

#
modbus:serial.ac_hall_timer_time.connection=/dev/ttyACM0:57600:8:none:1:rtu
modbus:serial.ac_hall_timer_time.id=1
modbus:serial.ac_hall_timer_time.start=21
modbus:serial.ac_hall_timer_time.length=4
modbus:serial.ac_hall_timer_time.type=holding

# DS18B20
modbus:serial.ac_hall_ds18b20.connection=/dev/ttyACM0:57600:8:none:1:rtu
modbus:serial.ac_hall_ds18b20.id=1
modbus:serial.ac_hall_ds18b20.start=25
modbus:serial.ac_hall_ds18b20.length=2
modbus:serial.ac_hall_ds18b20.type=holding

items
Contact AC_HALL_STATE_POWER             "AC_HALL_STATE_POWER [MAP(air_cond.map):%s]"    (){modbus="ac_hall_state:0"}
Contact AC_HALL_STATE_OXYGEN            "AC_HALL_STATE_OXYGEN [MAP(air_cond.map):%s]"   (){modbus="ac_hall_state:1"}
Contact AC_HALL_STATE_ION               "AC_HALL_STATE_ION [MAP(air_cond.map):%s]"      (){modbus="ac_hall_state:2"}
Contact AC_HALL_STATE_QUIET             "AC_HALL_STATE_QUIET [MAP(air_cond.map):%s]"    (){modbus="ac_hall_state:3"}
Contact AC_HALL_STATE_TIMER             "[MAP(air_cond.map):%s]"                  (){modbus="ac_hall_state:4"}

Switch  AC_HALL_CONTROL_POWER           ""                   <climate>       (){modbus="ac_hall_power:0"}
Switch  AC_HALL_CONTROL_OXYGEN          " O2"                                  (){modbus="ac_hall_power:1"}
Switch  AC_HALL_CONTROL_ION             ""                                     (){modbus="ac_hall_power:2"}
Switch  AC_HALL_CONTROL_QUIET           " "                                   (){modbus="ac_hall_power:3"}

Number  AC_HALL_RTC                     "RTC[%x]"                                       (){modbus="ac_hall_rtc:0"}
String  AC_HALL_RTC_S                   " [%s]"         <clock>         ()

Group   gAC_HALL_TEMPERATURE            "Living Room temp"

Number  AC_HALL_TEMPERATURE_ENV         "[%d]"                                   (){modbus="ac_hall_temperature:0"}
Number  AC_HALL_TEMPERATURE_NOZ         "[%d]"                                     (){modbus="ac_hall_temperature:1"}
Number  AC_HALL_TEMPERATURE_ENVF        " [%.2f °C]"     <temperature>           (gAC_HALL_TEMPERATURE)
Number  AC_HALL_TEMPERATURE_NOZF        " [%.2f °C]"       <temperature>           (gAC_HALL_TEMPERATURE)

Number  AC_HALL_DS18B20_ENV             "ENV[%x]"                                       (){modbus="ac_hall_ds18b20:0"}
Number  AC_HALL_DS18B20_NOZ             "NOZZLES[%x]"                                   (){modbus="ac_hall_ds18b20:1"}

Number  AC_HALL_MODE                    ""                                              (){modbus="ac_hall_mode:0"}

Number  AC_HALL_TEMP_AUTO               "[%d °C]"    <temperature>           (){modbus="ac_hall_temp:0"}
Number  AC_HALL_TEMP_COOL               "[%d °C]"    <temperature>           (){modbus="ac_hall_temp:1"}
Number  AC_HALL_TEMP_HEAT               "[%d °C]"    <temperature>           (){modbus="ac_hall_temp:2"}
Number  AC_HALL_TEMP_DRY                "[%d °C]"    <temperature>           (){modbus="ac_hall_temp:3"}

Number  AC_HALL_FAN_AUTO                "[%d]"                                  (){modbus="ac_hall_fan:0"}
Number  AC_HALL_FAN_COOL                "[%d]"                                  (){modbus="ac_hall_fan:1"}
Number  AC_HALL_FAN_HEAT                "[%d]"                                  (){modbus="ac_hall_fan:2"}
Number  AC_HALL_FAN_DRY                 "[%d]"                                  (){modbus="ac_hall_fan:3"}
Number  AC_HALL_FAN_SPEED               "[%d]"                                  (){modbus="ac_hall_fan:4"}

Number  AC_HALL_SWINGV                  ""                                              (){modbus="ac_hall_swing:0"}
Number  AC_HALL_SWINGH                  ""                                              (){modbus="ac_hall_swing:1"}

Switch  AC_HALL_TIMER_ON                " "              <clock>         (){modbus="ac_hall_timer:0"}
Switch  AC_HALL_TIMER_OFF               " "             <clock>         (){modbus="ac_hall_timer:1"}

Number  AC_HALL_TIME_ON_HR              "[%02d]"                                     (){modbus="ac_hall_timer_time:0"}
Number  AC_HALL_TIME_ON_MI              "[%02d]"                                  (){modbus="ac_hall_timer_time:1"}
Number  AC_HALL_TIME_OFF_HR             "[%02d]"                                     (){modbus="ac_hall_timer_time:2"}
Number  AC_HALL_TIME_OFF_MI             "[%02d]"                                  (){modbus="ac_hall_timer_time:3"}


规则用于将整数温度转换为实际温度,以及将控制器时间格式化为HH:MM格式。
规则设定
import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import java.io.File

rule "Update AC_HALL ENV temp"
        when
                Item AC_HALL_TEMPERATURE_ENV received update
        then
                var Number T = AC_HALL_TEMPERATURE_ENV.state as DecimalType
                var Number H = T/100
                postUpdate(AC_HALL_TEMPERATURE_ENVF, H)
end
rule "Update AC_HALL NOZZLES temp"
        when
                Item AC_HALL_TEMPERATURE_NOZ received update
        then
                var Number T = AC_HALL_TEMPERATURE_NOZ.state as DecimalType
                var Number H = T/100
                postUpdate(AC_HALL_TEMPERATURE_NOZF, H)
end
rule "Update AC_HALL_RTC clock"
        when
                Item AC_HALL_RTC received update
        then
                var Number T = AC_HALL_RTC.state as DecimalType
                var H = T.intValue / 256
                var M = T.intValue % 256
                var S = String::format("%02x:%02x",H,M)
                postUpdate(AC_HALL_RTC_S, S)
end


站点地图设置
sitemap demo label="Demo House"{
        Frame label="HOME"{
                Text label=" " icon="ac_cond"{
                        Frame label="" {
                                Switch item= AC_HALL_CONTROL_POWER labelcolor=[AC_HALL_STATE_POWER==OPEN="blue"]
                                Switch item= AC_HALL_CONTROL_OXYGEN labelcolor=[AC_HALL_STATE_OXYGEN==OPEN="blue"]
                                Switch item= AC_HALL_CONTROL_ION labelcolor=[AC_HALL_STATE_ION==OPEN="blue"]
                                Switch item= AC_HALL_CONTROL_QUIET labelcolor=[AC_HALL_STATE_QUIET==OPEN="blue"]
                                Text item=AC_HALL_STATE_TIMER labelcolor=[AC_HALL_STATE_TIMER==OPEN="blue"] icon="clock-on"
                                Text item=AC_HALL_RTC_S
                                Text item=AC_HALL_TEMPERATURE_ENVF
                                Text item=AC_HALL_TEMPERATURE_NOZF
                        }

                        Frame label=""{
                                Selection item=AC_HALL_MODE label="" mappings=[1=AUTO, 2=COOL, 4=HEAT, 8=DRY, 16=FAN]
                                Text item=AC_HALL_TEMP_AUTO visibility=[AC_HALL_MODE==1]
                                Text item=AC_HALL_TEMP_COOL visibility=[AC_HALL_MODE==2]
                                Text item=AC_HALL_TEMP_HEAT visibility=[AC_HALL_MODE==4]
                                Text item=AC_HALL_TEMP_DRY visibility=[AC_HALL_MODE==8]

                                Text item=AC_HALL_FAN_AUTO visibility=[AC_HALL_MODE==1]
                                Text item=AC_HALL_FAN_COOL visibility=[AC_HALL_MODE==2]
                                Text item=AC_HALL_FAN_HEAT visibility=[AC_HALL_MODE==4]
                                Text item=AC_HALL_FAN_DRY visibility=[AC_HALL_MODE==8]
                                Text item=AC_HALL_FAN_SPEED visibility=[AC_HALL_MODE==16]

                                Selection item=AC_HALL_SWINGV label="" mappings=[1=AUTO, 2="0°", 4="15°", 8="30°", 16="45°", 32="60°"]
                                Selection item=AC_HALL_SWINGH label="" mappings=[1=AUTO, 4="/   /", 8="/   |", 2="|   |", 16="|   \\", 32="\\   \\"]

                                Text label="" icon="settings"{
                                        Frame label="AUTO"{
                                                Setpoint item=AC_HALL_TEMP_AUTO minValue=16 maxValue=30 step=1
                                                Switch   item=AC_HALL_FAN_AUTO mappings=[0=AUTO, 1="1", 2="2", 3="3", 4="4", 5="5"]
                                        }
                                        Frame label="COOL"{
                                                Setpoint item=AC_HALL_TEMP_COOL minValue=16 maxValue=30 step=1
                                                Switch   item=AC_HALL_FAN_COOL mappings=[0=AUTO, 1="1", 2="2", 3="3", 4="4", 5="5"]
                                        }
                                        Frame label="HEAT"{
                                                Setpoint item=AC_HALL_TEMP_HEAT minValue=16 maxValue=30 step=1
                                                Switch   item=AC_HALL_FAN_HEAT mappings=[0=AUTO, 1="1", 2="2", 3="3", 4="4", 5="5"]
                                        }
                                        Frame label="DRY"{
                                                Setpoint item=AC_HALL_TEMP_DRY minValue=16 maxValue=30 step=1
                                                Switch   item=AC_HALL_FAN_DRY mappings=[0=AUTO, 1="1", 2="2", 3="3", 4="4", 5="5"]
                                        }
                                        Frame label="FAN"{
                                                Switch item=AC_HALL_FAN_SPEED mappings=[0=AUTO, 1="1", 2="2", 3="3", 4="4", 5="5"]
                                        }
                                        Frame label=""{
                                                Text item=AC_HALL_DS18B20_ENV
                                                Text item=AC_HALL_DS18B20_NOZ
                                        }
                                }
                        }
                        Frame label="" {
                                Switch item= AC_HALL_TIMER_ON labelcolor=[AC_HALL_STATE_TIMER==OPEN="blue"]
                                Setpoint item=AC_HALL_TIME_ON_HR minValue=0 maxValue=23 step=1
                                Setpoint item=AC_HALL_TIME_ON_MI minValue=0 maxValue=50 step=5

                                Switch item= AC_HALL_TIMER_OFF labelcolor=[AC_HALL_STATE_TIMER==OPEN="blue"]
                                Setpoint item=AC_HALL_TIME_OFF_HR minValue=0 maxValue=23 step=1
                                Setpoint item=AC_HALL_TIME_OFF_MI minValue=0 maxValue=50 step=5
                        }
                }
                Text item=AC_HALL_RTC_S
                Text item=AC_HALL_TEMPERATURE_ENVF{
                        Frame label=" "{
                                Chart item=gAC_HALL_TEMPERATURE period=h refresh=60000
                        }
                        Frame label=" 4 " {
                                Chart item=gAC_HALL_TEMPERATURE period=4h refresh=600000
                        }
                }
        }
}



结果通过浏览器看起来像这样:

结论


作为大象,我对结果感到满意。现在,无论有移动互联网还是WiFI,都可以使用空调控制。使用智能手机上的VPN客户端,我可以通过浏览器和移动应用程序访问我的家庭服务器上的OpenHAB。
无线解决方案使将控制器与空调紧密集成成为可能。
反馈的存在使您确信所发送的命令已被空调接收,并且温度传感器清楚地表明了这一点-几秒钟后,您可以观察到空调出口处的温度读数变化。好吧,几分钟后-和环境温度。
在接近给定条件时观察空调的轮廓很有趣。

毫无疑问,这将不是我计划使用的唯一无线控制器。

有计划使用空调本身的IR接收器读取本地遥控器的命令以更新控制器中的设置。此外,IR接收器本身已经通过光耦合器连接到控制器。

最后阅读特别的谢谢!

参考文献


  1. Arduino库ModbusRtu Modbus-Master-Slave-for-Arduino
  2. Arduino库ModbusRtuRF24 - RF24上的Modbus-Arduino网络

Source: https://habr.com/ru/post/zh-CN384243/


All Articles