WeatherShield giving wrong values [solved - wrong sketch]

Started by gert, May 24, 2017, 12:23:34 AM

gert

Hi All,

Bringing up a moteino with weathershield.

Plugged together moteino, weathershield and FTDI USB adapter (all standard issue) and uploaded the 'WeatherNode' code. Had to install 'SparkFunBME280' and 'LowPower' libs. Compiling and upload are OK but the serial dump shows totally bogus values. (I converted the printout to 'C' and 'hPa' for international units). I get the below output.

WeatherMote - transmitting at: 868 Mhz...
BAT=4.86V T=103.21C H=0.00% P=-1020.11hPa (packet length:41)
WAKEUP
WAKEUP
WAKEUP
BAT=4.86V T=103.21C H=0.00% P=2302.73hPa (packet length:40)
WAKEUP
WAKEUP
WAKEUP
BAT=4.86V T=103.21C H=0.00% P=2292.20hPa (packet length:40)
WAKEUP
WAKEUP
WAKEUP
BAT=4.86V T=103.21C H=0.00% P=2281.67hPa (packet length:40)
WAKEUP
WAKEUP
WAKEUP
BAT=4.86V T=103.21C H=0.00% P=2302.73hPa (packet length:40)
WAKEUP
WAKEUP
WAKEUP
BAT=4.86V T=103.21C H=0.00% P=2323.75hPa (packet length:40)
WAKEUP


Obviously the numbers are wrong. I tried touching the sensor with my finger to warm it a bit (which on other temp sensors that I've used always showed a slight numeric change) but here numbers are stuck. Also breathing on the sensor gave no change in humidity.

Debug help is much appreciated.

Thanks,
Gert

Felix

I want to mention as usual that the boards are tested for proper readings before they ship.
Can we see how it's wired/soldered just for the record?
Can we also see your full sketch?

Also to consider common problems in such cases are:

- a weak solder joint
- user "assumptions"
- code

gert

@Felix & All,

Thanks for your feedback.

A visual inspection shows nothing broken.

The parts:





And assembled:




Code with my mods for metric printout.
// **********************************************************************************************************
// WeatherShield R2 (BME280 sensor) sameple sketch that works with Moteinos equipped with RFM69W/RFM69HW
// It sends periodic weather readings (temp, hum, atm pressure) from WeatherShield to the base node Moteino
// For use with MoteinoMEGA you will have to revisit the pin definitions defined below
// http://www.LowPowerLab.com/WeatherShield
// Example setup (with R1): http://lowpowerlab.com/blog/2015/07/24/attic-fan-cooling-tests/
// **********************************************************************************
// Copyright Felix Rusu 2016, http://www.LowPowerLab.com/contact
// **********************************************************************************
// License
// **********************************************************************************
// This program 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 program 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.                              
//                                                        
// Licence can be viewed at                               
// http://www.gnu.org/licenses/gpl-3.0.txt
//
// Please maintain this license information along with authorship
// and copyright notices in any redistribution of this code
// **********************************************************************************
#include <RFM69.h>         //get it here: https://github.com/lowpowerlab/rfm69
#include <RFM69_ATC.h>     //get it here: https://github.com/lowpowerlab/rfm69
#include <RFM69_OTA.h>     //get it here: https://github.com/lowpowerlab/rfm69
#include <SPIFlash.h>      //get it here: https://github.com/lowpowerlab/spiflash
#include <SPI.h>           //included in Arduino IDE (www.arduino.cc)
#include <Wire.h>          //included in Arduino IDE (www.arduino.cc)
#include <SparkFunBME280.h>//get it here: https://github.com/sparkfun/SparkFun_BME280_Breakout_Board/tree/master/Libraries/Arduino/src
#include <LowPower.h>      //get it here: https://github.com/lowpowerlab/lowpower
                           //writeup here: http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/

//*********************************************************************************************
//************ IMPORTANT SETTINGS - YOU MUST CHANGE/CONFIGURE TO FIT YOUR HARDWARE ************
//*********************************************************************************************
#define GATEWAYID   1
#define NODEID      40
#define NETWORKID   42
//#define FREQUENCY     RF69_433MHZ
#define FREQUENCY     RF69_868MHZ
//#define FREQUENCY       RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ)
#define ENCRYPTKEY      "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less!
//#define IS_RFM69HW_HCW  //uncomment only for RFM69HW/HCW! Leave out if you have RFM69W/CW!
//*********************************************************************************************
#define ENABLE_ATC    //comment out this line to disable AUTO TRANSMISSION CONTROL
#define ATC_RSSI      -75
//*********************************************************************************************
#define SEND_LOOPS   3 //send data this many sleep loops (15 loops of 8sec cycles = 120sec ~ 2 minutes)
#define SLEEP_FASTEST SLEEP_15MS
#define SLEEP_FAST SLEEP_250MS
#define SLEEP_SEC SLEEP_1S
#define SLEEP_LONG SLEEP_2S
#define SLEEP_LONGER SLEEP_4S
#define SLEEP_LONGEST SLEEP_8S
period_t sleepTime = SLEEP_1S; //period_t is an enum type defined in the LowPower library (LowPower.h)
//*********************************************************************************************
#define BATT_MONITOR_EN A3 //enables battery voltage divider to get a reading from a battery, disable it to save power
#define BATT_MONITOR  A7   //through 1Meg+470Kohm and 0.1uF cap from battery VCC - this ratio divides the voltage to bring it below 3.3V where it is scaled to a readable range
#define BATT_CYCLES   2    //read and report battery voltage every this many sleep cycles (ex 30cycles * 8sec sleep = 240sec/4min). For 450 cyclesyou would get ~1 hour intervals
#define BATT_FORMULA(reading) reading * 0.00322 * 1.475  // >>> fine tune this parameter to match your voltage when fully charged
#define BATT_LOW      3.6  //(volts)
#define BATT_READ_LOOPS  SEND_LOOPS*10  // read and report battery voltage every this many sleep cycles (ex 30cycles * 8sec sleep = 240sec/4min). For 450 cycles you would get ~1 hour intervals between readings
//*****************************************************************************************************************************

#ifdef __AVR_ATmega1284P__
  #define LED           15 // Moteino MEGAs have LEDs on D15
  #define FLASH_SS      23 // and FLASH SS on D23
#else
  #define LED           9 // Moteinos have LEDs on D9
  #define FLASH_SS      8 // and FLASH SS on D8
#endif

#define BLINK_EN                 //uncomment to blink LED on every send
#define SERIAL_EN                //comment out if you don't want any serial output

#ifdef SERIAL_EN
  #define SERIAL_BAUD   115200
  #define DEBUG(input)   {Serial.print(input);}
  #define DEBUGln(input) {Serial.println(input);}
  #define SERIALFLUSH() {Serial.flush();}
#else
  #define DEBUG(input);
  #define DEBUGln(input);
  #define SERIALFLUSH();
#endif
//*****************************************************************************************************************************

#ifdef ENABLE_ATC
  RFM69_ATC radio;
#else
  RFM69 radio;
#endif

SPIFlash flash(FLASH_SS, 0xEF30); //WINDBOND 4MBIT flash chip on CS pin D8 (default for Moteino)

BME280 bme280;
char Pstr[10];
char Tstr[10];
char Hstr[10];
char buffer[50];

void setup(void)
{
#ifdef SERIAL_EN
  Serial.begin(SERIAL_BAUD);
#endif
  pinMode(LED, OUTPUT);
  
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW_HCW
  radio.setHighPower(); //must include this only for RFM69HW/HCW!
#endif
  radio.encrypt(ENCRYPTKEY);

//Auto Transmission Control - dials down transmit power to save battery (-100 is the noise floor, -90 is still pretty good)
//For indoor nodes that are pretty static and at pretty stable temperatures (like a MotionMote) -90dBm is quite safe
//For more variable nodes that can expect to move or experience larger temp drifts a lower margin like -70 to -80 would probably be better
//Always test your ATC mote in the edge cases in your own environment to ensure ATC will perform as you expect
#ifdef ENABLE_ATC
  radio.enableAutoPower(ATC_RSSI);
#endif

  sprintf(buffer, "WeatherMote - transmitting at: %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  DEBUGln(buffer);

  //initialize weather shield BME280 sensor
  bme280.settings.commInterface = I2C_MODE;
  bme280.settings.I2CAddress = 0x77;
  bme280.settings.runMode = 3; //Normal mode
  bme280.settings.tStandby = 0;
  bme280.settings.filter = 0;
  bme280.settings.tempOverSample = 1;
  bme280.settings.pressOverSample = 1;
  bme280.settings.humidOverSample = 1;

  radio.sendWithRetry(GATEWAYID, "START", 6);
  Blink(LED, 100);Blink(LED, 100);Blink(LED, 100);

  if (flash.initialize()) flash.sleep();

  for (uint8_t i=0; i<=A5; i++)
  {
    if (i == RF69_SPI_CS) continue;
    if (i == FLASH_SS) continue;
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);
  }
  
  SERIALFLUSH();
  readBattery();
}

unsigned long doorPulseCount = 0;
char input=0;
double T,P,H;
byte sendLoops=0;
byte battReadLoops=0;
float batteryVolts = 5;
char* BATstr="BAT:5.00v"; //longest battery voltage reading message = 9chars
byte sendLen;

void loop()
{
  if (battReadLoops--<=0) //only read battery every BATT_READ_LOOPS cycles
  {
    readBattery();
    battReadLoops = BATT_READ_LOOPS-1;
  }
  
  if (sendLoops--<=0)   //send readings every SEND_LOOPS
  {
    sendLoops = SEND_LOOPS-1;
    
    //read BME sensor
    bme280.begin();
    //P = bme280.readFloatPressure() * 0.0002953; //read Pa and convert to inHg
    P = bme280.readFloatPressure() * 0.01; //read Pa and convert to hPa
    T = bme280.readTempC();
    H = bme280.readFloatHumidity();
    bme280.writeRegister(BME280_CTRL_MEAS_REG, 0x00); //sleep the BME280

    dtostrf(T, 3,2, Tstr);
    dtostrf(H, 3,2, Hstr);
    dtostrf(P, 3,2, Pstr);

    sprintf(buffer, "BAT=%sV T=%sC H=%s%% P=%shPa", BATstr, Tstr, Hstr, Pstr);

    sendLen = strlen(buffer);
    radio.sendWithRetry(GATEWAYID, buffer, sendLen, 1); //retry one time
    DEBUG(buffer); DEBUG(" (packet length:"); DEBUG(sendLen); DEBUGln(")");

    #ifdef BLINK_EN
      Blink(LED, 5);
    #endif
  }
  
  //When this sketch is on a node where you can afford the power to keep the radio awake all the time
  //   you can make it receive messages and also make it wirelessly programmable
  //   otherwise this section can be removed
  if (radio.receiveDone())
  {
    boolean reportStatusRequest=false;
    DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] ");
    for (byte i = 0; i < radio.DATALEN; i++)
      DEBUG((char)radio.DATA[i]);

    flash.wakeup();
    // wireless programming token check - this only works when radio is kept awake to listen for WP tokens
    CheckForWirelessHEX(radio, flash, true);

    //first send any ACK to request
    DEBUG("   [RX_RSSI:");DEBUG(radio.RSSI);DEBUG("]");
    if (radio.ACKRequested())
    {
      radio.sendACK();
      DEBUG(" - ACK sent.");
    }
    DEBUGln();
  }
  
  SERIALFLUSH();
  flash.sleep();
  radio.sleep(); //you can comment out this line if you want this node to listen for wireless programming requests
  LowPower.powerDown(sleepTime, ADC_OFF, BOD_OFF);
  DEBUGln("WAKEUP");
}

void readBattery()
{
  unsigned int readings=0;
  
  //enable battery monitor on WeatherShield (via mosfet controlled by A3)
  pinMode(BATT_MONITOR_EN, OUTPUT);
  digitalWrite(BATT_MONITOR_EN, LOW);

  for (byte i=0; i<5; i++) //take several samples, and average
    readings+=analogRead(BATT_MONITOR);
  
  //disable battery monitor
  pinMode(BATT_MONITOR_EN, INPUT); //highZ mode will allow p-mosfet to be pulled high and disconnect the voltage divider on the weather shield
    
  batteryVolts = BATT_FORMULA(readings / 5.0);
  dtostrf(batteryVolts,3,2, BATstr); //update the BATStr which gets sent every BATT_CYCLES or along with the MOTION message
  if (batteryVolts <= BATT_LOW) BATstr = "LOW";
}

void Blink(byte PIN, byte DELAY_MS)
{
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS/2);
  digitalWrite(PIN,LOW);
  delay(DELAY_MS/2);  
}


To note, I've also tried the sample code (unaltered) from the BME280 examples library with same failing results.
File -> Examples -> SparkFun BME280 -> I2C_ReadAlLData

Program Started
Starting BME280... result of .begin(): 0x55
Displaying ID, reset and ctrl regs
ID(0xD0): 0x55
Reset register(0xE0): 0x0
ctrl_meas(0xF4): 0x3
ctrl_hum(0xF2): 0x0


