DHT22 driver

326 views
Skip to first unread message

Atommann

unread,
Sep 30, 2015, 3:43:28 AM9/30/15
to esp-op...@googlegroups.com
Hi,

I use extras/bmp180 in the code base as a template and adapted CHERTS'
DHT22 driver ( https://github.com/CHERTS/esp8266-dht11_22 )

I am not familiar with github, wish someone can add it into repository.

DHT22 is a single wire data bus, the timing is critical, so before the
reading starts I add
vTaskSuspendAll(); // timing critical start

And
xTaskResumeAll(); // timing critical ends
at the end of the reading. Is it the right way to do this (timing
critical stuff)?

BTW, this is the first time I use FreeRTOS and am also not a good C programmer.
Question: Is there any guideline/framework for how to write device
drivers for FreeRTOS?

If there is a framework I want to write more drivers.

It is a quick and dirty driver. But it works.
Here is the data stream https://data.sparkfun.com/streams/NJxKG6mjMpHGRWDVJ0DR

--
Best regards,
Atommann
dht22.tar.gz

Angus Gratton

unread,
Oct 6, 2015, 9:42:19 PM10/6/15
to Atommann, esp-op...@googlegroups.com
Hi Atommann,

Sorry I didn't reply to your email for so long. Thanks for getting involved! I'll reply to the individual questions inline below:

On Wed, Sep 30, 2015 at 03:43:27PM +0800, Atommann wrote:
> DHT22 is a single wire data bus, the timing is critical, so before the
> reading starts I add
> vTaskSuspendAll(); // timing critical start
>
> And
> xTaskResumeAll(); // timing critical ends
> at the end of the reading. Is it the right way to do this (timing
> critical stuff)?

That's the right approach. The best functions to use for this are probably

portENTER_CRITICAL(); // timing critical start

portEXIT_CRITICAL(); // timing critical end

... which is the "FreeRTOS way" of managing critical sections (handles things like recursive entry where a critical section is called inside a critical section, etc.)

The timing you see will be "pretty good", but in esp-open-rtos there is also an NMI exception which (as per the name Non Maskable Interrupt) can't be disabled.[*]

Probably the only thing you can really do from a driver perspective is try to detect when this has happened (ie you see an invalid read response), reocver, and retry.

> BTW, this is the first time I use FreeRTOS and am also not a good C programmer.
> Question: Is there any guideline/framework for how to write device
> drivers for FreeRTOS?
>
> If there is a framework I want to write more drivers.

FreeRTOS itself steers away from "drivers" as a concept, that part's really up to people who implement a FreeRTOS-based system (ie esp-open-rtos in this case).

There are some existing peripherals drivers in extras/i2c and extras/bmp180. Each one is just a single source file and a single header file. So I'm thinking maybe we coordinate those into a single "extras/peripherals" and put all external peripheral drivers in the same place. So a dht22 driver would just be another header file and source file under extras/peripherals.

Would you be interested in submitting it as a contribution? I can help walk you through any steps required.

> It is a quick and dirty driver. But it works.
> Here is the data stream https://data.sparkfun.com/streams/NJxKG6mjMpHGRWDVJ0DR

Neat!

If you're up to it as well, it'd be great to have an example in esp-open-rtos that showed how to push data to data.sparkfun.com.


Angus

Michael Jacobsen

unread,
Oct 7, 2015, 2:56:03 AM10/7/15
to esp-open-rtos mailing list
Hi,

I "ported" the Arduino DHT22 driver. I don't do anything to disable interrupts and it works too :-) Once in a while it fails to read from the DHT22, but in my application that's ok...

/michael

Alex Stewart

unread,
Oct 7, 2015, 2:53:08 PM10/7/15
to Angus Gratton, Atommann, esp-open-rtos mailing list
My apologies too.. I apparently completely missed the original message when it came through..

On Tue, Oct 6, 2015 at 6:40 PM, Angus Gratton <g...@projectgus.com> wrote:
On Wed, Sep 30, 2015 at 03:43:27PM +0800, Atommann wrote:
> DHT22 is a single wire data bus, the timing is critical, so before the
> reading starts I add
> vTaskSuspendAll(); // timing critical start
>
> And
> xTaskResumeAll(); // timing critical ends
> at the end of the reading. Is it the right way to do this (timing
> critical stuff)?

That's the right approach. The best functions to use for this are probably

portENTER_CRITICAL(); // timing critical start

portEXIT_CRITICAL(); // timing critical end

Note that portENTER_CRITICAL() / portEXIT_CRITICAL() do not do exactly the same thing as vTaskSuspendAll() / xTaskResumeAll().  As I understand it, the portENTER_CRITICAL macro actually disables interrupts completely (except for the NMI, obviously), whereas vTaskSuspendAll continues to allow interrupt handlers to be invoked, but just disables switching away to other user tasks.  Both are useful, but for different things.

In this case, since it looks (at a glance) as though the timing is critical enough that a preemptive context switch would probably screw it up, but not necessarily so critical that a (presumably fast) ISR invocation here and there would necessarily be a problem, it sounds to me like vTaskSuspendAll() might actually be the correct solution and that portENTER_CRITICAL() would be overkill.

If one is really concerned about timing to that degree, then it would probably be better to use an interrupt-driven approach instead of polling in a critical section anyway.

Alex Stewart

unread,
Oct 7, 2015, 3:04:20 PM10/7/15
to Angus Gratton, Atommann, esp-open-rtos mailing list
Oh, one other thing I did notice about the CHERTS driver..

os_delay_us(x) is not actually guaranteed to sleep exactly x microseconds.  In fact, the way it's written it will almost certainly sleep a little bit longer than that.  For most applications, the difference is so small that it really shouldn't matter, but when you're doing os_delay_us(1), there may be a noticeable skew to that (i.e. it might actually be sleeping 1.1 or 1.2 us instead, which would be 10% or 20% off).  I haven't actually tested it myself, but I might be a bit concerned that the way the driver is written there might be some potential for misreading bits under some circumstances if that isn't taken into account..

(A better approach would probably be to use the CPU's CCOUNT to measure timings instead of maintaining a loop counter onesself, but admittedly fixing that would be a bit more work than just porting the existing driver)

Atommann

unread,
Oct 7, 2015, 10:32:08 PM10/7/15
to esp-op...@googlegroups.com
2015-10-08 3:04 GMT+08:00 Alex Stewart <foo...@gmail.com>:
> Oh, one other thing I did notice about the CHERTS driver..
>
> os_delay_us(x) is not actually guaranteed to sleep exactly x microseconds.
> In fact, the way it's written it will almost certainly sleep a little bit
> longer than that. For most applications, the difference is so small that it
> really shouldn't matter, but when you're doing os_delay_us(1), there may be
> a noticeable skew to that (i.e. it might actually be sleeping 1.1 or 1.2 us
> instead, which would be 10% or 20% off). I haven't actually tested it
> myself, but I might be a bit concerned that the way the driver is written
> there might be some potential for misreading bits under some circumstances
> if that isn't taken into account..
>
> (A better approach would probably be to use the CPU's CCOUNT to measure
> timings instead of maintaining a loop counter onesself, but admittedly
> fixing that would be a bit more work than just porting the existing driver)

Yes, when I was porting the DHT22 driver I was also thinking about
using GPIO interrupt to capture the pulses from the sensor. But I want
to do it faster. Another reason is there is already a template (the
BMP180 driver).

--
Best regards,
Atommann

Atommann

unread,
Oct 7, 2015, 10:37:58 PM10/7/15
to esp-op...@googlegroups.com
Hi,

2015-10-07 9:40 GMT+08:00 Angus Gratton <g...@projectgus.com>:
> Hi Atommann,
>
> Sorry I didn't reply to your email for so long. Thanks for getting involved! I'll reply to the individual questions inline below:

No worries.

> There are some existing peripherals drivers in extras/i2c and extras/bmp180. Each one is just a single source file and a single header file. So I'm thinking maybe we coordinate those into a single "extras/peripherals" and put all external peripheral drivers in the same place. So a dht22 driver would just be another header file and source file under extras/peripherals.

In the future there will be more and more drivers for peripherals I think.

> Would you be interested in submitting it as a contribution? I can help walk you through any steps required.

I will give it a try.

> If you're up to it as well, it'd be great to have an example in esp-open-rtos that showed how to push data to data.sparkfun.com.

I'll also add an example and submit to github.

--
Best regards,
Atommann

angu...@gmail.com

unread,
Oct 13, 2015, 1:45:45 PM10/13/15
to esp-open-rtos mailing list
Hi Atommann,


Am Donnerstag, 8. Oktober 2015 04:37:58 UTC+2 schrieb Li Long:
Hi,

2015-10-07 9:40 GMT+08:00 Angus Gratton <g...@projectgus.com>:
> Hi Atommann,
>
> Sorry I didn't reply to your email for so long. Thanks for getting involved! I'll reply to the individual questions inline below:

No worries.

> There are some existing peripherals drivers in extras/i2c and extras/bmp180. Each one is just a single source file and a single header file. So I'm thinking maybe we coordinate those into a single "extras/peripherals" and put all external peripheral drivers in the same place. So a dht22 driver would just be another header file and source file under extras/peripherals.

In the future there will be more and more drivers for peripherals I think.
 
As the author of the bmp180 example I think completely the same way, after I finished the example and had a look into my "scrap box" I found additional sensors (MPL115A2 or HDC100X) I wanted to add, but my approach chosen was really useful only for an example. It's not extendable by any means. 

So to add the additional sensors I had to start implementing a "sensor" framework, which allows sensors to be "plugged in" and the hardware aspects are hidden in a small abstraction layer. This allows to use the sensors on any hardware and makes testing quite easy. Currently the framework supports the ESP8266, Freescale FRDM K64F and CppUtest. 
 
With the test framework added as the "first hardware" I was able to test all aspects of the sensor I wanted to implement and they worked right out of the box, when connected to the real hardware. :-) 

The "project" currently is an alpha state and I will bring it online with github, so that it can be extended. Maybe we can join forces and integrate your driver into it, but currently it might take me a week or two clean up everything and share it. 

> Would you be interested in submitting it as a contribution? I can help walk you through any steps required.

I will give it a try.

> If you're up to it as well, it'd be great to have an example in esp-open-rtos that showed how to push data to data.sparkfun.com.

I'll also add an example and submit to github.  

--
Best regards,
Atommann

Let me know if this is an option for you. I definitely let you know, when my code gets online, so that you can have a look. :-) 

Best regards

angus71

Reply all
Reply to author
Forward
0 new messages