Notifications
Clear all

Combining example DHT sensor sketch with LowPower lib; save battery


jBo
 jBo
(@jbo)
Trusted Member
Joined: 11 months ago
Posts: 81
Topic starter  

Hi. I was checking out the libraries for temperature and humidity

https://github.com/adafruit/DHT-sensor-library

https://github.com/adafruit/Adafruit_Sensor

I am using DHT11 modules for now, a tiny board with just 3 pins, but this is not I2C version.

I appreciate that the sensor needs a couple of seconds to stabilize between readings. The sketch works fine right out of the box, from the examples provided by those libraries. At this point, though, I wanted to look into reducing power, since I want to put several of these around the garden. I looked into an article by Sparkfun:

Reducing Arduino Power Consumption

I got this to work, though at first there were oddities and problems with the Serial.print() to the Serial Monitor. Sometimes I got complete garbage, even though the baud rate matched what was specified in Serial.begin(9600). Other times it had an odd pause after "Tem", then inserted two spaces for unknown reasons, then continued with "perature."

OK, so using it is a little "sensitive" to the placement of print() and possibly delay(). What I got to work was

delay(1000);

LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

delay(2000);

So I guess my real questions are:

* does anyone else use the LowPower library to save on battery?

* anyone else notice odd interactions with Serial.print() ?

Thank you. John

 

In theory, theory and practice are the same.
In practice, they're different.


Quote
jBo
 jBo
(@jbo)
Trusted Member
Joined: 11 months ago
Posts: 81
Topic starter  

Here's a small follow-up on my little experiment and where this is leading. I've learned quite a bit. One obvious thing I already knew before adapting this sketch is that if I give a special command to reduce power by turning off certain facilities, then those facilities will not be available for the whole duration that I've put the Arduino into idle, deep sleep, power down or whatever other special modes. For example, the ADC_OFF argument turns off analog to digital conversion, so don't depend on values coming in during the 8 seconds (or whatever) it's off. After it is turned back on, I still might insert a small delay to give the ADC a chance to initialize or stabilize. I'm not as clear on that part, but it doesn't hurt to put in a small wait, given that I'm waiting around most of the time anyway. I mean, the temperature changes outdoors, but not that quickly.

One thing I did NOT expect was that this type of battery-saving measure, the LowPower.powerDown() I used, also affects the millis() functions. I read that the powerDown() is not very precise, but close enough. I wanted to see just how much time had elapsed. What actually happened was that my calculation correctly captured the amount of elapsed time from my delay() statements, but not from the time in the powered down state. I guess this means that it shuts down one of the timers, so the millis() function doesn't notice any time elapsed. Here's the sample output, 3 seconds of delay() captured, but not the ~8 seconds of power down.

Temperature: 24.80°C - 76.64°F 
Humidity: 43.00%
3.03 seconds elapsed.

So, learned something. It won't affect the battery-based outdoor deployment. Here's the source code, which I had not included in my first post.

 

 

// DHT Temperature & Humidity Sensor
// Unified Sensor Library Example
// Written by Tony DiCola for Adafruit Industries
// Released under an MIT license.

// REQUIRES the following Arduino libraries:
// - DHT Sensor Library:  https://github.com/adafruit/DHT-sensor-library 
// - Adafruit Unified Sensor Lib:  https://github.com/adafruit/Adafruit_Sensor 

#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>

//2021-08-06 JEB. Downloaded from GitHub, v 1.8.x.
//   https://learn.sparkfun.com/tutorials/reducing-arduino-power-consumption/all 
#include <LowPower.h>


#define DHTPIN 2     // Digital pin connected to the DHT sensor 
// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
// Pin 15 can work but DHT must be disconnected during program upload.

// Uncomment the type of sensor in use:
#define DHTTYPE    DHT11     // DHT 11
//#define DHTTYPE    DHT22     // DHT 22 (AM2302)
//#define DHTTYPE    DHT21     // DHT 21 (AM2301)

// See guide for details on sensor wiring and usage:
//    https://learn.adafruit.com/dht/overview 

DHT_Unified dht(DHTPIN, DHTTYPE);

uint32_t delayMS;
long starttime_ms;


void setup() {
  Serial.begin(9600);
  // Initialize device.
  dht.begin();
  Serial.println(F("DHTxx Unified Sensor Example"));
  // Print temperature sensor details.
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
  Serial.println(F("------------------------------------"));
  Serial.println(F("Temperature Sensor"));
  Serial.print  (F("Sensor Type: ")); Serial.println(sensor.name);
  Serial.print  (F("Driver Ver:  ")); Serial.println(sensor.version);
  Serial.print  (F("Unique ID:   ")); Serial.println(sensor.sensor_id);
  Serial.print  (F("Max Value:   ")); Serial.print(sensor.max_value); Serial.println(F("°C"));
  Serial.print  (F("Min Value:   ")); Serial.print(sensor.min_value); Serial.println(F("°C"));
  Serial.print  (F("Resolution:  ")); Serial.print(sensor.resolution); Serial.println(F("°C"));
  Serial.println(F("------------------------------------"));
  // Print humidity sensor details.
  dht.humidity().getSensor(&sensor);
  Serial.println(F("Humidity Sensor"));
  Serial.print  (F("Sensor Type: ")); Serial.println(sensor.name);
  Serial.print  (F("Driver Ver:  ")); Serial.println(sensor.version);
  Serial.print  (F("Unique ID:   ")); Serial.println(sensor.sensor_id);
  Serial.print  (F("Max Value:   ")); Serial.print(sensor.max_value); Serial.println(F("%"));
  Serial.print  (F("Min Value:   ")); Serial.print(sensor.min_value); Serial.println(F("%"));
  Serial.print  (F("Resolution:  ")); Serial.print(sensor.resolution); Serial.println(F("%"));
  Serial.println(F("------------------------------------"));
  // Set delay between sensor readings based on sensor details.
  //  delayMS = sensor.min_delay / 1000;
  delayMS = 15 * 1000;  //2021-08-05 John Bowen. Don't see the need for reading 1/second.

  starttime_ms = millis();

}

void loop() {
  // Delay between measurements.
  //  delay(delayMS);

  delay(1000);

  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

  delay(2000);
  
  // Get temperature event and print its value.
  sensors_event_t event;
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println(F("Error reading temperature!"));
  }
  else {
    float t_Celsius = event.temperature;
    float t_Fahrenheit = event.temperature * 9 / 5 + 32;
    //    Serial.print(F("t_Celsius: "));
    //    Serial.print(t_Celsius);

    Serial.print(F("Temperature: "));
    Serial.print(t_Celsius);
    Serial.print(F("°C - "));

    Serial.print(t_Fahrenheit);
    Serial.print(F("°F "));
    Serial.println(" ");

  }
  // Get humidity event and print its value.
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println(F("Error reading humidity!"));
  }
  else {
    Serial.print(F("Humidity: "));
    Serial.print(event.relative_humidity);
    Serial.println(F("%"));
  }

  float elapsed_s = (millis() - starttime_ms) / 1000.0;

  Serial.print(elapsed_s);
  Serial.println(" seconds elapsed.");

  starttime_ms = millis();


} //end of loop()

 

 

 

This post was modified 3 months ago by jBo

In theory, theory and practice are the same.
In practice, they're different.


ReplyQuote