GarageMote with Weathershield [solved]

Started by sparky, April 27, 2018, 08:56:00 AM

sparky

Ok, so after days of pulling my hair out I'm asking for help to figure out what I'm doing wrong with regards to adding a WeatherShield to my GarageMote.

if I separate the WeatherShielld code from the GarageMote sketch the temperature, humidity, and pressure values show up in the UI fine.  See WeatherShield photo attached.

When I add the WeatherShield code to my GarageMote sketch the temperature, humidity, and pressure doesn't show.  Although when opening terminal from the UI I see the GarageMote information being polled, the WeatherShield information isn't.

From terminal in UI;
8:31:28 AM : {"_id":3,"updated":1524832119993,"type":"GarageMote","label":"Garage Opener","descr":"[3]","metrics":{"Status":{"label":"Status","value":"UNKNOWN!","updated":1524829419021,"pin":1,"graph":1},"RSSI":{"label":"RSSI","value":-50,"unit":"db","updated":1524829419021,"graph":1}},"events":{"garagePoll":{"enabled":1,"executeDateTime":"2018-04-27T12:31:56.939Z"}}}
8:31:28 AM : GARAGE POLL STATUS: UNKNOWN!


Here is my sketch;
//#define WEATHERSHIELD_R1         //uncomment if WeatherShield_R1 (Si7021+BMP180 sensors) is present to report temp/humidity/pressure periodically
#define WEATHERSHIELD_R2         //uncomment if WeatherShield_R2 (BME280 sensor) is present to report temp/humidity/pressure periodically
#define WEATHERSENDDELAY  300000 // send WeatherShield data every so often (ms)
// ***************************************************************************************************************************
#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 with Arduino IDE (www.arduino.cc)

#ifdef WEATHERSHIELD_R1
  #include <SFE_BMP180.h>    //get it here: https://github.com/LowPowerLab/SFE_BMP180
  #include <SI7021.h>        //get it here: https://github.com/LowPowerLab/SI7021
  #include <Wire.h>
#endif

#ifdef WEATHERSHIELD_R2
  #include <SparkFunBME280.h> //get it here: https://github.com/sparkfun/SparkFun_BME280_Breakout_Board/tree/master/Libraries/Arduino/src
  #include <Wire.h>
#endif

//****************************************************************************************************************
//**** IMPORTANT RADIO SETTINGS - YOU MUST CHANGE/CONFIGURE TO MATCH YOUR HARDWARE TRANSCEIVER CONFIGURATION! ****
//****************************************************************************************************************
#define GATEWAYID   1
#define NODEID      3
#define NETWORKID   100
//#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 HALLSENSOR1          A0
#define HALLSENSOR1_EN        4
#define HALLSENSOR2          A1
#define HALLSENSOR2_EN        5

#define RELAYPIN1             6
#define RELAYPIN2             7
#define RELAY_PULSE_MS      250  //just enough that the opener will pick it up

#define DOOR_MOVEMENT_TIME 14000 // this has to be at least as long as the max between [door opening time, door closing time]
                                 // my door opens and closes in about 12s
#define STATUS_CHANGE_MIN  1500  // this has to be at least as long as the delay 
                                 // between a opener button press and door movement start
                                 // most garage doors will start moving immediately (within half a second)
//*****************************************************************************************************************************
#define HALLSENSOR_OPENSIDE   0
#define HALLSENSOR_CLOSEDSIDE 1

#define STATUS_CLOSED        0
#define STATUS_CLOSING       1
#define STATUS_OPENING       2
#define STATUS_OPEN          3
#define STATUS_UNKNOWN       4

#define LED                  9   //pin connected to onboard LED
#define LED_PULSE_PERIOD  5000   //5s seems good value for pulsing/blinking (not too fast/slow)
#define SERIAL_BAUD     115200
#define SERIAL_EN                //comment out if you don't want any serial output

#ifdef SERIAL_EN
  #define DEBUG(input)   {Serial.print(input); delay(1);}
  #define DEBUGln(input) {Serial.println(input); delay(1);}
#else
  #define DEBUG(input);
  #define DEBUGln(input);
#endif

#ifdef WEATHERSHIELD_R1
  SI7021 weatherShield_SI7021;
  SFE_BMP180 weatherShield_BMP180;
#endif

#ifdef WEATHERSHIELD_R2
  BME280 bme280;
#endif

