Report Temperature, Humidity, and Power Usage
Things used in this project
Hardware components
Story
Temperature and humidity are important factor in a computers lifespan and performance. The hot components reliability and performance are diminished overtime. Humidity makes dust more likely to buildup on components resulting in poorer heat conductivity and higher likelyhood of electrical discharge.
Server efficiency is a useful metric that many homelab creators neglect to collect data on. Using a clamp transformer to measure the current through the cable to the powersupply of the server. This transformer creates an AC voltage relative to the current running through the wire it is clamped around. This AC signal is then measured by an ADS1115 to determine its peak to peak voltage. This is then converted to the approximate power usage of the server. While this isn't as accurate as I like, in retrospect my choice of components was not optimal and if I were to redo it I would choose better components that are actually meant to work together. One issue that I was never able to completely solve was the transformer building up a DC offset that could not be removed with a pull-down resistor. This is the primary reason for power reading inaccuracy as the ADS1115 has trouble reading it.
You can continue to see the reading inaccuracy in the other two sensors that will give a fairly consistent reading with some random inaccuracies. You will see a spike in temperature and a drop in humidity due to testing the sensors with a hairdryer.
Schematics
Temperature and Humidity
Michael Server Sensor Schematic
Cant find any actual schematic templates for the components I used. So a well lit overhead is the best I can do
Code
Humidity Reading
Arduino
Reads the water levels in the air. Important when dealing with electronics
// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_DHT.h>
// This #include statement was automatically added by the Particle IDE.
#include <ThingSpeak.h>
//This identifies the primary pin output to be read by the DHT sensor
#define DHTPIN D7
//Defines what the type of the DHT sensor we are using is.
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
bool humid = false;
TCPClient client;
//Identifies what ThingSpeak channel and specific channel set to send the data to and write to
unsigned long ThingSpeakChannelNum = 1244806;
const char * APIWriteKey = "TDB5CCVLGVT70DBN";
void setup()
{
ThingSpeak.begin(client);
pinMode(D5, OUTPUT);
pinMode(D7, OUTPUT);
Serial.begin(9600);
dht.begin();
Particle.subscribe("Group 30 IOT project", handler);
}
void loop()
{
delay(5000);
float humidity = dht.getHumidity();
//This instructs the argon to take a measurement of the relative humidity as reported by the DHT11 Sensor
float temperature = dht.getTempFarenheit();
//This instructs the argon to take a measurement of the temperature in Farenheit as reported by the DHT11 Sensor
//Sends the data recorded by the argon for relative humidity and temperature to the cloud for retrieval by partner's argon
Particle.publish("G30 Iot project Humid", String (humidity), PRIVATE);
Particle.publish("G30 Iot project Temp", String (temperature), PRIVATE);
//This tells what graph plot to send what data to for ThingSpeak
ThingSpeak.setField(1,humidity);
ThingSpeak.setField(3,temperature);
Serial.print(dht.getHumidity());
Serial.println("humidity");
Serial.print(dht.getTempFarenheit());
Serial.println("temperature");
ThingSpeak.writeFields(ThingSpeakChannelNum, APIWriteKey);
}
//This code confirms that the devices are achieving two-way communicatin by received an LED ping when the partner argon has successfully received exported data
void handler(const char *event, const char *data)
{
digitalWrite(D7, HIGH);
delay(2000);
digitalWrite(D7, LOW);
delay(500);
}
Temperature Reading
Arduino
This code's purpose is to record the temperature of a computer. Once the temperature breaches 90 degrees Farhenheit it will automatically send an alert to the user stating the computer is overheating.
// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_DHT.h>
// This #include statement was automatically added by the Particle IDE.
#include <ThingSpeak.h>
//This identifies the primary pin output to be read by the DHT sensor
#define DHTPIN D7
//Defines what the type of the DHT sensor we are using is.
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
bool humid = false;
TCPClient client;
//Identifies what ThingSpeak channel and specific channel set to send the data to and write to
unsigned long ThingSpeakChannelNum = 1244806;
const char * APIWriteKey = "TDB5CCVLGVT70DBN";
void setup()
{
ThingSpeak.begin(client);
pinMode(D5, OUTPUT);
pinMode(D7, OUTPUT);
Serial.begin(9600);
dht.begin();
Particle.subscribe("Group 30 IOT project", handler);
}
void loop()
{
delay(5000);
float humidity = dht.getHumidity();
//This instructs the argon to take a measurement of the relative humidity as reported by the DHT11 Sensor
float temperature = dht.getTempFarenheit();
//This instructs the argon to take a measurement of the temperature in Farenheit as reported by the DHT11 Sensor
//Sends the data recorded by the argon for relative humidity and temperature to the cloud for retrieval by partner's argon
Particle.publish("G30 Iot project Humid", String (humidity), PRIVATE);
Particle.publish("G30 Iot project Temp", String (temperature), PRIVATE);
//This tells what graph plot to send what data to for ThingSpeak
ThingSpeak.setField(1,humidity);
ThingSpeak.setField(3,temperature);
Serial.print(dht.getHumidity());
Serial.println("humidity");
Serial.print(dht.getTempFarenheit());
Serial.println("temperature");
ThingSpeak.writeFields(ThingSpeakChannelNum, APIWriteKey);
}
//This code confirms that the devices are achieving two-way communicatin by received an LED ping when the partner argon has successfully received exported data
void handler(const char *event, const char *data)
{
digitalWrite(D7, HIGH);
delay(2000);
digitalWrite(D7, LOW);
delay(500);
}
Michael Server Sensor Code
C#
Tracks humidity, temperature, and power usage. It also listens for the other two argons and alerts the main server though a serial connection that the other two are overheating. It also sends its own signal out if it overheats.
// This #include statement was automatically added by the Particle IDE.
#include <ThingSpeak.h>
// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_ADS1X15.h>
// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_DHT.h>
// This example assumes the sensor to be plugged into CONN2
#define DHTPIN D6 // what pin we're connected to
// Here we define the type of sensor used
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
bool humid = false;
TCPClient client;
Adafruit_ADS1115 ads;
unsigned long myChannelNumber = 1708544;
const char * myWriteAPIKey = "XGCMF66UFUM6LQTC";
void tempone(const char *event, const char *data) {
Serial.println("Server 1 Overheating");
}
void temptwo(const char *event, const char *data) {
Serial.println("Server 2 to much Humidity");
}
void setup() {
// ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV (DEFAULT)
// ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV
// ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV 0.0625mV
// ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV 0.03125mV
// ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV 0.015625mV
// ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV
ads.begin();
ads.setGain(GAIN_TWOTHIRDS); // Sets up ADS
pinMode(A0, INPUT);
pinMode(D7, OUTPUT);
Serial.begin(9600);
dht.begin(); // Sets up DHT
ThingSpeak.begin(client); // Sets up ThingSpeak
Particle.subscribe("Temperature", tempone, MY_DEVICES);
Particle.subscribe("OverHumid", temptwo, MY_DEVICES);
}
void loop() {
delay(1000);
float h = dht.getHumidity();
float t = dht.getTempCelcius();
float f = dht.getTempFarenheit();
float current = 0;
double multiplier = 0.1875F;
short adc0, adc1;
float av0, av1;
adc0 = ads.readADC_SingleEnded(0);
av0 = adc0 * multiplier;
adc1 = ads.readADC_SingleEnded(3);
av1 = adc1 * multiplier;
current = (av0 + av1) / 15.0; // takes reading from two sensors and avg to get semi accurate reading
if(isnan(h) || isnan(t) || isnan(f) || isnan(av1) || isnan(av0)) {
Serial.println("Failed to read");
return;
}
if(f >= 100) { // reduces random temperature noise resulting in 200+ degree readings
return;
}
if(true) {
//Particle.publish("Temperature_F", String(f), PRIVATE);
//Particle.publish("Humidity", String(h), PRIVATE);
if(f > 90) {
Particle.publish("Argon1 Overheating", String(f), PRIVATE);
}
ThingSpeak.setField(1, f);
ThingSpeak.setField(2, h);
ThingSpeak.setField(3, current);
ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
}
Serial.print(dht.getHumidity());
Serial.println("h");
Serial.print(dht.getTempFarenheit());
Serial.println("t");
Serial.println(av0);
Serial.println(av1);
delay(60000); // ThingSpeak delay
}
The article was first published in hackster, April 22, 2022
cr: https://www.hackster.io/459741/server-room-monitor-2859d0
author: Michael Starling, Aaron, Charlie12341234