GithubHelp home page GithubHelp logo

Comments (23)

spyder0069 avatar spyder0069 commented on July 24, 2024

One other question. I saw in the code it mentions some differences when using a ESP32. I am using the ESP32. Do I need to do anything other than what is in the examples? Or do I have to set it somewhere in my code to tell the library I have a ESP32? Thanks for the help!

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

Do you have a suggested way of handling errors?

That is one of the requirements tensions with Arduino libraries, you want to make them reliable as possible and as small as possible. So sometimes I build it in a library, mostly on request of a user or if a sensor is less reliable.

reading the status should work more or less but it is intended only to work when there is connection.

I am using the sht31 on a probe that can be plugged or unplugged ...

So if I interpret your question, you want an isConnected() method, and maybe even some checks build in on the I2C communication. This latter is mostly implemented without any checking to keep footprint smaller.

I will create a branch with isCOnnected method and would ask you if you can verify it if it meets your needs.

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

I have a 0.2.3 update to do first - it are minor changes only

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

@spyder0069
Please verify the code in the branch isConnected #9
The function is straightforward and there is an example added

Is there a way to to check if the data read back is valid?

In the meanwhile I will check if the low level functions can do some more "connection checking"

from sht31.

spyder0069 avatar spyder0069 commented on July 24, 2024

Thank you for looking into this. I should be able to try the isConnected option later this afternoon.

I was looking through your code and it looks like there is crc in place. Would I use it something like this:

bool crcpassed;
crcpassed=sht.read();
if(crcpassed){
  //data is good go ahead 
  float t =sht.getTemperature();
}

I have two sensors that are separated using the same CLK but different SDA. I have it working with your code by using something similar to this

If(sensorID==0){  
  Wire.endTransmission(true);
  Wire.begin(sensor0,sensorCLK);
  Wire.setClock(100000);
  sht.begin(0x44);
  sht.read();
  float t =sht.getTemperature();
  float h=sht.getHumidity();
  Wire.endTransmission(true);
}else{
  Wire.endTransmission(true);
  Wire.begin(sensor1,sensorCLK);
  Wire.setClock(100000);
  sht.begin(0x44);
  sht.read();
  float t =sht.getTemperature();
  float h=sht.getHumidity();
  Wire.endTransmission(true);
}

Do you see any issues with using it like this? I do also have a i2c clock and lcd on a seperate bus which is why I end the transmissions and then change the pins with the wire.begin statements.

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

TIP: add cpp after the three backquotes and you get syntax highlighting (see your post above)

Yes you can do a CRC check on the data.

bool crcpassed = sht.read(false);  // use slow version which does a CRC check by setting the fast flag to false
if (crcpassed) 
{
  //data is good go ahead 
  float temperature = sht.getTemperature();
  display(temperature); 
}

I'm working on a 0.3.0 version with more checks for errors. Will make a new branch tonight so you can have a sneak preview.

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

Is it not easier to have two sensors with different address?

have a look at this snippet

uint8_t sensorSDA[2] = { 23, 24 }; // make an array out of it.
uint8_t sensorCLK

sht.begin(0x44, sensorSDA[sensorID], sensorCLK);   // This is the ESP32 version for begin which combines some stuff.
Wire.setClock(100000);
bool crcpassed = sht.read(false);  // force crc check.
if (crcpassed) 
{
  float temperature = sht.getTemperature();
  float h = sht.getHumidity();
  // process data
}
else
{
  // handle error
}
// etc...

Tip: spaces makes code more readable

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

One other question. I saw in the code it mentions some differences when using a ESP32. I am using the ESP32. Do I need to do anything other than what is in the examples? Or do I have to set it somewhere in my code to tell the library I have a ESP32? Thanks for the help!

The only difference for the ESP32 is the begin(addr, SD, CLK) call which is not available for the UNO
This call allows the ESP to set the SDA and CLK pins in a single begin() call.

You can see this in the .h and .cpp file of the library, see these lines in SHT31.h

#if defined(ESP8266) || defined(ESP32)
  bool begin(const uint8_t address, uint8_t dataPin, uint8_t clockPin);
#endif

This is called conditional compiling (don't know your level of prog skills)

from sht31.

spyder0069 avatar spyder0069 commented on July 24, 2024

"Is it not easier to have two sensors with different address?"

If you are asking about having a different i2c address like 0x45 and have them on the same bus then in my project that won't work. I have probes made up but they are identical and removable. On the same port I am also choosing to run a sht31 or a ds18b20 one wire probe. The sensors have to be hot swappable with just my code changing between them. I was running the adafruit library but I was seeing errors and having sht31 sensors stop responding. Plus now they have a separate bus library that has to be added and its pretty complex. Your approach seems to be having better results so far.

I did not know about the conditional compiling. That is above my knowledge. I will implement passing the sda/sck to the begin statement instead of changing it manually with the wire. Since I will be switching between the two is it appropriate to do the Wire.endTransmission(true); before the next begin (and is that the correct statement for that process)? I just wonder if I need to shut down any previous .begin before starting a new one. Not sure how the wire library stuff works.

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

Can you post your sketch? (Zip file)
I can have a look at it.

from sht31.

spyder0069 avatar spyder0069 commented on July 24, 2024

example_code.zip

Here is a snip of my routine handling the sensors.

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

TIP: Using CTRL-T in the arduino-IDE does autoformat the code making it more readable. (indents and spaces)

I'll have a look


does it work if the sensors stay connected?

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

a first partial rewrite

void RH_hardreset(byte portid, word resetdelay)
{
  enablemydebug = 1;

  mydebug("SHT31 #" + String(portid) + " hard reset for " + String(resetdelay));

  pinstate = digitalRead(sensorCLK);
  mydebug("sensorCLK state=" + String(pinstate));

  pinMode(sensorCLK, OUTPUT);

  int pin = sensor0;
  if (portid == 1) pin = sensor1;
  mydebug("pin=" + String(pin));

  pinstate = digitalRead(pin);
  mydebug("pinstate=" + String(pinstate));

  pinMode(pin, OUTPUT);
  digitalWrite(pin, LOW);
  if (RHhardresetLOG[portid] < 30000)  RHhardresetLOG[portid] ++;

  digitalWrite(sensorCLK, LOW);
  delay(resetdelay);

  pinMode(pin, INPUT);
  pinMode(sensorCLK, INPUT);
  delay(50);
  enablemydebug = 0;
}

I do not understand why you are toggling the CLK and SDA pins of the I2C bus? to reset it?
Better let the Wire class handle that, it is made for that, Just call Wire.begin() again - I think...

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

To be continued tomorrow.

from sht31.

spyder0069 avatar spyder0069 commented on July 24, 2024

Good tip. It organizes some of my code and some it messes up. To be honest I never expect anyone to look at my code but me. LoL. Currently every works. The CRC check is doing the trick. I've been unplugging and plugging the sensor in and other than the occasional esp message about the bus not liking it my retry routine recovers and gives good data. I just need to let it run and see how it does over time.

TIP:
I am actually running these with just 3 wires. I have a Schottky diode on the scl and feed that to a capacitor that powers the SHT31 so it works like parasite power. :^) I'm sure the heater won't work due to power but I don't have that implemented.

from sht31.

spyder0069 avatar spyder0069 commented on July 24, 2024

When using the adafruit sht library after 2 minutes to about 2 days I would sometimes have a sensor lockup. I have several of these projects running and so far I was only able to recreate it with two devices so I don't 100% have it narrowed down. Basically the sensor stopped responding and software resets didn't make a difference. I needed to cut power to the sensor. Since my project uses the parasite power I have to drop both io to ground and let the cap drain so that the voltage to the sensor goes below its operating threshold and it reboots. Then I can recover from there. Your library seems to be working better. So the RH_hardreset routine is an effort to bandaid what is happening until I can further determine if its something in the library, something with that particular sensor, or something with that particular device. So I am mid experimenting with all this. :^)

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

To be honest I never expect anyone to look at my code but me.

From experience, when you see your code in 3 months time you might need to read it twice (or more)

The CRC check is doing the trick.

So that solves the problem you started this issue for. Good to hear.

TIP:
I am actually running these with just 3 wires. I have a Schottky diode on the scl and feed that to a capacitor that powers the SHT31 so it works like parasite power. :^) I'm sure the heater won't work due to power but I don't have that implemented.

Clever trick, your background is Electrical Engineer?

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

Refactored a bit

  • moved log counter to top and added it to log
  • moved all CLK operation together
  • moved all DATAPIN operations together
  • added a **Wire,begin() ** at the end.
