Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add enable / disable power supply pin #13

Closed
RobTillaart opened this issue May 28, 2020 · 7 comments
Closed

Add enable / disable power supply pin #13

RobTillaart opened this issue May 28, 2020 · 7 comments
Assignees
Labels
Milestone

Comments

@RobTillaart
Copy link
Owner

RobTillaart commented May 28, 2020

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.

DHT(datapin, powerPin = 0xFF);

void DHT.enable()
{
  if (_powerPin == 0xFF) return;
  digitalWrite(_powerPin , HIGH):
}

void DHT.disable()
{
  if (_powerPin == 0xFF) return;
  digitalWrite(_powerPin , LOW):
}

bool DHT.sensorEnabled()
{
  return (_powerPin != 0xFF);
}

uint8_t  _powerPin ;

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?

@RobTillaart RobTillaart self-assigned this May 28, 2020
@RobTillaart
Copy link
Owner Author

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?

@RobTillaart
Copy link
Owner Author

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();
}

@RobTillaart
Copy link
Owner Author

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):
}

@RobTillaart
Copy link
Owner Author

RobTillaart commented Jun 5, 2020

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.

@RobTillaart
Copy link
Owner Author

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

  • make a test branch
  • measure code size impact. (with + without call to power)
  • write a test sketch that uses the power code.

@RobTillaart
Copy link
Owner Author

RobTillaart commented Jun 16, 2020

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.

@RobTillaart RobTillaart added this to the 0.3.1 milestone Jun 16, 2020
@RobTillaart
Copy link
Owner Author

RobTillaart commented Jul 8, 2020

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.

RobTillaart added a commit that referenced this issue Jul 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant