SparkFun Weathershield killed my Photon

SPARKFUN-WEATHER-killedMyPhoton ** OH Crud*********************

After working on what should have been a fun and simple weather station using the Sparkfun weather shield and photon, I have now killed my 7th Photon. I don’t have time for all the hassle, so I kept buying new ones. I just sent 5 to their warehouse in Gilroy asking for replacements without an RMA. We’ll see what happens with that, but here is the problem.

When you use the Atom IDE with the Particle set up and install the SparkFun_Photon_Weather_Wunderground.ino
SparkFun_Photon_Weather_Shield_Library_h
.DS_Store

It kills the photon dead. What in the world is going on? These files are all on the sparkfun github site.

What a hassle. It is things like this that can kill what could be a great product.

Bob Vaughan

How do you determine they're 'dead'? What does the LED do (or doesn't do anymore)?

"... doing the same thing over and over again, expecting different results".

It's very unlikely that you've received 7 faulty Photons, and I don't expect the firmware to be the cause of the issues either, since there are more people using that code, and these issues haven't been reported before. As such, this leads me to believe there might be a hardware issue with the weathershield that's messing with the Photons, if they're indeed as dead as you proclaim them to be.
There might even be an issue in the way you hooked things up, though that's currently impossible to tell without knowing further details.

Seeing as that's the warehouse/distributing center, and they're not in charge of handling returned units, I'd highly recommend filing a support ticket, mentioning this thread.

Not the shield.

The shield was not attached when the Photon was programmed.

The led is off. Pressing the buttons in all different patterns fails to get the Photon in a listening mode.

Share your code and I’ll see if it kills my Photon also :smiley:

SparkFun_Photon_Weather_Shield_Library.cpp

/*
 SparkFun Photon Weather Shield Particle Library
 Compiled and Updated for Particle By: Joel Bartlett
 SparkFun Electronics
 Date: August 05, 2015

 This library combines multiple libraries together to make development on the SparkFun
 Photon Weather Shield easier. There are two versions of the Weather Shield, one containing
 the HTU21D Temp and Humidity sensor and one containing the Si7021-A10. Shortages of the HTU21D
 IC combined with contractual obligations led to the two versions existing. Thus, to make it
 easier on you, the end user, we have written this library to automatically detect which version
 you have without the need for you to have to figure it out and pick a corresponding library.
 The MPL3115A2 library was added to avoid the need to import two separate libraries for
 the shield.

 This library is based on the following libraries:

 MPL3115A2 Barometric Pressure Sensor Library
 By: Nathan Seidle
 SparkFun Electronics
 Date: September 24th, 2013
 https://github.com/sparkfun/MPL3115A2_Breakout

 Spark Core HTU21D Temperature / Humidity Sensor Library
 By: Romain MP
 https://github.com/romainmp/HTU21D

 Arduino Si7010 relative humidity + temperature sensor
 By: Jakub Kaminski, 2014
 https://github.com/teoqba/ADDRESS

 This Library is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This Library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 For a copy of the GNU General Public License, see
 <http://www.gnu.org/licenses/>.
 */

 #include "SparkFun_Photon_Weather_Shield_Library.h"

 //Initialize
 Weather::Weather(){}

 void Weather::begin(void)
{
  Wire.begin();

  uint8_t ID_Barro = IIC_Read(WHO_AM_I );
  uint8_t ID_Temp_Hum = checkID();

  int x,y = 0;

  if (ID_Barro == 0xC4)//Ping WhoAmI register
    x = 1;
  else
  	x = 0;

  if(ID_Temp_Hum == 0x15)//Ping CheckID register
    y = 1;
  else if(ID_Temp_Hum == 0x32)
    y = 2;
  else
    y = 0;

  if(x == 1 && y == 1)
  {
    Serial.println("MPL3115A2 Found");
    Serial.println("Si7021 Found");
  }
  else if(x == 1 && y == 2)
  {
    Serial.println("MPL3115A2 Found");
    Serial.println("HTU21D Found");
  }
  else if(x == 0 && y == 1)
  {
    Serial.println("MPL3115A2 NOT Found");
    Serial.println("Si7021 Found");
  }
  else if(x == 0 && y == 2)
  {
    Serial.println("MPL3115A2 NOT Found");
    Serial.println("HTU21D Found");
  }
  else if(x == 1 && y == 0)
  {
    Serial.println("MPL3115A2 Found");
    Serial.println("No Temp/Humidity Device Detected");
  }
  else
  	Serial.println("No Devices Detected");
}

/****************Si7021 & HTU21D Functions**************************************/


float Weather::getRH()
{
	// Measure the relative humidity
	uint16_t RH_Code = makeMeasurment(HUMD_MEASURE_NOHOLD);
	float result = (125.0*RH_Code/65536)-6;
	return result;
}

float Weather::readTemp()
{
	// Read temperature from previous RH measurement.
	uint16_t temp_Code = makeMeasurment(TEMP_PREV);
	float result = (175.25*temp_Code/65536)-46.85;
	return result;
}

float Weather::getTemp()
{
	// Measure temperature
	uint16_t temp_Code = makeMeasurment(TEMP_MEASURE_NOHOLD);
	float result = (175.25*temp_Code/65536)-46.85;
	return result;
}
//Give me temperature in fahrenheit!
float Weather::readTempF()
{
  return((readTemp() * 1.8) + 32.0); // Convert celsius to fahrenheit
}

float Weather::getTempF()
{
  return((getTemp() * 1.8) + 32.0); // Convert celsius to fahrenheit
}


void Weather::heaterOn()
{
	// Turns on the ADDRESS heater
	uint8_t regVal = readReg();
	regVal |= _BV(HTRE);
	//turn on the heater
	writeReg(regVal);
}

void Weather::heaterOff()
{
	// Turns off the ADDRESS heater
	uint8_t regVal = readReg();
	regVal &= ~_BV(HTRE);
	writeReg(regVal);
}

void Weather::changeResolution(uint8_t i)
{
	// Changes to resolution of ADDRESS measurements.
	// Set i to:
	//      RH         Temp
	// 0: 12 bit       14 bit (default)
	// 1:  8 bit       12 bit
	// 2: 10 bit       13 bit
	// 3: 11 bit       11 bit

	uint8_t regVal = readReg();
	// zero resolution bits
	regVal &= 0b011111110;
	switch (i) {
	  case 1:
	    regVal |= 0b00000001;
	    break;
	  case 2:
	    regVal |= 0b10000000;
	    break;
	  case 3:
	    regVal |= 0b10000001;
	  default:
	    regVal |= 0b00000000;
	    break;
	}
	// write new resolution settings to the register
	writeReg(regVal);
}

void Weather::reset()
{
	//Reset user resister
	writeReg(SOFT_RESET);
}

uint8_t Weather::checkID()
{
	uint8_t ID_1;

 	// Check device ID
	Wire.beginTransmission(ADDRESS);
	Wire.write(0xFC);
	Wire.write(0xC9);
	Wire.endTransmission();

    Wire.requestFrom(ADDRESS,1);

    ID_1 = Wire.read();

    return(ID_1);
}

uint16_t Weather::makeMeasurment(uint8_t command)
{
	// Take one ADDRESS measurement given by command.
	// It can be either temperature or relative humidity
	// TODO: implement checksum checking

	uint16_t nBytes = 3;
	// if we are only reading old temperature, read olny msb and lsb
	if (command == 0xE0) nBytes = 2;

	Wire.beginTransmission(ADDRESS);
	Wire.write(command);
	Wire.endTransmission();
	// When not using clock stretching (*_NOHOLD commands) delay here
	// is needed to wait for the measurement.
	// According to datasheet the max. conversion time is ~22ms
	 delay(100);

	Wire.requestFrom(ADDRESS,nBytes);
	//Wait for data
	int counter = 0;
	while (Wire.available() < nBytes){
	  delay(1);
	  counter ++;
	  if (counter >100){
	    // Timeout: Sensor did not return any data
	    return 100;
	  }
	}

	unsigned int msb = Wire.read();
	unsigned int lsb = Wire.read();
	// Clear the last to bits of LSB to 00.
	// According to datasheet LSB of RH is always xxxxxx10
	lsb &= 0xFC;
	unsigned int mesurment = msb << 8 | lsb;

	return mesurment;
}

