Controlador inalámbrico de aire acondicionado para el hogar de OpenHAB a través de Modbus a través de RF24Network


Después de mi primer artículo sobre el control del aire acondicionado con un controlador, pasaron poco más de 2 años. Durante este tiempo, la idea de controlar el aire acondicionado de forma remota no me abandonó y tuvo varios renacimientos. La condición principal era la ausencia de cables al aire acondicionado.

Es decir, el control del controlador debe ser inalámbrico.

Antecedentes


El primer prototipo fue el Arduino UNO. Ella aceptó equipos en UART y sabía cómo encender y apagar el aire acondicionado. Porque El arduinka conectado a la computadora en funcionamiento tenía poco sentido práctico, el jefe buscaba constantemente la oportunidad de conectar esta última al servidor doméstico. No hubo visibilidad directa del servidor al culpable de todos los rompecabezas. El máximo es un zócalo con una LAN en la misma computadora que funciona, ya que se encuentra casi enfrente del aire acondicionado. Un escudo de Ethernet no estaba disponible. Pero recordando que en algún lugar del zashashnik se encuentra un módem dsl DSL-2500U d-link que no se ha utilizado durante mucho tiempo, con solo un puerto a bordo. El deseo de darle una segunda vida a la pieza de hierro condujo a googlear, lo que, a su vez, condujo milagrosamente al artículo Convertir un módem ADSL en un escudo Ethernet para Arduino / CraftDuino .

Saltando hacia adelante y omitiendo el interesante proceso de crear firmware personalizado, todavía logré que el módem escuchara en el puerto deseado y "reenviara" el UART a través de él. Por lo tanto, en el servidor doméstico, podría enviar un comando para encender / apagar el puerto a la dirección local del módem, que irá al arduino conectado a él.

Pero este artículo no se trata de eso. La solución definitiva utiliza el protocolo Modbus y la red inalámbrica RF24Network . Y todo está controlado en OpenHAB.


Durante estos dos años, logré ordenar una gran cantidad de nishtyaks de China y la mayoría de ellos me estaban esperando. Esta lista incluía el módulo NRF24L01 +, comprado por un puñado para experimentación. Y él habría ido más lejos en algún lugar del armario inactivo, si un día no me hubiera topado con una serie de artículos:

desde Borich¡Gracias por eso!

Gracias a ellos, me familiaricé con el protocolo Modbus. Pero lo más importante, descubrí OpenHAB por mí mismo, lo que he estado buscando durante mucho tiempo. Esto me llevó a comenzar a implementar ideas de larga data.

Después de jugar con ejemplos de los artículos, decidí tratar de separar el controlador y el servidor usando el escudo de ethernet del módem descrito anteriormente. Esta solución nos permitió lograr la tarea planteada: el escudo y el controlador estaban ubicados en el escritorio, sin usar una computadora que funcionara, al mismo tiempo, el escudo siempre está conectado a la red local y es accesible desde el servidor doméstico.

Pero esta decisión estaba condenada al fracaso.
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 .

, . . , .


Idea


Y luego finalmente me establecí que necesitaba hacer un controlador que sea accesible por aire. ¡Los módulos NRF24L01 + no deberían desaparecer! ... Es cierto, esto requería al menos dos controladores: uno desempeña un papel directo, el segundo desempeña el papel de un enrutador. El segundo debe estar conectado al servidor y es a través de él que se lleva a cabo la comunicación inalámbrica con los demás. Al conectarse a él, especificamos la ID del subordinado a quien está destinado el paquete. Resulta que muchos esclavos están disponibles en un puerto serie. Sí, esta es una red inalámbrica basada en Modbus.

Modbus, por cierto, hizo posible construir una red con un maestro, muchos subordinados. Y la biblioteca RF24Network , para hacer que todo sea inalámbrico, e incluso con enrutamiento automático entre nodos de red.

Desarrollo de bibliotecas para Arduino


