Датчик температуры и влажности с RS485

Платки для датчика STH20 или функционально схожих модулей, микроконтроллером STM8, связью по RS485 и удобным подключением при помощи телефонных разъемов RJ12.

Является логическим завершением проекта описанного тут, тех попыток собрать на макетках. Датчик проектировался для использования в гараже, в качестве датчиков для системы осушения подвала и как уличный датчик температуры и влажности.

Сразу отвечу на мега популярный вопрос, почему провод и RS485, а не радио. Потому что для радио всеровно нужно подводить питание и провод, поэтому и микросхема MAX3485 за 15р оказывается проще, надежнее и не засоряет эфир.

Купить такое нельзя, но если надо, проект открытый, заказывайте платы, паяйте, прошивайте сами.


Схема:


Гербер:

Первая версия, с попутаными SDA и SCL для модуля GXHT30\SHT30, тут.

Исправленная и не проверенная, тут.


Код:

Код для ардуино под STM8. Логика работы: в шину отправляется запрос состоящий из двух символов, восклицательного знака и номера датчика, в ответ датчик отправляет пакет с данными в формате JSON. «!» в начале помогает отличить запрос от возможного мусора в шине, числовой «ID» для удобного перебора команд для датчиков на шине. JSON собирается без библиотек, его можно легко изменить под свои требования.

Для SHT20
#include <Wire.h>
#include <Serial.h> 

#define SHT20_address 0x40

#define DERE PD4             // PD4. ноги DERE RS485
#define LED PD3             // LED
const char cmd = '4';       // ID

void setup() {
  Wire_begin();
  Serial_begin(9600);
  delay(100);
  // Конф SHT20 отключение нагревателя
    // Wire_beginTransmission(SHT20_address);
    // Wire_write(0xE6);  // WRITE_USER_REG   
    // Wire_write(0b10000000);  
    // Wire_endTransmission();
    // // reset
    // Wire_beginTransmission(SHT20_address);
    // Wire_write(0xFE);  // SOFT_RESET      
    // Wire_endTransmission();
    
  pinMode(LED, OUTPUT);
  pinMode(DERE, OUTPUT);
//  digitalWrite(DERE, HIGH);  
//  Serial_print_s("OK");
  digitalWrite(DERE, LOW);  //  прием   
}

void loop() {
  // ждем команду   
   if (Serial_available()) {
    delay(2);  
    char val0 = Serial_read();                     // отсекаем команду от мусора  
    char readCmd = Serial_read();      
     if (val0 == '!' && readCmd == cmd){ 
     
  // SHT20
    byte data[2];
    Wire_beginTransmission(SHT20_address);
    Wire_write(0xF5);   
    Wire_endTransmission();
      delay(500);
    Wire_requestFrom(SHT20_address, 2);
      for (byte i = 0; Wire_available() > 0; i++){
        data[i] = Wire_read();
      }  
  // конвертируем данные с датчика в понятный  
    float hum = (((data[0] * 256.0 + data[1]) * 125.0) / 65536.0) - 6;
  // снова SHT20
  Wire_beginTransmission(SHT20_address);
    Wire_write(0xF3);   
    Wire_endTransmission();
      delay(500);
    Wire_requestFrom(SHT20_address, 2);
      for (byte y = 0; Wire_available() > 0; y++){
        data[y] = Wire_read();
      }  
  // конвертируем данные с датчика в понятный  
  float temp = (((data[0] * 256.0 + data[1]) * 175.72) / 65536.0) - 46.85;

 // включаем передачу и отправляем. 
    digitalWrite(LED, HIGH);
    digitalWrite(DERE, HIGH); 
     delay(100);
              //{"sensor":"cellar","temp":30.4,"hum":50.4}
    Serial_print_s("{\"s\":\"up\",\"temp\":");
    Serial_print_f(temp);
    Serial_print_s(",\"hum\":");
    Serial_print_f(hum);
    Serial_print_s("}");
  delay(100);
  digitalWrite(DERE, LOW);  
  digitalWrite(LED, LOW);    
  }  
//  delay(1000);
 }
}

Для SHT30
#include <Wire.h>
#include <Serial.h>

#define SHT30_address 0x45

#define DERE 13             // PD4. ноги DERE RS485
const char cmd = '1';       // ID

void setup() {
  Wire_begin();
  Serial_begin(9600);
  pinMode(DERE, OUTPUT);
//  digitalWrite(DERE, HIGH);  
//  Serial_print_s("OK");
  digitalWrite(DERE, LOW);  //  прием   
}

void loop() {
  // ждем команду   
   if (Serial_available()) {
    delay(2);  
    char val0 = Serial_read();                     // отсекаем команду от мусора  
    char readCmd = Serial_read();      
     if (val0 == '!' && readCmd == cmd){ 
     
  // SHT30
    byte data[6];
    Wire_beginTransmission(SHT30_address);
    Wire_write(0x2C);
    Wire_write(0x06);    
    Wire_endTransmission();
      delay(500);
    Wire_requestFrom(SHT30_address, 6);
      for (byte i = 0; Wire_available() > 0; i++){
        data[i] = Wire_read();
      }  
  // конвертируем данные с датчика в понятный  
    float temp = ((((data[0] * 256.0) + data[1]) * 175) / 65535.0) - 45;
    float hum = ((((data[3] * 256.0) + data[4]) * 100.0) / 65535.0);

 // включаем передачу и отправляем. 
    digitalWrite(DERE, HIGH); 
     delay(100);
              //{"sensor":"cellar","temp":30.4,"hum":50.4}
    Serial_print_s("{\"s\":\"cr\",\"temp\":");
    Serial_print_f(temp);
    Serial_print_s(",\"hum\":");
    Serial_print_f(hum);
    Serial_print_s("}");
  delay(100);
  digitalWrite(DERE, LOW);  
     
  }  
 }
}

Для SHT40
#include <Wire.h>
#include <Serial.h>

#define SHT40_address 0x44

#define DERE PD4             // PD4. ноги DERE RS485
#define LED PD3             // LED
const char cmd = '5';       // ID

void setup() {
  Wire_begin();
  Serial_begin(9600);
  pinMode(LED, OUTPUT);
  pinMode(DERE, OUTPUT);
//  digitalWrite(DERE, HIGH);  
//  Serial_print_s("OK");
  digitalWrite(DERE, LOW);  //  прием   
}

void loop() {
  // ждем команду   
   if (Serial_available()) {
    delay(2);  
    char val0 = Serial_read();                     // отсекаем команду от мусора  
    char readCmd = Serial_read();      
     if (val0 == '!' && readCmd == cmd){ 
     
  // SHT30
    byte data[6];
    Wire_beginTransmission(SHT40_address);
    Wire_write(0xFD); 
    Wire_endTransmission();
      delay(500);
    Wire_requestFrom(SHT40_address, 6);
      for (byte i = 0; Wire_available() > 0; i++){
        data[i] = Wire_read();
      }  
  // конвертируем данные с датчика в понятный  
    uint16_t t_ticks = data[0] * 256 + data[1];
    uint16_t rh_ticks = data[3] * 256 + data[4];
    float temp = t_ticks * 175.0 / 65535.0 - 45;
    float hum = rh_ticks * 125.0 / 65535.0 - 6;
    if (hum > 100.0) hum = 99.9;
    if (hum < 0.0) hum = 0.1;

 // включаем передачу и отправляем. 
    digitalWrite(LED, HIGH); 
    digitalWrite(DERE, HIGH); 
     delay(100);
              //{"sensor":"cellar","temp":30.4,"hum":50.4}
    Serial_print_s("{\"s\":\"in\",\"temp\":");
    Serial_print_f(temp);
    Serial_print_s(",\"hum\":");
    Serial_print_f(hum);
    Serial_print_s("}");
  delay(100);
  digitalWrite(DERE, LOW);  
  digitalWrite(LED, LOW);   
  }  
 }
//  delay(1000);

}


Видео:

https://youtu.be/y3IT4a37ptM