Skip to content

Instantly share code, notes, and snippets.

@jimblom
Created March 24, 2015 20:31
Show Gist options
  • Save jimblom/8bf222c059bd92a3e10a to your computer and use it in GitHub Desktop.
Save jimblom/8bf222c059bd92a3e10a to your computer and use it in GitHub Desktop.
Photon_Weather_Report
/**
* Phant.cpp
*
* .-.._
* __ /` '.
* .-' `/ ( a \
* / ( \,_ \
* /| '---` |\ =|
* ` \ /__.-/ / | |
* | / / \ \ \ \_\ jgs
* |__|_| |_|__\
* never forget.
*
* Author: Todd Treece <todd@sparkfun.com>
*
* Copyright (c) 2014 SparkFun Electronics.
* Licensed under the GPL v3 license.
*
*/
#include "Phant.h"
#include <stdlib.h>
Phant::Phant(String host, String publicKey, String privateKey) {
_host = host;
_pub = publicKey;
_prv = privateKey;
_params = "";
}
void Phant::add(String field, String data) {
_params += "&" + field + "=" + data;
}
void Phant::add(String field, char data) {
_params += "&" + field + "=" + String(data);
}
void Phant::add(String field, int data) {
_params += "&" + field + "=" + String(data);
}
void Phant::add(String field, byte data) {
_params += "&" + field + "=" + String(data);
}
void Phant::add(String field, long data) {
_params += "&" + field + "=" + String(data);
}
void Phant::add(String field, unsigned int data) {
_params += "&" + field + "=" + String(data);
}
void Phant::add(String field, unsigned long data) {
_params += "&" + field + "=" + String(data);
}
void Phant::add(String field, double data) {
char tmp[30];
//dtostrf(data, 1, 4, tmp);
sprintf(tmp, "%f", data);
_params += "&" + field + "=" + String(tmp);
}
void Phant::add(String field, float data) {
char tmp[30];
//dtostrf(data, 1, 4, tmp);
sprintf(tmp, "%f", data);
_params += "&" + field + "=" + String(tmp);
}
String Phant::queryString() {
return String(_params);
}
String Phant::url() {
String result = "http://" + _host + "/input/" + _pub + ".txt";
result += "?private_key=" + _prv + _params;
_params = "";
return result;
}
String Phant::get() {
String result = "GET /output/" + _pub + ".csv HTTP/1.1\n";
result += "Host: " + _host + "\n";
result += "Connection: close\n";
return result;
}
String Phant::post() {
String params = _params.substring(1);
String result = "POST /input/" + _pub + ".txt HTTP/1.1\n";
result += "Host: " + _host + "\n";
result += "Phant-Private-Key: " + _prv + "\n";
result += "Connection: close\n";
result += "Content-Type: application/x-www-form-urlencoded\n";
result += "Content-Length: " + String(params.length()) + "\n\n";
result += params;
_params = "";
return result;
}
String Phant::clear() {
String result = "DELETE /input/" + _pub + ".txt HTTP/1.1\n";
result += "Host: " + _host + "\n";
result += "Phant-Private-Key: " + _prv + "\n";
result += "Connection: close\n";
return result;
}
/**
* Phant.h
*
* .-.._
* __ /` '.
* .-' `/ ( a \
* / ( \,_ \
* /| '---` |\ =|
* ` \ /__.-/ / | |
* | / / \ \ \ \_\ jgs
* |__|_| |_|__\
* never forget.
*
* Author: Todd Treece <todd@sparkfun.com>
*
* Copyright (c) 2014 SparkFun Electronics.
* Licensed under the GPL v3 license.
*
*/
#ifndef Phant_h
#define Phant_h
#include "application.h"
class Phant {
public:
Phant(String host, String publicKey, String privateKey);
void add(String field, String data);
void add(String field, char data);
void add(String field, int data);
void add(String field, byte data);
void add(String field, long data);
void add(String field, unsigned int data);
void add(String field, unsigned long data);
void add(String field, float data);
void add(String field, double data);
String queryString();
String url();
String get();
String post();
String clear();
private:
String _pub;
String _prv;
String _host;
String _params;
};
#endif
#include "SFE_DHT22.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);
digitalWrite(_pin, HIGH);
_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
digitalWrite(_pin, HIGH);
delay(250);
// now pull it low for ~20 milliseconds
pinMode(_pin, OUTPUT);
digitalWrite(_pin, LOW);
delay(20);
noInterrupts();
digitalWrite(_pin, HIGH);
delayMicroseconds(40);
pinMode(_pin, INPUT);
// read in timings
for ( i=0; i< MAXTIMINGS; i++) {
counter = 0;
while (digitalRead(_pin) == laststate) {
counter++;
delayMicroseconds(1);
if (counter == 255) {
break;
}
}
laststate = digitalRead(_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;
}
#ifndef SFE_DHT22_H
#define SFE_DHT22_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
#include "Phant.h"
#include "SFE_DHT22.h"
int lightSensor = A0;
#define DHTPIN 2 // what pin we're connected to
#define DHTTYPE DHT22 // DHT 22 (AM2302)
DHT dht(DHTPIN, DHTTYPE);
const char server[] = "data.sparkfun.com";
const char publicKey[] = "zDaREyrLnGfAQxdyxJLA";
const char privateKey[] = "Yy4eqKJMZwTqPM69Mypq";
Phant phant(server, publicKey, privateKey);
const int POST_RATE = 30000; // Time between posts, in ms.
unsigned long lastPost = 0;
void setup()
{
Serial.begin(9600);
pinMode(lightSensor, INPUT);
dht.begin();
postToPhant();
}
void loop()
{
if (lastPost + POST_RATE < millis())
{
if (postToPhant() > 0)
{
lastPost = millis();
}
}
printWeather();
delay(1000);
}
int postToPhant()
{
// 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.getHumidity();
// Read temperature as Celsius
float t = dht.getTempCelcius();
// Read temperature as Farenheit
float f = dht.getTempFarenheit();
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t) || isnan(f)) {
//Serial.println("Failed to read from DHT sensor!");
return -4;
}
float hi = dht.getHeatIndex();
float dp = dht.getDewPoint();
phant.add("room1_light", analogRead(lightSensor));
phant.add("room1_temp", t);
phant.add("room2_light", hi);
phant.add("room2_temp", f);
phant.add("room3_humidity", h);
TCPClient client;
char response[512];
int i = 0;
int retVal = 0;
if (client.connect(server, 80))
{
Serial.println("Posting!");
client.print(phant.post());
delay(1000);
while (client.available())
{
char c = client.read();
//Serial.print(c);
if (i < 512)
response[i++] = c;
}
if (strstr(response, "200 OK"))
{
Serial.println("Post success!");
retVal = 1;
}
else if (strstr(response, "400 Bad Request"))
{
Serial.println("Bad request");
retVal = -1;
}
else
{
retVal = -2;
}
}
else
{
Serial.println("connection failed");
retVal = -3;
}
client.stop();
return retVal;
}
void printWeather()
{
// 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.getHumidity();
// Read temperature as Celsius
float t = dht.getTempCelcius();
// Read temperature as Farenheit
float f = dht.getTempFarenheit();
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t) || isnan(f)) {
//Serial.println("Failed to read from DHT sensor!");
return;
}
// Compute heat index
// Must send in temp in Fahrenheit!
float hi = dht.getHeatIndex();
float dp = dht.getDewPoint();
float k = dht.getTempKelvin();
Serial.print("Light: ");
Serial.println(analogRead(lightSensor));
Serial.print("Humid: ");
Serial.print(h);
Serial.print("% - ");
Serial.print("Temp: ");
Serial.print(t);
Serial.print("*C ");
Serial.print(f);
Serial.print("*F ");
Serial.print(k);
Serial.print("*K - ");
Serial.print("DewP: ");
Serial.print(dp);
Serial.print("*C - ");
Serial.print("HeatI: ");
Serial.print(hi);
Serial.println("*C");
Serial.println(Time.timeStr());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment