Reading AM2302 temp/humid sensor on RaspberryPi?

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

Reading AM2302 temp/humid sensor on RaspberryPi?

Bo Berglund
I wonder if there are any demo projects around for reading the AM2302
DHT sensor on a RaspberryPi through FreePascal?
Any links to sample code would be appreciated.
I have used it on an ESP-07 WiFi module (C language and Arduino
environment) but now I would like to get it going on an RPi using
FPC/Lazarus.


--
Bo Berglund
Developer in Sweden

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reading AM2302 temp/humid sensor on RaspberryPi?

Bo Berglund
On Wed, 22 Aug 2018 23:19:28 +0200, Bo Berglund
<[hidden email]> wrote:

>I wonder if there are any demo projects around for reading the AM2302
>DHT sensor on a RaspberryPi through FreePascal?
>Any links to sample code would be appreciated.
>I have used it on an ESP-07 WiFi module (C language and Arduino
>environment) but now I would like to get it going on an RPi using
>FPC/Lazarus.

Just to clarify, if I have to go the Do It Yourself route and read the
data from the sensor directly:

I have done some relay control GPIO I/O code before using FPC on the
RPi2 which used the PiGpio.pas unit:
(http://wiki.freepascal.org/Lazarus_on_Raspberry_Pi#PiGpio_Low-level_native_pascal_unit_.28GPIO_control_instead_of_wiringPi_c_library.29)

But that code only used simple pin on/off commands at low speed and
for the DHT sensor one needs to set and clear the pins at microsecond
timing and to read the data one needs to measure pin level durations
at microsecond level. This might not easily be accomplished on a Linux
system...
The DHT sensor is started by pulling the comm line low for about 1 ms,
then releasing it. Then the DHT will send 40 bits of data where the
bit value depends on the pulse high time in a 0-1-0 sequence where the
1 time is (nominal) 26 us for data=0 and 70 us for data=1.
So one has to measure the high time for each pulse to determine the
bit value. And the resolution is in the us range...

So I wonder if there are some examples of doing that, for example
using the PiGpio unit.
But better yet would be a complete DHT driver in pascal of course...

Question: Should I ask this on the Lazarus list instead?

(There seems to be no Pascal subforum at the Raspberrypi forum...)


--
Bo Berglund
Developer in Sweden

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reading AM2302 temp/humid sensor on RaspberryPi?

R0b0t1
In reply to this post by Bo Berglund
On Wed, Aug 22, 2018 at 4:19 PM, Bo Berglund <[hidden email]> wrote:
> I wonder if there are any demo projects around for reading the AM2302
> DHT sensor on a RaspberryPi through FreePascal?
> Any links to sample code would be appreciated.
> I have used it on an ESP-07 WiFi module (C language and Arduino
> environment) but now I would like to get it going on an RPi using
> FPC/Lazarus.
>

Can you briefly describe its protocol? Does it look anything like
Dallas/Maxim Semi 1-wire or I2C, or is it something else? If it is
either of those the I2C or SPI peripheral likely could do it. Even if
not the SPI peripheral may work.

It looks like pulse length modulation as used in IR receivers. Some
SPI peripherals have a mode that will read this; in other cases, you
can set the clock speed to the GCD of all signalling times and receive
a bitstream that maps to high/low intervals.


If you need to go DIY I think you will be able to easily, without
kernel modifications or writing kernelspace code. You should be able
to sleep for microseconds using nanosleep(2) (which is used by
usleep(3)). I think I read that for small values nanosleep(2) should
busy loop instead of yielding to the scheduler.  Or perhaps not.

I usually like to stick a small ARM chip somewhere (used to be an AVR)
to handle these things as the hardware is usually more configurable.

Cheers,
    R0b0t1
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reading AM2302 temp/humid sensor on RaspberryPi?

Bo Berglund
On Thu, 23 Aug 2018 00:33:05 -0500, R0b0t1
<[hidden email]> wrote:

>Can you briefly describe its protocol? Does it look anything like
>Dallas/Maxim Semi 1-wire or I2C, or is it something else? If it is
>either of those the I2C or SPI peripheral likely could do it. Even if
>not the SPI peripheral may work.

This is what the datasheet says (times here are the nominal ones):

1. It uses a 1-wire connection with 5K pullup and open drain drivers.

2. The master requests data by pulling the wire low for 1 ms

3. The sensor then waits 30 us before setting the wire low for 80 us
followed by high for 80 us.

4. Next follows 40 bits of data each composed of:
   - Low level for 50 us
   - High level for bit value depenednt time:
     Bit = 0 time = 26 us
     Bit = 1 time = 70 us

5. After the 40 bit transfer the line is held low for 50 us, then
released.

Data are sent as 4 bytes (16 bit humidity, 16 bit temp) followed by
one parity byte. The bytes are sent MSB first.

The DHT driver for Arduino ESP8266 (in C) seems to measure and stuff
pulse widths into an array during the transfer and after the fact
evaluates the bits depending on the recorded widths.

My problem is that I don't see how I could measure the high level
pulse widths....
Possibly a loop where the input level is checked:

function MeasureHighPulse: cardinal;
var
  Ts, Te: cardinal;
const
  Tmax = 100;  //Max allowed pulse length
begin
  Ts := TickCountus();  //Need a tickcount with us resolution...
  Te := Ts;
  while InputPin(Sensorpin) = 1 do
  begin
    Te := TickCountus();
    if Te - Ts > Tmax then
    begin
      Te := Ts;
      break;
    end;
  end;
  Result := Te - Ts;
end;

I will need a higher resolution GetTickCount for this...
The usleep() function is somethingh I have never seen before, but I
guess it "sleeps" for a certain number of microseconds...


--
Bo Berglund
Developer in Sweden

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reading AM2302 temp/humid sensor on RaspberryPi?

Bo Berglund
On Thu, 23 Aug 2018 09:00:07 +0200, Bo Berglund
<[hidden email]> wrote:

>
>I will need a higher resolution GetTickCount for this...

Is there in fact a way (on Linux - Raspbian) to get a tickcount with
higher resolution than 1 ms?
I need us so I can time between two events (pulse rise and pulse fall)
which are 20 to 90 us apart...

An alternate way would be to do an accurate sleep for a time between
the two limits, say 48 us, after seeing the pulse rise and then
determine the state of the I/O at that time.
If the input is 0 then the bit is zero and if it is still 1 the bit is
a 1...


--
Bo Berglund
Developer in Sweden

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reading AM2302 temp/humid sensor on RaspberryPi?

Alexander Hofmann
Hi,

I recently built a Weather-Station using an RPi and Lazarus/FPC, but:
anything that's not I2C or SPI (or otherwise supported within the RPi
hardware) is IHMO hard to realize. I went on and used an AVR (Arduino)
to interface the DHT11, and hooked that up to the Pi with UART (just
before dumping it completely, because it's accuracy and self-heating
issues were just to much to calibrate accurately).

Reason:

Am 23.08.2018 um 11:11 schrieb Bo Berglund:
> An alternate way would be to do an accurate sleep for a time between
> the two limits, say 48 us, after seeing the pulse rise and then
> determine the state of the I/O at that time.
> If the input is 0 then the bit is zero and if it is still 1 the bit is
> a 1...
There are commands like usleep() in Linux. But - as the typical system
on the Pi is not a realtime OS and we have the granularity of the system
scheduler, task switching, interrupts etc. pp. to account for, many
sources give it's accuracy to be only above 100 µs.
Generally I would say that, on any complex system, without considerably
effort, no loop or timer can be 100% sure not to be interrupted while
processing input data for at least a few µs, which is exactly the
problem here.

One solution might be possible, though I never digged in further (and I
suspect it's not possible for a user-land process, but I might be proven
wrong): try do define your own interrupt on the specific pin (there are
some libs for this, also in user-land) and find a hardware timer in the
Broadcom chip that is running stable enough to count a few µs. There are
timers and interrupts in the Chip (see
https://www.studica.com/blog/raspberry-pi-timer-embedded-environments).

Regards,

Alex

PS: I dumped the DHT11 and used a HTDU21D. I2C, stable and easy with FPC
;-))
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reading AM2302 temp/humid sensor on RaspberryPi?