void Weather::writeReg(uint8_t value)
{
	// Write to user register on ADDRESS
	Wire.beginTransmission(ADDRESS);
	Wire.write(WRITE_USER_REG);
	Wire.write(value);
	Wire.endTransmission();
}

uint8_t Weather::readReg()
{
	// Read from user register on ADDRESS
	Wire.beginTransmission(ADDRESS);
	Wire.write(READ_USER_REG);
	Wire.endTransmission();
	Wire.requestFrom(ADDRESS,1);
	uint8_t regVal = Wire.read();
	return regVal;
}

/****************MPL3115A2 Functions**************************************/
//Returns the number of meters above sea level
//Returns -1 if no new data is available
float Weather::readAltitude()
{
	toggleOneShot(); //Toggle the OST bit causing the sensor to immediately take another reading

	//Wait for PDR bit, indicates we have new pressure data
	int counter = 0;
	while( (IIC_Read(STATUS) & (1<<1)) == 0)
	{
		if(++counter > 600) return(-999); //Error out after max of 512ms for a read
		delay(1);
	}

	// Read pressure registers
	Wire.beginTransmission(MPL3115A2_ADDRESS);
	Wire.write(OUT_P_MSB);  // Address of data to get
	Wire.endTransmission(false); // Send data to I2C dev with option for a repeated start. THIS IS NECESSARY and not supported before Arduino V1.0.1!
	if (Wire.requestFrom(MPL3115A2_ADDRESS, 3) != 3) { // Request three bytes
		return -999;
	}

	byte msb, csb, lsb;
	msb = Wire.read();
	csb = Wire.read();
	lsb = Wire.read();

	// The least significant bytes l_altitude and l_temp are 4-bit,
	// fractional values, so you must cast the calulation in (float),
	// shift the value over 4 spots to the right and divide by 16 (since
	// there are 16 values in 4-bits).
	float tempcsb = (lsb>>4)/16.0;

	float altitude = (float)( (msb << 8) | csb) + tempcsb;

	return(altitude);
}

//Returns the number of feet above sea level
float Weather::readAltitudeFt()
{
  return(readAltitude() * 3.28084);
}

//Reads the current pressure in Pa
//Unit must be set in barometric pressure mode
//Returns -1 if no new data is available
float Weather::readPressure()
{
	//Check PDR bit, if it's not set then toggle OST
	if(IIC_Read(STATUS) & (1<<2) == 0) toggleOneShot(); //Toggle the OST bit causing the sensor to immediately take another reading

	//Wait for PDR bit, indicates we have new pressure data
	int counter = 0;
	while(IIC_Read(STATUS) & (1<<2) == 0)
	{
		if(++counter > 600) return(-999); //Error out after max of 512ms for a read
		delay(1);
	}

	// Read pressure registers
	Wire.beginTransmission(MPL3115A2_ADDRESS);
	Wire.write(OUT_P_MSB);  // Address of data to get
	Wire.endTransmission(false); // Send data to I2C dev with option for a repeated start. THIS IS NECESSARY and not supported before Arduino V1.0.1!
	if (Wire.requestFrom(MPL3115A2_ADDRESS, 3) != 3) { // Request three bytes
		return -999;
	}

	byte msb, csb, lsb;
	msb = Wire.read();
	csb = Wire.read();
	lsb = Wire.read();

	toggleOneShot(); //Toggle the OST bit causing the sensor to immediately take another reading

	// Pressure comes back as a left shifted 20 bit number
	long pressure_whole = (long)msb<<16 | (long)csb<<8 | (long)lsb;
	pressure_whole >>= 6; //Pressure is an 18 bit number with 2 bits of decimal. Get rid of decimal portion.

	lsb &= 0b00110000; //Bits 5/4 represent the fractional component
	lsb >>= 4; //Get it right aligned
	float pressure_decimal = (float)lsb/4.0; //Turn it into fraction

	float pressure = (float)pressure_whole + pressure_decimal;

	return(pressure);
}