Para implementar tal solución, tomó un poco modificar la biblioteca Modbus-Master-Slave-for-Arduino para poder heredarla y sobrecargar un par de métodos. Mi implementación también se actualiza (se agrega library.properties, el archivo de biblioteca se divide en encabezado y cuerpo) para el último Arduino IDE 1.6.5.

La biblioteca Modbus-over-RF24Network-for-Arduino le permite implementar dos comportamientos posibles: Proxy y Slave. Ejemplo ModbusRF24Proxy es en realidad una implementación de un "enrutador" y no requiere ninguna modificación que no sea establecer los pines necesarios.
Ejemplo 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);
}


Un enrutador o proxy utiliza un formato de constructor especial:
//  ,   TX
ModbusRF24 proxy(network, 0, 0);

y función
proxy.proxy();

para procesar paquetes entrantes en el puerto serie, enviarlos a la red RF24, recibir una respuesta de la red y enviar el resultado nuevamente al puerto serie.

En esta implementación, el proxy tiene una dirección RF24Network de cero:
// Address of our node
const uint16_t this_node = 0;

- es decir Este es el dispositivo raíz de la red. Si es necesario, la posición en la topología del controlador proxy se puede cambiar.

Ejemplo de Modbus RF24Slave
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();
}



El constructor en este caso ya es diferente:
//  
ModbusRF24 slave(network, ID);


Estructura de registro Modbus


Después de los primeros intentos exitosos de controlar el aire acondicionado con la capacidad de encender y apagar solo mi apetito solo aumentó. Ahora, esto no era suficiente, y dado que tengo la funcionalidad OpenHAB en mi aplicación móvil, debería hacer como mínimo toda la funcionalidad del panel de control nativo.
Esto significa que aquí hay una lista de características al menos:
  • indicación del estado actual
  • encendido y apagado del aire acondicionado, modos individuales (O 2 , ionización, modo silencioso);
  • selección del modo actual (automático, calefacción, refrigeración, drenaje, ventilador);
  • indicación de temperatura y velocidad del ventilador para cada modo. Para el modo de ventilador, solo velocidad;
  • ajuste de cortina vertical (automático, 0 °, 15 °, 30 °, 45 °, 60 °);
  • ajuste de cortina horizontal (automático, "| |", "/ /", "/ |", "| \", "\ \");
  • ajuste de hora (hora, minuto);
  • en la configuración del temporizador;
  • ajuste del temporizador de apagado;
  • ajuste a tiempo (hora, minuto);
  • ajuste del tiempo de apagado (hora, minuto);

Durante el proceso de desarrollo, la estructura de los registros ha cambiado muchas veces conmigo. La versión actual está debajo del spoiler.
Registros 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.


Los registros están organizados de tal manera que toda la matriz de datos se inicializa desde la EEPROM cuando se inicia el controlador.
Los primeros 3 registros (CFG_ *) contienen la configuración de características, nunca cambian y son inicializados por el firmware EEPROM.
Los registros 3-7 siempre muestran el estado actual del controlador. Los bits altos del registro 3 se usan para cambiar el estado. Sus cambios inician el encendido / apagado del aire acondicionado y los modos especiales. Después de ejecutar el comando, los bits de orden inferior de este registro se copian en los de orden superior.
El registro 4 contiene el tiempo actual del controlador, que se lee del RTC. El valor se guarda en formato BCD, de modo que cuando el registro se muestra en notación hexadecimal, el tiempo se lee como es: 12:34 es 0x1234.
El registro 5 se usa para cambiar el tiempo RTC.
Los registros 6-7 contienen la temperatura de los sensores DS18B20. El valor contiene un entero con signo y es igual a T * 100, es decir 25,67 ° C = 2567. Se proporciona un máximo de 2 sensores, pero el número se puede cambiar fácilmente expandiendo la tabla de registro para almacenar las direcciones de los sensores y sus temperaturas.
Los últimos 2 bytes de la dirección del sensor se almacenan en los registros 25-26. Al cambiar los sensores, restablezca el registro de dirección correspondiente. Cuando se detecta un nuevo sensor, se verifica su presencia en los registros 25-26. Si la dirección está en la tabla, el valor de temperatura del sensor se ingresa en el registro correspondiente 6-7. Si la dirección no está en la tabla y la tabla tiene cero celdas, la dirección del sensor actual se escribe en una celda libre.
Los registros 8-26, cuando los modifica el usuario, se guardan en la EEPROM.

Glándulas


El hardware consta de los siguientes componentes:
  1. Arduino Pro Mini.
    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. — , ,











La retroalimentación con el aire acondicionado se realiza conectando optoacopladores a los LED correspondientes. Por lo tanto, se garantiza el aislamiento galvánico con el circuito eléctrico del aire acondicionado. La corriente de las entradas para los optoacopladores se seleccionó experimentalmente usando resistencias para que la salida del optoacoplador también se abriera y el brillo del LED principal en el aire acondicionado no se redujera.

Se instaló un LED IR al lado del receptor IR del aire acondicionado.

El controlador funciona con carga mini-USB de algún tipo de milagro chino. Los contactos de tensión de red chinos fueron retirados de la caja de carga, los cables fueron retirados. La carga se instaló en las entrañas de la caja del aire acondicionado, conectada a la entrada 220 en paralelo con ella. El controlador se conecta a la carga con un cable USB AB normal.

El controlador "enrutador" se basa en el Arduino Mega2560 y NRF24L01 + con un LM1117-3.3 separado. Además de una fuente de alimentación 3.3 separada, se conecta un electrolito al módulo inalámbrico (lo encontré a 470 uf * 16 v) en las patas de alimentación. Como saben, el bus de alimentación interno Mega2560 3.3V es muy ruidoso y el módulo se negó a transmitir datos, aunque respondió correctamente. Pero incluso con una fuente de alimentación separada sin condensador, la conexión era muy inestable.
Para que el mega2560 no se reinicie al abrir el puerto a través de USB, se conecta un electrolito de 10 μf al pin de reinicio.

Openhab


El artículo de Arduino y OpenHAB describe una característica del complemento Modbus Binding, que con cada sondeo del controlador, el complemento envía un evento al bus, incluso si nada ha cambiado. Seguí su ejemplo y finalicé el complemento.

Configuración del complemento de enlace Modbus
#
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

Configuraciones de artículos
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"}


Las reglas se utilizan para convertir temperaturas enteras en temperaturas reales, así como para formatear el tiempo del controlador en la forma HH: MM.
Configuraciones de reglas
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


Configuración de sitemaps
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
                        }
                }
        }
}



El resultado se ve así a través de un navegador:

Conclusión


Estoy satisfecho con el resultado como un elefante. El control de aire acondicionado ahora está disponible para mí donde haya Internet móvil o WiFI. Utilizando un cliente VPN en un teléfono inteligente, OpenHAB en mi servidor doméstico se vuelve accesible para mí tanto a través de un navegador como a través de una aplicación móvil.
La solución inalámbrica permitió integrar estrechamente el controlador con el aire acondicionado.
La presencia de retroalimentación da confianza en que el comando enviado fue recibido por el aire acondicionado, y los sensores de temperatura lo demuestran claramente: después de unos segundos, puede observar un cambio en la lectura de temperatura en la salida del aire acondicionado. Bueno, después de unos minutos, y la temperatura ambiente.
Fue interesante observar el perfil del aire acondicionado al acercarse a las condiciones dadas.

Sin lugar a dudas, este no será el único controlador inalámbrico que planeo usar.

Hay planes para usar el receptor IR del acondicionador de aire para leer los comandos del control remoto nativo para actualizar la configuración en el controlador. Además, el receptor IR ya está conectado a través de un optoacoplador al controlador.

Lea hasta el final un agradecimiento especial!

Referencias


  1. Biblioteca Arduino ModbusRtu Modbus-Master-Slave-for-Arduino
  2. Biblioteca Arduino ModbusRtuRF24 Modbus-over-RF24 Network-for-Arduino

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


All Articles