Combine airquality, temperature code and send to the ethernet gateway



  • Dear All!

    My project: Node + EthernetGW + openhab2

    I try to combine the two example sketch codes (I would like to trigger the MQ2 sensor for smoke) , but it seems that the node sends the MQ2 sensors values, but
    -the gateway dont read that, and
    -i think that the node send the data more frequently than it should do.

    GW

    0;255;3;0;9;TSF:MSG:FPAR REQ,ID=1
    0;255;3;0;9;TSF:PNG:SEND,TO=0
    0;255;3;0;9;TSF:CKU:OK
    0;255;3;0;9;TSF:MSG:GWL OK
    0;255;3;0;9;TSF:MSG:SEND,0-0-1-1,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=255,c=3,t=24,pt=1,l=1,sg=0:1
    0;255;3;0;9;TSF:MSG:PINGED,ID=1,HP=1
    0;255;3;0;9;TSF:MSG:SEND,0-0-1-1,s=255,c=3,t=25,pt=1,l=1,sg=0,ft=0,st=OK:1
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=255,c=3,t=15,pt=6,l=2,sg=0:0100
    0;255;3;0;9;TSF:MSG:SEND,0-0-1-1,s=255,c=3,t=15,pt=6,l=2,sg=0,ft=0,st=OK:0100
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=255,c=0,t=17,pt=0,l=5,sg=0:2.1.1
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=255,c=3,t=6,pt=1,l=1,sg=0:0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=255,c=3,t=11,pt=0,l=22,sg=0:TemperatureAndHumidity
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=255,c=3,t=12,pt=0,l=3,sg=0:1.1
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=255,c=3,t=11,pt=0,l=18,sg=0:Air Quality Sensor
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=255,c=3,t=12,pt=0,l=3,sg=0:1.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=0,c=0,t=7,pt=0,l=0,sg=0:
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=1,c=0,t=6,pt=0,l=0,sg=0:
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=2,c=0,t=22,pt=0,l=0,sg=0:
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=255,c=3,t=26,pt=1,l=1,sg=0:2
    0;255;3;0;9;TSF:MSG:SEND,0-0-1-1,s=255,c=3,t=27,pt=1,l=1,sg=0,ft=0,st=OK:1
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=1,c=1,t=0,pt=7,l=5,sg=0:26.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=0,c=1,t=1,pt=7,l=5,sg=0:46.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=1,c=1,t=0,pt=7,l=5,sg=0:26.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=0,c=1,t=1,pt=7,l=5,sg=0:46.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=0,c=1,t=1,pt=7,l=5,sg=0:45.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=0,c=1,t=1,pt=7,l=5,sg=0:46.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=0,c=1,t=1,pt=7,l=5,sg=0:45.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=0,c=1,t=1,pt=7,l=5,sg=0:46.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=0,c=1,t=1,pt=7,l=5,sg=0:45.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=0,c=1,t=1,pt=7,l=5,sg=0:46.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=0,c=1,t=1,pt=7,l=5,sg=0:45.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=1,c=1,t=0,pt=7,l=5,sg=0:26.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=0,c=1,t=1,pt=7,l=5,sg=0:46.0
    0;255;3;0;9;TSF:MSG:READ,1-1-0,s=0,c=1,t=1,pt=7,l=5,sg=0:45.0
    

    NODE

    0 MCO:BGN:INIT NODE,CP=RNNNA--,VER=2.1.1
    3 TSM:INIT
    4 TSF:WUR:MS=0
    11 TSM:INIT:TSP OK
    13 TSM:INIT:STATID=1
    15 TSF:SID:OK,ID=1
    16 TSM:FPAR
    53 TSF:MSG:SEND,1-1-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
    875 TSF:MSG:READ,0-0-1,s=255,c=3,t=8,pt=1,l=1,sg=0:0
    880 TSF:MSG:FPAR OK,ID=0,D=1
    2060 TSM:FPAR:OK
    2061 TSM:ID
    2062 TSM:ID:OK
    2064 TSM:UPL
    2067 TSF:MSG:SEND,1-1-0-0,s=255,c=3,t=24,pt=1,l=1,sg=0,ft=0,st=OK:1
    2076 TSF:MSG:READ,0-0-1,s=255,c=3,t=25,pt=1,l=1,sg=0:1
    2081 TSF:MSG:PONG RECV,HP=1
    2084 TSM:UPL:OK
    2085 TSM:READY:ID=1,PAR=0,DIS=1
    2091 TSF:MSG:SEND,1-1-0-0,s=255,c=3,t=15,pt=6,l=2,sg=0,ft=0,st=OK:0100
    2098 TSF:MSG:READ,0-0-1,s=255,c=3,t=15,pt=6,l=2,sg=0:0100
    2105 TSF:MSG:SEND,1-1-0-0,s=255,c=0,t=17,pt=0,l=5,sg=0,ft=0,st=OK:2.1.1
    2113 TSF:MSG:SEND,1-1-0-0,s=255,c=3,t=6,pt=1,l=1,sg=0,ft=0,st=OK:0
    4121 TSF:MSG:SEND,1-1-0-0,s=255,c=3,t=11,pt=0,l=22,sg=0,ft=0,st=OK:TemperatureAndHumidity
    4131 TSF:MSG:SEND,1-1-0-0,s=255,c=3,t=12,pt=0,l=3,sg=0,ft=0,st=OK:1.1
    4141 TSF:MSG:SEND,1-1-0-0,s=255,c=3,t=11,pt=0,l=18,sg=0,ft=0,st=OK:Air Quality Sensor
    4150 TSF:MSG:SEND,1-1-0-0,s=255,c=3,t=12,pt=0,l=3,sg=0,ft=0,st=OK:1.0
    4158 TSF:MSG:SEND,1-1-0-0,s=0,c=0,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
    4166 TSF:MSG:SEND,1-1-0-0,s=1,c=0,t=6,pt=0,l=0,sg=0,ft=0,st=OK:
    4173 TSF:MSG:SEND,1-1-0-0,s=2,c=0,t=22,pt=0,l=0,sg=0,ft=0,st=OK:
    4179 MCO:REG:REQ
    4183 TSF:MSG:SEND,1-1-0-0,s=255,c=3,t=26,pt=1,l=1,sg=0,ft=0,st=OK:2
    4190 TSF:MSG:READ,0-0-1,s=255,c=3,t=27,pt=1,l=1,sg=0:1
    4195 MCO:PIM:NODE REG=1
    4197 MCO:BGN:STP
    4199 MCO:SLP:MS=1000,SMS=0,I1=255,M1=255,I2=255,M2=255
    4204 MCO:SLP:TPD
    4206 MCO:SLP:WUP=-1
    4208 MCO:BGN:INIT OK,TSP=1
    4235 TSF:MSG:SEND,1-1-0-0,s=1,c=1,t=0,pt=7,l=5,sg=0,ft=0,st=OK:26.0
    T: 26.00
    4243 TSF:MSG:SEND,1-1-0-0,s=0,c=1,t=1,pt=7,l=5,sg=0,ft=0,st=OK:46.0
    H: 46.00
    0
    LPG:0ppm    CO:0ppm    SMOKE:0ppm
    5257 MCO:SLP:MS=5000,SMS=0,I1=255,M1=255,I2=255,M2=255
    5262 MCO:SLP:TPD
    5263 MCO:SLP:WUP=-1
    0
    LPG:0ppm    CO:0ppm    SMOKE:0ppm
    6294 MCO:SLP:MS=5000,SMS=0,I1=255,M1=255,I2=255,M2=255
    6299 MCO:SLP:TPD```
    
    **Combined Node Sketch**
    

    Im attach the sketch of the node.0_1500791513747_DHT_MQ2_uj.ino

    Another question will be, that is this code OK for openhab:
    The temp and humidity works as expect, everything is OK. but the new manually entered code seems isnot recognized , but the openhab automatic search find the new child sensor but the values are zero.

    ~# cat /etc/openhab2/things/demo.things
    Bridge mysensors:bridge-eth:gateway [ ipAddress="100.100.6.41", tcpPort=5003, sendDelay=200, startupCheckEnabled=false,networkSanCheckEnabled=false ] {
         /** define things connected to that bridge here */
            humidity                hum01   [ nodeId=1, childId=0 ]
            temperature             temp01  [ nodeId=1, childId=1 ]
            AirQuality              airq01  [ nodeId=1, childId=2 ]
      }
    
    cat /etc/openhab2/items/demo.items
    Number hum01      "Humidity" { channel="mysensors:humidity:gateway:hum01:hum" }
    Number temp01     "Temperature" { channel="mysensors:temperature:gateway:temp01:temp" }
    Number airq01     "AirQuality" { channel="mysensors:airQuality:gateway:airq01:level" }
    
    cat /etc/openhab2/sitemaps/demo.sitemap
      sitemap demo label="Main Menu" {
            Frame {
                    Text item=hum01
                    Text item=temp01
                    Text item=airq01
    
            }
      }
    

    Thank you your help!

    Best regards,
    T


  • Mod

    Can you post the code of the node? Otherwise it's difficult to give an answer for the first question. I can't help for Openhab.



  • @gohan

    Hi Gohan!

    Thank you again for your help:)

    I have uploaded already but i see that the link dont work.
    I added comments to the MQ2 sections
    Code

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0: Henrik EKblad
     * Version 1.1 - 2016-07-20: Converted to MySensors v2.0 and added various improvements - Torben Woltjen (mozzbozz)
     * 
     * DESCRIPTION
     * This sketch provides an example of how to implement a humidity/temperature
     * sensor using a DHT11/DHT-22.
     *  
     * For more information, please visit:
     * http://www.mysensors.org/build/humidity
     * 
     */
    #define MY_NODE_ID 1
    // Enable debug prints
    #define MY_DEBUG
    
    // Enable and select radio type attached 
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    //#define MY_RS485
    /* TemperatureAndHumidity */
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DHT.h>
    
    // Set this to the pin you connected the DHT's data pin to
    #define DHT_DATA_PIN 3
    
    // Set this offset if the sensor has a permanent small offset to the real temperatures
    #define SENSOR_TEMP_OFFSET 0
    
    // Sleep time between sensor updates (in milliseconds)
    // Must be >1000ms for DHT22 and >2000ms for DHT11
    static const uint64_t UPDATE_INTERVAL = 5000;
    
    // Force sending an update of the temperature after n sensor reads, so a controller showing the
    // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
    // the value didn't change since;
    // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
    static const uint8_t FORCE_UPDATE_N_READS = 10;
    
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    
    float lastTemp;
    float lastHum;
    uint8_t nNoUpdatesTemp;
    uint8_t nNoUpdatesHum;
    bool metric = true;
    
    /*---------------------------------MQ2---------------------------------------------------------*/
    
    #define   CHILD_ID_MQ                   2
    /************************Hardware Related Macros************************************/
    #define   MQ_SENSOR_ANALOG_PIN         (0)  //define which analog input channel you are going to use
    #define         RL_VALUE                     (5)     //define the load resistance on the board, in kilo ohms
    #define         RO_CLEAN_AIR_FACTOR          (9.83)  //RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO,
    //which is derived from the chart in datasheet
    /***********************Software Related Macros************************************/
    #define         CALIBARAION_SAMPLE_TIMES     (50)    //define how many samples you are going to take in the calibration phase
    #define         CALIBRATION_SAMPLE_INTERVAL  (500)   //define the time interal(in milisecond) between each samples in the
    //cablibration phase
    #define         READ_SAMPLE_INTERVAL         (50)    //define how many samples you are going to take in normal operation
    #define         READ_SAMPLE_TIMES            (5)     //define the time interal(in milisecond) between each samples in
    //normal operation
    /**********************Application Related Macros**********************************/
    #define         GAS_LPG                      (0)
    #define         GAS_CO                       (1)
    #define         GAS_SMOKE                    (2)
    /*****************************Globals***********************************************/
    unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
    //VARIABLES
    float Ro = 10000.0;    // this has to be tuned 10K Ohm
    int val = 0;           // variable to store the value coming from the sensor
    float valMQ =0.0;
    float lastMQ =0.0;
    float           LPGCurve[3]  =  {2.3,0.21,-0.47};   //two points are taken from the curve.
    //with these two points, a line is formed which is "approximately equivalent"
    //to the original curve.
    //data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59)
    float           COCurve[3]  =  {2.3,0.72,-0.34};    //two points are taken from the curve.
    //with these two points, a line is formed which is "approximately equivalent"
    //to the original curve.
    //data format:{ x, y, slope}; point1: (lg200, 0.72), point2: (lg10000,  0.15)
    float           SmokeCurve[3] = {2.3,0.53,-0.44};   //two points are taken from the curve.
    //with these two points, a line is formed which is "approximately equivalent"
    //to the original curve.
    //data format:{ x, y, slope}; point1: (lg200, 0.53), point2:(lg10000,-0.22)
    /*--------------------MQ2 end---------------------------------*/
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    DHT dht;
    MyMessage msg(CHILD_ID_MQ, V_LEVEL);       
    
    
    void presentation()  
    { 
      // Send the sketch version information to the gateway
      sendSketchInfo("TemperatureAndHumidity", "1.1");
      sendSketchInfo("Air Quality Sensor", "1.0"); /*MQ2*/
      
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_HUM, S_HUM);
      present(CHILD_ID_TEMP, S_TEMP);
      present(CHILD_ID_MQ, S_AIR_QUALITY); /*MQ2*/
      metric = getControllerConfig().isMetric;
    
        
    }
    
    
    void setup()
    {
      dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor
      if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
        Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
    /*---MQ2---------------------------------------------------------*/
      Ro = MQCalibration(
               MQ_SENSOR_ANALOG_PIN);         //Calibrating the sensor. Please make sure the sensor is in clean air                                       
      }
      // Sleep for the time of the minimum sampling period to give the sensor time to power up
      // (otherwise, timeout errors might occure for the first reading)
      sleep(dht.getMinimumSamplingPeriod());
    }
    
    
    void loop()      
    {  
      // Force reading sensor, so it works also after sleep()
      dht.readSensor(true);
      
      // Get temperature from DHT library
      float temperature = dht.getTemperature();
      if (isnan(temperature)) {
        Serial.println("Failed reading temperature from DHT!");
      } else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) {
        // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
        lastTemp = temperature;
        if (!metric) {
          temperature = dht.toFahrenheit(temperature);
        }
        // Reset no updates counter
        nNoUpdatesTemp = 0;
        temperature += SENSOR_TEMP_OFFSET;
        send(msgTemp.set(temperature, 1));
    
        #ifdef MY_DEBUG
        Serial.print("T: ");
        Serial.println(temperature);
        #endif
      } else {
        // Increase no update counter if the temperature stayed the same
        nNoUpdatesTemp++;
      }
    
      // Get humidity from DHT library
      float humidity = dht.getHumidity();
      if (isnan(humidity)) {
        Serial.println("Failed reading humidity from DHT");
      } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) {
        // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
        lastHum = humidity;
        // Reset no updates counter
        nNoUpdatesHum = 0;
        send(msgHum.set(humidity, 1));
        
        #ifdef MY_DEBUG
        Serial.print("H: ");
        Serial.println(humidity);
        #endif
      } else {
        // Increase no update counter if the humidity stayed the same
        nNoUpdatesHum++;
      }
    
    /*----MQ2----*/
    uint16_t valMQ = MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO);
      Serial.println(val);
    
      Serial.print("LPG:");
      Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_LPG) );
      Serial.print( "ppm" );
      Serial.print("    ");
      Serial.print("CO:");
      Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO) );
      Serial.print( "ppm" );
      Serial.print("    ");
      Serial.print("SMOKE:");
      Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_SMOKE) );
      Serial.print( "ppm" );
      Serial.print("\n");
    
      if (valMQ != lastMQ) {
        send(msg.set((int16_t)ceil(valMQ)));
        lastMQ = ceil(valMQ);
      }
     
      // Sleep for a while to save energy
      sleep(UPDATE_INTERVAL); 
      
      
      
    }
    
    /*----MQ2----*/
    /****************** MQResistanceCalculation ****************************************
    Input:   raw_adc - raw value read from adc, which represents the voltage
    Output:  the calculated sensor resistance
    Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage
             across the load resistor and its resistance, the resistance of the sensor
             could be derived.
    ************************************************************************************/
    float MQResistanceCalculation(int raw_adc)
    {
      return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc));
    }
    
    /***************************** MQCalibration ****************************************
    Input:   mq_pin - analog channel
    Output:  Ro of the sensor
    Remarks: This function assumes that the sensor is in clean air. It use
             MQResistanceCalculation to calculates the sensor resistance in clean air
             and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about
             10, which differs slightly between different sensors.
    ************************************************************************************/
    float MQCalibration(int mq_pin)
    {
      int i;
      float val=0;
    
      for (i=0; i<CALIBARAION_SAMPLE_TIMES; i++) {          //take multiple samples
        val += MQResistanceCalculation(analogRead(mq_pin));
        delay(CALIBRATION_SAMPLE_INTERVAL);
      }
      val = val/CALIBARAION_SAMPLE_TIMES;                   //calculate the average value
    
      val = val/RO_CLEAN_AIR_FACTOR;                        //divided by RO_CLEAN_AIR_FACTOR yields the Ro
      //according to the chart in the datasheet
    
      return val;
    }
    /*****************************  MQRead *********************************************
    Input:   mq_pin - analog channel
    Output:  Rs of the sensor
    Remarks: This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
             The Rs changes as the sensor is in the different consentration of the target
             gas. The sample times and the time interval between samples could be configured
             by changing the definition of the macros.
    ************************************************************************************/
    float MQRead(int mq_pin)
    {
      int i;
      float rs=0;
    
      for (i=0; i<READ_SAMPLE_TIMES; i++) {
        rs += MQResistanceCalculation(analogRead(mq_pin));
        delay(READ_SAMPLE_INTERVAL);
      }
    
      rs = rs/READ_SAMPLE_TIMES;
      return rs;   
    }
                                      
               
       
    
    /*****************************  MQGetGasPercentage **********************************
    Input:   rs_ro_ratio - Rs divided by Ro
             gas_id      - target gas type
    Output:  ppm of the target gas
    Remarks: This function passes different curves to the MQGetPercentage function which
             calculates the ppm (parts per million) of the target gas.
    ************************************************************************************/
    int MQGetGasPercentage(float rs_ro_ratio, int gas_id)
    {
      if ( gas_id == GAS_LPG ) {
        return MQGetPercentage(rs_ro_ratio,LPGCurve);
      } else if ( gas_id == GAS_CO ) {
        return MQGetPercentage(rs_ro_ratio,COCurve);
      } else if ( gas_id == GAS_SMOKE ) {
        return MQGetPercentage(rs_ro_ratio,SmokeCurve);
            
      }
    
      return 0;
                  
    }
    
    /*****************************  MQGetPercentage **********************************
    Input:   rs_ro_ratio - Rs divided by Ro
             pcurve      - pointer to the curve of the target gas
    Output:  ppm of the target gas
    Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
             of the line could be derived if y(rs_ro_ratio) is provided. As it is a
             logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
             value.
    ************************************************************************************/
    int  MQGetPercentage(float rs_ro_ratio, float *pcurve)
    {
      return (pow(10,( ((log(rs_ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
    }
    /*----MQ2----*/
    

    Best regards,
    T



  • There are two errors:
    The serious one:

    void setup()
    {
      dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor
      if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
        Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
    /*---MQ2---------------------------------------------------------*/
      Ro = MQCalibration(MQ_SENSOR_ANALOG_PIN); //Calibrating the sensor. Please make sure the sensor is in clean air                                       
      }
      // Sleep for the time of the minimum sampling period to give the sensor time to power up
      // (otherwise, timeout errors might occure for the first reading)
      sleep(dht.getMinimumSamplingPeriod());
    }
    

    If you look at where you have put your initializing code you will realize that the code is never run unless you make the UPDATE_INTERVAL so small that it is less than dht.getMinimumSamplingPeriod
    Change the setup() to this instead:

    void setup()
    {
      dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor
      if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
        Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
      }
      // Sleep for the time of the minimum sampling period to give the sensor time to power up
      // (otherwise, timeout errors might occure for the first reading)
      sleep(dht.getMinimumSamplingPeriod());
      /*---MQ2---------------------------------------------------------*/
      Ro = MQCalibration(MQ_SENSOR_ANALOG_PIN);  //Calibrating the sensor. Please make sure the sensor is in clean air                                       
    }
    

    The second one is this:

      sendSketchInfo("TemperatureAndHumidity", "1.1");
      sendSketchInfo("Air Quality Sensor", "1.0"); /*MQ2*/
    

    You should only have one entry:

      sendSketchInfo("Temperature, Humidity and Gas", "1.1");
    


  • @mickecarlsson

    Thank you very much guys!

    I had to modify things for openhab, it is better now. But...
    in openhab2 i get this in the log:
    2017-07-24 19:23:36.497 [DEBUG] [rs.internal.gateway.MySensorsGateway] - Child 2 found in node 1
    2017-07-24 19:23:36.498 [WARN ] [rs.internal.gateway.MySensorsGateway] - Variable V_LEVEL not present

    Does someone know what i missed?

    Good afternoon!


  • Mod

    the first is just a debug message, the other I don't know what level is actually expecting



  • @gohan

    Dear Gohan!

    OK!
    I paste the new code again:

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0: Henrik EKblad
     * Version 1.1 - 2016-07-20: Converted to MySensors v2.0 and added various improvements - Torben Woltjen (mozzbozz)
     * 
     * DESCRIPTION
     * This sketch provides an example of how to implement a humidity/temperature
     * sensor using a DHT11/DHT-22.
     *  
     * For more information, please visit:
     * http://www.mysensors.org/build/humidity
     * 
     */
    #define MY_NODE_ID 1
    // Enable debug prints
    #define MY_DEBUG
    
    // Enable and select radio type attached 
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    //#define MY_RS485
    /* TemperatureAndHumidity */
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DHT.h>
    
    // Set this to the pin you connected the DHT's data pin to
    #define DHT_DATA_PIN 3
    
    // Set this offset if the sensor has a permanent small offset to the real temperatures
    #define SENSOR_TEMP_OFFSET 0
    
    // Sleep time between sensor updates (in milliseconds)
    // Must be >1000ms for DHT22 and >2000ms for DHT11
    static const uint64_t UPDATE_INTERVAL = 5000;
    
    // Force sending an update of the temperature after n sensor reads, so a controller showing the
    // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
    // the value didn't change since;
    // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
    static const uint8_t FORCE_UPDATE_N_READS = 10;
    
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    
    float lastTemp;
    float lastHum;
    uint8_t nNoUpdatesTemp;
    uint8_t nNoUpdatesHum;
    bool metric = true;
    
    /*---------------------------------MQ2---------------------------------------------------------*/
    
    #define   CHILD_ID_MQ                   2
    /************************Hardware Related Macros************************************/
    #define   MQ_SENSOR_ANALOG_PIN         (0)  //define which analog input channel you are going to use
    #define         RL_VALUE                     (5)     //define the load resistance on the board, in kilo ohms
    #define         RO_CLEAN_AIR_FACTOR          (9.83)  //RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO,
    //which is derived from the chart in datasheet
    /***********************Software Related Macros************************************/
    #define         CALIBARAION_SAMPLE_TIMES     (50)    //define how many samples you are going to take in the calibration phase
    #define         CALIBRATION_SAMPLE_INTERVAL  (500)   //define the time interal(in milisecond) between each samples in the
    //cablibration phase
    #define         READ_SAMPLE_INTERVAL         (50)    //define how many samples you are going to take in normal operation
    #define         READ_SAMPLE_TIMES            (5)     //define the time interal(in milisecond) between each samples in
    //normal operation
    /**********************Application Related Macros**********************************/
    #define         GAS_LPG                      (0)
    #define         GAS_CO                       (1)
    #define         GAS_SMOKE                    (2)
    /*****************************Globals***********************************************/
    //unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
    unsigned long SLEEP_TIME = 5000; // Sleep time between reads (in milliseconds)
    //VARIABLES
    float Ro = 10000.0;    // this has to be tuned 10K Ohm
    int val = 0;           // variable to store the value coming from the sensor
    float valMQ =0.0;
    float lastMQ =0.0;
    float           LPGCurve[3]  =  {2.3,0.21,-0.47};   //two points are taken from the curve.
    //with these two points, a line is formed which is "approximately equivalent"
    //to the original curve.
    //data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59)
    float           COCurve[3]  =  {2.3,0.72,-0.34};    //two points are taken from the curve.
    //with these two points, a line is formed which is "approximately equivalent"
    //to the original curve.
    //data format:{ x, y, slope}; point1: (lg200, 0.72), point2: (lg10000,  0.15)
    float           SmokeCurve[3] = {2.3,0.53,-0.44};   //two points are taken from the curve.
    //with these two points, a line is formed which is "approximately equivalent"
    //to the original curve.
    //data format:{ x, y, slope}; point1: (lg200, 0.53), point2:(lg10000,-0.22)
    /*--------------------MQ2 end---------------------------------*/
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    DHT dht;
    MyMessage msg(CHILD_ID_MQ, V_LEVEL);       
    
    
    void presentation()  
    { 
      // Send the sketch version information to the gateway
      // sendSketchInfo("TemperatureAndHumidity", "1.1");
      sendSketchInfo("Temperature, Humidity and Gas", "1.1"); /*MQ2*/
      
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_HUM, S_HUM);
      present(CHILD_ID_TEMP, S_TEMP);
      present(CHILD_ID_MQ, S_AIR_QUALITY); /*MQ2*/
      //present(CHILD_ID_MQ, S_SMOKE); /*MQ2*/
      metric = getControllerConfig().isMetric;
    
        
    }
    
    
    void setup()
    {
      dht.setup(DHT_DATA_PIN); // set data pin of DHT sensor
      if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
        Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
      }
      // Sleep for the time of the minimum sampling period to give the sensor time to power up
      // (otherwise, timeout errors might occure for the first reading)
      sleep(dht.getMinimumSamplingPeriod());
      /*---MQ2---------------------------------------------------------*/
      Ro = MQCalibration(MQ_SENSOR_ANALOG_PIN);  //Calibrating the sensor. Please make sure the sensor is in clean air                                       
    }
    
    void loop()      
    {  
      // Force reading sensor, so it works also after sleep()
      dht.readSensor(true);
      
      // Get temperature from DHT library
      float temperature = dht.getTemperature();
      if (isnan(temperature)) {
        Serial.println("Failed reading temperature from DHT!");
      } else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) {
        // Only send temperature if it changed since the last measurement or if we didn't send an update for n times
        lastTemp = temperature;
        if (!metric) {
          temperature = dht.toFahrenheit(temperature);
        }
        // Reset no updates counter
        nNoUpdatesTemp = 0;
        temperature += SENSOR_TEMP_OFFSET;
        send(msgTemp.set(temperature, 1));
    
        #ifdef MY_DEBUG
        Serial.print("T: ");
        Serial.println(temperature);
        #endif
      } else {
        // Increase no update counter if the temperature stayed the same
        nNoUpdatesTemp++;
      }
    
      // Get humidity from DHT library
      float humidity = dht.getHumidity();
      if (isnan(humidity)) {
        Serial.println("Failed reading humidity from DHT");
      } else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) {
        // Only send humidity if it changed since the last measurement or if we didn't send an update for n times
        lastHum = humidity;
        // Reset no updates counter
        nNoUpdatesHum = 0;
        send(msgHum.set(humidity, 1));
        
        #ifdef MY_DEBUG
        Serial.print("H: ");
        Serial.println(humidity);
        #endif
      } else {
        // Increase no update counter if the humidity stayed the same
        nNoUpdatesHum++;
      }
    
    /*----MQ2----*/
    uint16_t valMQ = MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO);
      Serial.println(val);
    
      Serial.print("LPG:");
      Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_LPG) );
      Serial.print( "ppm" );
      Serial.print("    ");
      Serial.print("CO:");
      Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_CO) );
      Serial.print( "ppm" );
      Serial.print("    ");
      Serial.print("SMOKE:");
      Serial.print(MQGetGasPercentage(MQRead(MQ_SENSOR_ANALOG_PIN)/Ro,GAS_SMOKE) );
      Serial.print( "ppm" );
      Serial.print("\n");
    
      if (valMQ != lastMQ) {
        send(msg.set((int16_t)ceil(valMQ)));
        lastMQ = ceil(valMQ);
      }
     
      // Sleep for a while to save energy
      sleep(UPDATE_INTERVAL); 
      
      
      
    }
    
    /*----MQ2----*/
    /****************** MQResistanceCalculation ****************************************
    Input:   raw_adc - raw value read from adc, which represents the voltage
    Output:  the calculated sensor resistance
    Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage
             across the load resistor and its resistance, the resistance of the sensor
             could be derived.
    ************************************************************************************/
    float MQResistanceCalculation(int raw_adc)
    {
      return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc));
    }
    
    /***************************** MQCalibration ****************************************
    Input:   mq_pin - analog channel
    Output:  Ro of the sensor
    Remarks: This function assumes that the sensor is in clean air. It use
             MQResistanceCalculation to calculates the sensor resistance in clean air
             and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about
             10, which differs slightly between different sensors.
    ************************************************************************************/
    float MQCalibration(int mq_pin)
    {
      int i;
      float val=0;
    
      for (i=0; i<CALIBARAION_SAMPLE_TIMES; i++) {          //take multiple samples
        val += MQResistanceCalculation(analogRead(mq_pin));
        delay(CALIBRATION_SAMPLE_INTERVAL);
      }
      val = val/CALIBARAION_SAMPLE_TIMES;                   //calculate the average value
    
      val = val/RO_CLEAN_AIR_FACTOR;                        //divided by RO_CLEAN_AIR_FACTOR yields the Ro
      //according to the chart in the datasheet
    
      return val;
    }
    /*****************************  MQRead *********************************************
    Input:   mq_pin - analog channel
    Output:  Rs of the sensor
    Remarks: This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
             The Rs changes as the sensor is in the different consentration of the target
             gas. The sample times and the time interval between samples could be configured
             by changing the definition of the macros.
    ************************************************************************************/
    float MQRead(int mq_pin)
    {
      int i;
      float rs=0;
    
      for (i=0; i<READ_SAMPLE_TIMES; i++) {
        rs += MQResistanceCalculation(analogRead(mq_pin));
        delay(READ_SAMPLE_INTERVAL);
      }
    
      rs = rs/READ_SAMPLE_TIMES;
      return rs;   
    }
                                      
               
       
    
    /*****************************  MQGetGasPercentage **********************************
    Input:   rs_ro_ratio - Rs divided by Ro
             gas_id      - target gas type
    Output:  ppm of the target gas
    Remarks: This function passes different curves to the MQGetPercentage function which
             calculates the ppm (parts per million) of the target gas.
    ************************************************************************************/
    int MQGetGasPercentage(float rs_ro_ratio, int gas_id)
    {
      if ( gas_id == GAS_LPG ) {
        return MQGetPercentage(rs_ro_ratio,LPGCurve);
      } else if ( gas_id == GAS_CO ) {
        return MQGetPercentage(rs_ro_ratio,COCurve);
      } else if ( gas_id == GAS_SMOKE ) {
        return MQGetPercentage(rs_ro_ratio,SmokeCurve);
            
      }
    
      return 0;
                  
    }
    
    /*****************************  MQGetPercentage **********************************
    Input:   rs_ro_ratio - Rs divided by Ro
             pcurve      - pointer to the curve of the target gas
    Output:  ppm of the target gas
    Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
             of the line could be derived if y(rs_ro_ratio) is provided. As it is a
             logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
             value.
    ************************************************************************************/
    int  MQGetPercentage(float rs_ro_ratio, float *pcurve)
    {
      return (pow(10,( ((log(rs_ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
    }
    /*----MQ2----*/```


  • @gohan

    Dear Gohan!

    I realized that I can not transfer the gas sensors calculated value through the V_LEVEL variable used in the sketch, because on the openhab side i should use tripped type value i think...
    So i think there is a missconfiguration between openhab item/sitemap configuration and the sketch.

    The goal would be to display the mq2 sensor's calculated value, which i can use for alarm in the future, but now i will be happy about the value:)

    Have a good day


  • Mod

    For alarm you need to create a rule in Openhab that when value goes over a certain value it sets of the alarm


Log in to reply
 

Suggested Topics

  • 3
  • 5
  • 1
  • 2

15
Online

11.4k
Users

11.1k
Topics

112.7k
Posts