A place users can post their projects. If you have a small project and would like your own dedicated place to post and have others chat about it then this is your spot.

User avatar
By sancho
#28651 Hi, everybody.
Not sure if someone already attempted this, but I'd like to share my experience.

I'd like to have multiple temperature probes around my house, however I have problem of getting wires to relevant places.

I wanted to use ESP8266 for communication, but that still needs power to operate.
I came up with quite simple (and cheap) solution.

I bought a rather small solar panel with 2W peak power output, connected it to TP4056 battery charger, got a 18650 battery scavenged from old laptop, ESP-01, DS1820 and finally DHT-22.
I had to do some small modifications - the charge resistor on the TP4056 module had to be de-soldered and I had to solder in a new one - bigger. I went with 4.7kOhm to get the charging current to a range between 250 and 300mA. With panel producing 6V and 2W that's around the maximum power output possible.
The ESP would waste the fully-charged 1600mA battery in a day, so I had to use the deep sleep functionality. That means I had to solder a tiny wire to post-sleep-reset-pin and connect it to reset as documented here. I also de-soldered the power led indicator as that would drain the battery and is useless for me.
Next I had to lower the resistor for the 1wire temperature sensor to 1k7 and increase the wait time to 1 second - otherwise the sensor was not able to get enough power for parasitic operation.

I am logging the voltage of the ESP, the temperature of the DS1820 and the temperature and humidity values from DHT-22 sensor to ThingSpeak server.

It works quite nice for more than a week. I had to clean the data on ThingSpeak as the logging structure (field order) was changed.
The logging interval is set to 180 seconds now.

Future improvements:
  • create a webserver after the start with static IP and AP functionality
  • allow maintenance of wifi connection data
  • allow maintenance of logging frequency and ThingSpeak API key
  • allow up to 8 DS1820 sensors on single ESP
  • enable static IP configuration for faster measurement
  • buy some small enclosure and get the module outside
  • try to incorporate light sensor (I2C) and use RX/TX pins for that
Even with DHCP enabled (therefore 4-6 seconds for each measurement and reporting cycle), the old battery is enough to keep the device on overnight and recharge during (cloudy) day.

For anyone interested, here is the BoM:
  • ESP-01 (however, I would recommend using ESP-12 as the deep sleep is MUCH easier there), price 1.97 EUR
  • Solar panel, 6V, 2W for 3.06 EUR
  • TP-4056 charger for 0.52 EUR
  • DS18S20 - I bought 5pcs as it was cheaper as to buy 1 (!!!) and got them for 7.62 EUR, which means 1.53 EUR per 1 piece
  • DHT-22 - again I bought a pack of 2 for 6.32 EUR, which means 3.16 EUR (DHT-11 can also be used, but the accuracy of measurement of humidity will suffer)
  • 18650 battery like this, I got mine for free from old laptop battery, however this is a pack of 2 so 1 would cost 2.46 EUR
  • 18650 battery holder for 0.38 EUR
  • resistor 1k7 and 4k7 - I got mine from resistor set like this, price is less then 0.1 EUR for both
The overall costs are 13.18 EUR.

However the DS1820 can be omitted as the DHT-22 can also measure temperature. But I found DS1820 to be a bit more accurate.

The current source code:
Code: Select all#include <ESP8266WiFi.h>
#include <dht.h>
#include <OneWire.h>

// measuring VCC using analogue input, MUST STAY HERE!
ADC_MODE(ADC_VCC);

// constants
const char* ssid     = "***********";  // use your wifi ssid
const char* password = "***********";  // use your wifi password

const char* tsAPI = "*************";   // use the API key provided by ThingSpeak when you create your own channel
const char* host = "api.thingspeak.com";
const int httpPort = 80;
const char* tsURL = "/update?api_key=";
// field1 = voltage
// field2 = DS1820 temperature
// field3 = DHT temperature
// field4 = DHT humidity

// variables for loop and measurement

// Variables for temperature
unsigned long currentMillis = 0UL;    // main time-counting var
unsigned long tRunLast = 0UL;         // Last time temperature measurement started (for 1wire parasite interval)
unsigned long tInt = 1000UL;          // Interval for temperature measurement
unsigned long tRunLast1w = 0UL;       // Last measurement of 1wire sensor
unsigned long tInt1w = 2000UL;        // Interval of measurement using 1wire sensor
                                      // (increased to 2 seconds for DHT)
unsigned long tWait = 1000UL;         // Interval for 1-wire parasite power stabilization (1 sec)