float Weather::readBaroTemp()
{
	if(IIC_Read(STATUS) & (1<<1) == 0) toggleOneShot(); //Toggle the OST bit causing the sensor to immediately take another reading

	//Wait for TDR bit, indicates we have new temp data
	int counter = 0;
	while( (IIC_Read(STATUS) & (1<<1)) == 0)
	{
		if(++counter > 600) return(-999); //Error out after max of 512ms for a read
		delay(1);
	}

	// Read temperature registers
	Wire.beginTransmission(MPL3115A2_ADDRESS);
	Wire.write(OUT_T_MSB);  // Address of data to get
	Wire.endTransmission(false); // Send data to I2C dev with option for a repeated start. THIS IS NECESSARY and not supported before Arduino V1.0.1!
	if (Wire.requestFrom(MPL3115A2_ADDRESS, 2) != 2) { // Request two bytes
		return -999;
	}

	byte msb, lsb;
	msb = Wire.read();
	lsb = Wire.read();

	toggleOneShot(); //Toggle the OST bit causing the sensor to immediately take another reading

    //Negative temperature fix by D.D.G.
    uint16_t foo = 0;
    bool negSign = false;

    //Check for 2s compliment
	if(msb > 0x7F)
	{
        foo = ~((msb << 8) + lsb) + 1;  //2’s complement
        msb = foo >> 8;
        lsb = foo & 0x00F0;
        negSign = true;
	}

	// The least significant bytes l_altitude and l_temp are 4-bit,
	// fractional values, so you must cast the calulation in (float),
	// shift the value over 4 spots to the right and divide by 16 (since
	// there are 16 values in 4-bits).
	float templsb = (lsb>>4)/16.0; //temp, fraction of a degree

	float temperature = (float)(msb + templsb);

	if (negSign) temperature = 0 - temperature;

	return(temperature);
}

//Give me temperature in fahrenheit!
float Weather::readBaroTempF()
{
  return((readBaroTemp() * 9.0)/ 5.0 + 32.0); // Convert celsius to fahrenheit
}

//Sets the mode to Barometer
//CTRL_REG1, ALT bit
void Weather::setModeBarometer()
{
  byte tempSetting = IIC_Read(CTRL_REG1); //Read current settings
  tempSetting &= ~(1<<7); //Clear ALT bit
  IIC_Write(CTRL_REG1, tempSetting);
}

//Sets the mode to Altimeter
//CTRL_REG1, ALT bit
void Weather::setModeAltimeter()
{
  byte tempSetting = IIC_Read(CTRL_REG1); //Read current settings
  tempSetting |= (1<<7); //Set ALT bit
  IIC_Write(CTRL_REG1, tempSetting);
}

//Puts the sensor in standby mode
//This is needed so that we can modify the major control registers
void Weather::setModeStandby()
{
  byte tempSetting = IIC_Read(CTRL_REG1); //Read current settings
  tempSetting &= ~(1<<0); //Clear SBYB bit for Standby mode
  IIC_Write(CTRL_REG1, tempSetting);
}

//Puts the sensor in active mode
//This is needed so that we can modify the major control registers
void Weather::setModeActive()
{
  byte tempSetting = IIC_Read(CTRL_REG1); //Read current settings
  tempSetting |= (1<<0); //Set SBYB bit for Active mode
  IIC_Write(CTRL_REG1, tempSetting);
}

//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.
void Weather::setOversampleRate(byte sampleRate)
{
  if(sampleRate > 7) sampleRate = 7; //OS cannot be larger than 0b.0111
  sampleRate <<= 3; //Align it for the CTRL_REG1 register

  byte tempSetting = IIC_Read(CTRL_REG1); //Read current settings
  tempSetting &= 0b11000111; //Clear out old OS bits
  tempSetting |= sampleRate; //Mask in new OS bits
  IIC_Write(CTRL_REG1, tempSetting);
}

