Skip to content

Instantly share code, notes, and snippets.

@ProfJayHam
Created November 7, 2015 19:26
Show Gist options
  • Save ProfJayHam/95cb4a0ec77171eb3836 to your computer and use it in GitHub Desktop.
Save ProfJayHam/95cb4a0ec77171eb3836 to your computer and use it in GitHub Desktop.
HTU21DF RH and temperature datalogger program (with statistics) for Arduino R3 and datalogger shield
/* HTU_logger_stat_V1.ino
RH and Temp data logger for the Arduino using a Adafruits HTU21D breakout board and
datalogger shield. Includes statistics - averages data over user defined intervals
J. Ham, Colorado State Univesity
last revision: 11/05/2015
Desciption: Program gets Temperature and RH from HTU21D sensor at a user-defined
interval (5s default), calculates averages over a user-defined interval (10 min default),
and saves the result to SD card with time stamp obtained from the RTC.
Also calculates and saves Dewpoint temperature as calculated with user-defined function.
The program waits to start until 0 seconds into a 1 min interval.
Output format:
Date and Time
Unix time
T
RH
Tdew
Number of samples in statistic
Avg T
Avg Tdew
Maximum T
Minimum T
Example header and output
datetime,unixtime,temp,RH,tdew,nT,avgT,avgtdew,maxT,minT
2015-11-06 16:20:00,1446826800,21.47,29.84,3.11,96,21.49,3.04,21.52,21.43
Reference: portions adapted from adafruits lighttemplogger.ped
http://learn.adafruit.com/adafruit-data-logger-shield/downloads
Notes:The RTC must be set prior to running this program.
https://learn.adafruit.com/ds1307-real-time-clock-breakout-board-kit/understanding-the-code
search for the word "unique" to find user-adjustable variables such as the sampling
interval or the file name to be stored on the sd card.
Libraries:
RTC library: https://github.com/adafruit/RTClib/
HTU21DF library: https://github.com/adafruit/Adafruit_HTU21DF_Library/
Statistic: https://github.com/kiuz/Arduino-Statistic-Library
Hardware Requirements:
Shield https://www.adafruit.com/products/1141
Sensor: https://www.adafruit.com/product/1899
Wiring for HTU21DF to Arduino or Datalogger Shield
VIN to 5V
GND to Ground
SCL to SCL (or analog 5, the I2C bus)
SDA to SDA (or analog 4, the I2C bus)
3Vo not used
Jumper wires: from D4 to L1, and D5 to L2 on Shield
*/
// include files
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
#include "Adafruit_HTU21DF.h"
#include "Statistic.h"
// ECHO_TO_SERIAL controls output to computers serial monitor
// turn on (1) for testing/troubleshooting,// turn off (0)during field deployment
#define ECHO_TO_SERIAL 1 // 1 = echo results to screen, 0 = no echo, unique
// digital pins that connect to the green and red LEDs on the datalogger shield
// run jumper wire from digital pins 4 and 5 to L1 and L2 connections on datalogger shield
#define greenLEDpin 4 // L1, flashing green indicates sampling
#define redLEDpin 5 // L2, solid red led indicates error
//class initialization
Adafruit_HTU21DF htu = Adafruit_HTU21DF(); // HTU21DF
RTC_DS1307 RTC; // define the Real Time Clock object
// for the data logging shield, we use digital pin 10 for the SD cs line
const int chipSelect = 10;
// the logging file for SD card
File logfile;
const unsigned long TRHSTEP = 5000UL; // Sensor query period, default 5000 ms or 5 sec, unique
const unsigned long LOGRATE = 10UL; // log and averaging period, default 10 minutes, unique
unsigned long trhMillis = 0; // Time interval tracking
//define global variables
float RH_htu, T_htu; // htu sensor output, RH and T
float T_dew; // dewpoint temperature
float avgT, avgTdew; // averages
float maxT, minT; // max and min T
int nT; // number of records for stats
int oldminute = 99;
//Statistics data
Statistic TStats; // Temperature, C
Statistic DStats; // dewpoint, C
//******************** Setup ********************
void setup(void)
{
Serial.begin(9600);
Serial.println();
// LEDs on datalogger shield
pinMode(redLEDpin, OUTPUT);
pinMode(greenLEDpin, OUTPUT);
// initialize the SD card
#if ECHO_TO_SERIAL
Serial.print("Initializing SD card...");
#endif
// make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
error("Card failed, or not present");
}
#if ECHO_TO_SERIAL
Serial.println("card initialized.");
#endif
// create a new file name
char filename[] = "RHlog_00.csv"; // "RHlog" is root name, must be 5 characters, unique
for (uint8_t i = 0; i < 100; i++) {
filename[6] = i/10 + '0';
filename[7] = i%10 + '0';
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
logfile = SD.open(filename, FILE_WRITE);
break; // leave the loop!
}
}
if (! logfile) {
error("couldnt create file");
}
#if ECHO_TO_SERIAL
Serial.print("Logging to: ");
Serial.println(filename);
#endif
// connect to RTC
Wire.begin();
if (!RTC.begin()) {
error("RTC failed");
}
#if ECHO_TO_SERIAL
Serial.println("RTC initalized");
#endif //ECHO_TO_SERIAL
// initialize HTU sensor
htu.begin();
Wire.begin();
if (!htu.begin()) {
error("HTU failed");
}
#if ECHO_TO_SERIAL
Serial.println("HTU initalized");
#endif //ECHO_TO_SERIAL
//clear data arrays
TStats.clear();
DStats.clear();
// delay until time is 0 second into 1 min interval
DateTime now;
#if ECHO_TO_SERIAL
Serial.println("waiting to start at O sec into 1 min");
#endif //ECHO_TO_SERIAL
while(now.second() !=0) {
now = RTC.now();
}
// write header to SD card and screen
logfile.println("datetime,unixtime,temp,RH,tdew,nT,avgT,avgtdew,maxT,minT");
#if ECHO_TO_SERIAL
Serial.println("datetime, unixtime, temp, RH, tdew");
#endif
}
//******************* Main Loop ***********************
void loop(void)
{
DateTime now=RTC.now();
unsigned long curMillis = millis(); // Get current time
// read sensor
if (curMillis - trhMillis >= TRHSTEP) { // Time for new measurements?
trhMillis = curMillis;
T_htu=htu.readTemperature(); // read temperature
RH_htu=htu.readHumidity(); // read humidity
T_dew=dewpoint(T_htu, RH_htu); // calc dewpoint
TStats.add(T_htu); // store var in array for stats
DStats.add(T_dew);
#if ECHO_TO_SERIAL
printData();
#endif
digitalWrite(greenLEDpin, HIGH); // tutn on LED in sample loop
} // end sampling loop
if (curMillis - trhMillis >= 500) { // turn off green LED after 0.5 sec
digitalWrite(greenLEDpin, LOW);
}
// Calculate statistics and log to sd card
if ( (now.minute() % LOGRATE)==0 & now.minute() != oldminute) {
oldminute=now.minute();
calcStat();
logData(); // send data to sd card
}
} // end main loop
//******************************************
//* subroutines and user defined functions *
//******************************************
float dewpoint(float T, float RH) {
// Murray (1967) On the Computation of Saturation Vapor Pressure
float b,dp;
b = (log(RH / 100) + ((17.27 * T) / (237.3 + T))) / 17.27;
dp = (237.3 * b) / (1 - b);
return dp;
}
void calcStat() {
//Averages
avgT = TStats.average();
avgTdew = DStats.average();
//avgRH = RStats.average();
maxT=TStats.maximum();
minT=TStats.minimum();
nT = TStats.count();
//clear data arrays
TStats.clear();
DStats.clear();
}
void printData() {
DateTime now;
now = RTC.now();
Serial.print(now.year(), DEC);
Serial.print(F("-"));
printDigits(now.month());
Serial.print(F("-"));
printDigits(now.day());
Serial.print(F(" "));
printDigits(now.hour());
Serial.print(F(":"));
printDigits(now.minute());
Serial.print(F(":"));
printDigits(now.second());
Serial.print(F(", "));
Serial.print(now.unixtime()); // seconds since 1/1/1970
Serial.print(F(", "));
Serial.print(T_htu);
Serial.print(F(", "));
Serial.print(RH_htu);
Serial.print(F(", "));
Serial.print(T_dew);
Serial.println();
}
void logData() {
DateTime now;
now = RTC.now();
logfile.print(now.year(), DEC);
logfile.print(F("-"));
logDigits(now.month());
logfile.print(F("-"));
logDigits(now.day());
logfile.print(F(" "));
logDigits(now.hour());
logfile.print(F(":"));
logDigits(now.minute());
logfile.print(F(":"));
logDigits(now.second());
logfile.print(F(","));
logfile.print(now.unixtime()); // seconds since 1/1/1970
logfile.print(F(","));
logfile.print(T_htu);
logfile.print(F(","));
logfile.print(RH_htu);
logfile.print(F(","));
logfile.print(T_dew);
logfile.print(F(","));
logfile.print(nT);
logfile.print(F(","));
logfile.print(avgT);
logfile.print(F(","));
logfile.print(avgTdew);
logfile.print(F(","));
logfile.print(maxT);
logfile.print(F(","));
logfile.print(minT);
logfile.println();
logfile.flush();
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
// Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
void logDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
// logfile.print(":");
if(digits < 10)
logfile.print('0');
logfile.print(digits);
}
// error subroutine, does this when error occurs
void error(char *str)
{
#if ECHO_TO_SERIAL
Serial.print("error: ");
Serial.println(str);
#endif
// turn on red LED to indicate error
digitalWrite(redLEDpin, HIGH);
while(1); // halt program
}
@ProfJayHam
Copy link
Author

A radiation shield for the HTU21DF is available here
http://www.thingiverse.com/thing:1067700

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment