ESPHome and SHT10 Temperature Humidity Sensor

I’ve got some ESP8266 based sensors that I was using with my Vera and I’m trying to convert them to ESPHome. I’m using Sonoff DEV boards and their SHT10 temperature/humidity brick. All that is fine and I know which pins are being used, etc., but I can’t find any configuration for the SHT1x sensors. I’ve done all kinds of searches but can’t find anything. Is there something that’s compatible that people use? It’s an I2C device. I was using ESPEasy before which has native support for those sensors.

If nobody has anything, is there an example of how I might read it myself manually?

1 Like

Thanks! This is helpful. I was just reading about how to create custom sensors. Appears someone has already done it.

So, in the above example, the person is copying the arduino library SHT1x to the local directory. That compiles just fine, but you can also add that library to the libraries: array in the configuration file, as in:

esphome:
  name: sonoff_dev_ths1
  platform: ESP8266
  board: esp8285

  includes:
    - ./sht1x/sht1x.h
    - ./sht1x/sht1x.cpp

  libraries:
    - SHT1x

However, I think I see why the other person brought it in locally. If you compile, you see that platformio actually has 5 libraries with that exact name, “SHT1x”. Most are some sort of fork of the original. Anyway, they are differentiated by a unique id at platformio. Is there a way to select a particular version in the configuration file? Maybe something like:

  libraries:
    - SHT1x
      id: 85

I don’t see anything about that in the docs. Might be a good feature request if there’s no way to do it currently. What happens now is it chooses the first library of the 5 by default when building the sensor.

Looking at the code, it apparently does look for a version appended to the name of the library, such as:

  libraries:
  - [email protected]+sha.be7042c3e3

but you can’t actually put the id of the library. I’m not sure if it’s working or not since this is the same library it installed by default anyway and it still shows there are 5 choices and it’s choosing the first one. The format appears to be correct, because putting anything else there except nothing will fail the compile.

1 Like

Dear,
it is still possible to use SHT temperature& humidity sensor with latest version EspHome?
I tried to update my old configuration and got such error:
To be honest I don’t change a single line related to sht1x.

Compiling /data/sht1x/.pioenvs/sht1x/src/SHT1x.cpp.o
Compiling /data/sht1x/.pioenvs/sht1x/src/main.cpp.o
Compiling /data/sht1x/.pioenvs/sht1x/src/sht1x.cpp.o
Compiling /data/sht1x/.pioenvs/sht1x/lib975/ESPAsyncTCP-esphome/ESPAsyncTCP.cpp.o
In file included from src/SHT1x.cpp:1:
src/SHT1x.h:25:17: error: 'GPIOPin' has not been declared
   25 |   void set_data(GPIOPin *pin) { data = pin; }
      |                 ^~~~~~~
src/SHT1x.h:26:18: error: 'GPIOPin' has not been declared
   26 |   void set_clock(GPIOPin *pin) { clock = pin; }
      |                  ^~~~~~~
src/SHT1x.h:29:3: error: 'GPIOPin' does not name a type
   29 |   GPIOPin *data;
      |   ^~~~~~~
src/SHT1x.h:30:3: error: 'GPIOPin' does not name a type
   30 |   GPIOPin *clock;
      |   ^~~~~~~
src/SHT1x.h:32:3: error: 'SHT1x' does not name a type
   32 |   SHT1x *sht1x_;
      |   ^~~~~
src/SHT1x.h: In constructor 'esphome::sht1x::SHT1XSensor::SHT1XSensor(int, int)':
src/SHT1x.h:15:24: error: expected type-specifier before 'GPIOPin'
   15 |     this->set_data(new GPIOPin(data, INPUT, false));
      |                        ^~~~~~~
src/SHT1x.h:16:25: error: expected type-specifier before 'GPIOPin'
   16 |     this->set_clock(new GPIOPin(clock, INPUT, false));
      |                         ^~~~~~~
src/SHT1x.h: In member function 'void esphome::sht1x::SHT1XSensor::set_data(int*)':
src/SHT1x.h:25:33: error: 'data' was not declared in this scope; did you mean 'std::data'?
   25 |   void set_data(GPIOPin *pin) { data = pin; }
      |                                 ^~~~
      |                                 std::data
