Terrarium Temperature Sensors with Arduino, Raspberry Pi, InfluxDB and Grafana

First I started with the Arduino and wrote some code to verify the sensors are working, initially using a Breadboard.

After I could read the metrics, I’ve set up InfluxDB on a Raspberry to store the data from the Arduino.

Then I extended the Sketch, so the Arduino connects to our Wifi and pushes the data via UDP to the InfluxDB.

The next step was to set up Grafana to have a nice dashboard view.


As everything was working fine, it was time to solder each DS18B20 sensor to a connector so they can easily be attached and detached if needed.

Then I soldered all the needed cables and the 4.7 KΩ resistor to the prototyping shield that is connected to the Arduino.

Afterwards I added a DHT22 Sensor directly to the shield to measure the room temperature.


Everything was now ready to be put into action.

I placed 3 sensors in the Chameleon enclosure, one in the rain forrest, and one in our smaller aquarium.

To make sure I can access the dashboard from anywhere, I configured a reverse proxy on my server that proxies requests from m1nd.io/terra to the Raspberry.

As I had a screen left, it was placed next to the terrariums. I hooked up another spare Raspberry and configured it to open the dashboard automatically in a browser.


Hardware:

  • Arduino Uno Wifi Rev. 2
  • Arduino Prototyping shield
  • 5x DS18B20 Temperature sensors
  • 1x 4.7 KΩ resistor
  • 1x DHT22 Temperature / Humidity sensor
  • Connectors
  • Raspberry Pi (2x)

Software

  • Arduino
    • Sketch
  • Raspberry Pi – 1
    • InfluxDB
    • Grafana
  • Raspberry Pi – 2
    • Browser
  • Webserver
    • Apache2 reverse proxy

Arduino Sketch:

// WIFI
#include <SPI.h>
#include <WiFiNINA.h>
#include "arduino_secrets.h"
#include <WiFiUdp.h>
#include <DHT.h>
#include <OneWire.h>
#include <DallasTemperature.h>
WiFiUDP udp;
int status = WL_IDLE_STATUS; // the Wifi radio’s status

// Network
IPAddress dns(8, 8, 8, 8);
IPAddress influxserver(192, 168, 178, 222);
const int influxport = 8089;
unsigned int localport = 8080;

// DHT22
#define DHTPIN 2 // what pin we’re connected to
#define DHTTYPE DHT22 // DHT 22 (AM2302)
DHT dht(DHTPIN, DHTTYPE);

// DS18B20
// Data wire is plugged into digital pin 3 on the Arduino
#define ONE_WIRE_BUS 3

// Setup a oneWire instance to communicate with any OneWire device
OneWire oneWire(ONE_WIRE_BUS);  

// Pass oneWire reference to DallasTemperature library
DallasTemperature sensors(&oneWire);

// Addresses of DS18B20s
uint8_t sensor1[8] = { 0x28, 0xF6, 0x84, 0xDB, 0x17, 0x20, 0x06, 0xB3 };
uint8_t sensor2[8] = { 0x28, 0xCF, 0xE5, 0x22, 0x18, 0x20, 0x06, 0xA9 };
uint8_t sensor3[8] = { 0x28, 0x26, 0xCE, 0x22, 0x18, 0x20, 0x06, 0x9E };
uint8_t sensor4[8] = { 0x28, 0xDE, 0xF7, 0x0A, 0x18, 0x20, 0x06, 0x56 };
uint8_t sensor5[8] = { 0x28, 0xA5, 0x2A, 0xF5, 0x17, 0x20, 0x06, 0x30 };

void setup() {
  Serial.begin(9600);
  
  // check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    while (true);
  }

  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(WIFI_SSID);
    status = WiFi.begin(WIFI_SSID, WIFI_PASS);
    delay(5000); // wait 5 seconds for connection
  }

  Serial.println("You’re connected to the network");
  WiFi.setDNS(dns);
  WiFi.reconnect()

  delay(10000);
  dht.begin(); // Init DHT22
  sensors.begin(); // Init DallasTemperature
  udp.begin(localport);
}

void loop() {
  delay(5000);
  sensors.requestTemperatures();

  // DHT22 Temperature
  String dht22_tempLine;
  dht22_tempLine = String("Temperature,sensor=DHT22,id=1,location=arduino value=" + String(dht.readTemperature()));
  Serial.println(dht22_tempLine);
  String beginpacket, printpacket, endpacket;
  udp.beginPacket(influxserver, influxport);
  udp.print(dht22_tempLine);
  udp.endPacket();

  // DHT22 Humidity
  String dht22_humLine;
  dht22_humLine = String("Humidity,sensor=DHT22,id=1,location=arduino value=" + String(dht.readHumidity()));
  Serial.println(dht22_humLine);
  udp.beginPacket(influxserver, influxport);
  udp.print(dht22_humLine);
  udp.endPacket();

  // DS18B20 - 1
  String ds18B20_1_tempLine;
  float ds18B20_1_temp;
  ds18B20_1_temp = getTemperature(sensor1);
  if ((ds18B20_1_temp != -127) && (ds18B20_1_temp != 85)) {
    ds18B20_1_tempLine = String("Temperature,sensor=DS18B20,id=2,location=Chameleon_top value=" + String(ds18B20_1_temp));
    Serial.println(ds18B20_1_tempLine);
    udp.beginPacket(influxserver, influxport);
    udp.print(ds18B20_1_tempLine);
    udp.endPacket();
  }
  // DS18B20 - 2
  String ds18B20_2_tempLine;
  float ds18B20_2_temp;
  ds18B20_2_temp = getTemperature(sensor2);
  if ((ds18B20_2_temp != -127) && (ds18B20_2_temp != 85)) {
    ds18B20_2_tempLine = String("Temperature,sensor=DS18B20,id=3,location=Chameleon_mid value=" + String(ds18B20_2_temp));
    Serial.println(ds18B20_2_tempLine);
    udp.beginPacket(influxserver, influxport);
    udp.print(ds18B20_2_tempLine);
    udp.endPacket();
  }
  // DS18B20 - 3
  String ds18B20_3_tempLine;
  float ds18B20_3_temp;
  ds18B20_3_temp = getTemperature(sensor3);
  if ((ds18B20_3_temp != -127) && (ds18B20_3_temp != 85)) {
    ds18B20_3_tempLine = String("Temperature,sensor=DS18B20,id=4,location=Chameleon_bot value=" + String(ds18B20_3_temp));
    Serial.println(ds18B20_3_tempLine);
    udp.beginPacket(influxserver, influxport);
    udp.print(ds18B20_3_tempLine);
    udp.endPacket();
  }
  // DS18B20 - 4
  String ds18B20_4_tempLine;
  float ds18B20_4_temp;
  ds18B20_4_temp = getTemperature(sensor4);
  if ((ds18B20_4_temp != -127) && (ds18B20_4_temp != 85)) {
    ds18B20_4_tempLine = String("Temperature,sensor=DS18B20,id=5,location=Rainforrest value=" + String(ds18B20_4_temp));
    Serial.println(ds18B20_4_tempLine);
    udp.beginPacket(influxserver, influxport);
    udp.print(ds18B20_4_tempLine);
    udp.endPacket();
  }
  // DS18B20 - 5
  String ds18B20_5_tempLine;
  float ds18B20_5_temp;
  ds18B20_5_temp = getTemperature(sensor5);
  if ((ds18B20_5_temp != -127) && (ds18B20_5_temp != 85)) {
    ds18B20_5_tempLine = String("Temperature,sensor=DS18B20,id=6,location=Fishtank value=" + String(ds18B20_5_temp));
    Serial.println(ds18B20_5_tempLine);
    udp.beginPacket(influxserver, influxport);
    udp.print(ds18B20_5_tempLine);
    udp.endPacket();
  }
}

float getTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  return tempC;
}