Skip to content

Commit d686ebc

Browse files
author
Nick Veys
committed
Add node-gyp config, Adafruit dep
1 parent 8ec627d commit d686ebc

File tree

12 files changed

+775
-0
lines changed

12 files changed

+775
-0
lines changed

binding.gyp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"targets": [
3+
{
4+
"target_name": "dht",
5+
"sources": [
6+
"dht/common_dht_read.c",
7+
"dht/Raspberry_Pi/pi_dht_read.c",
8+
"dht/Raspberry_Pi/pi_mmio.c",
9+
"dht/Raspberry_Pi_2/pi_2_dht_read.c",
10+
"dht/Raspberry_Pi_2/pi_2_mmio.c",
11+
"dht.cpp"
12+
],
13+
"include_dirs": [
14+
"<!(node -e \"require('nan')\")"
15+
]
16+
}
17+
]
18+
}

dht/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# DHT Sensor Reading for RPi
2+
3+
https://github.com/adafruit/Adafruit_Python_DHT

dht/Raspberry_Pi/pi_dht_read.c

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// Copyright (c) 2014 Adafruit Industries
2+
// Author: Tony DiCola
3+
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
// copies of the Software, and to permit persons to whom the Software is
9+
// furnished to do so, subject to the following conditions:
10+
11+
// The above copyright notice and this permission notice shall be included in all
12+
// copies or substantial portions of the Software.
13+
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
// SOFTWARE.
21+
#include <stdbool.h>
22+
#include <stdlib.h>
23+
24+
#include "pi_dht_read.h"
25+
#include "pi_mmio.h"
26+
27+
// This is the only processor specific magic value, the maximum amount of time to
28+
// spin in a loop before bailing out and considering the read a timeout. This should
29+
// be a high value, but if you're running on a much faster platform than a Raspberry
30+
// Pi or Beaglebone Black then it might need to be increased.
31+
#define DHT_MAXCOUNT 32000
32+
33+
// Number of bit pulses to expect from the DHT. Note that this is 41 because
34+
// the first pulse is a constant 50 microsecond pulse, with 40 pulses to represent
35+
// the data afterwards.
36+
#define DHT_PULSES 41
37+
38+
int pi_dht_read(int type, int pin, float* humidity, float* temperature) {
39+
// Validate humidity and temperature arguments and set them to zero.
40+
if (humidity == NULL || temperature == NULL) {
41+
return DHT_ERROR_ARGUMENT;
42+
}
43+
*temperature = 0.0f;
44+
*humidity = 0.0f;
45+
46+
// Initialize GPIO library.
47+
if (pi_mmio_init() < 0) {
48+
return DHT_ERROR_GPIO;
49+
}
50+
51+
// Store the count that each DHT bit pulse is low and high.
52+
// Make sure array is initialized to start at zero.
53+
int pulseCounts[DHT_PULSES*2] = {0};
54+
55+
// Set pin to output.
56+
pi_mmio_set_output(pin);
57+
58+
// Bump up process priority and change scheduler to try to try to make process more 'real time'.
59+
set_max_priority();
60+
61+
// Set pin high for ~500 milliseconds.
62+
pi_mmio_set_high(pin);
63+
sleep_milliseconds(500);
64+
65+
// The next calls are timing critical and care should be taken
66+
// to ensure no unnecssary work is done below.
67+
68+
// Set pin low for ~20 milliseconds.
69+
pi_mmio_set_low(pin);
70+
busy_wait_milliseconds(20);
71+
72+
// Set pin at input.
73+
pi_mmio_set_input(pin);
74+
// Need a very short delay before reading pins or else value is sometimes still low.
75+
for (volatile int i = 0; i < 500; ++i) {
76+
}
77+
78+
// Wait for DHT to pull pin low.
79+
uint32_t count = 0;
80+
while (pi_mmio_input(pin)) {
81+
if (++count >= DHT_MAXCOUNT) {
82+
// Timeout waiting for response.
83+
set_default_priority();
84+
return DHT_ERROR_TIMEOUT;
85+
}
86+
}
87+
88+
// Record pulse widths for the expected result bits.
89+
for (int i=0; i < DHT_PULSES*2; i+=2) {
90+
// Count how long pin is low and store in pulseCounts[i]
91+
while (!pi_mmio_input(pin)) {
92+
if (++pulseCounts[i] >= DHT_MAXCOUNT) {
93+
// Timeout waiting for response.
94+
set_default_priority();
95+
return DHT_ERROR_TIMEOUT;
96+
}
97+
}
98+
// Count how long pin is high and store in pulseCounts[i+1]
99+
while (pi_mmio_input(pin)) {
100+
if (++pulseCounts[i+1] >= DHT_MAXCOUNT) {
101+
// Timeout waiting for response.
102+
set_default_priority();
103+
return DHT_ERROR_TIMEOUT;
104+
}
105+
}
106+
}
107+
108+
// Done with timing critical code, now interpret the results.
109+
110+
// Drop back to normal priority.
111+
set_default_priority();
112+
113+
// Compute the average low pulse width to use as a 50 microsecond reference threshold.
114+
// Ignore the first two readings because they are a constant 80 microsecond pulse.
115+
uint32_t threshold = 0;
116+
for (int i=2; i < DHT_PULSES*2; i+=2) {
117+
threshold += pulseCounts[i];
118+
}
119+
threshold /= DHT_PULSES-1;
120+
121+
// Interpret each high pulse as a 0 or 1 by comparing it to the 50us reference.
122+
// If the count is less than 50us it must be a ~28us 0 pulse, and if it's higher
123+
// then it must be a ~70us 1 pulse.
124+
uint8_t data[5] = {0};
125+
for (int i=3; i < DHT_PULSES*2; i+=2) {
126+
int index = (i-3)/16;
127+
data[index] <<= 1;
128+
if (pulseCounts[i] >= threshold) {
129+
// One bit for long pulse.
130+
data[index] |= 1;
131+
}
132+
// Else zero bit for short pulse.
133+
}
134+
135+
// Useful debug info:
136+
//printf("Data: 0x%x 0x%x 0x%x 0x%x 0x%x\n", data[0], data[1], data[2], data[3], data[4]);
137+
138+
// Verify checksum of received data.
139+
if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) {
140+
if (type == DHT11) {
141+
// Get humidity and temp for DHT11 sensor.
142+
*humidity = (float)data[0];
143+
*temperature = (float)data[2];
144+
}
145+
else if (type == DHT22) {
146+
// Calculate humidity and temp for DHT22 sensor.
147+
*humidity = (data[0] * 256 + data[1]) / 10.0f;
148+
*temperature = ((data[2] & 0x7F) * 256 + data[3]) / 10.0f;
149+
if (data[2] & 0x80) {
150+
*temperature *= -1.0f;
151+
}
152+
}
153+
return DHT_SUCCESS;
154+
}
155+
else {
156+
return DHT_ERROR_CHECKSUM;
157+
}
158+
}

dht/Raspberry_Pi/pi_dht_read.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright (c) 2014 Adafruit Industries
2+
// Author: Tony DiCola
3+
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
// copies of the Software, and to permit persons to whom the Software is
9+
// furnished to do so, subject to the following conditions:
10+
11+
// The above copyright notice and this permission notice shall be included in all
12+
// copies or substantial portions of the Software.
13+
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
// SOFTWARE.
21+
#ifndef PI_DHT_READ_H
22+
#define PI_DHT_READ_H
23+
24+
#include "../common_dht_read.h"
25+
26+
// Read DHT sensor connected to GPIO pin (using BCM numbering). Humidity and temperature will be
27+
// returned in the provided parameters. If a successfull reading could be made a value of 0
28+
// (DHT_SUCCESS) will be returned. If there was an error reading the sensor a negative value will
29+
// be returned. Some errors can be ignored and retried, specifically DHT_ERROR_TIMEOUT or DHT_ERROR_CHECKSUM.
30+
int pi_dht_read(int sensor, int pin, float* humidity, float* temperature);
31+
32+
#endif

dht/Raspberry_Pi/pi_mmio.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright (c) 2014 Adafruit Industries
2+
// Author: Tony DiCola
3+
// Based on code from Gert van Loo & Dom: http://elinux.org/RPi_Low-level_peripherals#GPIO_Code_examples
4+
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
// SOFTWARE.
22+
#include <fcntl.h>
23+
#include <stdlib.h>
24+
#include <string.h>
25+
#include <sys/mman.h>
26+
#include <sys/stat.h>
27+
#include <sys/types.h>
28+
#include <unistd.h>
29+
30+
#include "pi_mmio.h"
31+
32+
#define BASE 0x20000000
33+
#define GPIO_BASE (BASE + 0x200000)
34+
#define GPIO_LENGTH 4096
35+
36+
volatile uint32_t* pi_mmio_gpio = NULL;
37+
38+
int pi_mmio_init(void) {
39+
if (pi_mmio_gpio == NULL) {
40+
int fd;
41+
42+
// On older kernels user readable /dev/gpiomem might not exists.
43+
// Falls back to root-only /dev/mem.
44+
if( access( "/dev/gpiomem", F_OK ) != -1 ) {
45+
fd = open("/dev/gpiomem", O_RDWR | O_SYNC);
46+
} else {
47+
fd = open("/dev/mem", O_RDWR | O_SYNC);
48+
}
49+
if (fd == -1) {
50+
// Error opening /dev/gpiomem.
51+
return MMIO_ERROR_DEVMEM;
52+
}
53+
// Map GPIO memory to location in process space.
54+
pi_mmio_gpio = (uint32_t*)mmap(NULL, GPIO_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO_BASE);
55+
close(fd);
56+
if (pi_mmio_gpio == MAP_FAILED) {
57+
// Don't save the result if the memory mapping failed.
58+
pi_mmio_gpio = NULL;
59+
return MMIO_ERROR_MMAP;
60+
}
61+
}
62+
return MMIO_SUCCESS;
63+
}

dht/Raspberry_Pi/pi_mmio.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) 2014 Adafruit Industries
2+
// Author: Tony DiCola
3+
// Based on code from Gert van Loo & Dom: http://elinux.org/RPi_Low-level_peripherals#GPIO_Code_examples
4+
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
// SOFTWARE.
22+
23+
// Simple fast memory-mapped GPIO library for the Raspberry Pi.
24+
#ifndef PI_MMIO_H
25+
#define PI_MMIO_H
26+
27+
#include <stdint.h>
28+
29+
#define MMIO_SUCCESS 0
30+
#define MMIO_ERROR_DEVMEM -1
31+
#define MMIO_ERROR_MMAP -2
32+
33+
extern volatile uint32_t* pi_mmio_gpio;
34+
35+
int pi_mmio_init(void);
36+
37+
static inline void pi_mmio_set_input(const int gpio_number) {
38+
// Set GPIO register to 000 for specified GPIO number.
39+
*(pi_mmio_gpio+((gpio_number)/10)) &= ~(7<<(((gpio_number)%10)*3));
40+
}
41+
42+
static inline void pi_mmio_set_output(const int gpio_number) {
43+
// First set to 000 using input function.
44+
pi_mmio_set_input(gpio_number);
45+
// Next set bit 0 to 1 to set output.
46+
*(pi_mmio_gpio+((gpio_number)/10)) |= (1<<(((gpio_number)%10)*3));
47+
}
48+
49+
static inline void pi_mmio_set_high(const int gpio_number) {
50+
*(pi_mmio_gpio+7) = 1 << gpio_number;
51+
}
52+
53+
static inline void pi_mmio_set_low(const int gpio_number) {
54+
*(pi_mmio_gpio+10) = 1 << gpio_number;
55+
}
56+
57+
static inline uint32_t pi_mmio_input(const int gpio_number) {
58+
return *(pi_mmio_gpio+13) & (1 << gpio_number);
59+
}
60+
61+
#endif

0 commit comments

Comments
 (0)