In file included from /data/cache/platformio/packages/toolchain-xtensa/xtensa-lx106-elf/include/c++/10.3.0/string:54,
                 from src/esphome/core/component.h:3,
                 from src/SHT1x.h:3,
                 from src/SHT1x.cpp:1:
/data/cache/platformio/packages/toolchain-xtensa/xtensa-lx106-elf/include/c++/10.3.0/bits/range_access.h:319:5: note: 'std::data' declared here
  319 |     data(initializer_list<_Tp> __il) noexcept
      |     ^~~~
In file included from src/SHT1x.cpp:1:
src/SHT1x.h: In member function 'void esphome::sht1x::SHT1XSensor::set_clock(int*)':
src/SHT1x.h:26:34: error: 'clock' was not declared in this scope; did you mean 'clock_t'?
   26 |   void set_clock(GPIOPin *pin) { clock = pin; }
      |                                  ^~~~~
      |                                  clock_t
In file included from src/esphome/components/sensor/sensor.h:3,
                 from src/SHT1x.h:4,
                 from src/SHT1x.cpp:1:
src/SHT1x.cpp: In member function 'virtual void esphome::sht1x::SHT1XSensor::setup()':
src/SHT1x.cpp:13:51: error: 'class esphome::sht1x::SHT1XSensor' has no member named 'data'
   13 |   ESP_LOGCONFIG(TAG, "Data pin is '%d'...", this->data->get_pin());
      |                                                   ^~~~
