Serial Gateway Sketch with si7021



  • Hi All,
    I have biuld a Serial Gateway based on RFM69 and a ProMini. Its working great so far. But I want to implement in this Sketch also a Sensor si7021. I have currently no idea how i can implent the sensor part into the Gateway Sketch. Hope someone can help me there.

    Thanks

    Markus


  • Mod

    Just add the code of a node in presentation, setup and loop, nothing fancy



  • Well the Problem seems to be in the first step to get a working SI7021 Sketch for MySensors 2.2.0 Beta or 2.1.1.
    I did Try to complie this one now:

    /* Sketch with Si7021 and battery monitoring.
    by m26872, 20151109 
    */
    
    #define MY_DEBUG
    #define MY_RADIO_NRF24
    #define MY_NODE_ID 5             // <<<<<<<<<<<<<<<<<<<<<<<<<<<   Enter Node_ID
    #define MY_BAUD_RATE 115200
    
    #include <MySensors.h>  
    #include <Wire.h>
    #include <SI7021.h>
    #include <SPI.h>
    #include <RunningAverage.h>
    
    //#define DEBUG
    
    #ifdef DEBUG
    #define DEBUG_SERIAL(x) Serial.begin(x)
    #define DEBUG_PRINT(x) Serial.print(x)
    #define DEBUG_PRINTLN(x) Serial.println(x)
    #else
    #define DEBUG_SERIAL(x)
    #define DEBUG_PRINT(x) 
    #define DEBUG_PRINTLN(x) 
    #endif
    
    #define CHILD_ID_TEMP 0
    #define CHILD_ID_HUM 1
    // #define SLEEP_TIME 15000 // 15s for DEBUG
    #define SLEEP_TIME 300000   // 5 min
    #define FORCE_TRANSMIT_CYCLE 36  // 5min*12=1/hour, 5min*36=1/3hour 
    #define BATTERY_REPORT_CYCLE 2880   // Once per 5min   =>   12*24*7 = 2016 (one report/week)
    #define VMIN 1900
    #define VMAX 3300
    #define HUMI_TRANSMIT_THRESHOLD 3.0  // THRESHOLD tells how much the value should have changed since last time it was transmitted.
    #define TEMP_TRANSMIT_THRESHOLD 0.5
    #define AVERAGES 2
    
    int batteryReportCounter = BATTERY_REPORT_CYCLE - 1;  // to make it report the first time.
    int measureCount = 0;
    float lastTemperature = -100;
    int lastHumidity = -100;
    
    RunningAverage raHum(AVERAGES);
    SI7021 humiditySensor;
    
    MyMessage msgTemp(CHILD_ID_TEMP,V_TEMP); // Initialize temperature message
    MyMessage msgHum(CHILD_ID_HUM,V_HUM);
    
    
    void presentation()  
    { 
      sendSketchInfo("EgTmpHumBat5min", "1.0 151106");
      present(CHILD_ID_TEMP, S_TEMP);   // Present sensor to controller
      present(CHILD_ID_HUM, S_HUM);
    }
    
    
    void setup() {
      DEBUG_SERIAL(115200);    // <<<<<<<<<<<<<<<<<<<<<<<<<< Note BAUD_RATE in MySensors.h
      DEBUG_PRINTLN("Serial started");
      
      DEBUG_PRINT("Voltage: ");
      DEBUG_PRINT(readVcc()); 
      DEBUG_PRINTLN(" mV");
    /*
      delay(500);
      DEBUG_PRINT("Internal temp: ");
      DEBUG_PRINT(GetInternalTemp()); // Probably not calibrated. Just to print something.
      DEBUG_PRINTLN(" *C");
    */  
      delay(500); // Allow time for radio if power useed as reset
      DEBUG_PRINT("Node and "); DEBUG_PRINTLN("2 children presented.");
      
      raHum.clear();
      
    }
    
    void loop() { 
    
      measureCount ++;
      batteryReportCounter ++;
      bool forceTransmit = false;
      
      if (measureCount > FORCE_TRANSMIT_CYCLE) {
        forceTransmit = true; 
      }
      sendTempHumidityMeasurements(forceTransmit);
    /*
      // Read and print internal temp
      float temperature0 = static_cast<float>(static_cast<int>((GetInternalTemp()+0.5) * 10.)) / 10.;
      DEBUG_PRINT("Internal Temp: "); DEBUG_PRINT(temperature0); DEBUG_PRINTLN(" *C");        
    */
      // Check battery
      if (batteryReportCounter >= BATTERY_REPORT_CYCLE) {
        long batteryVolt = readVcc();
        DEBUG_PRINT("Battery voltage: "); DEBUG_PRINT(batteryVolt); DEBUG_PRINTLN(" mV");
        uint8_t batteryPcnt = constrain(map(batteryVolt,VMIN,VMAX,0,100),0,255);   
        DEBUG_PRINT("Battery percent: "); DEBUG_PRINT(batteryPcnt); DEBUG_PRINTLN(" %");
        sendBatteryLevel(batteryPcnt);
        batteryReportCounter = 0;
      }
      
      sleep(SLEEP_TIME);
    }
    
    // function for reading Vcc by reading 1.1V reference against AVcc. Based from http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/
    // To calibrate reading replace 1125300L with scale_constant = internal1.1Ref * 1023 * 1000, where internal1.1Ref = 1.1 * Vcc1 (per voltmeter) / Vcc2 (per readVcc() function) 
    long readVcc() {
      // set the reference to Vcc and the measurement to the internal 1.1V reference
      ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
      delay(2); // Wait for Vref to settle
      ADCSRA |= _BV(ADSC); // Start conversion
      while (bit_is_set(ADCSRA,ADSC)); // measuring
      uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
      uint8_t high = ADCH; // unlocks both
      long result = (high<<8) | low;
      result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
      return result; // Vcc in millivolts
    }
    // function for reading internal temp. From http://playground.arduino.cc/Main/InternalTemperatureSensor 
    double GetInternalTemp(void) {  // (Both double and float are 4 byte in most arduino implementation)
      unsigned int wADC;
      double t;
      // The internal temperature has to be used with the internal reference of 1.1V. Channel 8 can not be selected with the analogRead function yet.
      ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));   // Set the internal reference and mux.
      ADCSRA |= _BV(ADEN);  // enable the ADC
      delay(20);            // wait for voltages to become stable.
      ADCSRA |= _BV(ADSC);  // Start the ADC
      while (bit_is_set(ADCSRA,ADSC));   // Detect end-of-conversion
      wADC = ADCW;   // Reading register "ADCW" takes care of how to read ADCL and ADCH.
      t = (wADC - 88.0 ) / 1.0;   // The default offset is 324.31.
      return (t);   // The returned temperature in degrees Celcius.
    }
    
    /*********************************************
     * * Sends temperature and humidity from Si7021 sensor
     * Parameters
     * - force : Forces transmission of a value (even if it's the same as previous measurement)
     *********************************************/
    void sendTempHumidityMeasurements(bool force) {
      bool tx = force;
    
      si7021_env data = humiditySensor.getHumidityAndTemperature();
      
      float temperature = data.celsiusHundredths / 100.0;
      DEBUG_PRINT("T: ");DEBUG_PRINTLN(temperature);
      float diffTemp = abs(lastTemperature - temperature);
      DEBUG_PRINT(F("TempDiff :"));DEBUG_PRINTLN(diffTemp);
      if (diffTemp > TEMP_TRANSMIT_THRESHOLD || tx) {
        send(msgTemp.set(temperature,1));
        lastTemperature = temperature;
        measureCount = 0;
        DEBUG_PRINTLN("T sent!");
      }
      
      int humidity = data.humidityPercent;
      DEBUG_PRINT("H: ");DEBUG_PRINTLN(humidity);
      raHum.addValue(humidity);
      humidity = raHum.getAverage();  // MA sample imply reasonable fast sample frequency
      float diffHum = abs(lastHumidity - humidity);  
      DEBUG_PRINT(F("HumDiff  :"));DEBUG_PRINTLN(diffHum); 
      if (diffHum > HUMI_TRANSMIT_THRESHOLD || tx) {
        send(msgHum.set(humidity));
        lastHumidity = humidity;
        measureCount = 0;
        DEBUG_PRINTLN("H sent!");
      }
    
    }
    

    But I get always follwoing error...

    exit status 1
    'si7021_env' has no member named 'humidityPercent'
    

    So I am a bit lost at the Moment due to my limited coding Knowledge.. :-(


  • Mod

    Why don't you start with a much simpler sketch? And that is for a node, it is missing all the defines for the gateway. Start with the gateway sketch and add only the code needed by the sensor. The error you get is probably a mismatch between the code and the library: check in the library examples how do you retrive humidity from the sensor



  • Did a mistake with the Libary. Used now the SI7021 from MySensorsArduinoExamples-master and this seems to be okay now



  • the Problem is I cnnaot find any simple Mysensors Sketch to read a SI7021 :-(
    Only with battery Monitoring which I don't Need...



  • can it work like this?

    // Enable debug prints to serial monitor
    #define MY_DEBUG
    
    
    // Enable and select radio type attached
    #define MY_RADIO_RFM69
    #define MY_RFM69_FREQUENCY RFM69_868MHZ
    
    #include <Wire.h>
    #include <SI7021.h>
    #include <SPI.h>
    #include <RunningAverage.h>
    
    
    #ifdef MY_DEBUG
    #define DEBUG_SERIAL(x) Serial.begin(x)
    #define DEBUG_PRINT(x) Serial.print(x)
    #define DEBUG_PRINTLN(x) Serial.println(x)
    #else
    #define DEBUG_SERIAL(x)
    #define DEBUG_PRINT(x) 
    #define DEBUG_PRINTLN(x) 
    #endif
    
    #define CHILD_ID_TEMP 0
    #define CHILD_ID_HUM 1
    // #define SLEEP_TIME 15000 // 15s for DEBUG
    #define SLEEP_TIME 300000   // 5 min
    #define FORCE_TRANSMIT_CYCLE 36  // 5min*12=1/hour, 5min*36=1/3hour 
    #define HUMI_TRANSMIT_THRESHOLD 3.0  // THRESHOLD tells how much the value should have changed since last time it was transmitted.
    #define TEMP_TRANSMIT_THRESHOLD 0.5
    #define AVERAGES 2
    
    int measureCount = 0;
    float lastTemperature = -100;
    int lastHumidity = -100;
    
    RunningAverage raHum(AVERAGES);
    SI7021 humiditySensor;
    
    
    // Enable serial gateway
    #define MY_GATEWAY_SERIAL
    
    // Define a lower baud rate for Arduino's running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
    #if F_CPU == 8000000L
    #define MY_BAUD_RATE 38400
    #endif
    
    // Enable inclusion mode
    #define MY_INCLUSION_MODE_FEATURE
    
    // Set inclusion mode duration (in seconds)
    #define MY_INCLUSION_MODE_DURATION 60
    
    // Set blinking period
    #define MY_DEFAULT_LED_BLINK_PERIOD 300
    
    // Inverses the behavior of leds
    //#define MY_WITH_LEDS_BLINKING_INVERSE
    
    // Flash leds on rx/tx/err
    // Uncomment to override default HW configurations
    //#define MY_DEFAULT_ERR_LED_PIN 4  // Error led pin
    //#define MY_DEFAULT_RX_LED_PIN  6  // Receive led pin
    //#define MY_DEFAULT_TX_LED_PIN  5  // the PCB, on board LED
    
    #include <MySensors.h>
    
    MyMessage msgTemp(CHILD_ID_TEMP,V_TEMP); // Initialize temperature message
    MyMessage msgHum(CHILD_ID_HUM,V_HUM);
    
    
    void setup()
    {
      DEBUG_SERIAL(38400);    // <<<<<<<<<<<<<<<<<<<<<<<<<< Note BAUD_RATE in MySensors.h
      DEBUG_PRINTLN("Serial started");
      delay(500); // Allow time for radio if power useed as reset
      DEBUG_PRINT("Node and "); DEBUG_PRINTLN("2 children presented.");
       raHum.clear();
      
    }
    
    void presentation()
    { 
      sendSketchInfo("Gateway_SI7021", "1.0 161017");
      present(CHILD_ID_TEMP, S_TEMP);   // Present sensor to controller
      present(CHILD_ID_HUM, S_HUM);
    }
    
    
    void loop()
    { 
    
      measureCount ++;
      bool forceTransmit = false;
      
      if (measureCount > FORCE_TRANSMIT_CYCLE) {
        forceTransmit = true; 
      }
      sendTempHumidityMeasurements(forceTransmit);
    /*
      // Read and print internal temp
      float temperature0 = static_cast<float>(static_cast<int>((GetInternalTemp()+0.5) * 10.)) / 10.;
      DEBUG_PRINT("Internal Temp: "); DEBUG_PRINT(temperature0); DEBUG_PRINTLN(" *C");        
    */
     
      sleep(SLEEP_TIME);
    }
    
    /*********************************************
     * * Sends temperature and humidity from Si7021 sensor
     * Parameters
     * - force : Forces transmission of a value (even if it's the same as previous measurement)
     *********************************************/
    void sendTempHumidityMeasurements(bool force) {
      bool tx = force;
    
      si7021_env data = humiditySensor.getHumidityAndTemperature();
      
      float temperature = data.celsiusHundredths / 100.0;
      DEBUG_PRINT("T: ");DEBUG_PRINTLN(temperature);
      float diffTemp = abs(lastTemperature - temperature);
      DEBUG_PRINT(F("TempDiff :"));DEBUG_PRINTLN(diffTemp);
      if (diffTemp > TEMP_TRANSMIT_THRESHOLD || tx) {
        send(msgTemp.set(temperature,1));
        lastTemperature = temperature;
        measureCount = 0;
        DEBUG_PRINTLN("T sent!");
      }
      
      int humidity = data.humidityPercent;
      DEBUG_PRINT("H: ");DEBUG_PRINTLN(humidity);
      raHum.addValue(humidity);
      humidity = raHum.getAverage();  // MA sample imply reasonable fast sample frequency
      float diffHum = abs(lastHumidity - humidity);  
      DEBUG_PRINT(F("HumDiff  :"));DEBUG_PRINTLN(diffHum); 
      if (diffHum > HUMI_TRANSMIT_THRESHOLD || tx) {
        send(msgHum.set(humidity));
        lastHumidity = humidity;
        measureCount = 0;
        DEBUG_PRINTLN("H sent!");
      }
    
    }
    
    

  • Mod

    Did you try it?



  • not yet ;-) Will try it later....



  • tried now the Sketch... Seems that something is wrong with the sensor.

     __  __       ____
    |  \/  |_   _/ ___|  ___ _ __  ___  ___  _ __ ___
    | |\/| | | | \___ \ / _ \ `_ \/ __|/ _ \| `__/ __|
    | |  | | |_| |___| |  __/ | | \__ \  _  | |  \__ \
    |_|  |_|\__, |____/ \___|_| |_|___/\___/|_|  |___/
            |___/                      2.2.0-beta
    
    0;255;3;0;9;53 MCO:BGN:INIT GW,CP=RRNGA---,VER=2.2.0-beta
    0;255;3;0;9;83 TSM:INIT
    0;255;3;0;9;92 TSF:WUR:MS=0
    0;255;3;0;9;100 TSM:INIT:TSP OK
    0;255;3;0;9;108 TSM:INIT:GW MODE
    0;255;3;0;9;118 TSM:READY:ID=0,PAR=0,DIS=0
    0;255;3;0;9;129 MCO:REG:NOT NEEDED
    0;255;3;0;14;Gateway startup complete.
    0;255;0;0;18;2.2.0-beta
    0;255;3;0;11;Gateway_SI7021
    0;255;3;0;12;1.0 161017
    0;0;0;0;6;
    0;1;0;0;7;
    0;255;3;0;9;159 MCO:BGN:STP
    Serial started
    Node and 2 children presented.
    0;255;3;0;9;684 MCO:BGN:INIT OK,TSP=1
    

    Also the issue with the attached sensor blocks completly the Gateway function.Means that the Gateway didn't receive anything. Is it possible to prevent such issue? what I mean, is it possible to seperate both functions in the Sketch in that way If something is wrong with the sensor, the Gateway can still operate?
    THX
    Markus


  • Mod

    add some more serial prints around to see where the code stops



  • @gohan how can i do this ? :-(


  • Mod

    Look at the "DEBUG_PRINTLN" you have in your code, add some of those where you see there aren't.



  • the Code stops here

    si7021_env data = humiditySensor.getHumidityAndTemperature();
    

    Anything wrong with the sensor I guess. But how can I handle such things?


  • Mod

    did you try an example sketch from the library to see if you can read the values correctly?



  • the sensor conenction was the Problem at the end. Changed SCD and SCL and now it Looks good so far. At the Moment is the Gateway not connected to a Controller. Hope the sensor will be then also send the values...

     __  __       ____
    |  \/  |_   _/ ___|  ___ _ __  ___  ___  _ __ ___
    | |\/| | | | \___ \ / _ \ `_ \/ __|/ _ \| `__/ __|
    | |  | | |_| |___| |  __/ | | \__ \  _  | |  \__ \
    |_|  |_|\__, |____/ \___|_| |_|___/\___/|_|  |___/
            |___/                      2.2.0-beta
    
    0;255;3;0;9;53 MCO:BGN:INIT GW,CP=RRNGA---,VER=2.2.0-beta
    0;255;3;0;9;83 TSM:INIT
    0;255;3;0;9;92 TSF:WUR:MS=0
    0;255;3;0;9;100 TSM:INIT:TSP OK
    0;255;3;0;9;108 TSM:INIT:GW MODE
    0;255;3;0;9;118 TSM:READY:ID=0,PAR=0,DIS=0
    0;255;3;0;9;129 MCO:REG:NOT NEEDED
    0;255;3;0;14;Gateway startup complete.
    0;255;0;0;18;2.2.0-beta
    0;255;3;0;11;Gateway_SI7021
    0;255;3;0;12;1.0 161017
    0;0;0;0;6;
    0;1;0;0;7;
    0;255;3;0;9;159 MCO:BGN:STP
    Serial started
    Node and 2 children presented.
    0;255;3;0;9;684 MCO:BGN:INIT OK,TSP=1
    Loop1 started
    T: 21.49
    TempDiff :121.49
    0;0;1;0;0;21.5
    T sent!
    H: 64
    HumDiff  :164.00
    0;1;1;0;1;64
    H sent!
    Before first sleep
    0;255;3;0;9;733 MCO:SLP:MS=300000,SMS=0,I1=255,M1=255,I2=255,M2=255
    0;255;3;0;9;768 !MCO:SLP:REP
    0;255;3;0;9;124672 TSF:MSG:READ,106-106-0,s=0,c=1,t=1,pt=7,l=5,sg=0:63.3
    106;0;1;0;1;63.3
    0;255;3;0;9;124702 TSF:MSG:READ,106-106-0,s=255,c=3,t=0,pt=1,l=1,sg=0:90
    106;255;3;0;0;90
    0;255;3;0;9;124735 TSF:MSG:READ,106-106-0,s=3,c=1,t=38,pt=7,l=5,sg=0:3.71
    106;3;1;0;38;3.71
    After first sleep
    Loop1 started
    T: 21.64
    TempDiff :0.15
    H: 65
    HumDiff  :0.00
    Before first sleep
    0;255;3;0;9;300797 MCO:SLP:MS=300000,SMS=0,I1=255,M1=255,I2=255,M2=255
    0;255;3;0;9;300830 !MCO:SLP:REP
    0;255;3;0;9;428443 TSF:MSG:READ,106-106-0,s=255,c=3,t=0,pt=1,l=1,sg=0:90
    106;255;3;0;0;90
    0;255;3;0;9;428476 TSF:MSG:READ,106-106-0,s=3,c=1,t=38,pt=7,l=5,sg=0:3.72
    106;3;1;0;38;3.72
    

    But how can I prevent the Situation that a defect or missing sensor on the Gateway blocks also the Gateway function ?

    Thanks

    Markus


  • Mod

    You need to make a check in the code that if the sensor read is fails it should keep going



  • @gohan ;-) will try it.... -> Learning leasson... :-)


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.