Онлайн датчики температури ESP8266-01+MQTT+3хDS18B20

В попредньому запису зробили датчик, що моніторить температуру та вологість в кабінеті у співробітників складу. Для розуміння ситуації на складі в цілому мені необхідно отримати інформацію про температуру безпосередньо на складі, на вулиці, а також в просторі між потолком та кришею (для відстеження тепловтрат).
По тому ж принципу що і в попередній системі, інформацію необхідно передавати MQTT-брокеру на сервері Amazon звідки NODE-RED буде брати дані для побудови графіків та подальшої обробки.

Так як показники вологості не є необхідними, в даному завданні для вимірювання ідеальними будуть DS18B20 так як дозволять подключити декілька датчиків на один пін ESP8266-01.
Отже нам необхідно:
1. ESP8266-01 - 1шт.
2. DS18B20 - 3шт.
3. USB-TTL конвертер BTE13-009 (процес підключення та прошивки описувати не буду, про це детально писав тут http://www.sast.in.ua/2017/01/esp-link.html)
4. Живлення отримаю від камери спостередження, а так як це 12в то для перетворення на 3.3в нам знадобиться щось серйозніше ніж модуль AMS1117-3.3, тому в нагоді став DC-DC понижуючий конвертер LM2596 з 4.5-40В до 3-35В
5. Корпус, зєднувальні дроти, макетна плата та ін.

Трішки модифікую скетч з попередньої роботи, додавши функцію роботи з OneWire та DS18B20, видаливши зайве та трышки оптимізувавши:

// esp8266 + ds18b20 + mqtt

#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <OneWire.h>
#include <DallasTemperature.h>

const char* ssid;
const char* ssid1 = "******";
const char* ssid2 = "******";
const char* password = "**********";

char* topict01 = "/sast/spf02/t01";
char* topict02 = "/sast/spf02/t02";
char* topict03 = "/sast/spf02/t03";
char* server = "***********";
char* hellotopic = "hello_topic";

#define ONE_WIRE_BUS 2  // DS18B20 pin
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
#define REPORT_INTERVAL 600 // in sec

int conprobe = 0;

String clientName;
WiFiClient wifiClient;
PubSubClient client(server, 1883, wifiClient);

float oldT01 ;
float oldT02 ;
float oldT03 ;

DeviceAddress sensor1 = {0x28, 0xFF, 0x90, 0x86, 0xC2, 0x15, 0x1, 0x7E};
DeviceAddress sensor2 = {0x28, 0xFF, 0xC3, 0x2F, 0xC2, 0x15, 0x2, 0x7D};
DeviceAddress sensor3 = {0x28, 0xFF, 0x5D, 0x3F, 0xC2, 0x15, 0x2, 0x50};

void setup() {
  Serial.begin(115200);
  Serial.println("DS18B20 test!");
  delay(20);
  ssid = ssid1;
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    conprobe = conprobe + 1;
    if (conprobe == 15) {
    if (ssid == ssid1) {ssid = ssid2;} else {ssid = ssid1;}
    Serial.println("");
    Serial.print("Connecting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, password);
    conprobe = 0;      
    }    
  }
  
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  clientName = "SAST-SPF02";
  
  Serial.print("Connecting to ");
  Serial.print(server);
  Serial.print(" as ");
  Serial.println(clientName);

  if (client.connect((char*) clientName.c_str())) {
    Serial.println("Connected to MQTT broker");
    Serial.println("Topic is: ");
    Serial.println(topict01);
    Serial.println(topict02);
    Serial.println(topict03);
    
    if (client.publish(hellotopic, "hello from ESP8266")) {
      Serial.println("Publish ok");
    }
    else {
      Serial.println("Publish failed");
    }
  }
  else {
    Serial.println("MQTT connect failed");
    Serial.println("Will reset and try again...");
    abort();
  }
  oldT01 = -1;
  oldT02 = -1;
  oldT03 = -1;
}

void loop() {

  float t01;
  float t02;
  float t03;

do {
    DS18B20.requestTemperatures(); 
    t01 = DS18B20.getTempC(sensor1);
    t02 = DS18B20.getTempC(sensor2);
    t03 = DS18B20.getTempC(sensor3);
    Serial.println("Temperature: ");
    Serial.println(t01);
    Serial.println(t02);
    Serial.println(t03);
  } while (t01 == 85.0 || t01 == (-127.0));

String  payloadt01 = "";
String  payloadt02 = "";
String  payloadt03 = "";
payloadt01 += t01;
payloadt02 += t02;
payloadt03 += t03;
 
  if (t01 != oldT01 || t02 != oldT02 ||t03 != oldT03)
  {
    sendTemperature(payloadt01, payloadt02, payloadt03);
    oldT01 = t01;
    oldT02 = t02;
    oldT03 = t03;
  }
 
  
  int cnt = REPORT_INTERVAL;

  while (cnt--)
    delay(1000);
}

void sendTemperature(String payloadt01,String payloadt02,String payloadt03) {
  if (!client.connected()) {
    if (client.connect((char*) clientName.c_str())) {
      Serial.println("Connected to MQTT broker again");
      Serial.println("Topic is: ");
      Serial.println(topict01);
      Serial.println(topict02);
      Serial.println(topict03);
    }
    else {
      Serial.println("MQTT connect failed");
      Serial.println("Will reset and try again...");
      abort();
    }
  }

  if (client.connected()) {
    Serial.println("Sending payload: ");
    Serial.println(payloadt01);
    Serial.println(payloadt02);
    Serial.println(payloadt03);

    if (client.publish(topict01, (char*) payloadt01.c_str())) {
      Serial.println("Publish T01 ok");
    }
    else {
      Serial.println("Publish T01 failed");
    }
    if (client.publish(topict02, (char*) payloadt02.c_str())) {
      Serial.println("Publish T02 ok");
    }
    else {
      Serial.println("Publish T02 failed");
    }

    if (client.publish(topict03, (char*) payloadt03.c_str())) {
      Serial.println("Publish T03 ok");
    }
    else {
      Serial.println("Publish T03 failed");
    }    
  }
}

Так як все налаштовую вдома, а працювати буде на складі, додав дві мережі пошук яких відбувається по черзі і в залежності яка доступна - до тої і приєднується.
Також важливим моментом є визначення фізичних адрес датчиків DS18B20 (в скетчі вказані ті що у мене, їх необхідно замінити). Щоб отримати адреси DS18B20 зручно використатит скетч що входить в стандартні приклади Arduino IDE:
#include <OneWire.h>

// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
  
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();

  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
  
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
}

Отримані з даного скетчу адреси зберігаємо і підставляємо в основний код в поля:
DeviceAddress sensor1 = {0x28, 0xFF, 0x90, 0x86, 0xC2, 0x15, 0x1, 0x7E};
DeviceAddress sensor2 = {0x28, 0xFF, 0xC3, 0x2F, 0xC2, 0x15, 0x2, 0x7D};
DeviceAddress sensor3 = {0x28, 0xFF, 0x5D, 0x3F, 0xC2, 0x15, 0x2, 0x50};

Заливаємо скетч в ESP8266-01, підключаємо згідно схеми:
Перевіряємо що отримали на на нашому MQTT-брокері, і якщо все зроблено вірно - з інтервалом 10хв на сервер буде відправлятися температура з кожного датчика.
І після незначних налаштувань NODE-RED - отримуємо зручний інструмент моніторингу.
Фото встановлених датчиків в робочому просторі додам коли відправлю систему на постійне місце перебування.....



Коментарі

Популярні дописи з цього блогу

ESP8266+ARDUINO NANO связь через ESP-link ч.1

Arduino выходит в Интернет (ARDUINO+MQTT+IBM Bluemix) ч.1