Terracontrol (reptile vivarium automation)

Getting measurements

The desired output will be in JSON format, this is a lightweight human readable data structure that allows us to use the data later in other devices or programs.

{
  "node": "84:F3:EB:EE:65:92",
  "measurements": {
    "temperature": [
      {
        "type": "DS18B20",
        "id": 0,
        "value": 24.8
      },
      {
        "type": "DS18B20",
        "id": 1,
        "value": 25
      },
      {
        "type": "SHT11",
        "value": 25.4
      }
    ],
    "humidity": [
      {
        "type": "SHT11",
        "value": 37
      }
    ]
  }
}

I use PlatformIO to program my microcontrollers but the used sketch should also work in the Arduino IDE.

Arduino code

The code I use to get the JSON output is:

main.cpp

#include <ESP8266WiFi.h>
#include "Ticker.h"               // Library for scheduling tasks without using delay()
#include <ArduinoJson.h>          // Needed to store configuration as JSON: https://github.com/bblanchon/ArduinoJson
#include <Sensirion_SHT1x.h>      // Declarations for the Sensirion SHT11 Temperature/Humidity sensor
#include <DS18B20_Sensors.h>      // Declarations for the Sensirion DS18B20 Temperature sensor

void getMeasurements();
Ticker timerMeasurement(getMeasurements, 5000); // execute getMeasurements() every 5000ms

void setup()
{
  Serial.begin(74880);

  // Print the Node identifier
  Serial.print("ESP Board MAC Address:  ");
  Serial.println(WiFi.macAddress());

  // Start up the DS18B20 library
  DS18B20.begin();

  // Find available DS18B20 sensors
  report_DS18B20_sensors();

  // Set the temperature resolution for each DS18B20 sensor
  for (int i=0; i<deviceCount; i++){
    DS18B20.setResolution(T[i].addr, TEMPERATURE_PRECISION_10_BIT);
    print_DS18B20_resolution(T[i].addr);
  }

  // start the timer for periodic measurements
  timerMeasurement.start();
}

void loop()
{
  // check to see if the timer has elapsed
  timerMeasurement.update();
}

void getMeasurements(){
  // create a JSON object
  const int capacity = JSON_OBJECT_SIZE(1024);
  StaticJsonDocument<capacity> obj;

  // add the node identifier to the JSON object
  obj["node"] = WiFi.macAddress();
  
  // request a measurement form each DS18B20 sensor
  Serial.println("Requesting temperatures...");
  DS18B20.requestTemperatures();

  // add the measured temperatures to the JSON object
  for (int i=0; i<deviceCount; i++){
    obj["measurements"]["temperature"][i]["type"] = "DS18B20";
    obj["measurements"]["temperature"][i]["id"] = i;
    obj["measurements"]["temperature"][i]["value"] = round(DS18B20.getTempCByIndex(i)*10) / 10;
  }

  // Read values from the SHT11 sensor
  temp_c = sht1x.readTemperatureC();
  temp_f = sht1x.readTemperatureF();
  humidity = sht1x.readHumidity();

  // add the SHT11 temperature values to the JSON object
  obj["measurements"]["temperature"][deviceCount]["type"] = "SHT11";
  obj["measurements"]["temperature"][deviceCount]["value"] = round(temp_c*10)/10;

  // add the SHT11 humidity values to the JSON object
  obj["measurements"]["humidity"][0]["type"] = "SHT11";
  obj["measurements"]["humidity"][0]["value"] = round(humidity);

  // print the JSON object to the serial port
  serializeJsonPretty(obj, Serial);

  Serial.println("");
  Serial.println("DONE");
}

DS18B20_Sensors.h

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

#define ONE_WIRE_BUS D3

// define possible precisions
#define TEMPERATURE_PRECISION_9_BIT 9
#define TEMPERATURE_PRECISION_10_BIT 10
#define TEMPERATURE_PRECISION_11_BIT 11
#define TEMPERATURE_PRECISION_12_BIT 12

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature DS18B20(&oneWire);

// arrays to hold device addresses
DeviceAddress insideThermometer, outsideThermometer;

// define a structure to store the unique DS18B20 addresses
uint8_t deviceCount = 0;
struct
{
  int id;
  DeviceAddress addr;
} T[255];


// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    // zero pad the address if necessary
    if (deviceAddress[i] < 16) {
      Serial.print("0");
    }
	i == 0 ? Serial.print("{0x"):Serial.print("");
    Serial.print(deviceAddress[i], HEX);
	i < 7 ? Serial.print(", 0x"):Serial.print("");
	i == 7 ? Serial.print("}"):Serial.print("");
  }
}

// function to print a device's resolution
void print_DS18B20_resolution(DeviceAddress deviceAddress)
{
  printAddress(deviceAddress);
  Serial.print(" resolution = ");
  Serial.print(DS18B20.getResolution(deviceAddress));
  Serial.println();
}

void report_DS18B20_sensors()
{
  deviceCount = DS18B20.getDeviceCount();
  Serial.println("Locating DS18B20 devices...");
  Serial.print("Found ");
  Serial.print(deviceCount, DEC);
  Serial.println(" sensors:");

  // Read ID's per sensor
  // and put them in T array
 
  for (uint8_t index = 0; index < deviceCount; index++)
  {
    // go through sensors
    DS18B20.getAddress(T[index].addr, index);
    T[index].id = index;
  }

  // Check sensors are set
  for (uint8_t index = 0; index < deviceCount; index++)
  {
    Serial.print("DS18B20[");
    Serial.print(T[index].id);
    Serial.print("] = ");
    printAddress(T[index].addr);
    Serial.println("");
  }
  Serial.println(".................");
}

Sensirion_SHT1x.h

#include <SHT1x.h>

// Specify data and clock connections and instantiate SHT1x object
#define dataPin  D2
#define clockPin D1
SHT1x sht1x(dataPin, clockPin);

float temp_c;
float temp_f;
float humidity;

Leave a Reply

Your email address will not be published. Required fields are marked *