Displaying all regs
0x80:A5 94 36 38 FF 27 8E 68 75 53 1C 8C FB CB C7 4B 
0x90:82 2F 61 E1 44 7A 19 73 00 26 80 00 D1 F6 0A E1 
0xA0:A5 94 36 38 FF 27 8E 68 75 53 1C 8C FB CB C7 4B 
0xB0:82 2F 61 E1 44 7A 19 73 00 26 80 00 D1 F6 0A E1 
0xC0:00 00 BC 33 00 00 00 00 00 00 00 10 00 00 00 03 
0xD0:55 02 06 00 00 00 00 00 00 00 00 00 00 00 00 00 
0xE0:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0xF0:00 00 00 04 03 00 7D F8 00 00 00 00 00 00 00 00 


Displaying concatenated calibration words
dig_T1, uint16: 21365
dig_T2, int16: -29668
dig_T3, int16: -13317
dig_P1, uint16: 19399
dig_P2, int16: 12162
dig_P3, int16: -7839
dig_P4, int16: 31300
dig_P5, int16: 29465
dig_P6, int16: 9728
dig_P7, int16: 128
dig_P8, int16: -2351
dig_P9, int16: -7926
dig_H1, uint8: 148
dig_H2, int16: 0
dig_H3, uint8: 0
dig_H4, int16: 0
dig_H5, int16: 0
dig_H6, uint8: 0

Temperature: 103.21 degrees C
Temperature: 217.78 degrees F
Pressure: 228167.21 Pa
Altitude: -7656.79m
Altitude: -25120.70ft
%RH: 0.00 %


I'm sure there's just a wrong bit somewhere that needs fixing.

Thanks,
Gert

Felix

Dear Gert,
This is the old WeatherShield, using separate Si7021 (temp, hum) and BME180 (pressure) not BME280 (temp, hum, pressure).
That is the problem.
Please use this older sketch for that purpose.

gert

@Felix,

Thanks! The 'old' code required additional libraries to install, but that worked fine. The code now produces more interesting results. The temperature seems to be an encoded fix point format?

Example : 7379 means 73.79F

eatherMote - transmitting at: 915 Mhz...
BMP180 init success
BAT:4.86v F:7379 H:52 P:29.84 (packet length:29)
WAKEUP
WAKEUP
WAKEUP
BAT:4.86v F:7377 H:52 P:29.84 (packet length:29)
WAKEUP
WAKEUP
WAKEUP
BAT:4.86v F:7376 H:52 P:29.84 (packet length:29)
WAKEUP
WAKEUP
WAKEUP
BAT:4.86v F:7379 H:52 P:29.84 (packet length:29)
WAKEUP
WAKEUP
WAKEUP
BAT:4.86v F:7381 H:52 P:29.84 (packet length:29)


If I may suggest to put a notice into the WeatherNode code header to remind folks of the different versions of the shield and the code?

Just one more question. Both the Si7021 and the BME180 can provide a temperature measurement. Why is the code not reporting both? (would be helpful as consistency check)

Cheers,
Gert

Felix

The R1 with Si7021 has been long discontinued and support has stopped for the code at that point.
The sketches are still available and the hundreds value is given by the sparkfun library not by the sketch, but you can divide by 100 if you would like the decimal value.