Martin Schreiber-2
In reply to this post by Bo Berglund
On Thursday 23 August 2018 11:11:34 Bo Berglund wrote:
> On Thu, 23 Aug 2018 09:00:07 +0200, Bo Berglund
>
> <[hidden email]> wrote:
> >I will need a higher resolution GetTickCount for this...
>
> Is there in fact a way (on Linux - Raspbian) to get a tickcount with
> higher resolution than 1 ms?

MSEgui has "timestamp()" (lib/common/kernel/msesysutils.pas) which returns
microseconds. MSEgui "ttimer" also has 1 us resolution.

> I need us so I can time between two events (pulse rise and pulse fall)
> which are 20 to 90 us apart...
>
I don't think that can be done reliably in user space.

Martin
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reading AM2302 temp/humid sensor on RaspberryPi?

Martin Schreiber-2
On Thursday 23 August 2018 11:54:14 Martin Schreiber wrote:
>
> I don't think that can be done reliably in user space.
>
As Alexander writes, the right way to do such a task is to use a hardware
timer in capture mode. I don't know how difficult this is on RPi.

Martin


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reading AM2302 temp/humid sensor on RaspberryPi?

Mark Morgan Lloyd-5
In reply to this post by Martin Schreiber-2
On 23/08/18 10:00, Martin Schreiber wrote:
> On Thursday 23 August 2018 11:11:34 Bo Berglund wrote:> On Thu, 23 Aug 2018 09:00:07 +0200, Bo Berglund>> <[hidden email]> wrote:> >I will need a higher resolution GetTickCount for this...>> Is there in fact a way (on Linux - Raspbian) to get a tickcount with> higher resolution than 1 ms?

On a mid-00s server I'm using clock_gettime(CLOCK_REALTIME which is
apparently better than 1uSec, but from previously looking at older PCs
and (I think) RPi3 your mileage may vary enormously. AIUI there's been a
lot of issues over the years with different cores not having their
counters in step, with counter frequency following dynamic clocks rather
than being fixed and so on.

The AM2302 datasheet suggests that it's a device to be avoided assiduously.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reading AM2302 temp/humid sensor on RaspberryPi?

Bo Berglund
On Thu, 23 Aug 2018 11:28:16 +0000, Mark Morgan Lloyd
<[hidden email]> wrote:

>The AM2302 datasheet suggests that it's a device to be avoided assiduously.

But it works fine hooked to an ESP-07 WiFi module, which is programmed
using the Arduino framework. I have a test running for several months
now and it logs T/H every 20 minutes.
I will probably just build myself a copy of this and put it at the
summer home. It can be set to transfer its data to the RPi2 at that
location via the WiFi network.

Of course I have to resort to C and C++ programming then...


--
Bo Berglund
Developer in Sweden

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reading AM2302 temp/humid sensor on RaspberryPi?

R0b0t1
In reply to this post by Mark Morgan Lloyd-5
On Thu, Aug 23, 2018 at 6:28 AM, Mark Morgan Lloyd
<[hidden email]> wrote:

> On 23/08/18 10:00, Martin Schreiber wrote:
>>
>> On Thursday 23 August 2018 11:11:34 Bo Berglund wrote:> On Thu, 23 Aug
>> 2018 09:00:07 +0200, Bo Berglund>> <[hidden email]> wrote:> >I will
>> need a higher resolution GetTickCount for this...>> Is there in fact a way
>> (on Linux - Raspbian) to get a tickcount with> higher resolution than 1 ms?
>
>
> On a mid-00s server I'm using clock_gettime(CLOCK_REALTIME which is
> apparently better than 1uSec, but from previously looking at older PCs and
> (I think) RPi3 your mileage may vary enormously. AIUI there's been a lot of
> issues over the years with different cores not having their counters in
> step, with counter frequency following dynamic clocks rather than being
> fixed and so on.
>

There is clock_getres(2) to test this. The problems you're talking
about do exist but have mostly been hidden behind the clock_gettime
interface, or, on Windows, QueryPerformanceCounter.

> The AM2302 datasheet suggests that it's a device to be avoided assiduously.
>

It's definitely not the best protocol. It's not even communication
line powered, so I don't see the point of the strange implementation.


