Experimenteren met een Arduino DHT 11 temperatuur en luchtvochtigheids sensor

Datum:  Mei 2024

Inleiding:

Experimenteren met Arduino en een eenvoudige sensor. Het primaire doel van dit experiment is het grafisch weergeven van de gemeten waardes in dit geval temperatuur en relatieve vochtigheid op een relatieve tijdschaal.

Materiaal en uitvoering:

  • Arduino
  • USB kabel
  • PC met Arduino software en Processing software geinstalleerd
  • DHT11 3Pin Digital Temperature Humidity Sensor Module
  • Breadboard
  • Jumperkabels
  • LCD display


Arduino Uno

DHT 11 basic temperature-humidity sensor

Uitvoering:

  • Bouw de schakeling op zoals weergegeven in onderstaand schema.
 
  • Om de DHT 11 sensor te kunnen gebruiken moet men de betreffende library inladen in de Aduino Sketch Software.
  • Het inladen van de betreffende library staat beschreven in Achtergrondinformatie
  • In Sketch kan men onder File - Examples nu ook DHT11 voorbeeld programma's vinden. Ik heb het DHTtester programma gebruikt en vervolgens vereenvoudigd om het functioneren van de DHT11 te testen.
// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain
// Modified by Ruud Herold in September 2020

// REQUIRES the following Arduino libraries:
// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library

#include "DHT.h"

#define DHTPIN 2     // Digital pin connected to the DHT sensor

#define DHTTYPE DHT11   // DHT 11  being used

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND

// Initialize DHT sensor.
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  Serial.println(F("DHTxx test!"));

  dht.begin();
}

void loop() {
  // Wait a few seconds between measurements.
  delay(2000);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();


  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) ) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C\r\n "));  // \r\n --> carriage return, line feed

}
  • Laad dit Sketch programma in de Arduino en laat het draaien om te controleren of deze goed draait door de resultaten op de Serial Monitor te volgen

  • Deze methode werkt wel maar als men de data actuele data grafisch kan weergeven is het beter mogelijk om veranderingen te zien. Dat is in principe mogelijk m.b.v. de ingebouwde serial plotter.
  • Daarvoor moeten we de code een klein beetje aanpassen o.a. door alle overbodige tekst te verwijderen.

// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain
// Modified by Ruud Herold

#include "DHT.h"
#define DHTPIN 2     // Digital pin connected to the DHT sensor
#define DHTTYPE DHT11   // DHT 11  being used

// Initialize DHT sensor.
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  Serial.println(F("DHT11 test!"));
  dht.begin();
}

void loop() {
  // Wait a few seconds between measurements.
  delay(2000);

  // Read sensor
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) ) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

   // Print the results in the serial plotter
//  -- Humidity --
  Serial.print(h);
  Serial.print("\t");
// -- Temperature --
  Serial.println(t);
}

  • Pas de code aan en upload deze.
  • Om variatie in het signaal te zien kan men even op de sensor ademen of deze vasthouden.

  • Zoals men in de resultaten kan zien werkt ook deze methode. Ik wil echter de data grafischer weergeven dan de mogelijkheden die geboden worden door de serial plotter.  De programmertaal Python mogelijkheden op dit gebied.
  • Installeer daarvoor Python op de computer
  • .
  • Om actuele info beter waar te kunnen nemen besloot ik een LCD scherm toe te voegen aan de opstelling.
  • De bijbehorende code (gedownload en aangepast).

 

Het schakelschema voor het LCD scherm:
// REQUIRES the following Arduino libraries:
//- "LiquidCrystal", "DHT_sensor_library" and "Adafruit_Sensor-master"

// Libraries
#include "DHT.h"
#include <LiquidCrystal.h>

// DHT11 Sensor
#define DHTPIN 12 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT11 // DHT 11
DHT dht(DHTPIN, DHTTYPE);

// LCD Dislay (LCD1602 Module)
// Create an LCD object. Parameters: (RS, E, D4, D5, D6, D7):
// Note: do not connect to 0 or 1, that creates gibberisch characters on the LCD
LiquidCrystal lcd = LiquidCrystal(2, 3, 4, 5, 6, 7);