//Enables the pressure and temp measurement event flags so that we can
//test against them. This is recommended in datasheet during setup.
void Weather::enableEventFlags()
{
  IIC_Write(PT_DATA_CFG, 0x07); // Enable all three pressure and temp event flags
}

//Clears then sets the OST bit which causes the sensor to immediately take another reading
//Needed to sample faster than 1Hz
void Weather::toggleOneShot(void)
{
  byte tempSetting = IIC_Read(CTRL_REG1); //Read current settings
  tempSetting &= ~(1<<1); //Clear OST bit
  IIC_Write(CTRL_REG1, tempSetting);

  tempSetting = IIC_Read(CTRL_REG1); //Read current settings to be safe
  tempSetting |= (1<<1); //Set OST bit
  IIC_Write(CTRL_REG1, tempSetting);
}


// These are the two I2C functions in this sketch.
byte Weather::IIC_Read(byte regAddr)
{
  // This function reads one byte over IIC
  Wire.beginTransmission(MPL3115A2_ADDRESS);
  Wire.write(regAddr);  // Address of CTRL_REG1
  Wire.endTransmission(false); // Send data to I2C dev with option for a repeated start. THIS IS NECESSARY and not supported before Arduino V1.0.1!
  Wire.requestFrom(MPL3115A2_ADDRESS, 1); // Request the data...
  return Wire.read();
}

void Weather::IIC_Write(byte regAddr, byte value)
{
  // This function writes one byte over IIC
  Wire.beginTransmission(MPL3115A2_ADDRESS);
  Wire.write(regAddr);
  Wire.write(value);
  Wire.endTransmission(true);
}

SparkFun_Photon_Weather_Shield_Library.h

/*
 SparkFun Photon Weather Shield Particle Library
 Compiled and Updated for Particle By: Joel Bartlett
 SparkFun Electronics
 Date: August 05, 2015

 This library combines multiple libraries together to make development on the SparkFun
 Photon Weather Shield easier. There are two versions of the Weather Shield, one containing
 the HTU21D Temp and Humidity sensor and one containing the Si7021-A10. Shortages of the HTU21D
 IC combined with contractual obligations led to the two versions existing. Thus, to make it
 easier on you, the end user, we have written this library to automatically detect which version
 you have without the need for you to have to figure it out and pick a corresponding library.
 The MPL3115A2 library was added to avoid the need to import two separate libraries for
 the shield.

 This library is based on the following libraries:

 MPL3115A2 Barometric Pressure Sensor Library
 By: Nathan Seidle
 SparkFun Electronics
 Date: September 24th, 2013
 https://github.com/sparkfun/MPL3115A2_Breakout

 Spark Core HTU21D Temperature / Humidity Sensor Library
 By: Romain MP
 https://github.com/romainmp/HTU21D

 Arduino Si7010 relative humidity + temperature sensor
 Jakub Kaminski, 2014
 https://github.com/teoqba/Si7020

 This Library is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This Library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 For a copy of the GNU General Public License, see
 <http://www.gnu.org/licenses/>.
 */

#include "application.h"//needed for all Particle libraries

#ifndef SparkFun_Photon_Weather_Shield_Library_h
#define SparkFun_Photon_Weather_Shield_Library_h

/****************Si7021 & HTU21D Definitions***************************/

#define ADDRESS      0x40

#define TEMP_MEASURE_HOLD  0xE3
#define HUMD_MEASURE_HOLD  0xE5
#define TEMP_MEASURE_NOHOLD  0xF3
#define HUMD_MEASURE_NOHOLD  0xF5
#define TEMP_PREV   0xE0

#define WRITE_USER_REG  0xE6
#define READ_USER_REG  0xE7
#define SOFT_RESET  0xFE

#define HTRE        0x02
#define _BV(bit) (1 << (bit))

#define CRC_POLY 0x988000 // Shifted Polynomial for CRC check

// Error codes
#define I2C_TIMEOUT 	998
#define BAD_CRC		999

/****************MPL3115A2 Definitions************************************/
#define MPL3115A2_ADDRESS 0x60 // Unshifted 7-bit I2C address for sensor

#define STATUS     0x00
#define OUT_P_MSB  0x01
#define OUT_P_CSB  0x02
#define OUT_P_LSB  0x03
#define OUT_T_MSB  0x04
#define OUT_T_LSB  0x05
#define DR_STATUS  0x06
#define OUT_P_DELTA_MSB  0x07
#define OUT_P_DELTA_CSB  0x08
#define OUT_P_DELTA_LSB  0x09
#define OUT_T_DELTA_MSB  0x0A
#define OUT_T_DELTA_LSB  0x0B
#define WHO_AM_I   0x0C
#define F_STATUS   0x0D
#define F_DATA     0x0E
#define F_SETUP    0x0F
#define TIME_DLY   0x10
#define SYSMOD     0x11
#define INT_SOURCE 0x12
#define PT_DATA_CFG 0x13
#define BAR_IN_MSB 0x14
#define BAR_IN_LSB 0x15
#define P_TGT_MSB  0x16
#define P_TGT_LSB  0x17
#define T_TGT      0x18
#define P_WND_MSB  0x19
#define P_WND_LSB  0x1A
#define T_WND      0x1B
#define P_MIN_MSB  0x1C
#define P_MIN_CSB  0x1D
#define P_MIN_LSB  0x1E
#define T_MIN_MSB  0x1F
#define T_MIN_LSB  0x20
#define P_MAX_MSB  0x21
#define P_MAX_CSB  0x22
#define P_MAX_LSB  0x23
#define T_MAX_MSB  0x24
#define T_MAX_LSB  0x25
#define CTRL_REG1  0x26
#define CTRL_REG2  0x27
#define CTRL_REG3  0x28
#define CTRL_REG4  0x29
#define CTRL_REG5  0x2A
#define OFF_P      0x2B
#define OFF_T      0x2C
#define OFF_H      0x2D

/****************Si7021 & HTU21D Class**************************************/
class Weather
{
public:
	// Constructor
	Weather();

	void  begin();

	// Si7021 & HTU21D Public Functions
	float getRH();
	float readTemp();
	float getTemp();
	float readTempF();
	float getTempF();
	void  heaterOn();
	void  heaterOff();
	void  changeResolution(uint8_t i);
	void  reset();
	uint8_t  checkID();

    //MPL3115A2 Public Functions
	float readAltitude(); // Returns float with meters above sealevel. Ex: 1638.94
	float readAltitudeFt(); // Returns float with feet above sealevel. Ex: 5376.68
	float readPressure(); // Returns float with barometric pressure in Pa. Ex: 83351.25
	float readBaroTemp(); // Returns float with current temperature in Celsius. Ex: 23.37
	float readBaroTempF(); // Returns float with current temperature in Fahrenheit. Ex: 73.96
	void setModeBarometer(); // Puts the sensor into Pascal measurement mode.
	void setModeAltimeter(); // Puts the sensor into altimetery mode.
	void setModeStandby(); // Puts the sensor into Standby mode. Required when changing CTRL1 register.
	void setModeActive(); // Start taking measurements!
	void setOversampleRate(byte); // Sets the # of samples from 1 to 128. See datasheet.
	void enableEventFlags(); // Sets the fundamental event flags. Required during setup.

private:
	//Si7021 & HTU21D Private Functions
	uint16_t makeMeasurment(uint8_t command);
	void     writeReg(uint8_t value);
	uint8_t  readReg();

	//MPL3115A2 Private Functions
	void toggleOneShot();
	byte IIC_Read(byte regAddr);
	void IIC_Write(byte regAddr, byte value);
};

#endif

Weathershield.ino