On Thu, Aug 23, 2018 at 4:54 AM, Martin Schreiber <[hidden email]> wrote:
> On Thursday 23 August 2018 11:11:34 Bo Berglund wrote:
>> I need us so I can time between two events (pulse rise and pulse fall)
>> which are 20 to 90 us apart...
>>
> I don't think that can be done reliably in user space.
>

I think it could, but the success of the program depends entirely on
what else is running. That could be avoided with scheduling settings
or running a "realtime" kernel.

I do think this could be done by beating the SPI peripheral over the
head, but just like the solution involving timers it may not be easy
to implement as you need to slide your code in to Linux.

Cheers,
    R0b0t1
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reading AM2302 temp/humid sensor on RaspberryPi?

Bo Berglund
In reply to this post by Mark Morgan Lloyd-5
On Thu, 23 Aug 2018 11:28:16 +0000, Mark Morgan Lloyd
<[hidden email]> wrote:

>The AM2302 datasheet suggests that it's a device to be avoided assiduously.

But it works fine hooked to an ESP-07 WiFi module, which is programmed
using the Arduino framework. I have a test running for several months
now and it logs T/H every 20 minutes.
I will probably just build myself a copy of this and put it at the
summer home. It can be set to transfer its data to the RPi2 at that
location via the WiFi network.

Of course I have to resort to C and C++ programming then...


--
Bo Berglund
Developer in Sweden

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reading AM2302 temp/humid sensor on RaspberryPi?

Mark Morgan Lloyd-5
In reply to this post by R0b0t1
On 24/08/18 09:15, R0b0t1 wrote:
> On Thu, Aug 23, 2018 at 6:28 AM, Mark Morgan Lloyd<[hidden email]> wrote:> On 23/08/18 10:00, Martin Schreiber wrote:>>>> On Thursday 23 August 2018 11:11:34 Bo Berglund wrote:> On Thu, 23 Aug>> 2018 09:00:07 +0200, Bo Berglund>> <[hidden email]> wrote:> >I will>> need a higher resolution GetTickCount for this...>> Is there in fact a way>> (on Linux - Raspbian) to get a tickcount with> higher resolution than 1 ms?>>> On a mid-00s server I'm using clock_gettime(CLOCK_REALTIME which is> apparently better than 1uSec, but from previously looking at older PCs and> (I think) RPi3 your mileage may vary enormously. AIUI there's been a lot of> issues over the years with different cores not having their counters in> step, with counter frequency following dynamic clocks rather than being> fixed and so on.>
> There is clock_getres(2) to test this.

That shows the nominal resolution, not the actual rate that the counter
is updated.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Reading AM2302 temp/humid sensor on RaspberryPi?

R0b0t1
On Fri, Aug 24, 2018 at 2:45 PM, Mark Morgan Lloyd
<[hidden email]> wrote:

> On 24/08/18 09:15, R0b0t1 wrote:
>>
>> On Thu, Aug 23, 2018 at 6:28 AM, Mark Morgan
>> Lloyd<[hidden email]> wrote:> On 23/08/18 10:00, Martin
>> Schreiber wrote:>>>> On Thursday 23 August 2018 11:11:34 Bo Berglund wrote:>
>> On Thu, 23 Aug>> 2018 09:00:07 +0200, Bo Berglund>> <[hidden email]>
>> wrote:> >I will>> need a higher resolution GetTickCount for this...>> Is
>> there in fact a way>> (on Linux - Raspbian) to get a tickcount with> higher
>> resolution than 1 ms?>>> On a mid-00s server I'm using
>> clock_gettime(CLOCK_REALTIME which is> apparently better than 1uSec, but
>> from previously looking at older PCs and> (I think) RPi3 your mileage may
>> vary enormously. AIUI there's been a lot of> issues over the years with
>> different cores not having their counters in> step, with counter frequency
>> following dynamic clocks rather than being> fixed and so on.>
>> There is clock_getres(2) to test this.
>
>
> That shows the nominal resolution, not the actual rate that the counter is
> updated.
>

The counter is updated, generally, at its resolution; the
implementation as far as I know reads the counter value directly which
may be associated with hardware.

What is more problematic is the scheduler's minimum timeslice. I
couldn't exactly find a way to find it though it exists as a define in
the Linux kernel, but that value may or may not be used as-is.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal