📜 ⬆️ ⬇️

Connecting "Aquastorozh" to "smart home" on Z-Wave



Last year, I bought equipment for emergency shut-off of cranes in case of leakage from Akvastorozh. Long could not put it. There was an idea to integrate it into the Z-Wave network and get an analogue of gidrolock, but running on batteries. Finally, the hands reached ...

Aquastorozh is a base with pluggable taps and leakage sensors. This complex can work as from a network of 220 V through the adapter, and from batteries. The developers have provided the possibility of connection to the systems of "smart home". By closing one pair of contacts in an Ethernet socket, you can open taps and the other close them. The relay contacts close for 1 second when a leak is detected. There is an unsoldered UART connector on the board, but in this article I’ll tell you about the implementation of the documented functions.

Development tasks



I decided to do on the basis of the ZUNo shield. It is supplied in a sealed enclosure with a sealed lead-in. It has terminals on board and free space for installing a battery and additional electronic components. Arduino is similar.
')

Ethernet connector




One of the locking wires is the “ground” of the “aquastoroz”. You can combine the lands of ZUNo and Aquastorozha and control the cranes directly through the GPIO ZUNo. So I did. But in the event of a failure of ZUNo (for example, a battery has sat down), the control line of the “Aquastorozha” is “zero” and it starts to reboot cyclically. Such a connection option strongly influences the reliability of the entire system, therefore, slightly complicating the circuit, I switched to two reed relays, which provided a galvanic isolation from Akvastorozh. Consume about 7 mA relay when turned on. To switch the taps you need to turn on one relay for one second, which is quite acceptable. The battery charge was enough for several thousand switches. (Now I have electromagnetic pulsed single-coil relays in my hands. To switch them, a 1 ms pulse is needed, which is much more energy efficient. But for control, 4 transistors and two I / O legs per relay are needed).

Z-wave sleep


I’ll talk a little about how Z-Wave devices sleep and the problem arising from this.
Z-wave devices can be asleep or often awake. The sleeping device is the most energy-efficient, but you cannot send a command to it (in my case, to switch cranes). The second type suits me. FLiRS - Frequently Listening Routing Slaves. A device tuned to this mode of operation wakes up every second and if within a short period of time it does not receive a wake-up signal from the controller, it falls asleep. For example: I send a command to open the taps. The controller understands that my device, which often listens, and sends a special short packet (wakeup beam) within a second so that all FLIRS devices on the network will wake up. As soon as my device accepts this packet, it sends a report that it has woken up and is ready to accept the command. Receives a command to close the taps. Falling asleep again. And so every time the device is controlled. The disadvantage is that the device can accept the wakeup beam both at the end of the broadcast by the controller and at the beginning. The controller sends it for about a second. In the worst case, the device will wake up at the beginning of this mailing, and will wait almost a second before the command arrives. But since it is often not necessary to open and close taps, this is not a serious drawback.

Implementation


ZUNo Shield has a small development board on which you can place the necessary components.



The circuit contains two relays and two transistors for their control. Simple shemka.



A few words about power consumption.

ZUNo shield contains a driver chip for the RS-485 protocol and a pull-up resistor for pin “11” on the bottom block, for the One Wire protocol. After the removal of these components, the main consumer remains ZUNo.



Consumption in sleep mode is about 5-10 ÎĽA, and in active mode it is up to 60 mA (the relay is active and ZUNa is transmitting).

Oscillograms of current consumption for different modes of operation


The direction of the current axis from top to bottom.

Device pending commands:



Approximately every second short peaks are visible, during which the device wakes up and checks if a wakeUp beam has arrived.

The device received the command:



First, the device woke up, received a wakeUp beam, waited to receive a command (from 0 to 1 second), if the command to control the taps, then turns on the corresponding relay for 1 second (at this stage you need to put the controller into sleep with the legs in the current state, but I I was afraid and lazy) and the rest of the time is spent on the internal operation of the chip, after which ZUNo falls asleep. Total almost 3.5 seconds for one operation of opening or closing taps. Terribly long, but due to the fact that such operations will be performed extremely rarely, optimization can be neglected. Yes, and it will give a little, because the sketch in the Arduino ide is only a small part of what is turned in this small microcontroller, and that is safely hidden by the manufacturer from the curious.

Connection to "Aquastorozhu"




Conclusion


It turned out to add quite accurately "Akvastorozh" in the existing Z-Wave network. The main disadvantage is the lack of feedback from Aquastorozh. At this stage, I am waiting for a new version of the ZUNo library, in which a bug will be fixed that prevents ZUNo from sleeping normally, therefore, instead of a photo with an installed and connected “Aquastoroge”, a picture with a debugging process.



Thanks for attention!

Sketch
//#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/447616/


All Articles