[ell-i-developers] DHT 22 humidity sensor now working with ELL-i

  • From: Félix Halcartegaray V. <felix@xxxxxxxx>
  • To: ell-i-developers@xxxxxxxxxxxxx
  • Date: Sun, 29 Jun 2014 16:08:37 +0300


I went back to testing the humidity sensors (complete old thread below),
and now I was able to find the datasheet for the sensor where the
communication protocol is explained:
They use for communication a strict timing, setting the line to low for 50
us and then if the next signal lasts between 26-28 us it is a zero, and if
it lasts 70 us the data is a one.

So the problem was not on setting pins as input or output or if the process
was too slow as I thought. The DHT library counts the number of cycles of a
while loop before a state change. If the number of cycles is under 6, then
it was less than 40 us so data is zero. If the cycles are over 6, then data
is one.

And therefore, the problem was that ELL-i in this case is too fast and too
optimized. :o)
Each while loop with an Arduino Mega 2560, considering a 1 us delay
included in the loop, takes about 7 us and un ELL-i the same loop, with the
1 us delay, takes 1.1 us. So it was counting too many loops for any data
the sensor was sending.

The fix was to change the 1 us delay to a 7 us delay, thus using timings
that the library is expecting to read the data, and the sensor is now
working with ELL-i. The sensor supports both 5 volts and 3.3 volts levels.

The issue with delayMicroseconds over 20 seconds and also with two calls to
the function with the same argument where only one call is executed is
still there. So I changed a delayMicroseconds(40) to three calls to
delayMicroseconds with 20, 15 and 5 microseconds and it works good.

A call to cli() and sei() also needs to be changed to noInterrupts and
Interrupts or just commented out, because it is not defined in ELL-i


2014-02-22 19:00 GMT+02:00 Pekka Nikander <pekka.nikander@xxxxxx>:

> Good work!
> > I tested the delays with the oscilloscope, and the ASM section on
> > function delayMicroseconds that performs the delays below 20
> > microseconds works perfectly in wiring_time.h:
> Good to know.
> > The next section, for delays equal or over 20 microsecond that
> > compares the current micros() with the micros() the function started
> > works well for delays over 1000 microseconds, so the delay and
> > delayMilisecond functions work fine.
> Based on your notes below I suspect it may not be that accurate there,
> either, but that we just don't see the jitter as it is so small (tens of
> us) compared to the 1 ms...
> > The problem is with delay times between 20 and 1000 microseconds, and
> > then strange things happen on the oscilloscope, with what appear to be
> > random delays appearing, sometimes too small and sometimes too big.
> Even the comments say that sometimes the current implementation fails if
> the millisecond counter rolls over.  I don't remember how often that
> happens, but apparently only once every few days.  Anyway, at some point
> that needs to be fixed too.
> In addition to changing the cutoff value of the asm loop, we could also
> explicitly compute timo - micros() (as the compiler needs to do that
> anyway), and compare that to the cutoff value.  If the difference is less
> than the cutoff value, run only the assembler loop for the rest of the
> time.  Something like the following:
>     remaining = us;
>     if (remaining > cutoff)
>        timo = micros() + us;
>     do {
>        if (remaining < cutoff) { do the asm loop); return; }
>        yield();
>        remaining = timo - micros();
>     while (remaining > 0);
> You need to be careful with signed and unsigned values.  But that should
> give you more accuracy.
> > I would like to know if there are problems of extending the ASM loop
> > that currently works with less than 20 microseconds into more than 20
> > microseconds, and how much more is reasonable? Currently it does 240
> > iterations of the code above for 20 microseconds.
> I think the cutoff could well be 2000 or even 3000 CPU clocks.
> > After several tests, I noticed that if I call twice the
> delayMicroseconds function with the same argument in consecutive lines, the
> second calls gets ignored.
> Hard to say more without seeing the generated assemble.  You can generate
> that with -S.
> > The sensor is still not working, but at least the delays are working
> > now. The library for the sensor first sets the pin as output, takes it
> > to LOW to signal the sensor to start sending data and sets the pin as
> > input to listen. I don't know how long this change takes, but if it is
> > more than a few microseconds, the problem with the reading might be
> > there. I will test it, but if someone has done it before, I am glad to
> > know.
> Have you tried to connect the sensor to the +5V, 3.3V may be too low?  If
> you connect it to +5V, please make sure you use an 5V tolerant I/O pin at
> the MCU.
> I still think the right way is to use a counter/timer instead of a delay.
>  Please note also that on STM32F it is possible to set the weak pulldown
> and pullup on an I/O even if it is an input.  See Figure 15 on page 126 of
> RM0091.  In that way you should be able to set the pin low and high without
> setting it as an output, and start receiving data as soon as it first
> transitions.
> I would use a timer to read the high-pulse length (26-28 us vs 70 us) and
> trigger an interrupt at each high-to-low edge.  Then, at the interrupt
> routine I could easily determine from the counter value whether the
> previous bit was one or zero.
> The timer could even be set up before pulling the line high after the long
> low.  The first interrupt would then be triggered by the first high-to-low
> transition, at the beginning of the transmission, and you could then see
> the that the 20-40 ms waiting time.
> It will take some time to figure out how to initialise the timer/counter
> correctly, but then you'll learn how to program bare metal in the first
> place. :-)
> --Pekka

Other related posts:

  • » [ell-i-developers] DHT 22 humidity sensor now working with ELL-i - Félix Halcartegaray V .