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

Waterelf32 startPeripherals not detecting DHT22 #15

Closed
cgmcintyr opened this issue Nov 16, 2017 · 9 comments
Closed

Waterelf32 startPeripherals not detecting DHT22 #15

cgmcintyr opened this issue Nov 16, 2017 · 9 comments
Assignees

Comments

@cgmcintyr
Copy link
Collaborator

As noted in https://www.sparkfun.com/datasheets/Sensors/Temperature/DHT22.pdf, the DHT22 has an average sensing period of 2s.

The function startPeripherals will occasionally not detect the DHT22 as a reading has not yet been made before initialising the sensor with dht.begin():

dht.begin(); // start the humidity and air temperature sensor
float airHumid = dht.readHumidity();
float airCelsius = dht.readTemperature();
if (isnan(airHumid) || isnan(airCelsius)) {
dln(monitorDBG, "failed to find humidity sensor");
} else {
GOT_HUMID_SENSOR = true;
}

Adding a delay(2000) before line 816 seems to work as a fix for this.

@layerzerolabs
Copy link
Collaborator

My reading of that datasheet (note however we are using AM2302, a clone of DHT22) is that the period between readings has to be >2s. However, the datasheet also states "When power is supplied to sensor, don't send any instruction to the sensor within one second to pass unstable status." Can you test with a 1s delay? Also I see that there are a number of startup functions such as startAP and startWebServer that don't depend on the peripherals - could we move the startPeripherals function after those to achieve a delay? Additionally we could move this sensor to the end of the startPeripherals function to get a bit more of a delay? Can you test and report back? Ta!

@cgmcintyr cgmcintyr self-assigned this Nov 17, 2017
@Eroc33
Copy link
Collaborator

Eroc33 commented Nov 21, 2017

This may be related to an issue I have been investigating where I discovered that turning off WiFi significantly increases the reliability of reading the DHT and Water temperature sensors. I have some idea of what's going on but it may need further investigation.

@Eroc33
Copy link
Collaborator

Eroc33 commented Nov 21, 2017

This issue in the DHT library may also be relevant: adafruit/DHT-sensor-library#48 (implementing this change appears to have decreased the failure rate of my sensor)

EDIT: This makes the sensor work 99% reliably in the example provided with the library (it was pretty intermittent otherwise), but it still doesn't get detected by the waterelf code.

@hamishcunningham
Copy link
Owner

Sounds like a timing issue if WiFi impacts on reliability, which was typical ESP8266 but is a bit more surprising on (dual core) ESP32. Perhaps having the handler for webserver requests in the main loop is part of the problem?

@layerzerolabs
Copy link
Collaborator

I'm shocked that despite excellent investigation and the simplicity of the fix suggested over at adafruit that it hasn't been implemented! Well found - have you tried increasing the second delay to 50us as well?

@Eroc33
Copy link
Collaborator

Eroc33 commented Nov 22, 2017

One solution I have found that works for the water temperature sensor, but doesn't have much effect on the DHT readings to to place the library calls doing soft serial in a critical section (which disables ISRs and task pre-emption). As far as I can tell the esp8266 uses co-operative tasks (as does the original arduino for which the libraries are designed), but the esp32 uses pre-emptive tasks so I suspect the issue is that the soft-serial routines are being pre-empted by the task running the WiFi stack which would disrupt the timing, but also explain why this was not seen on esp8266.

@Eroc33
Copy link
Collaborator

Eroc33 commented Dec 4, 2017

I've finally tracked down what seems to be the real source of the problem, which is that the arduino functions noInterrupts and interrupts are defined to be no-op in esp-arduino core, there is an issue open for this at espressif/arduino-esp32#832, but for now you can modify DHT.h in the DHT library changing the InterruptLock class to the following:

class InterruptLock {
  public:
   InterruptLock() {
	#ifdef ESP32
		portDISABLE_INTERRUPTS();
	#else
		noInterrupts();
	#endif
   }
   ~InterruptLock() {
	#ifdef ESP32
		portENABLE_INTERRUPTS();
	#else
		interrupts();
	#endif
   }
};

(I also tried putting portDISABLE/ENABLE_INTERRUPTS() around the whole section of code using the DHT in waterelf, but for some reason that didn't work, which is what threw me off of finding this answer for so long)

@cgmcintyr
Copy link
Collaborator Author

@Eroc33 nice work!

As a small change, looking into the FreeRTOS documentation they seem to recommend using taskENABLE_INTERRUPTS() and taskDISABLE_INTERRUPTS() over portENABLE_INTERRUPTS() and portDISABLE_INTERRUPTS().

Looking at the source code for tasks.h these are just macros that essentially alias their port equivalents, however they are meant to act as interfaces so we should probably use them :)

cgmcintyr added a commit to cgmcintyr/fishy-wifi that referenced this issue Dec 4, 2017
cgmcintyr added a commit to cgmcintyr/fishy-wifi that referenced this issue Dec 4, 2017
- Custom DHT.h correctly disables interrupts on ESP32, allowing for
conistent startup of sensor
- Closes hamishcunningham#15
@layerzerolabs
Copy link
Collaborator

Great stuff - nice to get the interface macros even for a hotfix...

cgmcintyr added a commit to cgmcintyr/fishy-wifi that referenced this issue Dec 4, 2017
- Custom DHT.h correctly disables interrupts on ESP32, allowing for
conistent startup of sensor
- Closes hamishcunningham#15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants