Conexão do Aquastorozh à Smart Home no Z-Wave



No ano passado, comprei equipamentos para desligamento de emergência de guindastes quando um vazamento de Aquastorozh foi detectado. Durante muito tempo não pude colocá-lo. Havia uma ideia de integrá-lo à rede Z-Wave e obter um analógico gidrolock, mas trabalhando com baterias. Finalmente, as mãos chegaram ...

O Aquastorozh é uma base com torneiras plugáveis ​​e sensores de vazamento. Esse complexo pode funcionar tanto a partir de uma rede de 220 V através de um adaptador quanto a partir de baterias. Os desenvolvedores forneceram a capacidade de se conectar aos sistemas de "casa inteligente". Ao fechar um par de contatos em uma tomada Ethernet, você pode abrir as torneiras e o outro fechá-las. Os contatos do relé fecham por 1 segundo quando um vazamento é detectado. Há um conector UART não soldado na placa, mas neste artigo falarei sobre a implementação de funções documentadas.

Tarefas de desenvolvimento


  • Torneiras remotas de ligar / desligar.
  • Informações de vazamento.
  • Dois medidores de água.
  • Não interrompa o trabalho de "Aquastorozh".

Decidiu fazer com base no escudo ZUNo. É entregue em um invólucro vedado com selo de pressão, possui blocos de terminais a bordo e espaço livre para instalação da bateria e componentes eletrônicos adicionais. Arduino é semelhante.

Conector Ethernet




Um dos fios que podem ser fechados é a "terra" do "aqua watchman". Você pode combinar as terras do ZUNo e Aqua-Watch e controlar os guindastes diretamente através do GPIO ZUNo. Então eu fiz. Porém, no caso de uma falha no ZUNo (por exemplo, a bateria acabou), as linhas de controle "Aquastorozh" recebem um "zero" e começam a reiniciar ciclicamente. Essa opção de conexão afeta muito a confiabilidade de todo o sistema, portanto, tendo complicado um pouco o circuito, mudei para dois relés de palheta, que forneciam isolamento galvânico de Aquastorozh. Os relés consomem cerca de 7 mA quando ativados. Para trocar os guindastes, você precisa ligar um relé por um segundo, o que é bastante aceitável. A carga da bateria foi suficiente para vários milhares de comutações. (Agora eu tenho relés de bobina única de pulso eletromagnético em minhas mãos. Para trocá-los, você precisa aplicar um pulso de 1 ms, que é muito mais eficiente em termos de energia. Mas, para controlar, você precisa de 4 transistores e duas pernas de entrada / saída para o relé).

Dormir na onda Z


Falarei um pouco sobre como os dispositivos Z-Wave dormem e sobre o problema resultante.
Os dispositivos de onda Z podem estar inativos ou muitas vezes acordando. O dispositivo de dormir é o mais eficiente em termos de energia, mas não pode ser enviado um comando (no meu caso, para trocar os guindastes). O segundo tipo combina comigo. Dispositivo FLiRS - Escuta frequente de escravos de roteamento. Um dispositivo configurado para este modo de operação é ativado a cada segundo e, por um curto período de tempo, não recebe um sinal de ativação completa do controlador, ele adormece. Por exemplo: envio um comando para abrir guindastes. O controlador entende que meu dispositivo está frequentemente ouvindo e envia um feixe de ativação curto especial em um segundo para que todos os dispositivos FLIRS da rede sejam ativados. Assim que meu dispositivo aceita esse pacote, ele envia um relatório que acordou e está pronto para aceitar o comando. Obtém um comando para fechar as torneiras. Adormecer novamente. E assim, toda vez que o dispositivo é controlado. A desvantagem é que o dispositivo pode receber um feixe de ativação no final da transmissão pelo controlador e no início. O controlador envia por cerca de um segundo. Na pior das hipóteses, o dispositivo acorda no início deste boletim e espera quase um segundo até que um comando chegue. Porém, como abrir e fechar torneiras geralmente não é necessário, isso não é uma desvantagem séria.

Implementação


O ZUNo Shield possui uma pequena placa de ensaio na qual você pode colocar os componentes necessários.



O circuito contém dois relés e dois transistores para seu controle. Um pequeno esboço simples.



Algumas palavras sobre consumo de energia.

A blindagem ZUNo contém um chip de driver para o protocolo RS-485 e um resistor de pull-up para o pino "11" no bloco inferior, para o protocolo One Wire. Depois de remover esses componentes, o principal consumidor permanece o ZUNo.



O consumo no modo de suspensão é de cerca de 5-10 μA e no modo ativo de até 60 mA (o relé está ativo e o ZUNa está transmitindo).

Oscilogramas de consumo de corrente para diferentes modos de operação


A direção do eixo atual é de cima para baixo.

O dispositivo está aguardando um comando:



Aproximadamente a cada segundo, picos curtos são visíveis durante os quais o dispositivo é ativado e verifica se o feixe de ativação chegou.

O dispositivo recebeu o comando:



Primeiro, o dispositivo acordou, recebeu um feixe wakeUp, aguardou um comando (de 0 a 1 segundo); se o comando para controlar os guindastes, ele liga o relé correspondente por 1 segundo (nesse estágio, você precisa colocar o controlador em suspensão enquanto mantém as pernas no estado atual, mas eu Eu estava com medo e com preguiça) e o resto do tempo é gasto na operação interna do chip, após o que o ZUNo adormece. Um total de quase 3,5 segundos por uma operação de abertura ou fechamento por torneiras. Um tempo terrivelmente longo, mas devido ao fato de que essas operações serão executadas muito raramente, a otimização pode ser negligenciada. Sim, e isso dará pouco, porque o esboço no ide Arduino é apenas uma pequena parte do que é jogado e girado neste pequeno microcontrolador, e o que é escondido pelos curiosos pelo fabricante.

Esquema de conexão com "Aquastorozh"




Conclusão


Acabou por adicionar "Aquastorozh" com bastante precisão à rede Z-Wave existente. A principal desvantagem é a falta de feedback de Aquastorozh. Nesta fase, estou aguardando uma nova versão da biblioteca ZUNo, na qual será corrigido um erro que impede o ZUNo de dormir normalmente. Portanto, em vez de uma foto com o Aquastorozh instalado e conectado, uma imagem com o processo de depuração.



Obrigado pela atenção!

Esboço
//#define _DEBUG #define OPEN_PIN 11 #define CLOSE_PIN 12 #define LEAK_PIN 19 #define INT1 18 uint8_t valve_action = 0; #ifdef _DEBUG uint8_t const METER1_PIN = 8; #else uint8_t const METER1_PIN = 7; #endif #define METER2_PIN 8 #include "EEPROM.h" #define MAGIC_VALUE 42 #define ADDR_ACTION 1 #define CH_METER_1 4 #define CH_METER_2 8 #define CNT_ON_OFF_CICL 12 // Global variables byte pin7SwitchBinaryState = 0; DWORD eeprom_buf = 0; #define LEAK_CHANNEL 3 DWORD meter_cnt1; DWORD meter_cnt2; #define ADR_MET1 4 #define ADR_MET2 5 uint8_t alarm_clr = LOW; // Z-Wave channels ZUNO_SETUP_CHANNELS( ZUNO_SWITCH_BINARY(pin7SwitchBinaryGetter, pin7SwitchBinarySetter), ZUNO_SWITCH_BINARY(alarmGetter, alarmSetter), ZUNO_SENSOR_BINARY(ZUNO_SENSOR_BINARY_TYPE_WATER, getterSensorBinary), ZUNO_METER(ZUNO_METER_TYPE_WATER, METER_RESET_ENABLE , ZUNO_METER_WATER_SCALE_PULSECOUNT, 4, 0, getterMETER1, resetterMETER1), ZUNO_METER(ZUNO_METER_TYPE_WATER, METER_RESET_ENABLE , ZUNO_METER_WATER_SCALE_PULSECOUNT, 4, 0, getterMETER2, resetterMETER2) ); ZUNO_SETUP_BATTERY_LEVELS(2700, 3300); ZUNO_SETUP_SLEEPING_MODE(ZUNO_SLEEPING_MODE_FREQUENTLY_AWAKE); void close_water() { #ifdef _DEBUG Serial1.println("close"); #endif digitalWrite(CLOSE_PIN, HIGH); delay(1000); digitalWrite(CLOSE_PIN, LOW); //delay(1000); } void open_water() { #ifdef _DEBUG Serial1.println("open"); #endif digitalWrite(OPEN_PIN, HIGH); delay(1000); digitalWrite(OPEN_PIN, LOW); //delay(1000); } #define LEAK_DETECTED LOW #define LEAK_END HIGH #define ADDR_LEAK_ST_LAST 2 #define ADR_B1_F 3 #define ADR_B2_F 4 #define NZ_ADR_LEAK 5 uint8_t last_leak_st; #define EEPROM_MAGIC 0x11223342 #define EEPROM_ADR_MAGIC 0 void setup() { #ifdef _DEBUG Serial1.begin(9600); Serial1.println("serial init"); #else pinMode(METER1_PIN, INPUT); pinMode(METER2_PIN, INPUT); #endif pinMode(CLOSE_PIN, OUTPUT); pinMode(OPEN_PIN, OUTPUT); pinMode(LEAK_PIN, INPUT_PULLUP); pinMode(INT1, INPUT_PULLUP); digitalWrite(CLOSE_PIN, LOW); digitalWrite(OPEN_PIN, LOW); byte n; NZRAM.get(0x0, &n, 1); if (n == MAGIC_VALUE) { // correct magic value after wake up from sleep mode // trust NZRAM data } else { // incorrect magic, first boot after battery insert ot rebooted due to low battery // initialize NZRAM magic n = MAGIC_VALUE; NZRAM.put(0x0, &n, 1); NZRAM.write(ADDR_ACTION, LOW); NZRAM.write(ADDR_LEAK_ST_LAST, LEAK_END); NZRAM.write(ADR_B1_F, HIGH); NZRAM.write(ADR_B2_F, HIGH); } EEPROM.get(EEPROM_ADR_MAGIC, &eeprom_buf, sizeof(DWORD)); if(eeprom_buf != EEPROM_MAGIC) { eeprom_buf = EEPROM_MAGIC; EEPROM.put(EEPROM_ADR_MAGIC, &eeprom_buf, sizeof(DWORD)); resetterMETER1(); resetterMETER2(); eeprom_buf = 0; EEPROM.put(CNT_ON_OFF_CICL, &eeprom_buf, sizeof(DWORD)); } } uint8_t last_btn_st; void check_btn(uint8_t meter_pin, uint8_t NZ_adr_st) { last_btn_st = NZRAM.read(NZ_adr_st); if(digitalRead(meter_pin) == LOW) { if(last_btn_st != LOW) { for(uint8_t i=0; i<3; ++i) { if(digitalRead(meter_pin) == LOW) delay(5); else return; } last_btn_st = LOW; NZRAM.write(NZ_adr_st, last_btn_st); } } else { if(last_btn_st == LOW) { for(uint8_t i=0; i<3; ++i) { if(digitalRead(meter_pin) == HIGH) delay(5); else return; } last_btn_st = HIGH; NZRAM.write(NZ_adr_st, last_btn_st); if(NZ_adr_st == ADR_B1_F) inc_met(ADR_MET1); else inc_met(ADR_MET2); } } } //=----------------------------------------------------------- void loop() { if(digitalRead(LEAK_PIN) == LEAK_DETECTED) { if(NZRAM.read(ADDR_LEAK_ST_LAST) != LEAK_END) { zunoSendReport(LEAK_CHANNEL); NZRAM.write(ADDR_LEAK_ST_LAST, LEAK_END); } } check_btn(METER1_PIN, ADR_B1_F); check_btn(METER2_PIN, ADR_B2_F); if(zunoGetWakeReason() == ZUNO_WAKEUP_REASON_RADIO) { uint32_t start_time=0; #define ACTION_T_OUT 2000 start_time = millis(); //while(NZRAM.read(ADDR_ACTION)== 0) while(valve_action== 0) if((millis() - start_time) >= ACTION_T_OUT) { #ifdef _DEBUG Serial1.println("T_OUT"); #endif break; } else delay(50); #ifdef _DEBUG Serial1.println(millis() - start_time); #endif if(NZRAM.read(ADDR_ACTION)) { valve_action = 0; NZRAM.write(ADDR_ACTION, LOW); if(pin7SwitchBinaryState == LOW) close_water(); else open_water(); } if(alarm_clr) //      { alarm_clr == LOW; zunoSendReport(LEAK_CHANNEL); } } if(digitalRead(INT1)==0) { zunoSetWUOptions(ZUNO_WUPFLAGS_INT1_HIGH); } else { zunoSetWUOptions(ZUNO_WUPFLAGS_INT1_LOW); } zunoSendDeviceToSleep(); } //----------------------------------------------------------- // Getters and setters void inc_met(uint8_t num_chennel) { uint8_t eeprom_adr_met; if(num_chennel == ADR_MET1) eeprom_adr_met = CH_METER_1; else eeprom_adr_met = CH_METER_2; EEPROM.get(eeprom_adr_met, &eeprom_buf, sizeof(DWORD)); eeprom_buf++; EEPROM.put(eeprom_adr_met, &eeprom_buf, sizeof(DWORD)); zunoSendReport(num_chennel); } DWORD getterMETER1() { EEPROM.get(CH_METER_1, &eeprom_buf, sizeof(DWORD)); return eeprom_buf; } DWORD getterMETER2() { EEPROM.get(CH_METER_2, &eeprom_buf, sizeof(DWORD)); return eeprom_buf; } void resetterMETER1() { eeprom_buf = 0; EEPROM.put(CH_METER_1, &eeprom_buf, sizeof(DWORD)); } void resetterMETER2() { eeprom_buf = 0; EEPROM.put(CH_METER_2, &eeprom_buf, sizeof(DWORD)); } void pin7SwitchBinarySetter(byte value) { valve_action = 1; NZRAM.write(ADDR_ACTION, HIGH); pin7SwitchBinaryState = value; if(value == 255) // if open valve, then off leak alarm { NZRAM.write(ADDR_LEAK_ST_LAST, LOW); zunoSendReport(LEAK_CHANNEL); } } byte pin7SwitchBinaryGetter() { return pin7SwitchBinaryState ? 0xFF : 0; } byte getterSensorBinary() { return digitalRead(LEAK_PIN) ? 0 : 0xFF; } byte alarmGetter() { uint8_t ret; ret = NZRAM.read(ADDR_LEAK_ST_LAST); return ret ? 0xFF : 0; } void alarmSetter(byte value) { alarm_clr = HIGH; NZRAM.write(ADDR_LEAK_ST_LAST, value); } 

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


All Articles