Menghubungkan Aquastorozh ke Smart Home di Z-Wave



Tahun lalu, saya membeli peralatan untuk menutup darurat crane ketika kebocoran dari Aquastorozh terdeteksi. Untuk waktu yang lama saya tidak bisa mengatakannya. Ada ide untuk mengintegrasikannya ke jaringan Z-Wave dan mendapatkan analog gidrolock, tetapi bekerja pada baterai. Akhirnya, tangan mencapai ...

Aquastorozh adalah pangkalan dengan keran plug-in dan sensor kebocoran. Kompleks ini dapat bekerja baik dari jaringan 220 V melalui adaptor, dan dari baterai. Para pengembang telah menyediakan kemampuan untuk terhubung ke sistem "rumah pintar". Dengan menutup satu pasang kontak di outlet Ethernet, Anda dapat membuka keran dan yang lainnya menutupnya. Relai kontak tutup selama 1 detik saat kebocoran terdeteksi. Ada konektor UART yang tidak disolder di papan tulis, tetapi dalam artikel ini saya akan berbicara tentang implementasi fungsi yang terdokumentasi.

Tugas pengembangan


  • Remote on / off tap.
  • Informasi kebocoran.
  • Dua meter air.
  • Jangan mengganggu pekerjaan "Aquastorozh"

Memutuskan untuk melakukan berdasarkan perisai ZUNo. Itu dikirim dalam selungkup tertutup dengan segel tekanan, memiliki blok terminal di papan dan ruang kosong untuk memasang baterai dan komponen elektronik tambahan. Arduino serupa.

Konektor ethernet




Salah satu kabel yang dapat ditutup adalah "bumi" dari "penjaga aqua". Anda dapat menggabungkan tanah ZUNo dan Aqua-Watch dan mengontrol derek secara langsung melalui GPIO ZUNo. Jadi saya lakukan. Tetapi dalam hal terjadi kegagalan ZUNo (misalnya, baterai telah habis), garis kontrol "Aquastorozh" menerima "nol" dan mulai memulai ulang secara siklis. Opsi koneksi semacam itu sangat memengaruhi keandalan seluruh sistem, oleh karena itu, setelah sedikit rumit sirkuitnya, saya beralih ke dua reed relay, yang menyediakan isolasi galvanik dari Aquastorozh. Relay mengkonsumsi sekitar 7 mA saat aktif. Untuk mengganti derek, Anda harus menyalakan satu relai selama satu detik, yang cukup bisa diterima. Daya baterai sudah cukup untuk beberapa ribu pergantian. (Sekarang saya memiliki relay kumparan single-elektromagnetik di tangan saya. Untuk menggantinya, Anda perlu menerapkan pulsa 1 ms, yang jauh lebih hemat energi. Tetapi untuk mengontrol Anda memerlukan 4 transistor dan dua kaki input / output untuk relai).

Tidur dalam gelombang Z


Saya akan berbicara sedikit tentang bagaimana perangkat Z-Wave tidur dan tentang masalah yang dihasilkan.
Perangkat Z-wave bisa tidak aktif atau sering terbangun. Perangkat tidur adalah yang paling hemat energi, tetapi tidak dapat mengirim perintah (dalam kasus saya, untuk mengganti crane). Tipe kedua cocok untuk saya. Perangkat FLiRS - Budak Routing yang Sering Mendengarkan. Perangkat yang dikonfigurasikan untuk mode operasi ini bangun setiap detik dan jika dalam waktu singkat ia tidak menerima sinyal untuk bangun penuh dari pengontrol, ia tertidur. Sebagai contoh: Saya mengirim perintah untuk membuka crane. Pengontrol memahami bahwa perangkat saya sering mendengarkan dan mengirimkan sinar wakeup pendek khusus dalam sedetik sehingga semua perangkat FLIRS pada jaringan terbangun. Segera setelah perangkat saya menerima paket ini, ia mengirimkan laporan bahwa ia telah bangun dan siap untuk menerima perintah. Mendapat perintah untuk menutup keran. Tertidur lagi. Dan setiap kali perangkat dikendalikan. Kerugiannya adalah bahwa perangkat dapat menerima sinar bangun pada akhir siaran oleh pengontrol dan di awal. Pengontrol mengirimkannya sekitar satu detik. Dalam kasus terburuk, perangkat bangun di awal buletin ini, dan akan menunggu hampir satu detik, sampai perintah tiba. Tetapi karena membuka dan menutup keran seringkali tidak diperlukan, ini bukan kelemahan serius.

Implementasi


ZUNo Shield memiliki papan tempat memotong roti kecil tempat Anda dapat meletakkan komponen yang diperlukan.



Rangkaian ini berisi dua relay dan dua transistor untuk kontrolnya. Sketsa kecil sederhana.



Beberapa kata tentang konsumsi energi.

Pelindung ZUNo berisi chip driver untuk protokol RS-485 dan resistor pull-up untuk pin "11" di blok bawah, untuk protokol One Wire. Setelah menghapus komponen-komponen ini, konsumen utama tetap ZUNo.



Konsumsi dalam mode tidur sekitar 5-10 μA, dan dalam mode aktif hingga 60 mA (relai aktif dan ZUNa mentransmisikan).

Oscillograms dari konsumsi saat ini untuk berbagai mode operasi


Arah sumbu saat ini adalah dari atas ke bawah.

Perangkat sedang menunggu perintah:



Kira-kira setiap detik, puncak-puncak pendek terlihat saat perangkat bangun dan memeriksa apakah berkas wakeUp telah tiba.

Perangkat menerima perintah:



Pertama, perangkat terbangun, menerima berkas wakeUp, menunggu perintah (dari 0 hingga 1 detik), jika perintah untuk mengontrol derek, nyala pada relai yang sesuai selama 1 detik (pada tahap ini Anda perlu meletakkan controller untuk tidur sambil menjaga kaki dalam keadaan saat ini, tetapi saya Saya takut dan terlalu malas) dan sisa waktu dihabiskan untuk operasi internal chip, setelah itu ZUNo tertidur. Total hampir 3,5 detik per satu operasi pembukaan atau penutupan dengan ketukan. Waktu yang sangat lama, tetapi karena fakta bahwa operasi seperti itu akan sangat jarang dilakukan, optimasi dapat diabaikan. Ya, dan itu akan memberikan sedikit, karena sketsa di ide Arduino hanya sebagian kecil dari apa yang dilemparkan dan dihidupkan mikrokontroler kecil ini, dan apa yang aman disembunyikan oleh produsen dari penasaran.

Skema koneksi ke "Aquastorozh"




Kesimpulan


Ternyata menambahkan "Aquastorozh" cukup akurat ke jaringan Z-Wave yang ada. Kerugian utama adalah kurangnya umpan balik dari Aquastorozh. Pada tahap ini saya sedang menunggu versi baru dari perpustakaan ZUNo, di mana bug akan diperbaiki yang mencegah ZUNo tidur normal, jadi alih-alih foto dengan Aquastorozh diinstal dan terhubung, gambar dengan proses debugging.



Terima kasih atas perhatian anda!

Sketsa
//#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/id447616/


All Articles