Sensor kebocoran air nirkabel pada nRF52832, proyek DIY

Salam kepada semua pembaca bagian DIY atau Do-it-yourself pada Habr! Hari ini saya ingin berbicara tentang proyek saya berikutnya, artikel ini akan membahas tentang detektor kebocoran air bertenaga baterai. Seperti pada proyek sebelumnya, perangkat ini berjalan pada mikrokontroler nRF52832. Ada tiga versi dari sensor ini, di ketiga versi modul siap pakai dengan nRF52832 digunakan, dalam artikel ini kita akan berbicara tentang versi tengah yang menggunakan modul YJ-17103 dari HOLYIOT.



Detektor fluida diimplementasikan pada chip SN74LVC1G00 | Datashit . Saya akan menjelaskan secara singkat desain sirkuit dan prinsip operasi. Sensor elektroda No. 1 terhubung ke tanah, elektroda sensor No. 2 terhubung ke kaki A dan B dari chip SN74LVC1G00 melalui resistor 100 Ohm, 3,3V melalui resistor 1M juga terhubung ke garis ini, kapasitansi juga ditambahkan ke sirkuit. Ketika tidak ada kontak dengan cairan pada kaki-kaki sirkuit mikro A dan B, unit logis, masing-masing, pada kaki Y yang terhubung ke kaki MK (yang secara terprogram dikonfigurasi untuk mendeteksi gangguan melalui pembanding bawaan) adalah logika nol. Segera setelah kontak dengan cairan terjadi dan kaki A dan B rendah, sinyal pada kaki Y dari rangkaian mikro SN74LVC1G00 juga terbalik, yang akan menyebabkan gangguan, yang pada gilirannya akan mengeluarkan MK dari tidur. Di masa depan, chip SN74LVC1G00 dapat diganti oleh chip SN74LVC1G14 | Datashit , dan mungkin tidak :). Deteksi cairan dari kaki MK melalui komparator internal tidak direncanakan.

Seperti semua proyek saya yang lain, yang ini juga merupakan proyek Arduino dan, seperti semua proyek selama setahun terakhir (kurang-lebih), proyek ini juga dibuat untuk proyek Mysensors. Seperti dalam artikel saya yang lain, saya akan sedikit menyentuh pada topik Mysensors dalam artikel ini.

Mysensors adalah komunitas pengembang open source. Protokol ini dikembangkan oleh komunitas untuk membuat radio dan jaringan kabel. Proyek ini awalnya dikembangkan untuk platform Arduino. Jaringan standar Mysensors terdiri dari gerbang (gateway), retransformers, dan perangkat akhir (node). Dalam satu jaringan bisa ada hingga 254 perangkat, masing-masing perangkat dapat dilengkapi dengan hingga 254 sensor, sensor, unit penggerak. Operasi jaringan, pemrosesan data, eksekusi skrip, dan interaksi di perangkat lain dilakukan menggunakan pengontrol UD. Beberapa pengendali (Majordomo) mendukung pekerjaan dengan beberapa jaringan dan Mysensor (multi-gerbang), sehingga mungkin ada lebih banyak jaringan daripada yang dikendalikan oleh satu pengontrol.

Platform perangkat keras yang didukung : Linux / Raspberry Pi / Orange Pi | ATMega 328P | ESP8266 | ESP32 | nRF5x (Cortex M0, M4) | Atmel SAMD digunakan dalam Arduino Zero (Cortex M0) | Teensy3 (MK66FX1M0VMD18) | STM32F1.

Pemancar Radio yang Didukung : NRF24L01 | RFM69 | RFM95 (LoRa) | nRF5x

Jenis Komunikasi Kabel yang Didukung : RS485

Komunikasi yang didukung antara gerbang dan pengontrol : MQTT | Serial USB | Wifi | Ethernet | GSM

Kembali ke sensor kebocoran. Perangkat ini didukung oleh baterai CR2430, CR2450 atau CR2477. Konsumsi tidur kurang dari 3ΞA. Kecepatan transmisi - 250Kbps, 10-15ms. Konsumsi daya pada saat transmisi tidak lebih dari 8mA. Secara teoritis, masa pakai baterai pada satu baterai kira-kira sama dengan waktu self-discharge baterai. Dalam prakteknya, tentu saja, semuanya kurang menyenangkan, karena ada pendaftaran, presentasi, pengiriman berkala tingkat pengisian, sehingga masa pakai baterai agak lebih dekat dengan nilai - waktu self-discharge / 2 :). Daya disuplai langsung dari baterai, level baterai dikendalikan langsung dari pin VDD. RGB LED dipasang di sensor untuk menunjukkan pendaftaran sensor di jaringan, untuk menunjukkan mode layanan dan untuk menunjukkan deteksi kebocoran. Secara alami, LED tidak dapat digunakan sama sekali atau digunakan sebagian.

Papan perangkat dibuat untuk pembuatan lebih lanjut sesuai dengan metode LUT. Oleh karena itu, dari nuansa opsi ini, ini merupakan peningkatan lebar trek, peningkatan jarak antar trek, peningkatan area untuk transisi antar lapisan (untuk pengeboran lubang yang lebih nyaman), dan tidak adanya pengisian di area kosong karena area kecil papan. Kemudian, opsi dibuat untuk pesanan dalam produksi.



Kasing perangkat dirancang dalam dua bagian. Penutup atas dengan tempat untuk memasang papan dan bagian bawah (bak) dengan 2 lubang untuk sekrup kontak baja (penyegelan dimungkinkan dengan sealant silikon untuk kepala sekrup atau tidak diperlukan) dan dua tabung untuk tombol (reset dan mode) pada papan. Pencetakan dilakukan pada printer 3D ANICUBIC PHOTON SLA. Setelah dicetak, amplas 320 dan 1000 diproses agar sesuai dengan sendi tutup dan bagian bawah tubuh.





Foto Sensor















Kode uji
wl_standart_test.ino

bool button_flag; bool send_flag; bool detection; bool nosleep; byte timer; bool AckG; bool AckB; bool AckL; bool PRESENT_ACK; bool flag_lq; unsigned long SLEEP_TIME = 172800000; //48 hours //unsigned long SLEEP_TIME = 3600000; //1 hour unsigned long oldmillis; unsigned long newmillis; unsigned long interrupt_time; unsigned long SLEEP_TIME_W; uint16_t currentBatteryPercent; uint16_t batteryVoltage = 0; uint16_t battery_vcc_min = 2300; uint16_t battery_vcc_max = 3000; int16_t linkQuality; #define MY_DISABLED_SERIAL #define MY_RADIO_NRF5_ESB #define MY_RF24_PA_LEVEL (NRF5_PA_MAX) //#define MY_PASSIVE_NODE #define MY_NODE_ID 86 #define MY_PARENT_NODE_ID 0 #define MY_PARENT_NODE_IS_STATIC #define MY_TRANSPORT_UPLINK_CHECK_DISABLED #define INTR_PIN 3 //(PORT0, gpio 5) #include <MySensors.h> // see https://www.mysensors.org/download/serial_api_20 #define W_L_SENS_CHILD_ID 0 #define LINK_QUALITY_CHILD_ID 253 MyMessage sensMsg(W_L_SENS_CHILD_ID, V_VAR1); //MyMessage voltMsg(CHILD_ID_VOLT, V_VOLTAGE); void preHwInit() { pinMode(POWER_PIN, OUTPUT); digitalWrite(POWER_PIN, HIGH); wait(3000); pinMode(RED_LED, OUTPUT); digitalWrite(RED_LED, HIGH); pinMode(GREEN_LED, OUTPUT); digitalWrite(GREEN_LED, HIGH); pinMode(BLUE_LED, OUTPUT); digitalWrite(BLUE_LED, HIGH); pinMode(PIN_BUTTON, INPUT); pinMode(W_L_SENS, INPUT); //pinMode(24, OUTPUT); //pinMode(20, OUTPUT); } void before() { NRF_POWER->DCDCEN = 1; NRF_UART0->ENABLE = 0; digitalWrite(BLUE_LED, LOW); sleep(50); digitalWrite(BLUE_LED, HIGH); } void presentation() { sendSketchInfo("EFEKTA ST WL Sensor", "1.1"); present(W_L_SENS_CHILD_ID, S_CUSTOM, "SWITCH STATUS"); present(LINK_QUALITY_CHILD_ID, S_CUSTOM, "LINK_QUALITY"); } void setup() { digitalWrite(BLUE_LED, LOW); wait(100); digitalWrite(BLUE_LED, HIGH); wait(200); digitalWrite(BLUE_LED, LOW); wait(100); digitalWrite(BLUE_LED, HIGH); lpComp(); detection = false; SLEEP_TIME_W = SLEEP_TIME; wait(100); sendBatteryStatus(); wait(100); send(sensMsg.set(detection), 1); wait(2000, 1, V_VAR1); } void loop() { if (nosleep == 0) { oldmillis = millis(); sleep(SLEEP_TIME_W); } if (detection) { if (digitalRead(PIN_BUTTON) == 1 && button_flag == 0 && digitalRead(W_L_SENS) == 0) { //back side button detection button_flag = 1; nosleep = 1; } if (digitalRead(PIN_BUTTON) == 1 && button_flag == 1 && digitalRead(W_L_SENS) == 0) { digitalWrite(GREEN_LED, LOW); wait(10); digitalWrite(GREEN_LED, HIGH); wait(50); } if (digitalRead(PIN_BUTTON) == 0 && button_flag == 1 && digitalRead(W_L_SENS) == 0) { nosleep = 0; button_flag = 0; digitalWrite(GREEN_LED, HIGH); lpComp_reset(); } if (digitalRead(W_L_SENS) == 1 && digitalRead(PIN_BUTTON) == 0) { //sens detection newmillis = millis(); interrupt_time = newmillis - oldmillis; SLEEP_TIME_W = SLEEP_TIME_W - interrupt_time; send(sensMsg.set(detection), 1); wait(3000, 1, V_VAR1); if (AckG == 1) { while (timer < 10) { timer++; digitalWrite(BLUE_LED, LOW); wait(20); digitalWrite(BLUE_LED, HIGH); wait(30); } timer = 0; AckG = 0; wait(200); } else { while (timer < 10) { timer++; digitalWrite(RED_LED, LOW); wait(20); digitalWrite(RED_LED, HIGH); wait(30); } timer = 0; send(sensMsg.set(detection), 1); wait(3000, 1, V_VAR1); if (AckG == 1) { while (timer < 10) { timer++; digitalWrite(BLUE_LED, LOW); wait(20); digitalWrite(BLUE_LED, HIGH); wait(30); } timer = 0; AckG = 0; } else { while (timer < 10) { timer++; digitalWrite(RED_LED, LOW); wait(20); digitalWrite(RED_LED, HIGH); wait(30); } timer = 0; } lpComp_reset(); } } if (SLEEP_TIME_W < 60000) { SLEEP_TIME_W = SLEEP_TIME; sendBatteryStatus(); } } else { //if (detection == -1) { SLEEP_TIME_W = SLEEP_TIME; sendBatteryStatus(); } } void receive(const MyMessage & message) { if (message.type == V_VAR1) { if (message.sensor == W_L_SENS_CHILD_ID) { if (mGetCommand(message) == 1) { if (message.isAck()) { AckG = 1; } else { } } } } if (message.type == I_BATTERY_LEVEL) { if (message.sensor == 255) { if (mGetCommand(message) == 3) { if (message.isAck()) { AckB = 1; } else { } } } } if (message.type == V_VAR1) { if (message.sensor == 255) { if (mGetCommand(message) == 1) { if (message.isAck()) { AckL = 1; } else { } } } } } void sendBatteryStatus() { wait(100); batteryVoltage = hwCPUVoltage(); wait(20); if (batteryVoltage > battery_vcc_max) { currentBatteryPercent = 100; } else if (batteryVoltage < battery_vcc_min) { currentBatteryPercent = 0; } else { currentBatteryPercent = (100 * (batteryVoltage - battery_vcc_min)) / (battery_vcc_max - battery_vcc_min); } sendBatteryLevel(currentBatteryPercent, 1); wait(3000, C_INTERNAL, I_BATTERY_LEVEL); if (AckB == 1) { AckB = 0; flag_lq = 1; } else { sendBatteryLevel(currentBatteryPercent, 1); wait(3000, C_INTERNAL, I_BATTERY_LEVEL); if (AckB == 1) { AckB = 0; flag_lq = 1; } } //send(powerMsg.set(batteryVoltage), 1); //wait(2000, 1, V_VAR1); //sleep(10000); // if (flag_lq == 1) { linkQuality = calculationRxQuality(); wait(50); sendSignalStrength(linkQuality, 1); wait(2000, 1, V_VAR1); if (AckL == 1) { AckL = 0; } else { sendSignalStrength(linkQuality, 1); wait(2000, 1, V_VAR1); if (AckL == 1) { AckG = 0; } } flag_lq = 0; } } void lpComp() { NRF_LPCOMP->PSEL = INTR_PIN; NRF_LPCOMP->ANADETECT = 1; NRF_LPCOMP->INTENSET = B0100; NRF_LPCOMP->ENABLE = 1; NRF_LPCOMP->TASKS_START = 1; NVIC_SetPriority(LPCOMP_IRQn, 15); NVIC_ClearPendingIRQ(LPCOMP_IRQn); NVIC_EnableIRQ(LPCOMP_IRQn); } void s_lpComp() { if ((NRF_LPCOMP->ENABLE) && (NRF_LPCOMP->EVENTS_READY)) { NRF_LPCOMP->INTENCLR = B0100; } } void r_lpComp() { NRF_LPCOMP->INTENSET = B0100; } #if __CORTEX_M == 0x04 #define NRF5_RESET_EVENT(event) \ event = 0; \ (void)event #else #define NRF5_RESET_EVENT(event) event = 0 #endif void lpComp_reset () { s_lpComp(); detection = false; NRF_LPCOMP->EVENTS_UP = 0; r_lpComp(); } //****************************** very experimental ******************************* bool sendSignalStrength(const int16_t level, const bool ack) { return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_SET, V_VAR1, ack).set(level)); } int16_t calculationRxQuality() { int16_t nRFRSSI_temp = transportGetReceivingRSSI(); int16_t nRFRSSI = map(nRFRSSI_temp, -85, -40, 0, 100); if (nRFRSSI < 0) { nRFRSSI = 0; } if (nRFRSSI > 100) { nRFRSSI = 100; } return nRFRSSI; } //****************************** very experimental ******************************* extern "C" { void LPCOMP_IRQHandler(void) { detection = true; NRF5_RESET_EVENT(NRF_LPCOMP->EVENTS_UP); NRF_LPCOMP->EVENTS_UP = 0; MY_HW_RTC->CC[0] = (MY_HW_RTC->COUNTER + 2); } } 

MyBoardNRF5.h

 #ifndef _MYBOARDNRF5_H_ #define _MYBOARDNRF5_H_ #ifdef __cplusplus extern "C" { #endif // __cplusplus #define PINS_COUNT (32u) #define NUM_DIGITAL_PINS (32u) #define NUM_ANALOG_INPUTS (8u) #define NUM_ANALOG_OUTPUTS (8u) #define PIN_LED1 (27) #define PIN_LED2 (25) #define PIN_LED3 (26) #define RED_LED (PIN_LED1) #define GREEN_LED (PIN_LED2) #define BLUE_LED (PIN_LED3) #define PIN_BUTTON (14) #define W_L_SENS (8) #define POWER_PIN (7) #define PIN_SERIAL_RX (12) #define PIN_SERIAL_TX (11) #ifdef __cplusplus } #endif #endif 


nRF52832 secara program dikonfigurasikan untuk beroperasi dalam mode daya rendah (Mode DC-DC). MC terbangun dari tidur oleh sinyal dari sirkuit mikro SN74LVC1G00 melalui komparator LPCOMP internal. Perangkat ini juga memiliki tombol jam untuk menerapkan mode layanan, seperti pemasangan perangkat, mengatur ulang perangkat, dll. Tombol terluka pada kaki MK yang sama dengan detektor kebocoran. Kedua garis dipisahkan oleh dioda Schottky. Chip SN74LVC1G00 dalam mode pemantauan tidak mengkonsumsi apa pun. Manajemen daya dari sirkuit mikro dilakukan dari kaki-kaki MK.

Saat ini, pengembangan pengontrol untuk kebocoran air yang dengannya sensor-sensor ini bekerja hampir selesai.

Video yang menunjukkan sensor kebocoran


Proyek Github
(file gerber, perangkat lunak, model kasus, daftar komponen)

Tempat di mana Anda selalu senang membantu semua orang yang ingin berkenalan dengan MYSENSORS (memasang papan, bekerja dengan mikrokontroler nRF5 di lingkungan IDE Arduino, kiat-kiat bekerja dengan protokol mysensors, membahas proyek-proyek hak cipta baru - telegram chat @mysensors_rus .

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


All Articles