//function prototypes
void setStatus(byte newSTATUS, boolean reportStatus=true);
void reportStatus();
boolean hallSensorRead(byte which);
void pulseRelay();

//global program variables
byte STATUS;
unsigned long lastStatusTimestamp=0;
unsigned long ledPulseTimestamp=0;
unsigned long lastWeatherSent=0;
int ledPulseValue=0;
boolean ledPulseDirection=false; //false=down, true=up
float temperature=0;
char Fstr[10];
float humidity=0;
char Hstr[10];
float pressure=0;
char sendBuf[32];
byte sendLen;

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

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

void setup(void)
{
#ifdef SERIAL_EN
  Serial.begin(SERIAL_BAUD);
#endif
  pinMode(HALLSENSOR1, INPUT);
  pinMode(HALLSENSOR2, INPUT);
  pinMode(HALLSENSOR1_EN, OUTPUT);
  pinMode(HALLSENSOR2_EN, OUTPUT);
  pinMode(RELAYPIN1, OUTPUT);
  pinMode(RELAYPIN2, OUTPUT);
  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);

#ifdef ENABLE_ATC
  radio.enableAutoPower(ATC_RSSI);
#endif

  char buff[50];
  sprintf(buff, "GarageMote : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  DEBUGln(buff);
  radio.sendWithRetry(GATEWAYID, "START", 5);
  
  #ifdef ENABLE_ATC
    DEBUGln("RFM69_ATC Enabled (Auto Transmission Control)\n");
  #endif
  
  if (flash.initialize()) flash.sleep(); //if Moteino has FLASH-MEM, make sure it sleeps

  if (hallSensorRead(HALLSENSOR_OPENSIDE)==true)
    setStatus(STATUS_OPEN);
  if (hallSensorRead(HALLSENSOR_CLOSEDSIDE)==true)
    setStatus(STATUS_CLOSED);
  else setStatus(STATUS_UNKNOWN);

char Pstr[10];
char Fstr[10];
char Hstr[10];

#ifdef WEATHERSHIELD_R1
  //initialize weather shield sensors  
  weatherShield_SI7021.begin();
  if (weatherShield_BMP180.begin())
  { DEBUGln("BMP180 init success"); }
  else { DEBUGln("BMP180 init fail\n"); }
#endif

#ifdef WEATHERSHIELD_R2
  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;
#endif
}

unsigned long doorPulseCount = 0;
char input=0;
double P;

