bme280 sensor missing/combining/domoticz heartbeat and battery level



  • Re: BME280 temp/humidity/pressure sensor
    Re2: DS18B20 ans SHT31-D show up as combined sensors on Domoticz
    Re3: Heartbeat working or not?

    I'm trying to make outdoors(now debugging indoors) sleep node with tqfp32 atmega328p internal 8mhz + bme280 + BH1750 (in future battery powered with two lithium AA batteries (not accumulators).
    I'm using Domoticz stable Version 4.9700 (June 23th 2018)
    and MySensors 2.3.0 at nodes and at gateway(almost shure about gateway version)

    Note, that according MYSController (by tekka) all messages and presentations are received and sent normally, so no problems in my pcb, radiochannel and gateway are expected. Only in code order and/or domoticz processing.

    I've faced three problems:


    First is related to combining sensors - i do not fully understand, how to avoid and how to not avoid. To avoid i've tried to change code, so to present humidity before temperature(but not id's), as mentioned in topic: humidity - temperature - pressure. But it didn't helped - temperature and humidity sensors are combined.
    I've also couldn't find topic about combining, mentioned in issue on git by gizmocuz.


    Second might be related to first. I see all presented childs in my node in domoticz hardware. But in devices i'm missing one of them (temp-hum-pres-lux). For code that i will show below - i'm missing pressure. That code uses @sundberg84 order of ID's and order of presenting, taken from his post here because he mentioned that he avoided combining. And what are "red nodes" in domoticz?
    (also i have one boolean and one text - for debugging and to be sure have reboot, it was before i found about smarts sleep "true". Also i have a lot of defines and ifdefs - to easily test this problem - about this later)
    Here is my code at the moment:

    //The maximum payload size is 25 bytes! The NRF24L01+ has a maximum of 32 bytes. The MySensors library (version 2.0) uses 7 bytes for the message header.
    //mysensors 8mhz bits L=0xE2 H=0xD2 E=0x06 L=0x3F
    
    #define MY_NODE_ID 4
    #define MY_BAUD_RATE 9600
    //#define MY_DEBUG 
    #define MY_SPECIAL_DEBUG
    #define MY_RADIO_RF24
    #define MY_RF24_IRQ_PIN (8)
    
    #define DEB_ID 88
    #define PRES_BME_ID 0
    #define TEMP_BME_ID 1
    #define HUMID_BME_ID 2
    #define LIGHT_LUX_ID 3
    #define REBOOT_ID 10
    
    
    #define MEASURE_BATT_FUNCT //uncomment to measure and send battery level
    #define LUX_FUNCT //uncomment to enable light measuring
    #define LUX_AUTOAJUST //uncomment to enable auto-ajust resolution of sensor
    #define BME_FUNCT //uncomment to enable bme measuring
    
    #define SLEEP_TIME 20000UL  // sleep time between reads (seconds * 1000 milliseconds)
    
    #include <MySensors.h>
    
    #define BME_PRES_FUNCT //uncomment to enable sending pressure
    #define BME_TEMP_FUNCT //uncomment to enable sending temperature
    #define BME_HUM_FUNCT //uncomment to enable sending humidity
    
    
    #if defined(LUX_FUNCT) || defined(BME_FUNCT)
      # include <Wire.h>
    #endif
    
    #ifdef LUX_FUNCT
      # include <BH1750.h>
      BH1750 lightMeter;
      MyMessage light_msg(LIGHT_LUX_ID, V_LEVEL); //VARIABLE_TYPE:    V_TEXT - из второй таблицы https://www.mysensors.org/download/serial_api_20#set,-req
    #endif
    
    #ifdef BME_FUNCT
      # include "SparkFunBME280.h"
      BME280 bme;
      MyMessage pressure_msg(PRES_BME_ID, V_PRESSURE); //VARIABLE_TYPE:    V_TEXT -set,req table https://www.mysensors.org/download/serial_api_20#set,-req
      MyMessage temperature_msg(TEMP_BME_ID, V_TEMP); //VARIABLE_TYPE:    V_TEXT -set,req table https://www.mysensors.org/download/serial_api_20#set,-req
      MyMessage humidity_msg(HUMID_BME_ID, V_HUM); //VARIABLE_TYPE:    V_TEXT -set,req table https://www.mysensors.org/download/serial_api_20#set,-req
    #endif
    //MyMessage(uint8_t childSensorId, uint8_t variableType);
    MyMessage deb_msg(DEB_ID, V_TEXT); //VARIABLE_TYPE:    V_TEXT -set,req table https://www.mysensors.org/download/serial_api_20#set,-req
    MyMessage reboot_msg(REBOOT_ID, V_STATUS);
    
    
    
    int oldBatteryPcnt = 0;
    long old_lux = 0;
    float old_t = 0;
    int old_h = 0;
    int old_p = 0;
    
    bool bme_init_status = false;
    bool lux_init_status = false;
    bool got_reboot_response = false;
    
    bool metric = false;
    /*
     * before
     * connect
     * present
     * setup
     * loop
    */
    void(* resetFunc) (void) = 0; //declare reset function @ address 0
    
    void before()
    {
      
    }
    
    void presentation()
    {
      // Send the sketch version information to the gateway and Controller
      //void sendSketchInfo(const char *name, const char *version, bool ack);
      sendSketchInfo("lodjiya", "0.1");
      
      //void present(uint8_t childSensorId, uint8_t sensorType, const char *description, bool ack);
      present(DEB_ID, S_INFO, "lodjiya_Debug");//SENSOR_TYPE:   S_INFO - из таблицы presentation https://www.mysensors.org/download/serial_api_20#presentation
    
    
    #ifdef BME_FUNCT
      # ifdef BME_PRES_FUNCT
      present(PRES_BME_ID, S_BARO, "lodjiya_bme_pres");
      wait(100);
      # endif
    #endif
    #ifdef LUX_FUNCT
      present(LIGHT_LUX_ID, S_LIGHT_LEVEL, "lodjiya_lux_light");
    #endif
    #ifdef BME_FUNCT
      # ifdef BME_TEMP_FUNCT
      present(TEMP_BME_ID, S_TEMP, "lodjiya_bme_t");
      wait(100);
      # endif
    #endif
      present(REBOOT_ID, S_BINARY, "lodjiya_reboot_bool");
    #ifdef BME_FUNCT
      # ifdef BME_HUM_FUNCT
      present(HUMID_BME_ID, S_HUM, "lodjiya_bme_humid");
      wait(100);
      # endif
    #endif
    }
    
    void setup()  
    {
      analogReference(INTERNAL);  // use the 1.1 V internal reference
      send(deb_msg.set(""));
    
    #if defined(LUX_FUNCT) || defined(BME_FUNCT)
      Wire.begin(); // Initialize the I2C bus (BH1750 library doesn't do this automatically)
    #endif
    
    #ifdef LUX_FUNCT
      lux_init_status = lightMeter.begin(BH1750::ONE_TIME_LOW_RES_MODE);
      if (lux_init_status == false)
        send(deb_msg.set("ErrorInitLux"));
    #endif
    
    #ifdef BME_FUNCT
      bme.setI2CAddress(0x76);
      bme_init_status = bme.beginI2C();
      if (bme_init_status == false)
        send(deb_msg.set("ErrorInitBme"));
      bme.setMode(MODE_SLEEP); //Sleep for now
    #endif
      send(reboot_msg.set(false));
    
    }
    
    void loop()     
    {     
      //wait(5000); //ждать команды bool wait(unsigned long ms, uint8_t cmd, uint8_t msgtype);
      unsigned long timer = millis();
      got_reboot_response = false;
      request(REBOOT_ID, V_STATUS);
      
    
    #ifdef MEASURE_BATT_FUNCT
      {
        int batteryPcnt = getBandgap() / 3.3;
    
        if (oldBatteryPcnt != batteryPcnt) {
          sendBatteryLevel(batteryPcnt);// Power up radio after sleep
          oldBatteryPcnt = batteryPcnt;
          wait(50);
        }
      }
    #endif
    
    #ifdef LUX_FUNCT
      if (lux_init_status)
      {
        long lux = lightMeter.readLightLevel();
        # ifdef LUX_AUTOAJUST
          /*
          After the measurement the MTreg value is changed according to the result:
          lux > 40000 ==> MTreg =  32
          lux < 40000 ==> MTreg =  69  (default)
          lux <    10 ==> MTreg = 138
          */
          if (lux < 0)
          {
            send(deb_msg.set("ErrorLuxMsr"));
          }
          else 
          {
            if (lux > 40000.0)  // reduce measurement time - needed in direct sun light
            {
              if (!lightMeter.setMTreg(32))
                send(deb_msg.set("ErrorSetMTReg32"));
            }
            else
            {
                if (lux > 10.0) // typical light environment
                {
                  if (!lightMeter.setMTreg(69))
                    send(deb_msg.set("ErrorSetMTReg69"));
                }
                else
                {
                  if (lux <= 10.0)  //very low light environment
                  {
                    if (!lightMeter.setMTreg(138))
                      send(deb_msg.set("ErrorSetMTReg138"));
                  }
               }
            }
          }
        # endif
    
        if (old_lux != lux)
        {
            send(light_msg.set(lux));
            old_lux = lux;
            wait(50);
        }
      }
    #endif
      
    #ifdef BME_FUNCT
      if (bme_init_status)
      {
        bme.setMode(MODE_FORCED);
        int p = bme.readFloatPressure()/133;
        int h = bme.readFloatHumidity();
        float t = bme.readTempC();
        bme.setMode(MODE_SLEEP);
    
        if (abs(old_t - t) > 0.1)
        {
          # ifdef BME_TEMP_FUNCT
            send(temperature_msg.set(t, 1));
          # endif
            old_t = t;
            wait(50);
        }
        if (old_h != h)
        {
          # ifdef BME_HUM_FUNCT
            send(humidity_msg.set(h));
          # endif
            old_h = h;
            wait(50);
        }
        if (old_p != p)
        {
          # ifdef BME_PRES_FUNCT
            send(pressure_msg.set(p));
          # endif
            old_p = p;
            wait(50);
        }
      }
    #endif
    
    
      // send(deb_msg.set((  abs(millis() - timer) ))); //50-60ms
      if (!got_reboot_response)
      {
        wait(3000, C_REQ, V_STATUS);//wait(const uint32_t waitingMS, const uint8_t cmd, const uint8_t msgType)
        // send(deb_msg.set("endwait1"));
      }
      // send(deb_msg.set((  abs(millis() - timer) ))); //800-900ms
      // sleep(SLEEP_TIME, true);
      wait(SLEEP_TIME);
      
      //void requestTime(); //answer will be back to void receiveTime(uint32_t ts);
    }
    
    
    const long InternalReferenceVoltage = 1068;  // Adjust this value to your board's specific internal BG voltage
     
    // Code courtesy of "Coding Badly" and "Retrolefty" from the Arduino forum
    // results are Vcc * 100
    // So for example, 5V would be 500.
    int getBandgap() 
    {
      // REFS0 : Selects AVcc external reference
      // MUX3 MUX2 MUX1 : Selects 1.1V (VBG)  
       ADMUX = bit (REFS0) | bit (MUX3) | bit (MUX2) | bit (MUX1);
       ADCSRA |= bit( ADSC );  // start conversion
       while (ADCSRA & bit (ADSC))
         { }  // wait for conversion to complete
       int results = (((InternalReferenceVoltage * 1024) / ADC) + 5) / 10; 
       return results;
    } // end of getBandgap
    
    void receive(const MyMessage &message) //handles received message
    {
      // send(deb_msg.set(message.type));
      // send(deb_msg.set(message.sensor));
      // send(deb_msg.set(mGetCommand(message)));
      
      if (message.type == V_STATUS) {
        if (message.sensor == REBOOT_ID)
        {
          got_reboot_response = true;
          // send(deb_msg.set("got answer"));
          if (message.getBool())
            resetFunc();
        }
      }
    }
    

    How i tried to test this behaviour:
    (a)comment in code one of (temp-hum-pres) ... start upload in MYSController
    while uploading code to node via MYSController (so node doesn't send any presentation or child data to domoticz)
    i go to domoticz-devices, select all devices realated to this node and in upper left corned press bucket to delete them (to do that i present all sensors with names, starting with "lodjiya", so i can find them by sorting by name. also remember to press "all devices" and choose in upper left to show all, not only 25 devices)
    then i go to hardware-mysensors-setup select node and delete it (or delete only testing childs)
    but domoticz may prevent them from appearing/registering/presentating again, so
    i go to my putty window and do sudo service domoticz.sh restart
    after that code is finished uploading, device reboots, present nodes, send first-time data for each sensor.
    then i checked and printsreened domoticz list of this node childs (that they all appeared and send their data, confirm identical for all last seen time) and same for list of devices
    (b)then uncomment sensor that was commented, and upload code (so "new" child-sensor will present himself and sent his data after upload and reboot while other sensors already present in domoticz system)
    after doing checking and printscreenenig i go and comment next one of (temp-hum-pres) and start from beginning

    Also i tested case without commenting any sensor (all appear at once after domoticz restart)

    ID's: lux=commented,disabled; p=1; t=2; hum=3; presenting order don't remember, but i think temperature was presented last
    I've got next results: (i have screens, bu will not post them, because it is already big and hard to read post)
    Note: in all cases in hardware all childs were present with all latest data!
    so, below are described DEVICES status only

    1. all sensors: t+h not combined, because temperature is missed in devices, h and p present
    2. p+h: a)ok b) t is missed, so nothing combined, p+h still present
    3. p+t: a)ok b) h is missed, so nothing combined, p+t still present
    4. t+h: a)ok b) p is missed, t+h still present and still combined (as one temp sensor and temp+hum WTGR800 device)

    so in all cases i always miss one of (temp-hum-pres), even if i tried to present to domoticz later


    Third is related to sendHeartbeat or sendbatterylevel without sending any sensors data or having no sensors.
    I've asked in old closed issue here (there is something about workaround after issue was closed, but i wasn't able to find in commits).
    So i've opened new issue, and i think i must look at line 470 which is called at line 1819 but i see only 12 types.
    And i do not understand if it is possible to update only node (first table) last seen time and/or #255 child (second table in hardware in domoticz in mysensors setup).
    If send no sensor data, but only heartbeat (with wait or with smartsleep) - node and childs will not update "last seen". Nor wait neither smart sleep. Only on presentation (without sending sensor data).
    Same for battery level if i send only battery level without any sensors data it seems not to update nor last seen neither battery level. Nor wait neither smart sleep. Only on presentation (if i do not send sensor data)...
    Function is called at line 1797 looks like must update all childs...


 

380
Online

8.0k
Users

8.8k
Topics

94.3k
Posts