Another round of updates late this week. I had ordered a Photon Weather Shield and a from Sparkfun and they arrived yesterday.
Weather Shield https://www.sparkfun.com/products/13630
Battery Shield https://www.sparkfun.com/products/13626
So last night added i2c header pins to the Weather Shield and connected my I2CXL-MaxSonar sensor. Also hooked up a uFL to RP-SMA pigtail and a higher gain antenna.
It didn’t take much to integrate the Sparkfun libraries and example code into my working proto code. (actually it was the other way around. I restarted from the SparkFun Photon Weather Shield basic example code, added to it and modified it to fit with my earlier work on power optimization.)
Below is the code I’m running this weekend and generating data that looks like this.
So far there is a small effect of temperature on the range value, but it may be small enough I don’t need to worry about it for my application.
/******************************************************************************
SparkFun Photon Weather Shield basic example
Joel Bartlett @ SparkFun Electronics
Original Creation Date: May 18, 2015
Updated August 21, 2015
This sketch prints the temperature, humidity, and barometric pressure OR
altitude to the Serial port.
The library used in this example can be found here:
https://github.com/sparkfun/SparkFun_Photon_Weather_Shield_Particle_Library
Hardware Connections:
This sketch was written specifically for the Photon Weather Shield,
which connects the HTU21D and MPL3115A2 to the I2C bus by default.
If you have an HTU21D and/or an MPL3115A2 breakout, use the following
hardware setup:
HTU21D ------------- Photon
(-) ------------------- GND
(+) ------------------- 3.3V (VCC)
CL ------------------- D1/SCL
DA ------------------- D0/SDA
MPL3115A2 ------------- Photon
GND ------------------- GND
VCC ------------------- 3.3V (VCC)
SCL ------------------ D1/SCL
SDA ------------------ D0/SDA
Development environment specifics:
IDE: Particle Dev
Hardware Platform: Particle Photon
Particle Core
This code is beerware; if you see me (or any other SparkFun
employee) at the local, and you've found our code helpful,
please buy us a round!
Distributed as-is; no warranty is given.
*******************************************************************************/
#include "SparkFun_Photon_Weather_Shield_Library/SparkFun_Photon_Weather_Shield_Library.h"
double humidity = 0;
double tempf = 0;
double pascals = 0;
double baroTemp = 0;
long lastPublish = 0;
//Create Instance of HTU21D or SI7021 temp and humidity sensor and MPL3115A2 barometric sensor
Weather sensor;
/******************************************************************************
Basic Range finding with I2CXL-MaxSonar
by Tom Sayles <TSayles@Soot-n-Smoke.com>
Code taken heavely from the I2CXL-MaxSonar® - WR/WRCTM Series data sheet
http://www.maxbotix.com/documents/I2CXL-MaxSonar-WR_Datasheet.pdf
Assumes the sensor is using the default address
*******************************************************************************/
//The Wire library uses the 7-bit version of the address, so the code example uses 0x70 instead of the 8-bit 0xE0
#define SensorAddress byte(0x70)
//The sensors ranging command has a value of 0x51
#define RangeCommand byte(0x51)
//These are the two commands that need to be sent in sequence to change the sensor address
#define ChangeAddressCommand1 byte(0xAA)
#define ChangeAddressCommand2 byte(0xA5)
int rangValue = 0;
int led2 = D7; // Instead of writing D7 over and over again, we'll write led2
//---------------------------------------------------------------
void setup()
{
// Create Particle.variables for each piece of data for easy access
Particle.variable("humidity", humidity);
Particle.variable("tempF", tempf);
Particle.variable("pressurePascals", pascals);
Particle.variable("baroTemp", baroTemp);
Particle.variable("range", rangValue);
//Initialize the I2C sensors and ping them
sensor.begin();
/*You can only receive accurate barometric readings or accurate altitude
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 accurate altitude and barometric
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 that 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 and alt
pinMode(led2, OUTPUT);
publishData();
delay(30000); // Wait for any over the air updates.
publishData();
delay(30000); // Wait for any over the air updates.
publishData();
delay(30000); // Wait for any over the air updates.
publishData();
delay(30000); // Wait for any over the air updates.
digitalWrite(led2, HIGH);
delay(500);
digitalWrite(led2, LOW);
delay(500);
digitalWrite(led2, HIGH);
delay(500);
digitalWrite(led2, LOW);
delay(500);
digitalWrite(led2, HIGH);
delay(1000);
digitalWrite(led2, LOW);
System.sleep(SLEEP_MODE_DEEP,1000); //shut down for 16 minutes and 40 seconds
}
//---------------------------------------------------------------
void loop()
{
publishData();
delay(10000);
}
//---------------------------------------------------------------
void publishData(){
digitalWrite(led2, HIGH);
//Get readings from all sensors
getWeather();
getRange();
// This math looks at the current time vs the last time a publish happened
//if(millis() - lastPublish > 30000) //Publishes every 5000 milliseconds, or 5 seconds
//{
// Record when you published
lastPublish = millis();
// Choose which values you actually want to publish- remember, if you're
// publishing more than once per second on average, you'll be throttled!
Particle.publish("humidity", String(humidity));
Particle.publish("tempF", String(tempf));
//Particle.variable("pressurePascals", pascals);
//Particle.variable("baroTemp", baroTemp);
Particle.publish("Range: ", String(rangValue)); // Publish a range event
//}
digitalWrite(led2, LOW);
}
void getWeather()
{
// 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();
//If in altitude mode, you can get a reading in feet with this line:
//float altf = sensor.readAltitudeFt();
}
void takeRangeReading(){
Wire.beginTransmission(SensorAddress);
//Start addressing
Wire.write(RangeCommand);
//send range command
Wire.endTransmission();
//Stop and do something else now
}
void getRange() {
takeRangeReading();
//Tell the sensor to perform a ranging cycle
delay(100);
//Wait for sensor to finish
uint16_t range = requestRange();
//Get the range from the sensor
rangValue = range; //update the online range varable
Serial.print("Range String: "); Serial.println(String(rangValue));
//Print to the user
}
//Returns the last range that the sensor determined in its last ranging cycle in centimeters. Returns 0 if there is no communication.
uint16_t requestRange(){
Wire.requestFrom(SensorAddress, byte(2));
if(Wire.available() >= 2){
//Sensor responded with the two bytes
byte HighByte = Wire.read();
//Read the high byte back
byte LowByte = Wire.read();
//Read the low byte back
//uint16_t range = uint16_t(HighByte, LowByte);
uint16_t range = 256 * HighByte + LowByte;
//Make a 16-bit word out of the two bytes for the range
return range;
}
else {
return uint16_t(0);
//Else nothing was received, return 0
}
}