void RH_hardreset(byte portid, word resetdelay)
{
  enablemydebug = 1;

  // LOGGING
  if (RHhardresetLOG[portid] < 30000)  RHhardresetLOG[portid] ++;
  mydebug("SHT31 #" + String(portid) + " hard reset for " + String(resetdelay));
  mydebug("Count: " + String(RHhardresetLOG[portid]) );

  // CLOCK PIN
  pinstate = digitalRead(sensorCLK);
  mydebug("sensorCLK state=" + String(pinstate));
  pinMode(sensorCLK, OUTPUT);
  digitalWrite(sensorCLK, LOW);

  // DATA PIN
  int datapin = sensor0;
  if (portid == 1) datapin = sensor1;
  mydebug("datapin = " + String(datapin));
  pinstate = digitalRead(datapin);
  mydebug("datapin state = " + String(pinstate));
  pinMode(datapin, OUTPUT);
  digitalWrite(datapin, LOW);

  // DRAIN THE CAPACITOR
  delay(resetdelay);
 
  // RESTART WIRE BUS
  mydebug("Restart Wire bus");
  Wire.begin(0x44, datapin, sensorCLK);  // restart Wire bus might be more correct.

  enablemydebug = 0;
}

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

Idea:
What you might add is an analogPort to measure the voltage of the capacitor.
Then the system really can wait until the cap is empty (certain time below a certain voltage)

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

some snippet how I would have setup the other code,
split the large getRH() in some more functions that have a focussed function.
gives a lot less nested if statements

void getRH()
{
  bool done = false;
  int maxRetries = 3;
  int retries = 0;

  while (not done and (retries < maxRetries))
  {
    done = readRH();
    if (not done) RH_hardreset();
    retries++;
  }
  
  if (not done) // means an error
  {
    // handle error
  }
  else
  {
    // display values
  }
}


bool readRH()
{
  enablemydebug = 1;

  Wire.endTransmission(true);
  if (not sht.begin(0x44, datapin, sensorCLK))
  {
    // update errorCode
    return false;
  }
  Wire.setClock(100000);

  if (not sht.isConnected() ) 
  {
    // update errorCode
    mydebug("SHT31 #" + String(RHid) + " Connection: FAILED");
    return false;
  }

  bool crcpassed = sht.read(false);    // use slow version which does a CRC check by setting the fast flag to false
  if (not crcpassed)
  {
    // update errorCode
    mydebug("SHT31 #" + String(RHid) + " CRC: FAILED");
    return false;
  }

  float t = sht.getTemperature();
  mytempdigital[RHid] = t * 10;
  if (displaytype == 0) mytempdigital[RHid] = ((t * 1.8) + 32.0) * 10.0;

  float h = sht.getHumidity(); 
  if (h >= 100)                   // 100% IS A VALID VALUE, NOTE THE LIBRARY CANNOT RETUR VALUES > 100.  (sht31.cpp line 193)
  {
    errorcode[RHid] = 2;  //if a read error this usually is 100 or more so flag it as a failure
  };        
  myRHdigital[RHid] = h;

  mydebug("SHT31 #" + String(RHid) + " CRC: PASSED");
  mydebug("SHT31 #" + String(RHid) + " TEMP: " + String(mytempdigital[RHid] / 10) + "." +  String(mytempdigital[RHid] % 10));
  mydebug("SHT31 #" + String(RHid) + " HUMIDITY: " + String(myRHdigital[RHid]) + "%");

  enablemydebug = 0;
}

from sht31.

spyder0069 avatar spyder0069 commented on July 24, 2024

Everything worked well overnight. Thanks for your help and i will take a look at your suggestions.

"What you might add is an analogPort to measure the voltage of the capacitor."

Can't see the voltage behind the diode. Diode is necessary so that it doesn't cause problems with clk and so that you can run one clk to all sensors and they don't interfere. Time based holding of clock low works since all caps are going to drain close to the same amount of time. Just go on the longer side of the delay to be safe. :^)

Thanks for your time and if you haven't already I think its safe to commit the isConnected changes to your library. Have a great holiday!

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

I will merge the isConnected branch asap

from sht31.

RobTillaart avatar RobTillaart commented on July 24, 2024

Done, 0.2.4 released.

from sht31.

Related Issues (13)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.