Контроллер протечки воды
Тип питания: Батарея cr2032
Характеристики:
Разработан для экосистемы MySensors
Питание от 2,0 до 3,6в (CR2032);
Потребление в активном режиме 1,3 мА;
Потребление в режиме отправки 16 мА
Потребление в режиме сна 4,3 мкА;
Температура эксплуатации: комнатный 0 до +70
Возвращает 1 при протечки воды (0 - нормальное состояние), Уровень батареи
Имеет компактный размер 40 х 14,5 мм
Датчик полностью герметичен, при большом уровне воды плавает.
Электрическая часть полностью защищена от попадания влаги в случае нарушения герметичности корпуса.
Полностью завершены испытания на срок службы от одной батареи. Испытания показали: при использовании нормального элемента питания срок службы измеряется от двух лет и более.
Для первого старта сенсора протечки воды достаточно минимального набора. Для этого нужен Гейт на связи и подключенный к контроллеру управления с любой системой (лучше применить majordomo и ему подобные, т. к. в некоторых системах, отсутствует ручное добавление сенсоров, которые могут понадобиться для калибровки и установки своих желаемых параметров). Дале нужно просто снять верхнюю крышку с устройства и вставить батарейку. Устройство сразу презентуется и начнет свою работу. Устройство сразу начнет слать данные на контроллер. Первые 5 минут устройство находится в режиме смарт слипа. Этот режим реализован для удобства быстрого изменения нужных параметров, т.к. если устройство выйдет в нормальный режим и настройки периода могут быть от нескольких минут до нескольких часов, то ждать придется очень долго. Также через настроенный промежуток времени 1- 24 часов включается режим smartsleep на 1 отправку, это реализовано для удобства правки некоторых параметров, чтоб не отключать батарею. Светодиод расположенный на плате устройства сигнализирует одной короткой вспышкой о том что устройство проснулось и идет анализ параметров.
Аналогию работы и настройку можно посмотреть тут: viewtopic.php?f=3&t=462
Примеры данных следующие:
1. Sensor:1, V_ARMED; Msg: – состояние детектора протечки. (0;1);
2. Sensor:5, V_VAR1; Msg: - уровень заряда батареи в относительных единицах. (min < V_VAR1 < max);
3. BATTERY_LEVEL; Msg: - уровень заряда батареи в процентах. (0 < BATTERY_LEVEL < 100);
Добавление калибровочных констант
Изначально калибровочные константы не отображаются в контроллере majordomo, чтобы их добавить нужно выполнить следующее: зайти в раздел сенсоры и нажать кнопку добавить новую запись. Появится окно добавления. Здесь нужно выбрать номер добавляемого сенсора и тип переменной для этого сенсора.
После выбора нажать добавить. После чего появятся новые сенсоры. Список всех сенсоров можно посмотреть в разделе презентация.
Описание настроек сенсоров и констант:
1. Сенсор: 5(S_MULTIMETER), Тип: V_VAR5 – этот параметр устанавливает нижнюю и верхнюю границы для расчета уровня заряда батареи. Калибровка производится так же как и в пункте 1. Надо подать на устройство напряжение с источника питания либо с батареи в пределах 0,75В-1,7, установить желаемые параметры и отправить на устройство. Также его можно запросить.
2. Сенсор: 212(S_CUSTOM), Тип: V_VAR1 - этот параметр устанавливает период отправки значений в минутах. Для его установки нужна отправит значение в минутах как описано в пункте 1. Также его можно запросить.
3. Сенсор: 211(S_CUSTOM, Тип: V_VAR1) – этот параметр осуществляет смену номера (ID) устройства. Смена осуществляется так же как описано в пункте 1. Параметр может быть в пределах 1-254.
4. Сенсор: 210(S_CUSTOM) - версия железа.
Видео с примером работы: https://youtu.be/q6JxO4Z9jfk
Исходники для первого проекта. Исходники устаревшие но все полностью рабочие и протестированные. Также может быть небольшое расхождение между схемой и платой или кодом.
Код: Выделить всё
/*
* Filename: Water-Detector.ino
* Created Date: Sunday, jule 28 2019, 2:16:34 pm
* Author: Sergey Lekarev
*
* Copyright (c) 2019 Sergey Lekarev
*
*
*/
#define MY_NODE_ID AUTO
#define MY_PARENT_NODE_ID AUTO
#define MY_SMART_SLEEP_WAIT_DURATION_MS (1000ul)
//#define MY_SIGNING_SOFT
//#define MY_SIGNING_ATSHA204 // Hardware signing using ATSHA204A
//--------------------------------------------
// Enable and select radio type attached
#define MY_RADIO_RF24
//#ifdef MY_SIGNING_ATSHA204
// #define MY_SIGNING_ATSHA204_PIN 17 // A3
//#else
// #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7
//#endif
// Enable debug prints to serial monitor
#define MY_DEBUG
//#define DEBUG
#include <MySensors.h>
#include <avr/wdt.h>
#include <EEPROM.h>
#include <Wire.h>
#define SKETCH_NAME "MSMDWater-Detector"
#define SKETCH_MAJOR_VER "1"
#define SKETCH_MINOR_VER "0"
#define BAT_PIN A0 // 23
#define SID_WATER 1
#define SID_BATTERY 5
#define SID_MSMD 210
#define SID_NodeID 211
#define SID_FREQ 212
#define MaxByte 0xFF
#define MaxWord 0xFFFF
#define mBatMin 0
#define mBatMax 2
#define mFreq 8
#define Master_parent 9
#define cGateAdr 0
#define SensorWateDetect 3
#define Led A1
#define DEF_FREQUENCY 1 // min
#define DEB_SWITCH_PIN 2
#define SmartSetting 5
#define MaxSmallTry 10 //Количество попыток отправки пакета.
#define PauseTX 100
word min_batt = 600;
word max_batt = 1000;
unsigned long Freq = DEF_FREQUENCY*60*60*1000ul;
const int MAX_ADC_VALUE = 1023;
int LastBat = 0;
byte CountPreSmartSleep = 0;
int SmartCount = 0, BatV;
bool flag = 0;
MyMessage msgWater(SID_WATER, V_ARMED);
MyMessage msgBat(SID_BATTERY, V_VAR1);
MyMessage msgFreq(SID_FREQ, V_VAR1);
void(* resetFunc) (void) = 0;
// String var = getValue( StringVar, ',', 2); // if a,4,D,r would return D
String getValue(String data, char separator, int index){
int found = 0;
int strIndex[] = { 0, -1 };
int maxIndex = data.length();
for (int i = 0; i <= maxIndex && found <= index; i++) {
if (data.charAt(i) == separator || i == maxIndex) {
found++;
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
} // END
void before(){
wdt_disable();
pinMode(DEB_SWITCH_PIN, INPUT_PULLUP);
if (digitalRead(DEB_SWITCH_PIN) == LOW){
for (int i=0;i<512;i++)
EEPROM.write(i, 0xFF);
}
// Battery
pinMode(BAT_PIN, INPUT);
//WATER sensor
pinMode(SensorWateDetect, INPUT);
//Led
pinMode(Led, OUTPUT);
//=== Read from memory
// Freq
uint8_t fBVal = loadState(mFreq);
if (fBVal != MaxByte) {
Freq = long(fBVal)*60*60*1000ul;
}
// Min bat
uint16_t fVal = word(loadState(mBatMin+1), loadState(mBatMin));
if (fVal != MaxWord) {
min_batt = fVal;
}
// Max bat
fVal = word(loadState(mBatMax+1), loadState(mBatMax));
if (fVal != MaxWord) {
max_batt = fVal;
}
}
void setup(){
wdt_enable(WDTO_8S);
analogReference(INTERNAL);
for(int i = 0; i < 10; i++){
digitalWrite(Led, HIGH);
wait(50);
digitalWrite(Led, LOW);
wait(50);
}
}
void presentation() {
// Send the sketch version information to the gateway and Controller
sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER"."SKETCH_MINOR_VER);
present(SID_WATER, S_WATER_LEAK, "Water-data");
present(SID_BATTERY, S_MULTIMETER, "Battery");
present(SID_MSMD, S_CUSTOM, "a00678cb4bc49c5e");
present(SID_NodeID, S_CUSTOM, "Node ID");
present(SID_FREQ, S_CUSTOM, "NODE FREQ HOUR");
}
void loop() {
wdt_reset();
if(CountPreSmartSleep >= SmartSetting){
int8_t slumber = sleep(digitalPinToInterrupt(SensorWateDetect), FALLING, Freq, true); // Засыпаем
digitalWrite(Led, HIGH);
if (slumber == 1){
while(digitalRead(SensorWateDetect) == 0){
digitalWrite(Led, HIGH);
bool Water = !digitalRead(SensorWateDetect);
SendWater(cGateAdr, Water);
digitalWrite(Led, LOW);
sleep(10000);
}
wait(1000);
bool Water = !digitalRead(SensorWateDetect);
SendWater(cGateAdr, Water);
}
if (BatV != LastBat) {
LastBat = BatV;
SendBatt(cGateAdr,BatV);
}
bool Water = !digitalRead(SensorWateDetect);
SendWater(cGateAdr, Water);
digitalWrite(Led, LOW);
}
else{
digitalWrite(Led, HIGH);
SendBatt(cGateAdr,BatV);
bool Water = !digitalRead(SensorWateDetect);
SendWater(cGateAdr, Water);
CountPreSmartSleep++;
digitalWrite(Led, LOW);
smartSleep(10000);
}
}
void receive(const MyMessage &message) {
if (message.isAck()) {
return;
}
String Str = "";
uint8_t Dest = message.sender;
// Request
if (mGetCommand(message) == C_REQ) {
switch (message.sensor) {
case SID_BATTERY:
switch (message.type) {
case V_VAR1:
SendBatt( Dest, analogRead(BAT_PIN) );
break;
case V_VAR5:
Str = String(min_batt) + "," + String(max_batt);
send(msgBat.set(Str.c_str()).setDestination(Dest).setType(V_VAR5));
break;
}
break;
case SID_FREQ:
send( msgFreq.set(Freq / (60*60*1000)) );
break;
}
return;
}
// Set NULL date (if empty sensors)
if (strlen(message.getString()) == 0) {
return;
}
switch (message.sensor) {
case SID_BATTERY:
switch (message.type) {
case V_VAR5:
min_batt = word(getValue(String(message.getString()), ',', 0).toInt()); //выделяется нулевой элемент строки и приводится к типу инт и потом в ворд
max_batt = word(getValue(String(message.getString()), ',', 1).toInt()); //выделяется первый элемент строки и приводится к типу инт и потом в ворд
saveState(mBatMin+1, highByte(min_batt));
saveState(mBatMin, lowByte(min_batt));
saveState(mBatMax+1, highByte(max_batt));
saveState(mBatMax, lowByte(max_batt));
break;
}
break;
case SID_FREQ:
Freq = message.getByte() * 60*60*1000ul;
saveState(mFreq, message.getInt());
break;
// NODE_NEW_ID; type == V_VAR1
case SID_NodeID:
byte Node_ID = message.getByte();
hwWriteConfig(EEPROM_NODE_ID_ADDRESS, Node_ID);
resetFunc();
break;
}
}
void SendWater(byte Dest, bool val){
int send_ok = TX(0, SID_WATER, V_ARMED, val);
}
void SendBatt(byte Dest, word val){
if(CountPreSmartSleep < SmartSetting){
send(msgBat.set(BatV).setDestination(cGateAdr).setType(V_VAR1));
}
if (Dest == 0){
sendBatteryLevel(constrain(map(val, min_batt, max_batt, 0, 100), 0, 100));
}
BatV = analogRead(BAT_PIN);
}
int TX(byte Master_id, byte ID_sensors, byte Type_variable, bool variable)
{
wdt_reset();
byte count_tx = 0;
MyMessage msg(ID_sensors, Type_variable);
int send_data = send(msg.setDestination(Master_id).setSensor(ID_sensors).set(variable), true);
wait(1000, ID_sensors, Type_variable);
if (send_data == 0)
{
Serial.print("Delivery failed: ");
Serial.println(send_data);
while (send_data == 0 && count_tx < MaxSmallTry)
{
wdt_reset();
count_tx++;
Serial.print("Sending a message try No.");
Serial.println(count_tx);
send_data = send(msg.set(variable), true);
wait(1000, ID_sensors, Type_variable);
}
}
else
{
Serial.print("Delivery: OK - ");
Serial.println(send_data);
}
Serial.print("Count: ");
Serial.println(count_tx);
count_tx = 0;
return send_data;
}