// Variables for reporting
unsigned long reportRunLast = 0UL;    // time of last report
unsigned long reportInt = 1000UL;     // reporting attempt interval
unsigned long reportTimeout = 10000UL;// timeout for reporting - if unable to measure and send
                                      // temperature in 10 secs, go back to deep sleep
unsigned long sleepInt = 180000UL;    // sleep interval

byte stage = 0;                       // storing measurement stages
byte poradie1w = 0;                   // Storing the last measured temperature sensor ID
byte i;
byte type_s;
byte data[12];
byte addr[8];
float tempDS = -999;                   // last temperature measurement
float tempDHT = -999;                  // last temperature measurement
float humiDHT = -999;                  // last temperature measurement

OneWire  ds(2);  // on pin 2 (a 1.7K resistor is necessary)
dht DHT;
#define DHT22_PIN 0


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Starting setup");
  startWifi();
}

void loop() {
  currentMillis = millis();

  // temperature loop - initial start
  if (stage == 0 && currentMillis - tRunLast >= tInt) {
    // start of temperature measurement (no measurement is running now)
    getTemp1();
    stage = 1;
    tRunLast = currentMillis;
  }
  if (stage == 1 && currentMillis - tRunLast >= tInt1w) {
    // defined interval for 1wire parasite power and measurement over
    // we can measure the temperature now
    getTemp2();
    DHTread();
    stage = 2;
    tRunLast1w = currentMillis;
    tRunLast = currentMillis;
  }
  if (currentMillis - reportRunLast >= reportInt && stage == 2 && wifiStat() == true) {
    Serial.println("Reporting");
    wifiInfo();
    report();
    reportRunLast = currentMillis;
    stage = 3;
  }

  // fix for timeout in measurement/reporting - force sleep
  if (currentMillis - reportRunLast >= reportTimeout) {
    stage = 3;
    Serial.println("Forcing sleep due to timeout");
    Serial.print("Current millis: ");
    Serial.println(currentMillis);
    Serial.print("Report last run: ");
    Serial.println(reportRunLast);
    Serial.print("Report timeout: ");
    Serial.println(reportTimeout);
    reportRunLast = currentMillis;
  }
 
  if (stage == 3) {
    Serial.println("Sleeping for " + String(sleepInt) + "ms");
    ESP.deepSleep(sleepInt * 1000, WAKE_RF_DEFAULT);
  }

}

void startWifi() {
  Serial.println("Connecting to wifi");
  Serial.print("Wifi status: ");
  Serial.println(WiFi.status());

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
}


void wifiInfo() {
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

}


byte wifiStat() {
  return (WiFi.status() == WL_CONNECTED);
}

void getTemp1() {
  Serial.println("Gettemp 1 started");
  if (!ds.search(addr)) {
    ds.reset_search();
    poradie1w = 0;
    return;
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);
  stage = 1;
  tRunLast1w = millis();
}

void getTemp2() {
  Serial.println("Gettemp2 started");
  // the first ROM byte indicates which chip
  type_s = (addr[0] == 0x10) ? 1 : 0;

  ds.reset();
  ds.select(addr);
  ds.write(0xBE);
  for (int i = 0; i < 12; i++) data[i] = ds.read();
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  tempDS = (float)raw / 16.0;
  Serial.print("Temp: ");
  Serial.println(tempDS);
  stage = 2;
  tRunLast1w = millis();
  poradie1w++;
}



void report() {
  Serial.print("Connecting to ");
  Serial.println(host);
  WiFiClient client;
  if (!client.connect(host, httpPort)) {
    Serial.println("Connection failed!!!");
    return;
  }

  String url = String(tsURL) + String(tsAPI) + "&field1=" + String(ESP.getVcc() / 1000.00);
  url += "&field2=" + String(tempDS) + "&field3=" + String(tempDHT) + "&field4=" + String(humiDHT);
  Serial.println(url);
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  delay(100);

  // Read all the lines of the reply from server and print them to Serial
  while (client.available()) {
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }

  Serial.println();
  Serial.println("Closing connection.");
}


void DHTread() {

  // READ DATA
  int chk = DHT.read22(DHT22_PIN);

  switch (chk)
  {
    case DHTLIB_OK:
      tempDHT = DHT.temperature;
      humiDHT = DHT.humidity;
      break;
    default:
      Serial.println("Unknown DHT error");
      break;
  }
}
User avatar
By Hernani Delindro
#31361 Hi, I'm trying to learn how to work with the ESP8266 and I thought your project would be a good start.
I'm just wondering if you could provide a circuit diagram, or at least just a bit more information on how to connect the sensors to the ESP since I've never used them.

Also, are there any changes to the code/circuit if I use an ESP-12?

Thanks!