Closed RobTillaart closed 4 years ago
The names in the interface above are not 100%
better alternative below, the extra function defines if the other 3 have meaning (user responsible)
bool DHT.usesPowerPin()
{
return (_powerPin != 0xFF);
};
void DHT.powerUp()
{
digitalWrite(_powerPin , HIGH):
}
void DHT.powerDown()
{
digitalWrite(_powerPin , LOW):
}
bool DHT.power();
{
return digitalRead(_powerPin));
} ;
Although the functions are super simple this way, the read() function could check if the sensor is powered up or shut it down. (still check if delay after powerup is needed)
do we need DHTLIB_ERROR_POWERDOWN ?
do we need AUTO_POWER flag?
From the DHT11/21/22 datasheets
When power is supplied to sensor, don't send any instruction to the sensor within one second to pass unstable status.
This implies something like this or the user should take care of this second.
void DHT.powerUp()
{
uint32_t start = millis();
digitalWrite(_powerPin , HIGH):
while (millis() - start < 1000) yield();
}
Note: when disabling the power pin, the processor should also set the (free running) data pin to LOW. And of course also set it HIGH again when powering up. Otherwise no gain.
void DHT.powerUp()
{
uint32_t start = millis();
digitalWrite(_powerPin , HIGH):
digitalWrite(_dataPin , HIGH):
while (millis() - start < 1000) yield(); // blocking for a second...
}
void DHT.powerDown()
{
digitalWrite(_powerPin , LOW):
digitalWrite(_dataPin , LOW):
}
A powerup timestamp might be needed to remove the blocking code in powerUp(). When read is called it should be checked similar like lastRead timestamp. merging the two timestamps is not an option. Such timestamps might affect measurements after millis() wraps around. Verify this. However it could be used instead of start in prev post.
rename DHT.power() to uint32_t DHT.uptime() => returns false == 0 if down.
do we need DHTLIB_ERROR_POWERDOWN ?
no, consider a DHTLIB_STATE_POWERDOWN and DHTLIB_STATE_STARTING.
Current thoughts about code, it looks pretty complete
#define DHTLIB_STATE_DOWN 10
#define DHTLIB_STATE_STARTING 11
uint32_t _powerChange = 0;
DHTNEW::DHTNEW(uint8_t dataPin, uint8_t powerPin = 0xFF)
{
_dataPin = dataPin;
pinMode(_dataPin , OUTPUT);
digitalWrite(_dataPin , HIGH):
_powerPin = powerPin;
if (_powerPin != 0xFF)
{
pinMode(_powerPin, OUTPUT);
digitalWrite(_powerPin , HIGH):
}
_powerChange = millis();
}
void DHTNEW::power(const uint8_t mode)
{
if (_powerPin == 0xFF) return;
if (digitalRead(_powerPin) == mode) return;
_powerChange = millis();
digitalWrite(_powerPin , mode):
digitalWrite(_dataPin , mode):
}
uint32_t DHTNEW::uptime()
{
if (_powerPin == 0xFF) return millis() - _powerChange;
if (digitalRead(_powerPin) == LOW) return 0;
return millis() - _powerChange;
}
/*
// not needed, very similar to uptime()
uint32_t DHTNEW::downtime()
{
if (_powerPin == 0xFF) return 0;
if (digitalRead(_powerPin) == HIGH) return 0;
return millis() - _powerChange;
}
*/
int DHTNEW::read()
{
uint32_t ut = uptime();
if (ut == 0) return DHTLIB_STATE_DOWN;
if (ut < 1000) return DHTLIB_STATE_STARTING;
....
}
The function power() only works when a powerPin is set to a value other than 0xFF. The function uptime() works always. The function read() checks if the sensor is down or started long enough ago.
The user is responsible to use a valid power-pin.
TODO
The control of the power pin can very well be done outside the library, probably even more optimal. The library (current 0.3.0) does pull the data pin HIGH between reads. No energy measurements have been made how much this costs.
For a low power application the library could support toggling this data pin to LOW / HIGH to reduce energy consumption. The minimal implementation:
// to be used by low power applications, not tested
void DHTNEW::power(const uint8_t mode)
{
digitalWrite(_dataPin , mode):
}
It makes sense to implement this and add documentation that the user should take care of the boot delay of the sensor after the power is enabled again.
At least not in 0.3.x the library will not support switching of the power pin as this is breaking. To make a step in the right direction, these two functions shall be implemented as these would fit in the long term vision. described above. For now they will only affect the _dataPin.
void DHTNEW::powerUp();
void DHTNEW::powerDown();
After the powerUp(), the first read() can be out of sync, so one must make 1 dummy read() and wait for 2 seconds after it. The dummy read should be in the powerUp() function, but the delay should be users responsibility.
To support low power usage e.g. when batteries power the sensor, one need to be able to switch of the power supply of the DHT sensor.
This would imply an additional power pin in the constructor. This power pin has a default of 0xFF that states ==>no power pin.
investigate depending on the processor it can or cannot deliver the power from an IO pin directly. Working with an extra mosfet is always possible
investigate After startup a delay is needed. Put this in the library or is the user responsible?