/******************************************************************************
  SparkFun_Photon_Weather_Wunderground.ino
  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.

//---------------------------------------------------------------

  Weather Underground Upload sections: Dan Fein @ Weather Underground
  Weather Underground Upload Protocol:
  http://wiki.wunderground.com/index.php/PWS_-_Upload_Protocol
  Sign up at http://www.wunderground.com/personal-weather-station/signup.asp

*******************************************************************************/
#include "SparkFun_Photon_Weather_Shield_Library.h"
#include "math.h"   //For Dew Point Calculation

float humidity = 0;
float humTempF = 0;  //humidity sensor temp reading, fahrenheit
float humTempC = 0;  //humidity sensor temp reading, celsius
float baroTempF = 0; //barometer sensor temp reading, fahrenheit
float baroTempC = 0; //barometer sensor temp reading, celsius
float tempF = 0;     //Average of the sensors temperature readings, fahrenheit
float tempC = 0;     //Average of the sensors temperature readings, celsius
float dewptF = 0;
float dewptC = 0;
float pascals = 0;
float inches = 0;

//Wunderground Vars

//char SERVER[] = "rtupdate.wunderground.com";        //Rapidfire update server - for multiple sends per minute
char SERVER [] = "weatherstation.wunderground.com";   //Standard server - for sends once per minute or less
char WEBPAGE [] = "GET /weatherstation/updateweatherstation.php?";

//Station Identification
char ID [] = "KCAAUBUR39"; //Your station ID here
char PASSWORD [] = "Rv9530319"; //your Weather Underground password here

TCPClient client;

//Create Instance of HTU21D or SI7021 temp and humidity sensor and MPL3115A2 barometric sensor
Weather sensor;

//---------------------------------------------------------------
void setup()
{
    Serial.begin(9600);   // open serial over USB at 9600 baud

    //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()
{
      //Get readings from all sensors
      getWeather();

      //Print to console
      printInfo();

      //Send data to Weather Underground
      sendToWU();

      //Power down between sends to save power, measured in seconds.
      System.sleep(SLEEP_MODE_DEEP,300);  //for Particle Photon
      //Spark.sleep(SLEEP_MODE_DEEP,300);   //for Spark Core
}
//---------------------------------------------------------------
void printInfo()
{
//This function prints the weather data out to the default Serial Port

  Serial.print("Temp:");
  Serial.print(tempF);
  Serial.print("F, ");

  Serial.print("Humidity:");
  Serial.print(humidity);
  Serial.print("%, ");

  Serial.print("Baro_Temp:");
  Serial.print(baroTempF);
  Serial.print("F, ");

  Serial.print("Humid_Temp:");
  Serial.print(humTempF);
  Serial.print("F, ");

  Serial.print("Pressure:");
  Serial.print(pascals/100);
  Serial.print("hPa, ");
  Serial.print(inches);
  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

  //If in altitude mode, print with these lines
  //Serial.print("Altitude:");
  //Serial.print(altf);
  //Serial.println("ft.");

}
//---------------------------------------------------------------
void sendToWU()
{
  Serial.println("connecting...");

  if (client.connect(SERVER, 80)) {
  Serial.println("Connected");
  client.print(WEBPAGE);
  client.print("ID=");
  client.print(ID);
  client.print("&PASSWORD=");
  client.print(PASSWORD);
  client.print("&dateutc=now");      //can use 'now' instead of time if sending in real time
  client.print("&tempf=");
  client.print(tempF);
  client.print("&dewptf=");
  client.print(dewptF);
  client.print("&humidity=");
  client.print(humidity);
  client.print("&baromin=");
  client.print(inches);
  client.print("&action=updateraw");    //Standard update rate - for sending once a minute or less
  //client.print("&softwaretype=Particle-Photon&action=updateraw&realtime=1&rtfreq=30");  //Rapid Fire update rate - for sending multiple times per minute, specify frequency in seconds
  client.println();
  Serial.println("Upload complete");
  delay(300);                         //Without the delay it goes to sleep too fast and the send is unreliable
  }else{
    Serial.println(F("Connection failed"));
  return;
  }
}
//---------------------------------------------------------------
void getWeather()
{
  // Measure Relative Humidity from the HTU21D or Si7021
  humidity = sensor.getRH();

  // Measure Temperature from the HTU21D or Si7021
  humTempC = sensor.getTemp();
  humTempF = (humTempC * 9)/5 + 32;
  // 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
  baroTempC = sensor.readBaroTemp();
  baroTempF = (baroTempC * 9)/5 + 32; //convert the temperature to F

  //Measure Pressure from the MPL3115A2
  pascals = sensor.readPressure();
  inches = pascals * 0.0002953; // Calc for converting Pa to inHg (Wunderground expects inHg)

  //If in altitude mode, you can get a reading in feet with this line:
  //float altf = sensor.readAltitudeFt();

  //Average the temperature reading from both sensors
  tempC=((humTempC+baroTempC)/2);
  tempF=((humTempF+baroTempF)/2);

  //Calculate Dew Point
  dewptC = dewPoint(tempC, humidity);
  dewptF = (dewptC * 9.0)/ 5.0 + 32.0;
}
//---------------------------------------------------------------
// dewPoint function from NOAA
// reference (1) : http://wahiduddin.net/calc/density_algorithms.htm
// reference (2) : http://www.colorado.edu/geography/weather_station/Geog_site/about.htm
//---------------------------------------------------------------
double dewPoint(double celsius, double humidity)
{
	// (1) Saturation Vapor Pressure = ESGG(T)
	double RATIO = 373.15 / (273.15 + celsius);
	double RHS = -7.90298 * (RATIO - 1);
	RHS += 5.02808 * log10(RATIO);
	RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1/RATIO ))) - 1) ;
	RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1) ;
	RHS += log10(1013.246);

  // factor -3 is to adjust units - Vapor Pressure SVP * humidity
	double VP = pow(10, RHS - 3) * humidity;

  // (2) DEWPOINT = F(Vapor Pressure)
	double T = log(VP/0.61078);   // temp var
	return (241.88 * T) / (17.558 - T);
}
//---------------------------------------------------------------

Sometimes it takes a while to figure out the problem. It is called persistence.

Those are the kinds of things you want to mention in advance.

Being a bit curious I flashed it to a photon of mine using the 0.5.2 firmware.
I see the same thing: both LEDs are off, and can't get it into listening mode using the buttons. Then again, it's hardly surprising considering it's the expected behavior for that firmware.

void loop()
{
      //Get readings from all sensors
      getWeather();

      //Print to console
      printInfo();

      //Send data to Weather Underground
      sendToWU();

      //Power down between sends to save power, measured in seconds.
      System.sleep(SLEEP_MODE_DEEP,300);  //for Particle Photon
      //Spark.sleep(SLEEP_MODE_DEEP,300);   //for Spark Core
}

The last part will put the device to sleep for 5 minutes, disabling the LEDs, and making it (apparently) unresponsive to the MODE button. It's sleepy, but most definitely not dead. If you leave it connected for ~5 minutes, it should turn back on, connect to the cloud, try to do some measurements, and go back to sleep again. All perfectly fine.

Did you try Safe mode yet?

Fair enough. What did you do differently, and what have you learned during the course of seven 'dead' Photons?

2 Likes

Can’t seem to make it work in safe mode. Now that I see the sleep issue and am able to change the code, I bought two more that will be delivered next week.

Bob Vaughan

It won't do anything in safe mode, but it'll allow you to flash new firmware OTA. If that doesn't work, you can still flash it in DFU mode over USB.

That seems to be very much a similar case as this one

I do like the reaction of the OP there :+1:

2 Likes

I had this same issue, with the stupid sleep mode. Trying to flash did not work because it would goto sleep too fast.Trying to flash in DFU would not work. said it could not find a photon in DFU mode even though it was showing in device manager. After and hour I plugged it into a USB2.0, tried the "photon flash --usb tinker and it worked. Then I got rid of the crazy sleep mode in the code. The code I am using is still not working, but at least I can flash it normally.
Problem : my USB3.0