MSMD, Temp, HUM. Датчик температуры и влажности - первый старт и последующая настройка.
Для первого старта сенсора измерения температуры и влажности достаточно минимального набора. Для этого нужен Гейт на связи и подключенный к контроллеру управления с любой системой (лучше применить majordomo и ему подобные, т. к. в некоторых системах, отсутствует ручное добавление сенсоров, которые могут понадобиться для калибровки и установки своих желаемых параметров). Дале нужно просто снять верхнюю крышку с устройства и вставить батарейку. Устройство сразу презентуется и начнет свою работу. Устройство сразу начнет слать данные на контроллер. Первые 8 минут устройство находится в режиме смарт слипа. Этот режим реализован для удобства быстрого изменения нужных параметров, т.к. если устройство выйдет в нормальный режим и настройки периода могут быть от нескольких минут до нескольких часов, то ждать придется очень долго. Также через каждые 6 либо 24 часов включается режим smartsleep на 1 отправку, это реализовано для удобства правки некоторых параметров, чтоб не отключать батарею.
- Безымянный2.png (38.65 КБ) 14482 просмотра
Примеры данных следующие:
1. Sensor:2, V_HUM; Msg: – уровень влажности воздуха в процентах. (0 < V_HUM < 100);
2. Sensor:1, V_TEMP; Msg: – температура воздуха °С.
3. Sensor:5, V_VAR1; Msg: - уровень заряда батареи в относительных единицах. (min < V_VAR1 < max);
4. BATTERY_LEVEL; Msg: - уровень заряда батареи в процентах. (0 < BATTERY_LEVEL < 100);
Пример данных в системе с привязкой к свойствам:
- Безымянный.png (29.12 КБ) 14482 просмотра
Добавление калибровочных констант
Изначально калибровочные константы не отображаются в контроллере majordomo, чтобы их добавить нужно выполнить следующее: зайти в раздел сенсоры и нажать кнопку добавить новую запись. Появится окно добавления. Здесь нужно выбрать номер добавляемого сенсора и тип переменной для этого сенсора.
- 123-2.png (326.08 КБ) 14482 просмотра
- 123-3.png (331.2 КБ) 14482 просмотра
После выбора нажать добавить. После чего появятся новые сенсоры. Список всех сенсоров можно посмотреть в разделе презентация.
- Безымянный1.png (19.8 КБ) 14482 просмотра
Описание настроек сенсоров и констант:
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) - версия железа.
Краткие Технические характеристики:
Питание от 2,1 до 3,6в (CR2032);
Потребление в активном режиме 1,3 мА;
Потребление в режиме отправки 16 мА
Потребление в режиме сна 7 мкА;
Устройство сохраняет работоспособность при разряде батареи до 1,8 В, но есть вероятность нестабильности или полного отсутствия показаний температуры.
Полностью завершены испытания на срок службы от одной батареи. Испытания показали: при использовании нормального элемента питания и периодом отправки сенсора в 10 минуть, срок службы измеряется от двух лет и более.
Исходники для первого проекта. Исходники устаревшие но все полностью рабочие и протестированные. Также может быть небольшое расхождение между схемой и платой или кодом.
Код: Выделить всё
/*
* Filename: Test.ino
* Created Date: Sunday, june 16 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>
#include <SHT2x.h>
#define SKETCH_NAME "MSMDTemp_Hum-Meter"
#define SKETCH_MAJOR_VER "1"
#define SKETCH_MINOR_VER "0"
#define BAT_PIN A0 // 23
#define SID_TEMP 1
#define SID_HUM 2
#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 cGateAdr 0
#define SmartSetting 5
#define DEF_FREQUENCY 1 // min
#define DEB_SWITCH_PIN 4
word min_batt = 600;
word max_batt = 1000;
unsigned long Freq = DEF_FREQUENCY*60*1000ul;
int SmartTime = 360 / DEF_FREQUENCY;
const int MAX_ADC_VALUE = 1023;
float LastTemp = 0;
int LastHum = 0;
int LastBat = 0, SmartCount = 0;
byte CountPreSmartSleep = 0;
int BatV;
MyMessage msgTemp(SID_TEMP, V_TEMP);
MyMessage msgHum(SID_HUM, V_HUM);
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);
//=== Read from memory
// Freq
uint8_t fBVal = loadState(mFreq);
if (fBVal != MaxByte) {
Freq = int(fBVal)*60*1000ul;
SmartTime = 360 / int(fBVal);
}
// 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);
Wire.begin();
analogReference(INTERNAL);
}
void presentation() {
// Send the sketch version information to the gateway and Controller
sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER"."SKETCH_MINOR_VER);
present(SID_TEMP, S_TEMP, "Temp-data");
present(SID_HUM , S_HUM, "Hum-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 MINUTE");
}
void loop() {
wdt_reset();
// Read temp
float fTemp = GetTemp();
// Read hum
int fHum = GetHum();
// Send temp
if (fTemp != LastTemp) {
LastTemp = fTemp;
SendTmp(cGateAdr, fTemp);
}
// Send hum
if (fHum != LastHum) {
LastHum = fHum;
SendHum(cGateAdr, fHum);
}
if(SmartCount < SmartTime && CountPreSmartSleep >= SmartSetting){
SmartCount++;
// Send bat
if (BatV != LastBat) {
LastBat = BatV;
SendBatt(cGateAdr,BatV);
}
sleep(Freq); }
else{
if(CountPreSmartSleep < SmartSetting){
CountPreSmartSleep++; SendBatt(cGateAdr,BatV); smartSleep(60000);}
else{
SmartCount = 0; smartSleep(Freq); }}
// Serial.print("SmartCount");
//Serial.println(SmartCount);
// Serial.print("SmartTime");
// Serial.println(SmartTime);
// Serial.print("CountPreSmartSleep");
// Serial.println(CountPreSmartSleep);
}
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*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.getInt() * 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 SendTmp(byte Dest, float val){
send(msgTemp.set(val, 1).setDestination(Dest).setType(V_TEMP));
}
void SendHum(byte Dest, int val){
send(msgHum.set(val, 0).setDestination(Dest).setType(V_HUM));
}
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));
}
// Read bat
BatV = analogRead(BAT_PIN);
}
float GetTemp(){
float Temp;
Temp = (SHT2x.readT());
return Temp;
}
float GetHum(){
float Humidity;
Humidity = (SHT2x.readRH());
return Humidity;
}