Created
November 25, 2015 22:02
-
-
Save toolboc/c2adb6a5ea1a00a1bca8 to your computer and use it in GitHub Desktop.
SoilMonitor.ino for Particle Photon
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
// This #include statement was automatically added by the Particle IDE. | |
#include "AzureMobileService/AzureMobileService.h" | |
// This #include statement was automatically added by the Particle IDE. | |
#include "SparkFun_Photon_Weather_Shield_Library/SparkFun_Photon_Weather_Shield_Library.h" | |
//Azure Mobile Service Configuration | |
#define MYSERVICE "soilmonitor" | |
#define MYKEY "FINDTHISKEYINAZUREPORTAL" | |
AzureMobileService ams; | |
const char* table = "Data"; | |
//SoilMonitor Zone Configuration and ADC_MAX_RES | |
const char *LOCATION_NAME = "Paul's Backyard"; | |
const int NUMBER_OF_ZONES = 6; | |
//Zone Names may not containt whitespace | |
const char *ZONE_NAMES[NUMBER_OF_ZONES] = {"Orange", "Lemon", "Yard", "Bottlebrush", "Fig", "Peach"}; | |
const float ADC_MAX_RES = 4096; //Particle Core | Particle Photon use 12-bit Resolution ADCs (2^12 = 4096) | |
float currentSaturation = -1; | |
float saturationData[NUMBER_OF_ZONES]; | |
float reading = 0; | |
//WeatherShield Configuration | |
float humidity = 0; | |
float tempf = 0; | |
float pascals = 0; | |
float baroTemp = 0; | |
//Create Instance of HTU21D or SI7021 temp and humidity sensor and MPL3115A2 barrometric sensor | |
Weather sensor; | |
//Put Device to Sleep when not reporting data | |
int ReportAndSleepIntervalInSeconds = 1800; //Default 1800 seconds equates to 2 reads per hour | |
//The maximum message size to send to Azure Mobile Services | |
//Careful with the payload size, if you raise this too high, you may experience a 'red light' fault on the Particle device | |
const int MaxAzurePayloadSize = 500; | |
void setup() { | |
Serial.begin(9600); | |
delay(6000); | |
//Using D7 to drive current, we can rest sensors during sleep, this is a hack but gets the job done ;) | |
pinMode(D7, OUTPUT); | |
pinMode(A0, INPUT); | |
pinMode(A1, INPUT); | |
pinMode(A2, INPUT); | |
pinMode(A3, INPUT); | |
pinMode(A4, INPUT); | |
pinMode(A5, INPUT); | |
ams.configure(MYSERVICE, MYKEY); | |
//Initialize the I2C sensors and ping them | |
sensor.begin(); | |
/*You can only receive acurate barrometric readings or acurate altitiude | |
readings at a given time, not both at the same time. The following two lines | |
tell the sensor what mode to use. You could easily write a function that | |
takes a reading in one made and then switches to the other mode to grab that | |
reading, resulting in data that contains both acurate altitude and barrometric | |
readings. For this example, we will only be using the barometer mode. Be sure | |
to only uncomment one line at a time. */ | |
sensor.setModeBarometer();//Set to Barometer Mode | |
//baro.setModeAltimeter();//Set to altimeter Mode | |
//These are additional MPL3115A2 functions the MUST be called for the sensor to work. | |
sensor.setOversampleRate(7); // Set Oversample rate | |
//Call with a rate from 0 to 7. See page 33 for table of ratios. | |
//Sets the over sample rate. Datasheet calls for 128 but you can set it | |
//from 1 to 128 samples. The higher the oversample rate the greater | |
//the time between data samples. | |
sensor.enableEventFlags(); //Necessary register calls to enble temp, baro ansd alt | |
} | |
void loop() { | |
//Turn Saturation Sensors On | |
digitalWrite(D7, HIGH); | |
ReadSaturationSensors(); | |
//Turn Saturation Sensors Off | |
digitalWrite(D7, LOW); | |
ReadWeatherSensors(); | |
PublishData(); | |
Serial.println("***************************************"); | |
Serial.println(" Begin Sleep "); | |
Serial.println("***************************************"); | |
delay(1000); | |
System.sleep(SLEEP_MODE_DEEP, ReportAndSleepIntervalInSeconds); | |
} | |
void ReadSaturationSensors() { | |
Serial.println("***************************************"); | |
Serial.println(" Begin Saturation Data"); | |
Serial.println("***************************************"); | |
for(int i = 0; i < NUMBER_OF_ZONES; i++) | |
{ | |
reading = analogRead(i); | |
currentSaturation = ((reading/ADC_MAX_RES - 1) * -1); | |
saturationData[i] = currentSaturation; | |
Serial.print(ZONE_NAMES[i]); | |
Serial.print(": "); | |
Serial.println(currentSaturation); | |
delay(1000); | |
} | |
} | |
void ReadWeatherSensors() { | |
// Measure Relative Humidity from the HTU21D or Si7021 | |
humidity = sensor.getRH(); | |
// Measure Temperature from the HTU21D or Si7021 | |
tempf = sensor.getTempF(); | |
// Temperature is measured every time RH is requested. | |
// It is faster, therefore, to read it from previous RH | |
// measurement with getTemp() instead with readTemp() | |
//Measure the Barometer temperature in F from the MPL3115A2 | |
baroTemp = sensor.readBaroTempF(); | |
//Measure Pressure from the MPL3115A2 | |
pascals = ((sensor.readPressure()/100) * 0.0295300); | |
//If in altitude mode, you can get a reading in feet with this line: | |
//float altf = sensor.readAltitudeFt(); | |
Serial.println("***************************************"); | |
Serial.println(" Begin Weather Data"); | |
Serial.println("***************************************"); | |
Serial.print("Temp:"); | |
Serial.print(tempf); | |
Serial.println("F "); | |
Serial.print("Humidity:"); | |
Serial.print(humidity); | |
Serial.println("% "); | |
Serial.print("Baro_Temp:"); | |
Serial.print(baroTemp); | |
Serial.println("F "); | |
Serial.print("Pressure:"); | |
Serial.print(pascals); | |
Serial.println("in.Hg"); | |
//The MPL3115A2 outputs the pressure in Pascals. However, most weather stations | |
//report pressure in hectopascals or millibars. Divide by 100 to get a reading | |
//more closely resembling what online weather reports may say in hPa or mb. | |
//Another common unit for pressure is Inches of Mercury (in.Hg). To convert | |
//from mb to in.Hg, use the following formula. P(inHg) = 0.0295300 * P(mb) | |
//More info on conversion can be found here: | |
//www.srh.noaa.gov/images/epz/wxcalc/pressureConversion.pdf | |
} | |
void PublishData() { | |
Serial.println("***************************************"); | |
Serial.println(" Begin Publish To Azure"); | |
Serial.println("***************************************"); | |
char *payload = (char *) malloc(MaxAzurePayloadSize); | |
snprintf(payload, MaxAzurePayloadSize, "{ \"Location\":\"%s\",", LOCATION_NAME); | |
for(int i = 0; i < NUMBER_OF_ZONES; i++) | |
{ | |
//Old method for sending each Zone as a row, retained as example | |
//snprintf(payload, MaxAzurePayloadSize, "{ \"Location\":\"%s\", \"Zone\":\"%s\", \"Saturation\":%f,\"Humidity\":%f,\"TempF\":%f,\"BaroTemp\":%f,\"Pascals\":%f }", LOCATION_NAME, ZONE_NAMES[i], saturationData[i], humidity, tempf, baroTemp, pascals); | |
char currentZoneData[50]; | |
snprintf(currentZoneData, 50, " \"%s\":%f,", ZONE_NAMES[i], saturationData[i]); | |
strcat(payload, currentZoneData); | |
} | |
char weatherData[100]; | |
snprintf(weatherData, 100, "\"Humidity\":%f,\"TempF\":%f,\"BaroTemp\":%f,\"Pascals\":%f }", humidity, tempf, baroTemp, pascals); | |
strcat(payload,weatherData); | |
int response = ams.create(table, payload); | |
free(payload); | |
if(response != 201) | |
{ | |
Serial.print("Expected Response Code 201, Received Code: "); | |
Serial.println(response); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment