Created
June 20, 2016 14:37
-
-
Save pwillard/d42a140175932cd162147dd0c02fd35a to your computer and use it in GitHub Desktop.
weather stuff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//============================================================================== | |
// W W EEEEE AAA TTTTT H H EEEEE RRRR III N N OOOOO | |
// W W E A A T H H E R R I NN N O O | |
// W W W EEEE AAAAA T HHHHH EEEE RRRR I N N N O O | |
// W W W E A A T H H E R R .. I N NN O O | |
// W W EEEEE A A T H H EEEEE R R .. III N N OOOOO | |
//============================================================================== | |
//============================================================================== | |
// Program: Weather.ino | |
// Author: Pete Willard | |
// Version: 1.2 | |
// Target: UNO - IDE 1.03 | |
// Date: 4/23/2012 | |
// Updated: 10/22/2012 - Teat Index & Wind Chill | |
// 1/3/2012 - Barometric Pressure tweak | |
// 1/4/2012 - Fixed error in DS2438 Library (Rob Tillaart) | |
// 6/13/2013 - clean up and refactor | |
// 9/27/2013 - Troubleshoot issues with Rain counter | |
// 11/15/2013 - Fix Windspeed | |
// 12/05/2013 - Revise variable layout for logger tool on RPI | |
// Notes: | |
// Location: Cumming, GA | |
// Latitude: 34.2601 | |
// Longitude: -84.2556 | |
// | |
// References/Influences: Paul East, Peter H Anderson, Limor Fried | |
//============================================================================== | |
// Libraries: OneWire, DallasTemperature, Wire, Adafruit_BMP085, DS2438 | |
// | |
//============================================================================== | |
// Additional Information: | |
// Connect VCC of the BMP085 sensor to 3.3V (NOT 5.0V!) | |
// | |
// The Following 2 signals use a Sparkfun Level Converter | |
// Connect SCL to i2c clock - on STD Arduino that's Analog 5 | |
// Connect SDA to i2c data - on STD Arduino that's Analog 4 | |
// | |
// EOC is not used, it signifies an end of conversion | |
// XCLR is a reset pin, also not used here | |
//============================================================================= | |
// External Hardware: | |
// 1-wire Power Injector - My own design, provides 12V for Humidity sensor | |
// 1-wire HB Temperature/Humidity board, uses 12V supply, onboard 5V Vreg. | |
// 1-wire Anemometer and Vane (AAG 1-wire, version 2) POWERED bt 5V | |
// 1-wire Rain Counter - hacked from a wireless LaCrosse WS-9004u (DS2423) | |
// BMP085 Pressure sensor - Sparkfun (With 3V level converter | |
// 1-wire DS18B20 (2 sensors) | |
// | |
//============================================================================= | |
// heat index (HI) calculations | |
// http://en.wikipedia.org/wiki/Heat_index | |
// http://www.nws.noaa.gov/os/heat/index.shtml#heatindex | |
// http://www.4wx.com/wxcalc/formulas/heatIndex.php | |
// FORMULA: | |
// HI = -42.379 + 2.04901523T + 10.14333127R - 0.22475541TR - 6.83783x10 | |
// -3T2 - 5.481717x10 - 2R2 + 1.22874x10 -3T2R + 8.5282x10 | |
// -4TR2 - 1.99x10-6T2R2 | |
// where T = ambient dry bulb temperature (°F) | |
// R = relative humidity (integer percentage). | |
//============================================================================= | |
// Wind Chill Calculations | |
// http://en.wikipedia.org/wiki/Wind_chill | |
//============================================================================= | |
#define DEBUG 1 // Enable debugging statements 1=on | |
#define CSVMODE 0 // Output CSV versus Human readable | |
//=====[ INCLUDE ]============================================================== | |
#include <math.h> | |
#include <OneWire.h> // 1-wire support | |
#include <DallasTemperature.h> // Temperature specific routines | |
#include <ds2438.h> // Humidity Sensor | |
#include <Wire.h> // I2C Support | |
#include <Adafruit_BMP085.h> // Sparkfun Pressure Sensor BMP085 | |
#include <Time.h> // Serial time | |
//#include <LiquidCrystal.h> | |
//#include <LCDKeypad.h> | |
//#include <avr/wdt.h> // Watch Dog Timer | |
//====[ PINS ]================================================================== | |
#define ONEWBUS 2 // PIN used for 1-wire bus | |
#define BACKLIGHT 10 // for PWM control of back light | |
//====[ CONSTANTS ]============================================================= | |
#define TIME_HEADER "T" // Header tag for serial time sync message | |
#define WEATHER_HEADER "W" // Header tag for serial weather update | |
#define TIME_REQUEST 7 // ASCII bell character requests a time sync message | |
const int ONE_WIRE_RESCAN = 10000; // Bus Scan period in ms | |
const int WINDSPEED_RESCAN = 3000; // wind speed scan period in ms | |
const unsigned long MILES_PER_HOUR = 2.453; // revolution ticks per second | |
//const unsigned long DEFAULT_TIME = 1388534401; // Jan 1 2014 | |
// what is our longitude (west values negative) | |
// and latitude (south values negative) | |
//float const LATITUDE = 34.2601; | |
//float const LONGITUDE = -84.2556; | |
//const int loopMax = 4; | |
//=====[ VARIABLES ]============================================================ | |
typedef struct { | |
float temperatureIN ; | |
float temperatureOUT ; | |
float pressure ; | |
float humidityIN ; | |
float humidityOUT ; | |
float dewpoint ; | |
float windchill ; | |
float heatindex ; | |
float windspeed ; | |
char* winddirection ; | |
float rainttl ; | |
float rain1hr ; | |
float rain24hr ; | |
int light ; | |
} | |
weather; | |
weather results; // external struct containing the current weather conditions | |
unsigned long lastUpdateMillis = 0; // Timer | |
unsigned long currentTicks = 0; // Timer | |
unsigned long ms_ticks = 0; | |
int HighByte, LowByte; // Used by DS2450 | |
boolean Summer = false; // Do we compute Heat Index? | |
boolean Winter = false; // Do we compute Wind Chill? | |
float anemSpeedMAX; | |
float anemSpeed; | |
char buffer[10]; | |
char uartbuffer[16]; | |
char logline[100]; | |
//int loopCount; | |
//int maxLoops; | |
// Value Arrays for daily totals and averages | |
float WindSpeedHRSTable[12] = { | |
0,0,0,0,0,0,0,0,0,0,0,0}; | |
float RainHRSTable[12] = { | |
0,0,0,0,0,0,0,0,0,0,0,0}; | |
float RainDayTable[24] = { | |
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | |
int LightningHRSTable[12] = { | |
0,0,0,0,0,0,0,0,0,0,0,0}; | |
int LightningDayTable[24] = { | |
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | |
/* | |
typedef struct | |
{ | |
ushort Second; | |
ushort Minute; | |
ushort Hour; | |
} | |
TimeStruct; | |
TimeStruct myTime; | |
*/ | |
//-------------------------------------------------------------- | |
// SENSORS | |
//-------------------------------------------------------------- | |
// Global One Wire Library Variables | |
byte present = 0; | |
byte data[12]; | |
byte addr[8]; | |
OneWire oneWire(ONEWBUS); | |
DallasTemperature sensors(&oneWire); | |
//============================================================================== | |
// ONEWIRE SENSORS definitions | |
//============================================================================== | |
// NOTE (DeviceAddress Array definition is in DallasTemperature.h) | |
// Standard 1-wire temp sensors | |
// Polling and auto-discovery is not used | |
//DS18X20 | |
DeviceAddress IN_TEMP_ID = { | |
0x28,0x99,0x71,0x60,0x03,0x00,0x00,0xED | |
}; | |
//DS18X20 | |
DeviceAddress OUT_TEMP_ID = { | |
0x28,0xAC,0x7A,0x60,0x03,0x00,0x00,0x9B | |
}; | |
// DS2423 | |
DeviceAddress RAIN_COUNT_ID = { | |
0x1D,0xDE,0xF6,0x0E,0x00,0x00,0x00,0x3B | |
}; | |
// DS2423 | |
DeviceAddress WIND_SPD_ID = { | |
0x1D,0x6F,0x50,0x01,0x00,0x00,0x00,0x3E | |
}; | |
// DS2438 | |
DeviceAddress HUMIDITY_ID = { | |
0x26,0x26,0xD8,0xCA,0x00,0x00,0x00,0x27 | |
}; | |
// DS2450 | |
DeviceAddress WIND_VECTOR_ID = { | |
0x20,0x09,0x5E,0x0A,0x00,0x00,0x00,0x55 | |
}; | |
//============================================================================== | |
// Rain Counter | |
//============================================================================== | |
// Inches per tip = 0.01 | |
float bucketSize = 0.011; // Inches per tip | |
float rainCount = 0.0; | |
int rainThreshold = 0; | |
float rainInches = 0.0; | |
float lastRainInches= 0.0; | |
float rain1hour = 0.0; | |
float rain24hour = 0.0; | |
float rainDiffCount = 0.0; | |
float rainLastCount = 0.0; | |
//============================================================================== | |
// PRESSURE SENSOR | |
//============================================================================== | |
// Verified against known altitude at current location | |
// http://www.engineeringtoolbox.com/pressure-units-converter-d_569.html | |
// Yes, this is tricky and relies on some extra calibration steps | |
const float P_OFFSET = 102608; // Sea level Pressure Offset in pascals | |
float P_ADJ = (P_OFFSET - 98150.00); // Adjusted for 30.30 | |
Adafruit_BMP085 bmp; // Class Initialization | |
//Variables for the AD conversion and wind direction | |
int currentWindDirection, WindPos, WindDirection, ChA, ChB, ChC, ChD, ADVal; | |
char* windDirectionArray[17] = { | |
"000", "022", "045", "067", "090", "112", "135", | |
"157", "180", "202", "225", "247", "270", "292","315", "337", "NaN" | |
}; | |
// NaN = Not a Number or incorrect result | |
float lookupTable[16][4] = { | |
{ | |
4.5, 4.5, 2.5, 4.5 | |
} | |
, // N 0 0 | |
{ | |
4.5, 2.5, 2.5, 4.5 | |
} | |
, // NNE 1 22.5 | |
{ | |
4.5, 2.5, 4.5, 4.5 | |
} | |
, // NE 2 45 | |
{ | |
2.5, 2.5, 4.5, 4.5 | |
} | |
, // ENE 3 67.5 | |
{ | |
2.5, 4.5, 4.5, 4.5 | |
} | |
, // E 4 90 | |
{ | |
2.5, 4.5, 4.5, 0.0 | |
} | |
, // ESE 5 112.5 | |
{ | |
4.5, 4.5, 4.5, 0.0 | |
} | |
, // SE 6 135 | |
{ | |
4.5, 4.5, 0.0, 0.0 | |
} | |
, // SSE 7 157.50 | |
{ | |
4.5, 4.5, 0.0, 4.5 | |
} | |
, // S 8 180 | |
{ | |
4.5, 0.0, 0.0, 4.5 | |
} | |
, // SSW 9 202.50 | |
{ | |
4.5, 0.0, 4.5, 4.5 | |
} | |
, // SW 10 225 | |
{ | |
0.0, 0.0, 4.5, 4.5 | |
} | |
, // WSW 11 247.50 | |
{ | |
0.0, 4.5, 4.5, 4.5 | |
} | |
, // W 12 270 | |
{ | |
0.0, 4.5, 4.5, 2.5 | |
} | |
, // WNW 13 292.50 | |
{ | |
4.5, 4.5, 4.5, 2.5 | |
} | |
, // NW 14 315 | |
{ | |
4.5, 4.5, 2.5, 2.5 | |
} | |
, // NNW 15 337.50 | |
}; | |
//============================================================================== | |
// Wind Speed | |
unsigned long lastCount = 0; | |
unsigned long lastTicks = 0; | |
unsigned long windCount = 0; | |
//============================================================================== | |
// HUMIDITY SENSOR | |
//============================================================================== | |
ds2438 hum1(&oneWire, HUMIDITY_ID); | |
float hum_Offset = -15.0; // Humidity calibration adjustment | |
//============================================================================== | |
//=====[ SETUP ]================================================================ | |
void setup() { | |
Serial.begin(9600); // Setup Serial In/Out | |
bmp.begin(); // Pressure, does wire.begin() | |
sensors.begin(); // Setup 1 wire | |
sensors.setResolution(IN_TEMP_ID, 9); // 1-wire resolution | |
Configure_2450(WIND_VECTOR_ID); // Initialize Wind Vane | |
currentTicks = millis(); // Time Independent cycle | |
ms_ticks = currentTicks; | |
//setSyncProvider( requestSync); // set function to call when sync required | |
//setSyncInterval(900); // Hpw many seconds between sync updates | |
//lcd.print("Time Sync Req"); | |
// // Keep Alive | |
Serial.print("Ready...\n"); | |
delay(1000); | |
} | |
//=====[ LOOP ]================================================================= | |
void loop() { | |
if (Serial.available() >0) { | |
int index = 0; | |
delay(50); | |
int numchar = Serial.available(); | |
if (numchar > 16) { | |
numchar = 16; | |
} | |
while (numchar--) { | |
uartbuffer[index++] = Serial.read(); | |
} | |
processMessage(uartbuffer); | |
for (int x=0; x<16; x++) { | |
uartbuffer[x] = '\0'; | |
} | |
} | |
///////////////////////////////////////////// | |
if (millis() - ms_ticks > WINDSPEED_RESCAN) { | |
ms_ticks += WINDSPEED_RESCAN; | |
results.windspeed = getWindSpeed(WIND_SPD_ID); | |
if (results.windspeed > 0.0) { | |
if (results.windspeed > 0.0 && results.windspeed <100) { | |
anemSpeed = results.windspeed; | |
if (anemSpeed > anemSpeedMAX) { | |
anemSpeedMAX = anemSpeed; | |
} | |
} | |
} | |
else { | |
results.windspeed = 0.0; // speed be crazy | |
} | |
} | |
///////////////////////////////// | |
// if enough time has passed, sample the sensors | |
if (cycleCheck(&lastUpdateMillis, ONE_WIRE_RESCAN)) { | |
// | |
if (DEBUG == 1) { | |
Serial.println("sample sensors"); | |
} | |
sampleSensors(); | |
if (DEBUG == 1) { | |
Serial.println("done sampling"); | |
} | |
if (CSVMODE == 1) { | |
sprintResults(); | |
} | |
else { | |
printResults(); | |
} | |
} | |
} | |
//============================================================================= | |
//====[ SUBROUTINES ]========================================================== | |
//============================================================================= | |
// Elapsed time tracking routine | |
boolean cycleCheck(unsigned long *lastMillis, unsigned int cycle) | |
// This happens regardless if the the software clock is set. | |
{ | |
unsigned long currentMillis = millis(); | |
if (currentMillis - *lastMillis >= cycle) { | |
*lastMillis = currentMillis; | |
return true; | |
} | |
else | |
return false; | |
} | |
//============================================================================= | |
void sampleSensors(void) { | |
results.temperatureIN = 0; | |
results.temperatureOUT = 0; | |
results.pressure = 0; | |
results.humidityIN = 0; | |
results.humidityOUT = 0; | |
results.dewpoint = 0; | |
results.windchill = 0; | |
results.heatindex = 0; | |
//results.windspeed = 0; // Do this separately | |
results.winddirection = ""; | |
results.rainttl = 0; | |
results.rain1hr = 0; | |
results.rain24hr = 0; | |
results.light = 0; | |
sensors.requestTemperatures(); // initialize | |
Serial.print("get temps\n"); | |
results.temperatureIN = getTemperature(IN_TEMP_ID); | |
Serial.print("got results\n"); | |
delay(200); // needed for sequential temperature reads. | |
Serial.print("get outside temps\n"); | |
results.temperatureOUT = getTemperature(OUT_TEMP_ID); | |
delay(200); // needed for sequential reads. | |
Serial.print("got results\n"); | |
results.pressure = getPressure(); | |
Serial.print("got pressure results\n"); | |
delay(200); // needed for sequential reads. | |
results.winddirection = getWindVector(WIND_VECTOR_ID); | |
delay(200); // needed for sequential reads. | |
Serial.print("got wind vector results\n"); | |
//results.windspeed = getWindSpeed(WIND_SPD_ID); | |
results.humidityIN = 0.0; | |
results.humidityOUT = getHumidity(); | |
results.dewpoint = getDewpoint(); | |
// Determine if we need to use Windchill or HeatIndex | |
if (results.temperatureOUT > 80.00) { | |
results.heatindex = getHeatIndex(); | |
Summer = true; | |
} | |
else { | |
Summer = false; | |
results.heatindex = 0.0; | |
} | |
if (results.temperatureOUT < 50.00) { | |
results.windchill = getWindChill(); | |
Winter = true; | |
} | |
else { | |
Winter = false; | |
results.windchill = 0.0; | |
} | |
rainCount = getRainCount(RAIN_COUNT_ID); | |
results.rainttl = (rainCount * bucketSize); | |
if (rainLastCount > 0) { | |
rainDiffCount = results.rainttl - rainLastCount; | |
} | |
rainLastCount = results.rainttl; | |
if (rainDiffCount > 0) { | |
results.rain1hr += rainDiffCount; | |
results.rain24hr += rainDiffCount; | |
}; | |
results.light = 0.0; | |
} | |
//============================================================================== | |
// received serial data from remote server, is it a sync update? | |
// is it a request for data? | |
void processMessage(char* data) { | |
//----------------------------------------- | |
if (data[0] == 'W' ) { | |
if (strlen(logline) > 0) { | |
Serial.println(logline); | |
} | |
else { | |
Serial.println("N"); | |
} | |
} | |
//------------------------------------------ | |
if (data[0] == 'T') { | |
Serial.println("ack"); | |
} | |
} | |
void printResults() { | |
printBreak(); | |
//if (timeStatus()!= timeNotSet) { | |
// digitalClockDisplay(); | |
// } | |
// time here | |
// Internal Temperature | |
Serial.print("Inside: \t"); | |
if (results.temperatureIN == -999) { | |
Serial.println( "IE"); | |
} | |
else { | |
Serial.println( results.temperatureIN ); // Internal Temperature | |
} | |
// External Temperature | |
Serial.print("Outside: \t"); | |
if (results.temperatureOUT == -999) { | |
Serial.println( "OE"); | |
} | |
else { | |
Serial.println( results.temperatureOUT ); | |
} | |
Serial.print("Windchill: \t"); | |
if (Winter) { | |
Serial.println( results.windchill ); | |
} | |
else { | |
Serial.println( "NULL" ); | |
} | |
Serial.print("Pressure: \t"); | |
Serial.println( results.pressure ); | |
Serial.print("Humidity: \t"); | |
Serial.println( results.humidityOUT ); | |
Serial.print("Dewpoint: \t"); | |
Serial.println( results.dewpoint ); | |
Serial.print("Heat Index: \t"); | |
if (Summer) { | |
Serial.println( results.heatindex ); | |
} | |
else { | |
Serial.println( "NULL" ); | |
} | |
Serial.print("Wind Speed: \t"); | |
Serial.println( results.windspeed ); | |
Serial.print("Wind Speed,Gust:\t"); | |
Serial.println(anemSpeedMAX); | |
Serial.print("Wind Vector: \t"); | |
Serial.println( results.winddirection ); | |
Serial.print("TTL Rain Inches: \t"); | |
Serial.println( results.rainttl ); | |
// Serial.print( results.light ); | |
printBreak(); | |
} | |
//============================================================================== | |
void sprintResults() { | |
// Clear array | |
memset(&logline[0], 0, sizeof(logline)); | |
// This crazy mess will assemble the single line of CSV data for the | |
// serial transmission | |
if (CSVMODE == 1) { | |
// 0 indoor temp | |
dtostrf(results.temperatureIN, 4, 2, buffer); | |
strcat(logline,buffer); | |
strcat(logline,","); | |
// 1 outdoor temp | |
dtostrf(results.temperatureOUT, 4, 2, buffer); | |
strcat(logline,buffer); | |
strcat(logline,","); | |
// 2 air pressure in InHg | |
dtostrf(results.pressure, 4, 2, buffer); | |
strcat(logline,buffer); | |
strcat(logline,","); | |
// 3 indoor humidity | |
dtostrf(results.humidityIN, 4, 2, buffer); | |
strcat(logline,buffer); | |
strcat(logline,","); | |
// 4 outdoor humidity | |
dtostrf(results.humidityOUT, 4, 2, buffer); | |
strcat(logline,buffer); | |
strcat(logline,","); | |
// 5 dewpoint | |
dtostrf(results.dewpoint, 4, 2, buffer); | |
strcat(logline,buffer); | |
strcat(logline,","); | |
// 6 windchill | |
dtostrf(results.windchill, 4, 2, buffer); | |
strcat(logline,buffer); | |
strcat(logline,","); | |
// 7 heat index | |
dtostrf(results.heatindex, 4, 2, buffer); | |
strcat(logline,buffer); | |
strcat(logline,","); | |
// 8 wind speed | |
dtostrf(results.windspeed, 4, 2, buffer); | |
strcat(logline,buffer); | |
strcat(logline,","); | |
// 9 wind speed - gust | |
dtostrf(anemSpeedMAX, 4, 2, buffer); | |
strcat(logline,buffer); | |
strcat(logline,","); | |
// 10 wind sirection in compass degrees | |
strcat(logline,results.winddirection); | |
strcat(logline,","); | |
// 11 rain total | |
dtostrf(results.rainttl, 4, 2, buffer); | |
strcat(logline,buffer); | |
strcat(logline,","); | |
// 12 rain per last hour | |
dtostrf(results.rain1hr, 4, 2, buffer); | |
strcat(logline,buffer); | |
strcat(logline,","); | |
// 13 rain per last 24 hour | |
dtostrf(results.rain24hr, 4, 2, buffer); | |
strcat(logline,buffer); | |
strcat(logline,","); | |
// 14 light in watts/in | |
dtostrf(results.light, 4, 2, buffer); | |
strcat(logline,buffer); | |
// Send CSV Buffer to attached server | |
Serial.println(logline); | |
} | |
} | |
//============================================================================== | |
void printBreak() { | |
Serial.println("============================="); | |
} | |
//============================================================================== | |
//============================================================================== | |
// function to print a device address - for debugging | |
void printAddress(DeviceAddress deviceAddress) | |
{ | |
for (uint8_t i = 0; i < 8; i++) | |
{ | |
if (deviceAddress[i] < 16) Serial.print("0"); | |
Serial.print(deviceAddress[i], HEX); | |
Serial.print("."); | |
} | |
} | |
//============================================================================== | |
// Format the results from DallasTemperature library | |
float getTemperature(DeviceAddress deviceAddress) | |
{ | |
float mytempF = 0.0; | |
float mytempC = sensors.getTempC(deviceAddress); | |
if (mytempC == -127.00) { | |
Serial.print("Error getting temperature"); | |
} | |
else { | |
mytempF = DallasTemperature::toFahrenheit(mytempC); | |
return mytempF; | |
} | |
return -999; | |
} | |
//============================================================================== | |
// Format the results from BMP085 library | |
// *** Not 1-wire *** | |
// * must be calibrated for current altitude above sea level | |
// Reference: http://en.wikipedia.org/wiki/Barometric_formula | |
// ft = m * 3.2808 | |
float getPressure() { | |
float temperature; // Celcius | |
float pascals; | |
float p_adj; | |
float raw_pascals; | |
float baro_millibars; | |
float baro_inHg; | |
float altitude; // Meters | |
temperature = bmp.readTemperature(); | |
raw_pascals = bmp.readPressure(); | |
altitude = bmp.readAltitude(P_OFFSET); | |
// based on local calibration | |
//pascals =(raw_pascals/pow((1-altitude/44330),5.255)); | |
pascals = raw_pascals + P_ADJ; // pascals with local offset | |
baro_millibars = (pascals / 100); | |
baro_inHg = baro_millibars / 33.86; | |
return (baro_inHg); | |
} | |
//============================================================================== | |
// Format the results from DS2450 subroutine | |
// Convert from A/D values to circular degrees | |
char* getWindVector(DeviceAddress deviceAddress) | |
{ | |
currentWindDirection = GetWindDirection(deviceAddress); | |
return (windDirectionArray[currentWindDirection]); | |
} | |
//============================================================================== | |
// Format the windspeed results from DS2423 subroutine | |
float getWindSpeed(DeviceAddress deviceAddress) | |
{ | |
// Base windspeed on 1-wire update cycle period. | |
// Note: Cannot realistically be less than about 2.5 seconds. | |
float windSpeed = 0.0; // Clear speed counter | |
float diffCount = 0.0; // Clear difference counter | |
windCount = GetCounter(deviceAddress); // Get the current counter value | |
// Calculate the wind speed based on anemometer revolutions per second | |
// ((Count Difference/TimeDifference/1000))/counts per rev * miles_per_hour constant | |
if (lastCount != 0) | |
{ | |
// windSpeed = diffcount/((1-wire Cycle Time in seconds) * MILES_PER_HOUR); | |
diffCount = windCount-lastCount; | |
windSpeed = diffCount /((WINDSPEED_RESCAN/1000) * MILES_PER_HOUR); | |
} | |
// remember count & time for later | |
lastCount = windCount; | |
if (DEBUG) { | |
Serial.print("Wind Count: \t"); | |
Serial.println(windCount); | |
Serial.print("Diff Count: \t"); | |
Serial.println(diffCount); | |
Serial.print("Wind Speed: \t"); | |
Serial.println(windSpeed); | |
} | |
return (windSpeed); | |
} | |
//============================================================================== | |
float getHumidity() { | |
// Note: my DS2438 reads a bit high using the HIH4000 | |
float humidity; | |
humidity = hum1.readHum(); | |
humidity += hum_Offset; | |
humidity = constrain(humidity, 0, 100); | |
return humidity; | |
} | |
//============================================================================== | |
float getDewpoint() { | |
float humidity; | |
float dewpoint; | |
float humtempc; | |
float humtempk; | |
humtempc = hum1.readTempC(); | |
humtempk = humtempc + 273.15; | |
humidity = getHumidity(); | |
dewpoint = humtempk/((-0.0001846 * log(humidity/100.0) * humtempk) +1.0); | |
dewpoint = dewpoint - 273.15; // Convert to C | |
dewpoint = (dewpoint * 9/5) +32; // Convert to F | |
return dewpoint; | |
} | |
//============================================================================== | |
float getHeatIndex() { | |
// See http links at top for how this was derived. | |
float heatindex; | |
double c1 = -42.38, c2 = 2.049, c3 = 10.14, c4 = -0.2248, c5= -6.838e-3; | |
double c6=-5.482e-2, c7=1.228e-3, c8=8.528e-4, c9=-1.99e-6; | |
float T = hum1.readTempF(); | |
float R = getHumidity(); | |
double A = (( c5 * T) + c2) * T + c1; | |
double B = ((c7 * T) + c4) * T + c3; | |
double C = ((c9 * T) + c8) * T + c6; | |
heatindex = (C * R + B) * R + A; | |
return heatindex; | |
} | |
//============================================================================= | |
float getWindChill() { | |
// See http links at top for how this was derived. | |
float WindChillTemp; | |
if ((results.temperatureOUT <50.0) && (results.windspeed > 3.0)) | |
{ | |
WindChillTemp=35.74+0.6215*results.temperatureOUT-35.75*pow(results.windspeed,0.16)+0.4275*results.temperatureOUT*pow(results.windspeed,0.16); | |
} | |
else { | |
WindChillTemp=results.temperatureOUT; | |
} | |
return WindChillTemp; | |
} | |
//============================================================================== | |
// Format the windspeed results from DS2423 subroutine | |
// Current device is 0.02 inches per tip | |
// Counter cannot be zeroed unless battery is removed from sensor | |
float getRainCount(DeviceAddress deviceAddress) | |
{ | |
long rainCount = 0.0; | |
rainCount = GetCounter(RAIN_COUNT_ID); | |
if (rainCount <0) { | |
Serial.print("Error getting RainCount"); | |
} | |
else { | |
return rainCount; | |
} | |
return -999; | |
} | |
//============================================================================= | |
//Returns the value of the external counter A in the DS2423. | |
// | |
//The DS2423 returns the counter A count at the end of page 0x01c0 and is | |
//returned by sending the instruction 0xa5. | |
//============================================================================== | |
int GetCounter(DeviceAddress deviceAddress) | |
{ | |
uint32_t count; | |
uint8_t data[4]; | |
byte i; | |
oneWire.reset(); | |
oneWire.select(deviceAddress); | |
oneWire.write(0xa5, 0); // Read memory and counter command | |
oneWire.write(0xc0, 0); // Start at page 14 which has external counter A at the end... | |
oneWire.write(0x01, 0); // = 0x01c0 | |
for (i = 0; i<32; i++) //Read back the 32 bits in the datapage (no information for us here) | |
{ | |
oneWire.read(); | |
} | |
for (int i=0; i<3; i++) { | |
data[i] = oneWire.read(); // read in counter data | |
} | |
count = data[3]; | |
count = count << 8; | |
count |= data[2]; | |
count = count << 8; | |
count |= data[1]; | |
count = count << 8; | |
count |= data[0]; | |
return count; | |
//You could check the checksum here if you wanted | |
//return(data[0]); //we only need the lowest byte | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment