Search code examples
c++arduinoi2c

Soft I²C ping function


I am using a soft I²C implementation to read a set of Sensirion SHT21 sensors. I am trying to figure out a way of having the sensors answer to see if they are actually connected to the device. I am using the Arduino which means all my code is C/C++

The libraries I am using are here.

The code used to read the sensors is the following:

#include <Ports.h>
#include <PortsSHT21.h>

//Define soft I²C channels for three sensors
SHT21 hsensor2 (2); // pins A1 and D5 - Sensor 2

//define variables for temp data
float h, t;

void setup() {}

void loop()
{
    // Get data from sensor soft I²C
    hsensor2.measure(SHT21::HUMI);
    hsensor2.measure(SHT21::TEMP);
    hsensor2.calculate(h, t);
    float hum2 = (h);
    float temp2 = (t);
}

Solution

  • The large code block is the code for the measure() function. Notice that it returns 0 at one point without performing a connReset(). This should be a way to detect a valid device such as ...

    bool hasHUMI;
    if (hsensor2.measure(SHT21::HUMI))
    {
      hasHUMI=true;
    }
    

    or

    if (hsensor2.measure(SHT21::HUMI) && hsensor2.measure(SHT21::TEMP))
    {
     hsensor2.calculate(h, t); 
     float hum2 = (h); 
     float temp2 = (t);    
    }
    

    or

    Your code should be clearing h and t to 0 before making the read so that you can test for valid values. Like this...

    void loop() 
    { 
        h=0.00f;
        t=0.00f;
        // Get data from sensor soft I²C 
        hsensor2.measure(SHT21::HUMI); 
        hsensor2.measure(SHT21::TEMP); 
        hsensor2.calculate(h, t); 
        float hum2 = (h); 
        float temp2 = (t); 
        if (h>0) {
        }
        if (t>0) {
        }
    } 
    

    If not then you could make (copy) your own version of the measure() function that tests for valid return value in meas[type]. You would need to set meas[type] to a known invalid value before the read (such as 0).

    uint8_t SHT21::measure(uint8_t type, void (*delayFun)()) {
    
        start();
        writeByte(type == TEMP? MEASURE_TEMP : MEASURE_HUMI)
    
        for (uint8_t i = 0; i < 250; ++i) {
            if (!digiRead()) {
                meas[type] = readByte(1) << 8;
                meas[type] |= readByte(1);
                uint8_t flipped = 0;
    
                for (uint8_t j = 0x80; j != 0; j >>= 1) {
                    flipped >>= 1;
                }
    
                if (readByte(0) != flipped)
                    break;
    
                return 0;
            }
    
    
            if (delayFun)
                delayFun();
            else
                delay(1);
        }
    
        connReset();
        return 1;
    }
    

    You probably know that if you add a method to a library cpp then you also need to add a corresponding prototype to the .h otherwise the arduino will fail to compile your code.

    .cpp

    uint8_t SHT21::measureTest(uint8_t type, void (*delayFun)()) {
    
        }
    

    .h

    uint8_t measureTest(uint8_t type, void (*delayFun)() =0);