void setup() {

// LCD Display
lcd.begin(16, 2);

// LCD Display (Temp and Humidity)
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Temp:");
lcd.setCursor(0,1);
lcd.print("Humid:");
delay(1500);

// DHT11 start
Serial.begin(9600);
dht.begin();
// Labels for Serial plotter
while(!Serial);
Serial.println("Temperature Humidity");

}

void loop() {
// Wait 2 seconds between measurements.
delay(2000);

// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();

// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t)) {
Serial.println(F("Failed to read from DHT sensor!"));
return;
}

// LCD Display (Temp and Humidity)
lcd.setCursor(10,0);
lcd.print("oC");
lcd.setCursor(10,1);
lcd.print("%");

// LCD Display (values), without decimals
lcd.setCursor(7,0);
lcd.print(t,0);
lcd.setCursor(7,1);
lcd.print(h,0);

// Serial Plotter with labels
Serial.print(t);
Serial.print("\t");
Serial.println(h);

}
 
  • Zoals men in de resultaten kan zien werken alle methoden naar behoren. Ik wil echter de data grafischer weergeven dan de mogelijkheden die geboden worden door de serial plotter.  De programmertaal Python mogelijkheden op dit gebied.
  • Installeer daarvoor Python op de computer
  • .
  • Het pythonprogramma leest de data van de Aruino volgens een gespecificeerd interval. Interactie vindt plaats via het terminal window. Daarin wordt ook de ingelezen data weergegeven. Het programma draait in een oneindig loop die men kan verlaten door of op de q-toets te drukken of door "control c" te gebruiken. Twintig datapunten worden ook grafisch weergegeven in een apart window. DE data wordt tussentijds opgeslagen in een CSV file waardoor men deze ook achteraf nog kan beoordelen. Bij het verlaten van de loop wordt alle ingelezen data  grafisch weergegeven. De verzamelde data wordt statistisch geëvalueerd en deze data wordt opgeslagen in een teks file en ook weergegeven in de terminal.
Het pythonprogramma kan men downloaden via de link: DHT11_plottingV3.py
 

Resultaten:

Test 1:

Testen van de sensor m.b.v. het geleverde voorbeeld en de serial monitor.


Weergeven van de resultaten op de serial plotter.

Weergeven van de resultaten op het LCD scherm.

De output van het Python programma

Interactie aan het begin van het programma en rapportage eerste resultaten
Het real-rime dta plotting window
De grafiek die alle verzamelde data weergeeft.
De eindrapportage in het terminal window.
Die ook opgeslagen wordt in een tekstfile.
Alle data wordt ook opgeslagen in een csv file.

Discussie:

Voor mij was dit een leuk experiment om mijn programmeren weer eens te oefenen. Daarnaast wilde ik een basis pakket opbouwen dat ik kan gebruiken als ik andere sensoren aan een arduino wil koppelen.

Opmerkingen:

  • Er zijn ook 4-pins DHP-11 sensoren op de markt. Deze zijn een iets oudere versie. Zoek op het internet op hoe deze op het breadboard geïnstalleerd moeten worden.
  • Library's kan men ook als Zip file downloaden en toevoegen.
  • Ik heb deze exercitie op een Windows computer uitgevoerd.

Literatuur:

  • Tero Karvinen, Kimmo Karvinen, Ville Valtokari; "Make: Sensors"; Maker Media; 2014; ISBN9781449368104; p. 332-337.
  • John Nussey; "Arduino voor dummies"; BBNC; 2016; ISBN 9789045351865.
  • Lee Vaughan; "Python tools for scientists"; No starch press;2023; ISBN 9781718502666

Relevante websites:

Minder relevante websites:

 

Achtergrondinformatie:

Arduino

Arduino is een open source computer platform (printplaat, computer) bedoeld voor iedereen die geïnteresseerd is in het maken en ontwerpen van objecten die kunnen reageren op hun omgeving, door het aansluiten van allerlei sensoren en actuatoren op de Arduino.

Via de sensoren kan digitale en analoge inputsignalen genereren die door de Arduino verwerkt worden en dan weer een actie kunnen initiëren door het afgeven van digitale en analoge outputsignalen. Input kan bijvoorbeeld worden gegenereerd door schakelaars, lichtsensoren, bewegingsmeters, afstandsmeters, temperatuursensoren, of op basis van commando's afkomstig van internet, een radiomodule of een ander apparaat met een seriële interface. Outputsignalen kunnen bijvoorbeeld motoren, lampjes, pompjes en beeldschermen aansturen, maar ook input genereren voor een andere Arduino module.

Op de Arduino kan men zogenaamde "shields" zetten door dezen op de input-/outputpinnen van de Arduino te plaatsen. Deze shields kunnen bv extra functie toevoegen of verschillende sensoren en modules in één printplaat combineren. Het meest bekende shield is het ProtoShield dat dienst doet als breadboard, om op te experimenteren.
 

Toevoegen Library aan Arduino
  • Open Sketch
  • Selecteer Sketch --> Include Library --> Manage Library
  • Type DHT11 in het zoekveld en enter
  • Selecteer de "DHT sensor library" van Adafruit en installeer deze
  • Als de library toegevoegd is verschijnt de boodschap INSTALLED in het groen
  • Onder File - Examples kan men zien dat de libary is toegevoegd.
  • Selecteer DHTtester
 
Python code (indentation is verloren gegaan)
# Project: read data and display it from Arduino equipped with a DHT11 sensor
# Note: ensure that only Pyserial is installed. If serial is installed also, uninstall it

import serial
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, FormatStrFormatter
import time
import keyboard
from datetime import datetime
import csv
import statistics

def main():

# ----------------------SET UP COMMUNICATION WITH ARDUINO---------------------
# Replace 'COMX' with the apropriate COM port name on your system
arduino = serial.Serial('COM5', 9600)
# Confirm which port is used
print("Serial Port: " + arduino.name)
# ask for measurement interval
interval = input("Time between measurements in s (mininimum is 2)? ")
print("Program reads and displays data every "+ interval + " s")
# print("Press q to stop the program")
print("Use CTRL-C or press q to stop the program"'\n')
# Read data from the serial port
arduino.close()
arduino.open()

# ----------------------------------- SET UP DATA STORAGE --------------------------
# create lists for data
temperature_list= []
humidity_list=[]
time_list=[]
# create a csv file for storage of the collected data
# get current date and time
current_datetime = datetime.now().strftime("%Y%m%d_%H%M")
print("Current date & time : ", current_datetime)
# convert datetime obj to string
str_current_datetime = str(current_datetime).lstrip()
date = str_current_datetime[0:8]
# create a file object along with extension
file_name = str_current_datetime + ".csv"
file = open(file_name, 'w', newline='')
data_file = csv.DictWriter(file, fieldnames=["date", "time", "temperature", "humidity"])
data_file.writerow({"date": "Date", "time": "Time", "temperature": "Temperature (°C)", "humidity": "Humidity (%)"})

# ---------------------------- SET UP REAL TIME DATA PLOTTING WINDOW -------------------
plt.style.use('ggplot')
fig_w, (ax1,ax2) = plt.subplots(nrows=2, ncols=1, sharex=True)
i=0

# ------------------------------ READ AND STORE DATA ---------------------------
# ---------------------------- WITHIN AN INFINITE LOOP -------------------------
# ----------------------- INCORPORATES ACTIONS TO STOP THE LOOP -----------------
try:
while True:
data = arduino.readline()
# data as such is unreadable, needs to be decoded and assigned
data2 = data.decode()
items = data2.split()
temperature = round(float(items[0]),1)
humidity = round(float(items[1]),1)
# add the time of measurement
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
# print data in terminal
print ("Date: ", date, "Time: ", current_time, " Temperature: " + str(temperature) + " oC ", "Humidity: " + str(humidity) + " %")

# store the data in the lists
time_list.append(current_time)
temperature_list.append(temperature)
humidity_list.append(humidity)

# store the data in the file
data_file.writerow({"date": date, "time": current_time, "temperature": temperature, "humidity": humidity})

# Plot in a time window real time data
ax1.plot(time_list, temperature_list, color='r')
ax2.plot(time_list, humidity_list, color='b')
fig_w.canvas.draw()