void loop()
{
#ifdef SERIAL_EN
  if (Serial.available())
    input = Serial.read();
#endif

  if (input=='r')
  {
    DEBUGln("Relay test...");
    pulseRelay();
    input = 0;
  }
    
  // UNKNOWN => OPEN/CLOSED
  if (STATUS == STATUS_UNKNOWN && millis()-(lastStatusTimestamp)>STATUS_CHANGE_MIN)
  {
    if (hallSensorRead(HALLSENSOR_OPENSIDE)==true)
      setStatus(STATUS_OPEN);
    if (hallSensorRead(HALLSENSOR_CLOSEDSIDE)==true)
      setStatus(STATUS_CLOSED);
  }

  // OPEN => CLOSING
  if (STATUS == STATUS_OPEN && millis()-(lastStatusTimestamp)>STATUS_CHANGE_MIN)
  {
    if (hallSensorRead(HALLSENSOR_OPENSIDE)==false)
      setStatus(STATUS_CLOSING);
  }

  // CLOSED => OPENING  
  if (STATUS == STATUS_CLOSED && millis()-(lastStatusTimestamp)>STATUS_CHANGE_MIN)
  {
    if (hallSensorRead(HALLSENSOR_CLOSEDSIDE)==false)
      setStatus(STATUS_OPENING);
  }

  // OPENING/CLOSING => OPEN (when door returns to open due to obstacle or toggle action)
  //                 => CLOSED (when door closes normally from OPEN)
  //                 => UNKNOWN (when more time passes than normally would for a door up/down movement)
  if ((STATUS == STATUS_OPENING || STATUS == STATUS_CLOSING) && millis()-(lastStatusTimestamp)>STATUS_CHANGE_MIN)
  {
    if (hallSensorRead(HALLSENSOR_OPENSIDE)==true)
      setStatus(STATUS_OPEN);
    else if (hallSensorRead(HALLSENSOR_CLOSEDSIDE)==true)
      setStatus(STATUS_CLOSED);
    else if (millis()-(lastStatusTimestamp)>DOOR_MOVEMENT_TIME)
      setStatus(STATUS_UNKNOWN);
  }
  
  if (radio.receiveDone())
  {
    byte newStatus=STATUS;
    boolean reportStatusRequest=false;
    DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] ");
    for (byte i = 0; i < radio.DATALEN; i++)
      DEBUG((char)radio.DATA[i]);

    if (radio.DATALEN==3)
    {
      //check for an OPEN/CLOSE/STATUS request
      if (radio.DATA[0]=='O' && radio.DATA[1]=='P' && radio.DATA[2]=='N')
      {
        if (millis()-(lastStatusTimestamp) > STATUS_CHANGE_MIN && (STATUS == STATUS_CLOSED || STATUS == STATUS_CLOSING || STATUS == STATUS_UNKNOWN))
          newStatus = STATUS_OPENING;
        //else radio.Send(requester, "INVALID", 7);
      }
      if (radio.DATA[0]=='C' && radio.DATA[1]=='L' && radio.DATA[2]=='S')
      {
        if (millis()-(lastStatusTimestamp) > STATUS_CHANGE_MIN && (STATUS == STATUS_OPEN || STATUS == STATUS_OPENING || STATUS == STATUS_UNKNOWN))
          newStatus = STATUS_CLOSING;
        //else radio.Send(requester, "INVALID", 7);
      }
      if (radio.DATA[0]=='S' && radio.DATA[1]=='T' && radio.DATA[2]=='S')
      {
        reportStatusRequest = true;
      }
    }
    
    // wireless programming token check
    // DO NOT REMOVE, or GarageMote will not be wirelessly programmable any more!
    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.");
    }
    
    //now take care of the request, if not invalid
    if (STATUS != newStatus)
    {
      pulseRelay();
      setStatus(newStatus);
    }
    if (reportStatusRequest)
    {
      reportStatus();
    }
      
    DEBUGln();
  }
  
  //use LED to visually indicate STATUS
  if (STATUS == STATUS_OPEN || STATUS == STATUS_CLOSED) //solid ON/OFF
  {
    digitalWrite(LED, STATUS == STATUS_OPEN ? LOW : HIGH);
  }
  if (STATUS == STATUS_OPENING || STATUS == STATUS_CLOSING) //pulse
  {
    if (millis()-(ledPulseTimestamp) > LED_PULSE_PERIOD/256)
    {
      ledPulseValue = ledPulseDirection ? ledPulseValue + LED_PULSE_PERIOD/256 : ledPulseValue - LED_PULSE_PERIOD/256;

      if (ledPulseDirection && ledPulseValue > 255)
      {
        ledPulseDirection=false;
        ledPulseValue = 255;
      }
      else if (!ledPulseDirection && ledPulseValue < 0)
      {
        ledPulseDirection=true;
        ledPulseValue = 0;
      }
      
      analogWrite(LED, ledPulseValue);
      ledPulseTimestamp = millis();
    }
  }
  if (STATUS == STATUS_UNKNOWN) //blink
  {
    if (millis()-(ledPulseTimestamp) > LED_PULSE_PERIOD/20)
    {
      ledPulseDirection = !ledPulseDirection;
      digitalWrite(LED, ledPulseDirection ? HIGH : LOW);
      ledPulseTimestamp = millis();
    }
  }
  
#if defined(WEATHERSHIELD_R1) || defined(WEATHERSHIELD_R2)
  if (millis()-lastWeatherSent > WEATHERSENDDELAY)
  {
    lastWeatherSent = millis();
    int fahrenheitHundreds=0;
    int humidityPercent=0;

  #ifdef WEATHERSHIELD_R1
    //read Si7021 and BMP180 sensors
    fahrenheitHundreds = weatherShield_SI7021.getFahrenheitHundredths();
    humidityPercent = weatherShield_SI7021.getHumidityPercent();
    P = getPressure();
    P*=0.0295333727; //transform to inHg
    dtostrf(P, 3,2, Pstr);
    sprintf(sendBuf, "F:%d H:%d P:%s", fahrenheitHundreds, humidityPercent, Pstr);    

  #elsif defined(WEATHERSHIELD_R2)
    //read BME280 sensor
    bme280.begin();
    dtostrf(bme280.readTempF(), 3,1, Fstr);
    dtostrf(bme280.readFloatHumidity(), 2,0, Hstr);
    float p = bme280.readFloatPressure();
    p = p / 3311.8352;  // this is conversion from Pascals to inches of mercury, adjusted for my location above sea level 
    dtostrf(p, 2,2, Pstr);    
    bme280.writeRegister(BME280_CTRL_MEAS_REG, 0x00); //sleep the BME280
    sprintf(sendBuf, "F:%s H:%s P:%s", Fstr, Hstr, Pstr);  // we skip transmitting battery voltage to save battery life 
  #endif
  
    byte sendLen = strlen(sendBuf);
    radio.send(GATEWAYID, sendBuf, sendLen);
  }
#endif
}

//returns TRUE if magnet is next to sensor, FALSE if magnet is away
boolean hallSensorRead(byte which)
{
  //while(millis()-lastStatusTimestamp<STATUS_CHANGE_MIN);
  digitalWrite(which ? HALLSENSOR2_EN : HALLSENSOR1_EN, HIGH); //turn sensor ON
  delay(1); //wait a little
  byte reading = digitalRead(which ? HALLSENSOR2 : HALLSENSOR1);
  digitalWrite(which ? HALLSENSOR2_EN : HALLSENSOR1_EN, LOW); //turn sensor OFF
  return reading==0;
}

void setStatus(byte newSTATUS, boolean reportIt)
{
  if (STATUS != newSTATUS) lastStatusTimestamp = millis();
  STATUS = newSTATUS;
  DEBUGln(STATUS==STATUS_CLOSED ? "CLOSED" : STATUS==STATUS_CLOSING ? "CLOSING" : STATUS==STATUS_OPENING ? "OPENING" : STATUS==STATUS_OPEN ? "OPEN" : "UNKNOWN");
  if (reportIt)
    reportStatus();
}

void reportStatus(void)
{
  char buff[10];
  sprintf(buff, STATUS==STATUS_CLOSED ? "CLOSED" : STATUS==STATUS_CLOSING ? "CLOSING" : STATUS==STATUS_OPENING ? "OPENING" : STATUS==STATUS_OPEN ? "OPEN" : "UNKNOWN");
  byte len = strlen(buff);
  radio.sendWithRetry(GATEWAYID, buff, len);
}

void pulseRelay()
{
  digitalWrite(RELAYPIN1, HIGH);
  digitalWrite(RELAYPIN2, HIGH);
  delay(RELAY_PULSE_MS);
  digitalWrite(RELAYPIN1, LOW);
  digitalWrite(RELAYPIN2, LOW);
}

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

#ifdef WEATHERSHIELD_R1
double getPressure()
{
  char status;
  double T,P,p0,a;
  // If you want sea-level-compensated pressure, as used in weather reports,
  // you will need to know the altitude at which your measurements are taken.
  // We're using a constant called ALTITUDE in this sketch:
  
  // If you want to measure altitude, and not pressure, you will instead need
  // to provide a known baseline pressure. This is shown at the end of the sketch.
  // You must first get a temperature measurement to perform a pressure reading.
  // Start a temperature measurement:
  // If request is successful, the number of ms to wait is returned.
  // If request is unsuccessful, 0 is returned.
  status = weatherShield_BMP180.startTemperature();
  if (status != 0)
  {
    // Wait for the measurement to complete:
    delay(status);

    // Retrieve the completed temperature measurement:
    // Note that the measurement is stored in the variable T.
    // Function returns 1 if successful, 0 if failure.
    status = weatherShield_BMP180.getTemperature(T);
    if (status != 0)
    {
      // Start a pressure measurement:
      // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait).
      // If request is successful, the number of ms to wait is returned.
      // If request is unsuccessful, 0 is returned.
      status = weatherShield_BMP180.startPressure(3);
      if (status != 0)
      {
        // Wait for the measurement to complete:
        delay(status);

        // Retrieve the completed pressure measurement:
        // Note that the measurement is stored in the variable P.
        // Note also that the function requires the previous temperature measurement (T).
        // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
        // Function returns 1 if successful, 0 if failure.
        status = weatherShield_BMP180.getPressure(P,T);
        if (status != 0)
        {
          return P;
        }
      }
    }        
  }
  return 0;
}
#endif


Here is my GarageMote / WeatherShield metrics;
exports.metrics = {
  //GarageMote
  //NOTE the \b word boundary is used to avoid matching "OPENING" (ie OPEN must be followed by word boundary/end of word)
  open : { name:'Status', regexp:/(?:STS\:)?(OPN|OPEN)\b/i, value:'OPEN', pin:1, graph:1, logValue:2, graphOptions:{ legendLbl:'Garage door events', yaxis: {ticks:0}, colors:['#4a0'], /*lines: { lineWidth:1 }*/}},
  opening : { name:'Status', regexp:/(?:STS\:)?(OPNING|OPENING)/i, value:'OPENING..', pin:1, graph:1, logValue:1 },
  closed : { name:'Status', regexp:/(?:STS\:)?(CLS|CLOSED)/i, value:'CLOSED', pin:1, graphValPrefix:' Door: ', graph:1, logValue:0 },
  closing : { name:'Status', regexp:/(?:STS\:)?(CLSING|CLOSING)/i, value:'CLOSING..', pin:1, graph:1, logValue:1.1 }, //1.1 to avoid a match with "OPENING"
  unknown : { name:'Status', regexp:/(?:STS\:)?(UNK|UNKNOWN)/i, value:'UNKNOWN!', pin:1, graph:1, logValue:0.5 },
  
  //WeatherShield metrics
  //uncomment FtoC if you want a F:1234 to be valuated as a Centigrade isntead of F (the first match is picked up and will evaluate, any following defs are ignored)
  //FtoC : { name:'C', regexp:/F\:(-?\d+\.\d+)/i, value:'', duplicateInterval:3600, valuation:function(value) {return (value - 32) * 5/9;}, unit:'°', pin:1, graph:1, graphValSuffix:'C', graphOptions:{ legendLbl:'Temperature', lines: { lineWidth:1 }}}
  F : { name:'F', regexp:/\bF\:(-?\d+\.\d+)\b/i, value:'', duplicateInterval:3600, unit:'°', pin:1, graph:1, graphValSuffix:'F', graphOptions:{ legendLbl:'Temperature', lines: { lineWidth:1 } }},
  //uncomment FHtoC if you want a F:1234 to be valuated as a Centigrade isntead of F (the first match is picked up and will evaluate, any following defs are ignored)
  //FHtoC : { name:'C', regexp:/\bF\:(-?\d+)\b/i, value:'', duplicateInterval:3600, valuation:function(value) {return (value/100 - 32) * 5/9;}, unit:'°', pin:1, graph:1, graphValSuffix:'C', graphOptions:{ legendLbl:'Temperature', lines: { lineWidth:1 }}}
  FH : { name:'F', regexp:/\bF\:(-?\d+)\b/i, value:'', duplicateInterval:3600, valuation:function(value) {return value/100;}, unit:'°', pin:1, graph:1, graphValSuffix:'F', graphOptions:{ legendLbl:'Temperature', lines: { lineWidth:1 }}},
  C : { name:'C', regexp:/\bC\:([-\d\.]+)\b/i, value:'', duplicateInterval:3600, unit:'°', pin:1, graph:1, graphValSuffix:'C', graphOptions:{ legendLbl:'Temperature' }},
  H : { name:'H', regexp:/\bH\:([\d\.]+)\b/i, value:'', duplicateInterval:3600, unit:'%', pin:1, graph:1, graphOptions:{ legendLbl:'Humidity', lines: { lineWidth:1 }}},
  P : { name:'P', regexp:/\bP\:([\d\.]+)\b/i, value:'', duplicateInterval:3600, unit:'"', pin:1, },
};


exports.events = {
  garageSMSO : { label:'Garage opening : SMS', icon:'comment', descr:'Send SMS when garage is OPENING', serverExecute:function(node) { if (node.metrics['Status'] && (node.metrics['Status'].value.indexOf('OPENING')>-1) && (Date.now() - new Date(node.metrics['Status'].updated).getTime() < 2000)) { sendSMS('Garage event', 'Garage was opening on node : [' + node._id + ':' + node.label + '] @ ' + new Date().toLocaleTimeString()); }; } },
  garageSMSC : { label:'Garage closing : SMS', icon:'comment', descr:'Send SMS when garage is CLOSING', serverExecute:function(node) { if (node.metrics['Status'] && (node.metrics['Status'].value.indexOf('CLOSING')>-1) && (Date.now() - new Date(node.metrics['Status'].updated).getTime() < 2000)) { sendSMS('Garage event', 'Garage was closing on node : [' + node._id + ':' + node.label + '] @ ' + new Date().toLocaleTimeString()); }; } },
  garageEmailO : { label:'Garage opening : Email', icon:'mail', descr:'Send Email when garage is OPENING', serverExecute:function(node) { if (node.metrics['Status'] && (node.metrics['Status'].value.indexOf('OPENING')>-1) && (Date.now() - new Date(node.metrics['Status'].updated).getTime() < 2000)) { sendEmail('Garage event', 'Garage was opening on node : [' + node._id + ':' + node.label + '] @ ' + new Date().toLocaleTimeString()); }; } },
  garageEmailC : { label:'Garage closing : Email', icon:'mail', descr:'Send Email when garage is CLOSING', serverExecute:function(node) { if (node.metrics['Status'] && (node.metrics['Status'].value.indexOf('CLOSING')>-1) && (Date.now() - new Date(node.metrics['Status'].updated).getTime() < 2000)) { sendEmail('Garage event', 'Garage was closing on node : [' + node._id + ':' + node.label + '] @ ' + new Date().toLocaleTimeString()); }; } },
  
};


exports.motes = {
   GarageMote : {
    label   : 'Garage Opener',
    icon : 'icon_garage.png',
    controls : { refresh : { states: [{ label:'Refresh', action:'STS', icon:'refresh' }]},
                 opencls : { states: [{ label:'Open!', action:'OPN', icon:'arrow-u', css:'background-color:#FF9B9B;', condition:''+function(node) { return node.metrics['Status'].value == 'CLOSED';}},
                                      { label:'Opening..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status'].value == 'OPENING';}},
                                      { label:'Close!', action:'CLS', icon:'arrow-d', css:'background-color:#9BFFBE;color:#000000', condition:''+function(node) { return node.metrics['Status'].value == 'OPEN';}},
                                      { label:'Closing..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status'].value == 'CLOSING';}}]
                           }
              }
  },
}


Appreciate any input..

Thanks!


LukaQ

#1
what do you mean, when I add the code... (I know what you mean... rhetorical )
Look at buff, this is what you send. In your buff, you only put in
sprintf(buff, STATUS==STATUS_CLOSED ? "CLOSED" : STATUS==STATUS_CLOSING ? "CLOSING" : STATUS==STATUS_OPENING ? "OPENING" : STATUS==STATUS_OPEN ? "OPEN" : "UNKNOWN");

At no point you put in any data from weather shield. That is just garage stuff

Why don't you just combine two sketches, send part for garage, and then with second radio.sendWithRetry, send P, H and whatever else with the SAME ID

you need to have something like
sprintf(buff, "BAT:%sv F:%s H:%s P:%s", BATstr, Fstr, Hstr, Pstr);
also in the code.

OR combine from both into one, as long as your sending length is below max of 65 or what it was... but you can also try to go over that, to see how part of the data will be cut off :)


sparky

#2
Thanks for the response Luka

Instead of saying "when I add the code.." I should have said when I combine the garagemote and weathershield code.. sorry for the confusion..

Shouldn't this code send the data of the weather shield;  (it's located about 3/4 of the way thru the sketch..)

#elsif defined(WEATHERSHIELD_R2)
    //read BME280 sensor
    bme280.begin();
    dtostrf(bme280.readTempF(), 3,1, Fstr);
    dtostrf(bme280.readFloatHumidity(), 2,0, Hstr);
    float p = bme280.readFloatPressure();
    p = p / 3311.8352;  // this is conversion from Pascals to inches of mercury, adjusted for my location above sea level 
    dtostrf(p, 2,2, Pstr);    
    bme280.writeRegister(BME280_CTRL_MEAS_REG, 0x00); //sleep the BME280
    sprintf(sendBuf, "F:%s H:%s P:%s", Fstr, Hstr, Pstr);  // we skip transmitting battery voltage to save battery life 
  #endif


I will try your suggestions




ssmall

Have you defined WEATHERSHIELD_R2?

sparky

Quote from: LukaQ on April 27, 2018, 09:34:19 AM
Why don't you just combine two sketches, send part for garage, and then with second radio.sendWithRetry, send P, H and whatever else with the SAME ID

Ok, at first I thought I knew how to go about doing this but apparently not, I'm confused..


sparky

Quote from: ssmall on April 27, 2018, 10:38:39 AM
Have you defined WEATHERSHIELD_R2?

I was looking at this;