src/esphome/core/log.h:94:90: note: in definition of macro 'esph_log_config'
   94 |   esp_log_printf_(ESPHOME_LOG_LEVEL_CONFIG, tag, __LINE__, ESPHOME_LOG_FORMAT(format), ##__VA_ARGS__)
      |                                                                                          ^~~~~~~~~~~
src/SHT1x.cpp:13:3: note: in expansion of macro 'ESP_LOGCONFIG'
   13 |   ESP_LOGCONFIG(TAG, "Data pin is '%d'...", this->data->get_pin());
      |   ^~~~~~~~~~~~~
src/SHT1x.cpp:14:52: error: 'class esphome::sht1x::SHT1XSensor' has no member named 'clock'
   14 |   ESP_LOGCONFIG(TAG, "Clock pin is '%d'...", this->clock->get_pin());
      |                                                    ^~~~~
src/esphome/core/log.h:94:90: note: in definition of macro 'esph_log_config'
   94 |   esp_log_printf_(ESPHOME_LOG_LEVEL_CONFIG, tag, __LINE__, ESPHOME_LOG_FORMAT(format), ##__VA_ARGS__)
      |                                                                                          ^~~~~~~~~~~
src/SHT1x.cpp:14:3: note: in expansion of macro 'ESP_LOGCONFIG'
   14 |   ESP_LOGCONFIG(TAG, "Clock pin is '%d'...", this->clock->get_pin());
      |   ^~~~~~~~~~~~~
src/SHT1x.cpp:15:9: error: 'class esphome::sht1x::SHT1XSensor' has no member named 'sht1x_'
   15 |   this->sht1x_ = new SHT1x(this->data->get_pin(), this->clock->get_pin());
      |         ^~~~~~
src/SHT1x.cpp:15:22: error: expected type-specifier before 'SHT1x'
   15 |   this->sht1x_ = new SHT1x(this->data->get_pin(), this->clock->get_pin());
      |                      ^~~~~
src/SHT1x.cpp: In member function 'virtual void esphome::sht1x::SHT1XSensor::update()':
src/SHT1x.cpp:20:22: error: 'class esphome::sht1x::SHT1XSensor' has no member named 'sht1x_'
   20 |   float temp = this->sht1x_->readTemperatureC();
      |                      ^~~~~~
src/SHT1x.cpp:24:26: error: 'class esphome::sht1x::SHT1XSensor' has no member named 'sht1x_'
   24 |   float humidity = this->sht1x_->readHumidity();
      |                          ^~~~~~
*** [/data/sht1x/.pioenvs/sht1x/src/SHT1x.cpp.o] Error 1
In file included from src/sht1x.h:5,
                 from src/sht1x.cpp:1:
src/SHT1x.h:25:17: error: 'GPIOPin' has not been declared
   25 |   void set_data(GPIOPin *pin) { data = pin; }
      |                 ^~~~~~~
src/SHT1x.h:26:18: error: 'GPIOPin' has not been declared
   26 |   void set_clock(GPIOPin *pin) { clock = pin; }
      |                  ^~~~~~~
src/SHT1x.h:29:3: error: 'GPIOPin' does not name a type
   29 |   GPIOPin *data;
      |   ^~~~~~~
src/SHT1x.h:30:3: error: 'GPIOPin' does not name a type
   30 |   GPIOPin *clock;
      |   ^~~~~~~
src/SHT1x.h:32:3: error: 'SHT1x' does not name a type
   32 |   SHT1x *sht1x_;
      |   ^~~~~
src/SHT1x.h: In constructor 'esphome::sht1x::SHT1XSensor::SHT1XSensor(int, int)':
src/SHT1x.h:15:24: error: expected type-specifier before 'GPIOPin'
   15 |     this->set_data(new GPIOPin(data, INPUT, false));
      |                        ^~~~~~~
src/SHT1x.h:16:25: error: expected type-specifier before 'GPIOPin'
   16 |     this->set_clock(new GPIOPin(clock, INPUT, false));
      |                         ^~~~~~~
src/SHT1x.h: In member function 'void esphome::sht1x::SHT1XSensor::set_data(int*)':
src/SHT1x.h:25:33: error: 'data' was not declared in this scope; did you mean 'std::data'?
   25 |   void set_data(GPIOPin *pin) { data = pin; }
      |                                 ^~~~
      |                                 std::data
In file included from /data/cache/platformio/packages/toolchain-xtensa/xtensa-lx106-elf/include/c++/10.3.0/string:54,
                 from src/esphome/core/component.h:3,
                 from src/sht1x.h:3,
                 from src/sht1x.cpp:1:
/data/cache/platformio/packages/toolchain-xtensa/xtensa-lx106-elf/include/c++/10.3.0/bits/range_access.h:319:5: note: 'std::data' declared here
  319 |     data(initializer_list<_Tp> __il) noexcept
      |     ^~~~
In file included from src/sht1x.h:5,
                 from src/sht1x.cpp:1:
src/SHT1x.h: In member function 'void esphome::sht1x::SHT1XSensor::set_clock(int*)':
src/SHT1x.h:26:34: error: 'clock' was not declared in this scope; did you mean 'clock_t'?
   26 |   void set_clock(GPIOPin *pin) { clock = pin; }
      |                                  ^~~~~
      |                                  clock_t
In file included from src/sht1x.cpp:1:
src/sht1x.h: At global scope:
src/sht1x.h:11:7: error: redefinition of 'class esphome::sht1x::SHT1XSensor'
   11 | class SHT1XSensor : public sensor::Sensor, public PollingComponent {
      |       ^~~~~~~~~~~
In file included from src/sht1x.h:5,
                 from src/sht1x.cpp:1:
src/SHT1x.h:11:7: note: previous definition of 'class esphome::sht1x::SHT1XSensor'
   11 | class SHT1XSensor : public sensor::Sensor, public PollingComponent {
      |       ^~~~~~~~~~~
In file included from src/esphome/components/sensor/sensor.h:3,
                 from src/sht1x.h:4,
                 from src/sht1x.cpp:1:
src/sht1x.cpp: In member function 'virtual void esphome::sht1x::SHT1XSensor::setup()':
src/sht1x.cpp:13:51: error: 'class esphome::sht1x::SHT1XSensor' has no member named 'data'
   13 |   ESP_LOGCONFIG(TAG, "Data pin is '%d'...", this->data->get_pin());
      |                                                   ^~~~
src/esphome/core/log.h:94:90: note: in definition of macro 'esph_log_config'
   94 |   esp_log_printf_(ESPHOME_LOG_LEVEL_CONFIG, tag, __LINE__, ESPHOME_LOG_FORMAT(format), ##__VA_ARGS__)
      |                                                                                          ^~~~~~~~~~~
src/sht1x.cpp:13:3: note: in expansion of macro 'ESP_LOGCONFIG'
   13 |   ESP_LOGCONFIG(TAG, "Data pin is '%d'...", this->data->get_pin());
      |   ^~~~~~~~~~~~~
src/sht1x.cpp:14:52: error: 'class esphome::sht1x::SHT1XSensor' has no member named 'clock'
   14 |   ESP_LOGCONFIG(TAG, "Clock pin is '%d'...", this->clock->get_pin());
      |                                                    ^~~~~
src/esphome/core/log.h:94:90: note: in definition of macro 'esph_log_config'
   94 |   esp_log_printf_(ESPHOME_LOG_LEVEL_CONFIG, tag, __LINE__, ESPHOME_LOG_FORMAT(format), ##__VA_ARGS__)
      |                                                                                          ^~~~~~~~~~~
src/sht1x.cpp:14:3: note: in expansion of macro 'ESP_LOGCONFIG'
   14 |   ESP_LOGCONFIG(TAG, "Clock pin is '%d'...", this->clock->get_pin());
      |   ^~~~~~~~~~~~~
src/sht1x.cpp:15:9: error: 'class esphome::sht1x::SHT1XSensor' has no member named 'sht1x_'
   15 |   this->sht1x_ = new SHT1x(this->data->get_pin(), this->clock->get_pin());
      |         ^~~~~~
src/sht1x.cpp:15:22: error: expected type-specifier before 'SHT1x'
   15 |   this->sht1x_ = new SHT1x(this->data->get_pin(), this->clock->get_pin());
      |                      ^~~~~
src/sht1x.cpp: In member function 'virtual void esphome::sht1x::SHT1XSensor::update()':
src/sht1x.cpp:20:22: error: 'class esphome::sht1x::SHT1XSensor' has no member named 'sht1x_'
   20 |   float temp = this->sht1x_->readTemperatureC();
      |                      ^~~~~~
src/sht1x.cpp:24:26: error: 'class esphome::sht1x::SHT1XSensor' has no member named 'sht1x_'
   24 |   float humidity = this->sht1x_->readHumidity();
      |                          ^~~~~~
*** [/data/sht1x/.pioenvs/sht1x/src/sht1x.cpp.o] Error 1
In file included from src/main.cpp:25:
src/SHT1x.h:32:3: error: 'SHT1x' does not name a type
   32 |   SHT1x *sht1x_;
      |   ^~~~~
src/SHT1x.h: In constructor 'esphome::sht1x::SHT1XSensor::SHT1XSensor(int, int)':
src/SHT1x.h:15:50: error: invalid new-expression of abstract class type 'esphome::GPIOPin'
   15 |     this->set_data(new GPIOPin(data, INPUT, false));
      |                                                  ^
In file included from src/esphome/core/hal.h:4,
                 from src/esphome/core/application.h:8,
                 from src/esphome/components/api/api_connection.h:4,
                 from src/esphome.h:3,
                 from src/main.cpp:3:
src/esphome/core/gpio.h:50:7: note:   because the following virtual functions are pure within 'esphome::GPIOPin':
   50 | class GPIOPin {
      |       ^~~~~~~
src/esphome/core/gpio.h:52:16: note:     'virtual void esphome::GPIOPin::setup()'
   52 |   virtual void setup() = 0;
      |                ^~~~~
src/esphome/core/gpio.h:54:16: note:     'virtual void esphome::GPIOPin::pin_mode(esphome::gpio::Flags)'
   54 |   virtual void pin_mode(gpio::Flags flags) = 0;
      |                ^~~~~~~~
src/esphome/core/gpio.h:56:16: note:     'virtual bool esphome::GPIOPin::digital_read()'
   56 |   virtual bool digital_read() = 0;
      |                ^~~~~~~~~~~~
src/esphome/core/gpio.h:58:16: note:     'virtual void esphome::GPIOPin::digital_write(bool)'
   58 |   virtual void digital_write(bool value) = 0;
      |                ^~~~~~~~~~~~~
src/esphome/core/gpio.h:60:23: note:     'virtual std::string esphome::GPIOPin::dump_summary() const'
   60 |   virtual std::string dump_summary() const = 0;
      |                       ^~~~~~~~~~~~
In file included from src/main.cpp:25:
src/SHT1x.h:16:52: error: invalid new-expression of abstract class type 'esphome::GPIOPin'
   16 |     this->set_clock(new GPIOPin(clock, INPUT, false));
      |                                                    ^
*** [/data/sht1x/.pioenvs/sht1x/src/main.cpp.o] Error 1
========================= [FAILED] Took 10.45 seconds =========================

thanks in advance

greetings
woojtekk

@tom_l & @brucehvn is it still possible to use sth10 somehow? tried your suggestions but getting bunch of errors, same as @woojtekk

I’m still using it. But in my sensor module, I had to remove any reference to the GPIOPin class and just hard code pin numbers to get it to compile. Here’s how I’m getting it to work:

SHT1XSensor.h

#pragma once

#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/components/sensor/sensor.h"
#include "SHT1x.h"

namespace esphome {
namespace sht1xsensor {

/// This class implements support for 
class SHT1XSensor : public sensor::Sensor, public PollingComponent {
 public:
  SHT1XSensor() : PollingComponent(15000) { }
  SHT1XSensor(int data, int clock) : PollingComponent(15000) { 
    this->set_data(data);
    this->set_clock(clock);
}

  Sensor *temperature_sensor = new Sensor();
  Sensor *humidity_sensor = new Sensor();
  // ========== INTERNAL METHODS ==========
  // (In most use cases you won't need these)
  void setup() override;
  void update() override;
  void set_data(int pin) { data = pin; }
  void set_clock(int pin) { clock = pin; }

 protected:
  int data;
  int clock;

  SHT1x *sht1x_;
};

}  // namespace sht1xsensor
}  // namespace esphome

SHT1XSensor.cpp

#include "SHT1XSensor.h"
#include "esphome/core/log.h"
namespace esphome {
namespace sht1xsensor {

#define MIN_TEMP -40
#define MAX_TEMP 254

static const char *TAG = "sht1xsensor.sensor";

void SHT1XSensor::setup() {
  ESP_LOGCONFIG(TAG, "Setting up SHT1X '%s'...", this->name_.c_str());
  ESP_LOGCONFIG(TAG, "Data pin is '%d'...", this->data);
  ESP_LOGCONFIG(TAG, "Clock pin is '%d'...", this->clock);
  this->sht1x_ = new SHT1x(this->data, this->clock);
  ESP_LOGCONFIG(TAG, "Done setting up SHT1X '%s'...", this->name_.c_str());
}

void SHT1XSensor::update() {
  float temp = this->sht1x_->readTemperatureF();
  if (temp >= MIN_TEMP && temp <= MAX_TEMP) {
    this->temperature_sensor->publish_state(temp);
  }
  float humidity = this->sht1x_->readHumidity();
  if (humidity >= 0 && humidity <= 100) {
    this->humidity_sensor->publish_state(humidity);
  }
}
}  // namespace sht1xsensor
}  // namespace esphome

My ESPHome configuration (relevant parts)

esphome:
  name: sonoff-dev-ths1
  platform: ESP8266
  board: esp01_1m

  includes:
    - SHT1XSensor/SHT1XSensor.h
    - SHT1XSensor/SHT1XSensor.cpp

  libraries:
    - "practicalarduino/[email protected]+sha.be7042c3e3"

wifi:
# Clipped for security purposes

output:
  - platform: gpio
    pin: 13
    inverted: True
    id: blue_led

sensor:
  - platform: custom
    lambda: |-
      auto sd_ths1_sensor = new esphome::sht1xsensor::SHT1XSensor(4, 5);
      App.register_component(sd_ths1_sensor);
      return {sd_ths1_sensor->temperature_sensor, sd_ths1_sensor->humidity_sensor};
    sensors:
    - name: "Workshed Temperature Sensor"
      unit_of_measurement: °F
      accuracy_decimals: 1
    - name: "Workshed Humidity Sensor"
      unit_of_measurement: "%"
      accuracy_decimals: 1
      on_value:
        then:
          - output.turn_on: blue_led
          - delay: 500ms
          - output.turn_off: blue_led
1 Like

Hi,
@brucehvn @typeonegative
It’s working - at least I can compile it under raspberry pi 4.

before (previous version) it was possible to compile under linux on pc and problems appeared when i tried to use raspberry pi.

Anyway, thanks for the update.

Greetings
Wojtek Z.

I made an external component for this

external_components:
  - source: github://landonr/esphome-components
    components: [ SHT1XSensor ]

SHT1XSensor:
  update_interval: 10s
  data_pin: 22
  clock_pin: 23
  humidity: 
    id: humidity_sensor
    internal: false
  temperature: 
    id: temperature_sensor
    internal: false
1 Like