|
| 1 | +/* Python module for DHT temperature/humidity sensors |
| 2 | + * |
| 3 | + * Modified by Qingping Hou from DHT reader example, original header: |
| 4 | + * |
| 5 | + * How to access GPIO registers from C-code on the Raspberry-Pi |
| 6 | + * Example program |
| 7 | + * 15-January-2012 |
| 8 | + * Dom and Gert |
| 9 | + */ |
| 10 | + |
| 11 | + |
| 12 | +/* for usleep */ |
| 13 | +#define _BSD_SOURCE |
| 14 | + |
| 15 | +#include <stdio.h> |
| 16 | +#include <string.h> |
| 17 | +#include <stdlib.h> |
| 18 | +#include <dirent.h> |
| 19 | +#include <fcntl.h> |
| 20 | +#include <assert.h> |
| 21 | +#include <unistd.h> |
| 22 | +#include <sys/mman.h> |
| 23 | +#include <sys/types.h> |
| 24 | +#include <sys/stat.h> |
| 25 | +#include <sys/time.h> |
| 26 | +#include <bcm2835.h> |
| 27 | +#include <unistd.h> |
| 28 | + |
| 29 | +#include <Python.h> |
| 30 | + |
| 31 | +#define MAXTIMINGS 100 |
| 32 | + |
| 33 | +//#define DEBUG |
| 34 | + |
| 35 | +#define DHT11 11 |
| 36 | +#define DHT22 22 |
| 37 | +#define AM2302 22 |
| 38 | + |
| 39 | +int readDHT(int type, int pin, float *temp_p, float *hum_p) |
| 40 | +{ |
| 41 | + int counter = 0; |
| 42 | + int laststate = HIGH; |
| 43 | + int i = 0; |
| 44 | + int j = 0; |
| 45 | + int checksum = 0; |
| 46 | +#ifdef DEBUG |
| 47 | + int bitidx = 0; |
| 48 | + int bits[250]; |
| 49 | +#endif |
| 50 | + int data[100]; |
| 51 | + |
| 52 | + // Set GPIO pin to output |
| 53 | + bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP); |
| 54 | + |
| 55 | + bcm2835_gpio_write(pin, HIGH); |
| 56 | + usleep(500000); // 500 ms |
| 57 | + bcm2835_gpio_write(pin, LOW); |
| 58 | + usleep(20000); |
| 59 | + |
| 60 | + bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT); |
| 61 | + |
| 62 | + data[0] = data[1] = data[2] = data[3] = data[4] = 0; |
| 63 | + |
| 64 | + // wait for pin to drop? |
| 65 | + while (bcm2835_gpio_lev(pin) == 1) { |
| 66 | + usleep(1); |
| 67 | + } |
| 68 | + |
| 69 | + // read data! |
| 70 | + for (i = 0; i < MAXTIMINGS; i++) { |
| 71 | + counter = 0; |
| 72 | + while ( bcm2835_gpio_lev(pin) == laststate) { |
| 73 | + counter++; |
| 74 | + //nanosleep(1); // overclocking might change this? |
| 75 | + if (counter == 1000) |
| 76 | + break; |
| 77 | + } |
| 78 | + laststate = bcm2835_gpio_lev(pin); |
| 79 | + if (counter == 1000) break; |
| 80 | +#ifdef DEBUG |
| 81 | + bits[bitidx++] = counter; |
| 82 | +#endif |
| 83 | + |
| 84 | + if ((i>3) && (i%2 == 0)) { |
| 85 | + // shove each bit into the storage bytes |
| 86 | + data[j/8] <<= 1; |
| 87 | + if (counter > 200) |
| 88 | + data[j/8] |= 1; |
| 89 | + j++; |
| 90 | + } |
| 91 | + } |
| 92 | + |
| 93 | +#ifdef DEBUG |
| 94 | + for (int i=3; i<bitidx; i+=2) { |
| 95 | + printf("bit %d: %d\n", i-3, bits[i]); |
| 96 | + printf("bit %d: %d (%d)\n", i-2, bits[i+1], bits[i+1] > 200); |
| 97 | + } |
| 98 | + printf("Data (%d): 0x%x 0x%x 0x%x 0x%x 0x%x\n", j, data[0], data[1], data[2], data[3], data[4]); |
| 99 | +#endif |
| 100 | + |
| 101 | + if (j >= 39) { |
| 102 | + checksum = (data[0] + data[1] + data[2] + data[3]) & 0xFF; |
| 103 | + if (data[4] == checksum) { |
| 104 | + /* yay! checksum is valid */ |
| 105 | + if (type == DHT11) { |
| 106 | + /*printf("Temp = %d *C, Hum = %d \%\n", data[2], data[0]);*/ |
| 107 | + *temp_p = (float)data[2]; |
| 108 | + *hum_p = (float)data[0]; |
| 109 | + } else if (type == DHT22) { |
| 110 | + *hum_p = data[0] * 256 + data[1]; |
| 111 | + *hum_p /= 10; |
| 112 | + |
| 113 | + *temp_p = (data[2] & 0x7F)* 256 + data[3]; |
| 114 | + *temp_p /= 10.0; |
| 115 | + if (data[2] & 0x80) |
| 116 | + *temp_p *= -1; |
| 117 | + /*printf("Temp = %.1f *C, Hum = %.1f \%\n", f, h);*/ |
| 118 | + } |
| 119 | + return 0; |
| 120 | + } |
| 121 | + return -2; |
| 122 | + } |
| 123 | + |
| 124 | + return -1; |
| 125 | +} |
| 126 | + |
| 127 | + |
| 128 | +static PyObject * |
| 129 | +dhtreader_init(PyObject *self, PyObject *args) |
| 130 | +{ |
| 131 | + return Py_BuildValue("i", bcm2835_init()); |
| 132 | +} |
| 133 | + |
| 134 | +static PyObject * |
| 135 | +dhtreader_read(PyObject *self, PyObject *args) |
| 136 | +{ |
| 137 | + int type, dhtpin; |
| 138 | + |
| 139 | + if (!PyArg_ParseTuple(args, "ii", &type, &dhtpin)) |
| 140 | + return NULL; |
| 141 | + |
| 142 | + float t, h; |
| 143 | + int re = readDHT(type, dhtpin, &t, &h); |
| 144 | + |
| 145 | + if (re == 0) { |
| 146 | + return Py_BuildValue("(d,d)", t, h); |
| 147 | + } else if (re == -1) { |
| 148 | +#ifdef DEBUG |
| 149 | + printf("sensor read failed! not enough data received\n"); |
| 150 | +#endif |
| 151 | + } else if (re == -2) { |
| 152 | +#ifdef DEBUG |
| 153 | + printf("sensor read failed! checksum failed!\n"); |
| 154 | +#endif |
| 155 | + } |
| 156 | + |
| 157 | + return Py_BuildValue(""); |
| 158 | +} |
| 159 | + |
| 160 | + |
| 161 | +static PyMethodDef DHTReaderMethods[] = { |
| 162 | + {"init", dhtreader_init, METH_VARARGS, |
| 163 | + "initialize dht reader"}, |
| 164 | + {"read", dhtreader_read, METH_VARARGS, |
| 165 | + "temperature and humidity from sensor"}, |
| 166 | + {NULL, NULL, 0, NULL} /* Sentinel */ |
| 167 | +}; |
| 168 | + |
| 169 | +PyMODINIT_FUNC |
| 170 | +initdhtreader(void) |
| 171 | +{ |
| 172 | + PyObject *m; |
| 173 | + |
| 174 | + m = Py_InitModule("dhtreader", DHTReaderMethods); |
| 175 | + if (m == NULL) |
| 176 | + return; |
| 177 | +} |
| 178 | + |
| 179 | + |
0 commit comments