#ifdef WEATHERSHIELD_R2
  #include <SparkFunBME280.h> //get it here: https://github.com/sparkfun/SparkFun_BME280_Breakout_Board/tree/master/Libraries/Arduino/src
  #include <Wire.h>
#endif

thinking it was.. I guess I didn't  :P

Thank you!

sparky

Quote from: ssmall on April 27, 2018, 10:38:39 AM
Have you defined WEATHERSHIELD_R2?

Yes, it was there.. 

//#define WEATHERSHIELD_R1         //uncomment if WeatherShield_R1 (Si7021+BMP180 sensors) is present to report temp/humidity/pressure periodically
#define WEATHERSHIELD_R2         //uncomment if WeatherShield_R2 (BME280 sensor) is present to report temp/humidity/pressure periodically
#define WEATHERSENDDELAY  300000 // send WeatherShield data every so often (ms)

LukaQ

#7
Did you check, that you do enter either one, R1 or R2 with something like serial.print?

Also note, that Sparkfun and I changed the code to newer code, what you have still works. Sleep mode is more easy to use (read as: you have it without changing anything)

ssmall

Try putting this: DEBUGln(sendBuf)

After the following code and see what is printed for sendBuf:

#elsif defined(WEATHERSHIELD_R2)
    //read BME280 sensor
    bme280.begin();
    dtostrf(bme280.readTempF(), 3,1, Fstr);
    dtostrf(bme280.readFloatHumidity(), 2,0, Hstr);
    float p = bme280.readFloatPressure();
    p = p / 3311.8352;  // this is conversion from Pascals to inches of mercury, adjusted for my location above sea level 
    dtostrf(p, 2,2, Pstr);    
    bme280.writeRegister(BME280_CTRL_MEAS_REG, 0x00); //sleep the BME280
    sprintf(sendBuf, "F:%s H:%s P:%s", Fstr, Hstr, Pstr);  // we skip transmitting battery voltage to save battery life 
  #endif



sparky

Here is all I get;


LukaQ

I think you need to change your code to

#ifdef WEATHERSHIELD_R1
//
  #endif

  #ifdef WEATHERSHIELD_R2
//
  #endif


You were not entering

#elsif defined(WEATHERSHIELD_R2)
    //read BME280 sensor
    bme280.begin();
    dtostrf(bme280.readTempF(), 3,1, Fstr);
    dtostrf(bme280.readFloatHumidity(), 2,0, Hstr);
    float p = bme280.readFloatPressure();
    p = p / 3311.8352;  // this is conversion from Pascals to inches of mercury, adjusted for my location above sea level 
    dtostrf(p, 2,2, Pstr);    
    bme280.writeRegister(BME280_CTRL_MEAS_REG, 0x00); //sleep the BME280
    sprintf(sendBuf, "F:%s H:%s P:%s", Fstr, Hstr, Pstr);  // we skip transmitting battery voltage to save battery life 
  #endif

sparky

#11
QuoteI think you need to change your code to

#ifdef WEATHERSHIELD_R1
//
  #endif

  #ifdef WEATHERSHIELD_R2
//
  #endif

Didn't work.. no data

QuoteWhy don't you just combine two sketches, send part for garage, and then with second radio.sendWithRetry, send P, H and whatever else with the SAME ID

Any tips how I can go about doing this?

LukaQ

man I would love to test, but I'm packing for few day of holiday and I only have moteino without RFM in front of me

Try my sketch, you will see you do enter 1, then 2 and R2 as last. If this happens with other code enabled, then you are probably sending it also. You could set one moteino RF to serial, the other sketch that is not PIgateway, just gateway

GarageMote : 868 Mhz...
RFM69_ATC Enabled (Auto Transmission Control)

OPEN
CLOSED
1
1
1
1
1
1
2
R2
1
1

Felix

First make sure the readings from the WeatherShield are valid, use the WeatherShield example for that just to send weather readings.
Then you can combine those into the GarageMote similar to how the older example does it with BMP180.

sparky

Quote from: Felix on April 27, 2018, 11:56:14 AM
First make sure the readings from the WeatherShield are valid, use the WeatherShield example for that just to send weather readings.
Then you can combine those into the GarageMote similar to how the older example does it with BMP180.

Yes, as stated, the weather shield is working great when the code is separated from the GarageMote.. it's when I do the combining (GarageMote_WS) the data for the weather shield stops transmitting.

Thanks