[SOLVED] ds18b20 vs si7021 loss of granularity in measurement

  • I've got two nodes sitting right next to each other taking measurements every 3-4 minutes and I'm finding the si7021 doesn't present a very fine-grained measurement like the dallas:
    The green line is the dallas sensor and the red line is the si7021. How do I get the si7021 to behave more like the dallas?
    as you can see I'm getting temperatures in steps greater than .5 degrees fahrenheit.

    The si7021 is using @NeverDie round board with this code:

    // SUMMARY: This demo sketch runs on MultiSensor Version 7 board with an I2C Si7021 module to transmit temperature, humidity, and battery voltage to a MySensors gateway using MySensors protocols.
    // Note: because this is a passive node, node ID must be set manually to a unique sensor node ID:
    #define MY_NODE_ID 128  // Passive mode requires static node ID
     * 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-2017 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.
     * Version 1.0 - tekka
     * Passive node example: This is a passive & independent reporting node
    // This demo sketch uses the LowPowerLab SI7021 library and also some of its sample code:  https://github.com/LowPowerLab/SI7021
    // This demo sketch also draws from the MySensor's example MockMySensors sketch.
    // This demo sketch also draws from some of the code posted by smilvert here: https://forum.mysensors.org/topic/7961/why-do-passive-nodes-need-to-set-their-node-id-manually/14
    #define SHORT_WAIT 50
    #include <Wire.h>
    #include <SI7021.h>  //from LowPowerLab:  https://github.com/LowPowerLab/SI7021
    SI7021 sensor;
    // Enable debug prints
    #define MY_DEBUG
    // Enable passive mode
    #define MY_PASSIVE_NODE
    // Enable and select radio type attached
    //#define MY_RADIO_NRF24
    #define MY_RADIO_NRF5_ESB
    //#define MY_RADIO_RFM69
    //#define MY_RADIO_RFM95
    #include <MySensors.h>
    #define CHILD_ID_TEMP 0  //definitions contributed by smilvert (see above credit)
    #define CHILD_ID_HUM 1
    // Initialize general message
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    #define ID_S_MULTIMETER        28
    float batteryVoltage=0;  
    float temperature=0;
    int humidity=0;
    void blinkityBlink(uint8_t repetitions) {
      for (int x=0;x<repetitions;x++) {
        if (x<(repetitions-1)) {  //skip waiting at the end of the final repetition
    void setup()
      blinkityBlink(5);  //signify power-up and start of operations
      NRF_CLOCK->TASKS_HFCLKSTART=1;  //start the high frequency crystal oscillator clock
      while (!(NRF_CLOCK->EVENTS_HFCLKSTARTED)) {} //wait until high frequency crystal oscillator clock is up to speed and working
    void presentation()
    	// Send the sketch version information to the gateway and controller
    	sendSketchInfo("Passive node", "1.0");
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_TEMP, S_TEMP);
      present(CHILD_ID_HUM, S_HUM);
      present(ID_S_MULTIMETER,S_MULTIMETER,"Electric Station");
    void loop() {
        // get humidity and temperature in one shot, saves power because sensor takes temperature when doing humidity anyway
        si7021_env data = sensor.getHumidityAndTemperature();
        temperature = data.celsiusHundredths/100;
        // humidity is an integer representing percent
        humidity = data.humidityBasisPoints/100;
        sleep(60000);  //sleep for one minute to recover voltage after temperature and humidity measurements.
        sleep(60000);  //sleep for 60 seconds
        batteryVoltage=((float)hwCPUVoltage())/1000.0;  //take voltage measurement after transmission to hopefully measure lowest voltage that occurs.
        sleep(60000);  //sleep for one minute
        send(msg_S_MULTIMETER_V_VOLTAGE.set(batteryVoltage,3));  //send battery voltage with 3 decimal places
        sleep(60000);  //sleep for 60 seconds

  • @waspie said in ds18b20 vs si7021 loss of granularity in measurement:

    temperature = data.celsiusHundredths/100;

    In my opinion does the above line not cohere with the statement that the steps are greater than .5 degrees fahrenheit.

    Have you tried using:

    temperature = data.getFahrenheitHundredths/100;

    and what was the result.

    Could it be you've been playing with the examples as provided with the library from LowPowerLab and you accidentally forgot to "turn the heater off"? I'm guessing at the moment, but you could end up with the device being heated up in the range of 70ºC (which is 158 degrees fahrenheit...😬 )



  • @boozz
    That isn't 100% the exact code. I convert the celcius manually so that temp graphed is farhenheit.

    The first 2-3 nodes i put together I didn't know about the ismetric thing going on and I didn't want to go back and reflash those modules so I just make sure to calculate before sending to the GW. Definitely not a heater issue.

  • Mod

    @waspie Seems like you're rounding to full degrees in the line

    temperature = data.celsiusHundredths/100;

    In the si7021 library the si7021_env type is defined as:

    typedef struct si7021_env {
        int celsiusHundredths;
        int fahrenheitHundredths;
        unsigned int humidityBasisPoints;
    } si7021_env;

    so temperature is an integer in 1/100th increments.

    Try converting this integer to float before dividing, like:

    temperature = float(data.celsiusHundredths)/100.0;

  • @yveaux
    thank you, this sounds very promising! I will try it this evening

  • @Yveaux this has resolved it, thank you

  • @Yveaux
    Good to see it solved for @waspie

    Conversion from int (or byte) to float and vise versa is something that often brings me a headache.
    I literaly spend many hours searching for a good guide in via google, but never really found one.

    Are you maybe aware of a good guide how to properly do the conversions between different types (byte from floats etc. without getting involved in memory hungry libraries).



  • Mod

    @boozz this is standard c / c++.
    Any good book on the topic should explain how it works.
    Basically it comes down to when you cast from float to integer that the value will be rounded down and that you will loose any decimals.
    From integer to float will introduce decimals, set to 0.

  • @yveaux
    Thanks for the hint and explanation. I appreciate that!

    I always used the search term: "conversion" (English is not my native language). I tried "casting" in combination with "c#" and I was almost immediately directed to my favorit c++ internet source (cplusplus.com)


    Many thanks! πŸ‘


Log in to reply

Suggested Topics

  • 3
  • 2
  • 2
  • 2
  • 3
  • 2