ax1.set_title('Plotting sensor data in real time')
# plt.ylabel('Temperature (°C)')
ax2.set_xlabel('Time (hh:mm:ss)')
ax1.set_ylabel('Temperature (°C)')
ax2.set_ylabel('Humidity (%)')
ax2.tick_params(axis='x', labelrotation=90)
ax1.set_xlim(left=max(0,i-18), right=i+1)
ax2.set_xlim(left=max(0,i-18), right=i+1)
plt.tight_layout()
fig_w.show()
plt.pause(0.001) # not sure why we need this to make the window active
i+=1

# Sleep for the specified seconds
time.sleep(int(interval))

# press q to stop the program
if keyboard.is_pressed("q"):
print('Program stopped by pressing q(uit)'+ '\n')
Plot_all_data(time_list, temperature_list, humidity_list)
Evaluate_data(time_list, temperature_list, humidity_list, interval, current_datetime)
file.close()
break
except KeyboardInterrupt:
# use CTRL-C to stop the program
print ('Program stopped by CTRL-C' + '\n')
Plot_all_data(time_list, temperature_list, humidity_list)
Evaluate_data(time_list, temperature_list, humidity_list, interval, current_datetime)
file.close()

# ------------- FUNCTION FOR PLOTTING ALL DATA COLLECTED ----------------------
def Plot_all_data(time_list, temperature_list, humidity_list):
# data to be plotted
x_values = time_list
y_values = temperature_list
y2_values = humidity_list
# dimensions and markup of plot)
fig, ax1 = plt.subplots(figsize=(8, 8))
ax2 = ax1.twinx() # ensures both y-axes are aligned
ax1.set_title('Plotting collected Sensor Data', weight='bold', fontsize=20)
ax1.set_xlabel('Time (HH:MM:SS)',weight='bold', fontsize=15)
ax1.tick_params(axis='x', labelrotation=90)
ax1.yaxis.label.set_color('red')
ax2.yaxis.label.set_color('blue')
ax1.set_ylabel('Temperature (°C)', weight='bold', fontsize=15)
ax2.set_ylabel('Humidity (%)', weight='bold', fontsize=15)
# set a grid pattern applicable to both axes
ax1.set_ylim([0, 50])
ax2.set_ylim([0, 100])
ax1.grid(which = 'major', color = 'green', linestyle = '--', linewidth = 0.5)
ax2.grid(which = 'major', color = 'green', linestyle = '--', linewidth = 0.5)
plt.grid(True)
# plot the plot, autoscale the x-axis and show it
ax1.xaxis.set_major_locator(MultipleLocator(20))
ax1.plot(x_values, y_values, 'ro-')
ax2.plot(x_values, y2_values, 'b^-')
plt.tight_layout()
plt.show()

# ------- FUNCTION FOR CALCULATING SOME DATA CHARACTERISTICS ------------------
def Evaluate_data(time_list, temperature_list, humidity_list, interval, current_datetime):
# Calculate some statistical data, display it and store it in a text file
# Create a text file and write the data to the text file as well as the console

# create a file object along with extension
O_file_name = current_datetime + ".txt"
O_file = open(O_file_name, 'w')
O_file.write('Analysis of data collected\n')
print('Analysis of data collected')
# calculate basic statistical data
Mean_T = ('Mean Temperature (°C): '+ str(round(statistics.mean(temperature_list),2)))
O_file.write(str(Mean_T) + '\n')
print(Mean_T)
Sd_T = ('Standard deviation Temperature (°C): '+ str(round(statistics.stdev(temperature_list),2)))
O_file.write(str(Sd_T) + '\n')
print(Sd_T)
Mean_H = ('Mean Humidity (%): ' + str(round(statistics.mean(humidity_list),2)))
O_file.write(str(Mean_H) + '\n')
print(Mean_H)
Sd_H = ('Standard deviation Humidity (%): ' + str(round(statistics.stdev(humidity_list),2)))
O_file.write(str(Sd_H) + '\n')
print(Sd_H)
Elem_List = len(time_list)
Data_Points = str('A total of ' + str(Elem_List) + ' data points were collected with a ' + str(interval) + ' s interval')
O_file.write(Data_Points + '\n')
print(Data_Points)
#close the file
O_file.close()


if __name__ == "__main__":
main()