MSMD, TempHumidity, Контроллер Температуры/Влажности

Показывайте и делитесь своими замечательными проектами здесь! Мы любим картинки!
Ответить
Аватара пользователя
Ivan
Администратор
Сообщения: 21
Зарегистрирован: 07 июн 2017, 08:03
Откуда: Taganrog
Контактная информация:

MSMD, TempHumidity, Контроллер Температуры/Влажности

Сообщение Ivan »

IMG_1441m.jpg
IMG_1441m.jpg (33.56 КБ) 14502 просмотра
Описание:
  • Контроллер температуры/влажности
  • Тип питания: Батарея cr2032
Характеристики:
  • Разработан для экосистемы MySensors
  • Питание от батареи cr2032 (1 год работы, при отправке данных раз в час)
  • Температура эксплуатации: комнатный 0 до +70
  • Возвращает Температуру, Влажность, Уровень батареи
  • Имеет компактный размер 38 х 12,5 мм
GitHub: https://github.com/Serg2055/MDMSTempHum
Разработчики: Сергей Лекарев

Фото:
Spoiler
Show
6.jpg
6.jpg (47.92 КБ) 14903 просмотра
5.jpg
5.jpg (36.51 КБ) 14903 просмотра
4.jpg
4.jpg (40.79 КБ) 14903 просмотра
3.jpg
3.jpg (33.98 КБ) 14903 просмотра
2.jpg
2.jpg (81.82 КБ) 14903 просмотра
1.jpg
1.jpg (25.1 КБ) 14903 просмотра
Аватара пользователя
Ivan
Администратор
Сообщения: 21
Зарегистрирован: 07 июн 2017, 08:03
Откуда: Taganrog
Контактная информация:

Re: MSMD, TempHumidity, Контроллер Температуры/Влажности

Сообщение Ivan »

Датчик испытан и готов к продаже

Притаился на холодильнике
IMG_1431.JPG
IMG_1431.JPG (200.43 КБ) 14537 просмотров
Sergey2055
Сообщения: 50
Зарегистрирован: 04 июл 2017, 13:43

Re: MSMD, TempHumidity, Контроллер Температуры/Влажности

Сообщение Sergey2055 »

MSMD, Temp, HUM. Датчик температуры и влажности - первый старт и последующая настройка.

Для первого старта сенсора измерения температуры и влажности достаточно минимального набора. Для этого нужен Гейт на связи и подключенный к контроллеру управления с любой системой (лучше применить majordomo и ему подобные, т. к. в некоторых системах, отсутствует ручное добавление сенсоров, которые могут понадобиться для калибровки и установки своих желаемых параметров). Дале нужно просто снять верхнюю крышку с устройства и вставить батарейку. Устройство сразу презентуется и начнет свою работу. Устройство сразу начнет слать данные на контроллер. Первые 8 минут устройство находится в режиме смарт слипа. Этот режим реализован для удобства быстрого изменения нужных параметров, т.к. если устройство выйдет в нормальный режим и настройки периода могут быть от нескольких минут до нескольких часов, то ждать придется очень долго. Также через каждые 6 либо 24 часов включается режим smartsleep на 1 отправку, это реализовано для удобства правки некоторых параметров, чтоб не отключать батарею.
Безымянный2.png
Безымянный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
Безымянный.png (29.12 КБ) 14482 просмотра
Добавление калибровочных констант
Изначально калибровочные константы не отображаются в контроллере majordomo, чтобы их добавить нужно выполнить следующее: зайти в раздел сенсоры и нажать кнопку добавить новую запись. Появится окно добавления. Здесь нужно выбрать номер добавляемого сенсора и тип переменной для этого сенсора.
123-2.png
123-2.png (326.08 КБ) 14482 просмотра
123-3.png
123-3.png (331.2 КБ) 14482 просмотра
После выбора нажать добавить. После чего появятся новые сенсоры. Список всех сенсоров можно посмотреть в разделе презентация.
Безымянный1.png
Безымянный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;
}
Вложения
temp_sensors.zip
(11.49 КБ) 516 скачиваний
image_2019_06_26T07_16_41_971Z.png
image_2019_06_26T07_16_41_971Z.png (129.22 КБ) 14393 просмотра
photo_2019-05-30_12-42-37.jpg
photo_2019-05-30_12-42-37.jpg (113.17 КБ) 14482 просмотра
Ответить