These two sensors can accurately measure a home dryer's temperature and power consumption to help monitor a dryer from a distance.
Things used in this project
Hardware components
Story
My partner and I decided to create a dryer temperature and power sensor after trying to think of more practical uses of a temperature sensor than just reading the ambient temperature. Not only is measuring the power consumption and temperature of a dryer a neat gimmick, but it has practical applications as well. For industrial purposes, it can help to measure the overall efficiency of the system with a relatively cost effective method. The temperature sensor works by using a DHT11 temperature sensor connected to a particle argon and sticking it into the dryer exhaust vent. The DHT11 measures the temperature while the argon records the data and publishes it to a Thingspeak page located here Temperature - ThingSpeak IoT. To measure the power consumption of the dryer, an ammeter is used. The ammeter works by using a DFRobot Analog AC Current sensor which can measure the current from a wire and convert it to voltage so the argon can read it. The argon converts the voltage reading from the current sensor and then converts it back to current and publishes the data to the same Thinspeak page.
Schematics
Assembled Temperature Sensor
温度传感器放置
Argon Temperature Sensor
This is the schematic for the DHT11 temperature sensor connected to the Particle Argon. The DHT11 has three prongs, the left prong connected to the USB voltage for a 5V supply, the middle prong connected to the D2 pin for output signal, and the right pin connected to ground.
Current Sensor
Code
Dryer Temp
C/C++
This is the code that uploads the dryer's temperature to the thingspeak page
// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_DHT.h>
#define DHTPIN D2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(9600);
dht.begin(); // initialize the sensor
// Subscribe to the integration response event
Particle.subscribe("hook-response/Temperature", myHandler, MY_DEVICES);
}
void myHandler(const char *event, const char *data) {
// Handle the integration response
}
void loop() {
// wait a few seconds between measurements.
delay(10000);
// read temperature as Celsius
float tempC = dht.getTempCelcius();
// read temperature as Fahrenheit
float tempF = dht.getTempFarenheit();
Serial.print("Temperature: ");
Serial.print(tempC);
Serial.print("°C ~ ");
Serial.print(tempF);
Serial.println("°F");
// Get some data
String data = String(tempF);
String Celsius = String(tempC);
// Trigger the integration
Particle.publish("Temperature", data, PRIVATE);
// Wait 20 seconds
delay(20000);
}
Adafruit_DHT.ccp
C/C++
This is the code from the Adafruit particle library that runs the DHT11 temperature/humidity sensor
/* DHT library
*
* MIT license
* written by Adafruit Industries
* modified for Spark Core by RussGrue
* */
#include "Adafruit_DHT.h"
DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) {
_pin = pin;
_type = type;
_count = count;
firstreading = true;
}
void DHT::begin(void) {
// set up the pins!
pinMode(_pin, INPUT);
pinSetFast(_pin);
_lastreadtime = 0;
}
float DHT::readTemperature() {
float f;
if (read()) {
switch (_type) {
case DHT11:
f = data[2];
return f;
case DHT22:
case DHT21:
f = data[2] & 0x7F;
f *= 256;
f += data[3];
f /= 10;
if (data[2] & 0x80)
f *= -1;
return f;
}
}
return NAN;
}
float DHT::getHumidity() {
return readHumidity();
}
float DHT::getTempCelcius() {
return readTemperature();
}
float DHT::getTempFarenheit() {
return convertCtoF(readTemperature());
}
float DHT::getTempKelvin() {
return convertCtoK(readTemperature());
}
float DHT::getHeatIndex() {
return convertFtoC(computeHeatIndex(convertCtoF(readTemperature()), readHumidity()));
}
float DHT::getDewPoint() {
return computeDewPoint(readTemperature(), readHumidity());
}
float DHT::convertFtoC(float f) {
return (f - 32) * 5 / 9;
}
float DHT::convertCtoF(float c) {
return c * 9 / 5 + 32;
}
float DHT::convertCtoK(float c) {
return c + 273.15;
}
float DHT::readHumidity(void) {
float f;
if (read()) {
switch (_type) {
case DHT11:
f = data[0];
return f;
case DHT22:
case DHT21:
f = data[0];
f *= 256;
f += data[1];
f /= 10;
return f;
}
}
return NAN;
}
float DHT::computeHeatIndex(float tempFahrenheit, float percentHumidity) {
// Adapted from equation at: https://github.com/adafruit/DHT-sensor-library/issues/9 and
// Wikipedia: http://en.wikipedia.org/wiki/Heat_index
return -42.379 +
2.04901523 * tempFahrenheit +
10.14333127 * percentHumidity +
-0.22475541 * tempFahrenheit * percentHumidity +
-0.00683783 * pow(tempFahrenheit, 2) +
-0.05481717 * pow(percentHumidity, 2) +
0.00122874 * pow(tempFahrenheit, 2) * percentHumidity +
0.00085282 * tempFahrenheit * pow(percentHumidity, 2) +
-0.00000199 * pow(tempFahrenheit, 2) * pow(percentHumidity, 2);
}
float DHT::computeDewPoint(float tempCelcius, float percentHumidity) {
double a = 17.271;
double b = 237.7;
double tC = (a * (float) tempCelcius) / (b + (float) tempCelcius) + log( (float) percentHumidity / 100);
double Td = (b * tC) / (a - tC);
return Td;
}
boolean DHT::read(void) {
uint8_t laststate = HIGH;
uint8_t counter = 0;
uint8_t j = 0, i;
unsigned long currenttime;
// Check if sensor was read less than two seconds ago and return early
// to use last reading.
currenttime = millis();
if (currenttime < _lastreadtime) {
// ie there was a rollover
_lastreadtime = 0;
}
if (!firstreading && ((currenttime - _lastreadtime) < 2000)) {
return true; // return last correct measurement
// delay(2000 - (currenttime - _lastreadtime));
}
firstreading = false;
/*
Serial.print("Currtime: "); Serial.print(currenttime);
Serial.print(" Lasttime: "); Serial.print(_lastreadtime);
*/
_lastreadtime = millis();
data[0] = data[1] = data[2] = data[3] = data[4] = 0;
// pull the pin high and wait 250 milliseconds
pinSetFast(_pin);
delay(250);
// now pull it low for ~20 milliseconds
pinMode(_pin, OUTPUT);
pinResetFast(_pin);
delay(20);
noInterrupts();
pinSetFast(_pin);
delayMicroseconds(40);
pinMode(_pin, INPUT);
// read in timings
for ( i=0; i< MAXTIMINGS; i++) {
counter = 0;
while (pinReadFast(_pin) == laststate) {
counter++;
delayMicroseconds(1);
if (counter == 255) {
break;
}
}
laststate = pinReadFast(_pin);
if (counter == 255) break;
// ignore first 3 transitions
if ((i >= 4) && (i%2 == 0)) {
// shove each bit into the storage bytes
data[j/8] <<= 1;
if (counter > _count)
data[j/8] |= 1;
j++;
}
}
interrupts();
/*
Serial.println(j, DEC);
Serial.print(data[0], HEX); Serial.print(", ");
Serial.print(data[1], HEX); Serial.print(", ");
Serial.print(data[2], HEX); Serial.print(", ");
Serial.print(data[3], HEX); Serial.print(", ");
Serial.print(data[4], HEX); Serial.print(" =? ");
Serial.println(data[0] + data[1] + data[2] + data[3], HEX);
*/
// check we read 40 bits and that the checksum matches
if ((j >= 40) &&
(data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) ) {
return true;
}
return false;
}
Adafruit_DHT.h
C/C++
This is more code from the Adafruit particle library that allows the DHT11 sensor to be read and converted particle coding page
/* DHT library
*
* MIT license
* written by Adafruit Industries
* modified for Spark Core by RussGrue
* */
#ifndef DHT_H
#define DHT_H
#include "application.h"
#include "math.h"
// how many timing transitions we need to keep track of. 2 * number bits + extra
#define MAXTIMINGS 85
#define DHT11 11
#define DHT22 22
#define DHT21 21
#define AM2301 21
class DHT {
private:
uint8_t data[6];
uint8_t _pin, _type, _count;
unsigned long _lastreadtime;
boolean firstreading;
float readTemperature();
float convertFtoC(float);
float convertCtoF(float);
float convertCtoK(float);
float computeHeatIndex(float tempFahrenheit, float percentHumidity);
float computeDewPoint(float tempCelcius, float percentHumidity);
float readHumidity(void);
boolean read(void);
public:
DHT(uint8_t pin, uint8_t type, uint8_t count=6);
void begin(void);
float getHumidity();
float getTempCelcius();
float getTempFarenheit();
float getTempKelvin();
float getHeatIndex();
float getDewPoint();
};
#endif
Current Sensor
C/C++
This is the code that runs the current sensor
const int ACPin = A2; //set argon signal read pin
#define ACTectionRange 20; //set Non-invasive AC Current Sensor tection range (5A,10A,20A)
// VREF: Analog reference
// For argon UNO, Leonardo and mega2560, etc. change VREF to 5
// For argon Zero, Due, MKR Family, ESP32, etc. 3V3 controllers, change VREF to 3.3
#define VREF 5.0
void myHandler(const char *event, const char *data) {
// Handle the integration response
}
float readACCurrentValue()
{
float ACCurrtntValue = 0;
float peakVoltage = 0;
float voltageVirtualValue = 0; //Vrms
for (int i = 0; i < 5; i++)
{
peakVoltage += analogRead(ACPin); //read peak voltage
delay(1);
}
peakVoltage = peakVoltage / 5;
voltageVirtualValue = peakVoltage * 0.707; //change the peak voltage to the Virtual Value of voltage
/*The circuit is amplified by 2 times, so it is divided by 2.*/
voltageVirtualValue = (voltageVirtualValue / 1024 * VREF ) / 2;
ACCurrtntValue = voltageVirtualValue * ACTectionRange;
return ACCurrtntValue;
}
void setup()
{
// Subscribe to the integration response event
Particle.subscribe("hook-response/Temperature", myHandler, MY_DEVICES);
}
void loop()
{
float ACCurrentValue = readACCurrentValue(); //read AC Current Value
Serial.print(ACCurrentValue);
Particle.publish("current", String(ACCurrentValue), PRIVATE);
Serial.println(" A");
delay(1000);
}
The article was first published in hackster, November 16, 2021
cr: https://www.hackster.io/andrew-collins/megr-3171-dryer-temperature-and-power-sensor-a26f66
author: Andrew Collins