41 extern int SIMlight; |
41 extern int SIMlight; |
42 |
42 |
43 #endif |
43 #endif |
44 |
44 |
45 |
45 |
46 #ifdef HAVE_WIRINGPI_H |
|
47 |
|
48 #define MAXTIMINGS 100 |
46 #define MAXTIMINGS 100 |
49 |
47 |
50 /* |
48 /* |
51 * Since kernel version 4 there is a module, and a dtoverlay so that the |
49 * Since kernel version 4 there is a module, and a dtoverlay so that the |
52 * temperature and humidity can simply read from the /sys filesystem. |
50 * temperature and humidity can simply read from the /sys filesystem. |
53 * But this isn't as reliable as this userspace function, so we leave |
51 * But this isn't as reliable as this userspace function, so we leave |
54 * that here. |
52 * that here. |
55 */ |
53 */ |
56 |
54 |
57 int dht11_pin = -1; |
|
58 int dht11_temperature = -1; |
55 int dht11_temperature = -1; |
59 int dht11_humidity = -1; |
56 int dht11_humidity = -1; |
60 int dht11_valid = FALSE; |
57 int dht11_valid = FALSE; |
|
58 int dht11_present = FALSE; |
61 time_t dht11_last = (time_t)0; |
59 time_t dht11_last = (time_t)0; |
62 |
|
63 |
|
64 static uint8_t sizecvt(const int read_value) { |
|
65 /* |
|
66 * digitalRead() and friends from wiringpi are defined as returning a value |
|
67 * < 256. However, they are returned as int() types. This is a safety function |
|
68 */ |
|
69 if (read_value > 255 || read_value < 0) { |
|
70 syslog(LOG_NOTICE, "invalid data from wiringPi library"); |
|
71 } |
|
72 |
|
73 return (uint8_t)read_value; |
|
74 } |
|
75 |
60 |
76 |
61 |
77 |
62 |
78 /* |
63 /* |
79 * DHT11 sensor read. |
64 * DHT11 sensor read. |
80 */ |
65 */ |
81 void dht11Read(void) { |
66 void dht11Read(void) |
82 int tries = 5; |
67 { |
83 unsigned short got_correct_data = 0; |
68 int tries, temp, hum; |
84 struct timespec ts; |
69 int fd, rc, err; |
85 |
70 char buffer[25]; |
86 if (dht11_pin == -1) |
71 |
|
72 dht11_valid = FALSE; |
|
73 dht11_present = FALSE; |
|
74 dht11_temperature = -1; |
|
75 dht11_humidity = -1; |
|
76 |
|
77 /* |
|
78 * Read DHT11 name. This only means the kernel module is loaded, |
|
79 * it doesn't show if the chip is really present. |
|
80 */ |
|
81 fd = open("/sys/bus/iio/devices/iio:device0/name", O_RDONLY); |
|
82 if (fd == -1) { |
|
83 syslog(LOG_NOTICE, "no DHT11 device"); |
87 return; |
84 return; |
88 |
85 } |
89 while (tries && !got_correct_data) { |
86 |
90 uint8_t laststate = HIGH; |
87 memset(&buffer, 0, 25); |
91 uint8_t counter = 0; |
88 read(fd, buffer, 25); |
92 uint8_t j = 0, i = 0; |
89 close(fd); |
93 int dht11_dat[5] = {0,0,0,0,0}; |
90 buffer[strlen(buffer) - 1] = '\0'; |
94 |
91 syslog(LOG_NOTICE, "dht11 name %s", buffer); |
95 /* |
92 |
96 * Select output mode to send the start signal. |
93 tries = 5; |
97 */ |
94 while (tries) { |
98 pinMode(dht11_pin, OUTPUT); |
95 |
99 digitalWrite(dht11_pin, HIGH); |
96 fd = open("/sys/bus/iio/devices/iio:device0/in_temp_input", O_RDONLY); |
100 /* 1 mSec */ |
97 rc = read(fd, buffer, 25); |
101 ts.tv_sec = 0; |
98 if (rc == -1) { |
102 ts.tv_nsec = 1000000; |
99 err = errno; |
103 nanosleep(&ts, &ts); |
100 syslog(LOG_NOTICE, "DHT11 read temperature: %d %s", err, strerror(err)); |
104 |
|
105 /* |
|
106 * Low for at least 18 milliseconds |
|
107 */ |
|
108 digitalWrite(dht11_pin, LOW); |
|
109 /* 20 mSec */ |
|
110 ts.tv_sec = 0; |
|
111 ts.tv_nsec = 20 * 1000000; |
|
112 nanosleep(&ts, &ts); |
|
113 digitalWrite(dht11_pin, HIGH); |
|
114 pinMode(dht11_pin, INPUT); |
|
115 |
|
116 /* |
|
117 * Detect change and read data |
|
118 */ |
|
119 for (i=0; i<MAXTIMINGS; i++) { |
|
120 counter = 0; |
|
121 /* 10 uS */ |
|
122 ts.tv_sec = 0; |
|
123 ts.tv_nsec = 10 * 1000; |
|
124 // nanosleep(&ts, NULL); |
|
125 delayMicroseconds(10); |
|
126 while (sizecvt(digitalRead(dht11_pin)) == laststate) { |
|
127 counter++; |
|
128 /* 1 uS */ |
|
129 ts.tv_sec = 0; |
|
130 ts.tv_nsec = 1000; |
|
131 // nanosleep(&ts, NULL); |
|
132 delayMicroseconds(1); |
|
133 if (counter == 255) { |
|
134 break; |
|
135 } |
|
136 } |
|
137 laststate = sizecvt(digitalRead(dht11_pin)); |
|
138 |
|
139 if (counter == 255) |
|
140 break; |
|
141 |
|
142 /* |
|
143 * ignore first 3 transitions |
|
144 */ |
|
145 if ((i >= 4) && (i%2 == 0)) { |
|
146 |
|
147 // shove each bit into the storage bytes |
|
148 dht11_dat[(int)((double)j/8)] <<= 1; |
|
149 if (counter > 16) |
|
150 dht11_dat[(int)((double)j/8)] |= 1; |
|
151 j++; |
|
152 } |
|
153 } |
|
154 |
|
155 /* |
|
156 * If there is no sensor, j = 0 |
|
157 */ |
|
158 if ((counter == 255) && (j == 0)) { |
|
159 if (dht11_temperature != -1) { |
|
160 syslog(LOG_NOTICE, "dht11 sensor disappeared"); |
|
161 } else { |
|
162 syslog(LOG_NOTICE, "dht11 sensor not present"); |
|
163 } |
|
164 dht11_temperature = -1; |
101 dht11_temperature = -1; |
|
102 } else { |
|
103 sscanf(buffer, "%d", &temp); |
|
104 syslog(LOG_NOTICE, "read temp rc=%d %f", rc, temp / 1000.0); |
|
105 dht11_temperature = temp; |
|
106 } |
|
107 close(fd); |
|
108 |
|
109 fd = open("/sys/bus/iio/devices/iio:device0/in_humidityrelative_input", O_RDONLY); |
|
110 rc = read(fd, buffer, 25); |
|
111 if (rc == -1) { |
|
112 err = errno; |
|
113 syslog(LOG_NOTICE, "DHT11 read temperature: %d %s", err, strerror(err)); |
165 dht11_humidity = -1; |
114 dht11_humidity = -1; |
166 dht11_valid = FALSE; |
|
167 return; |
|
168 } |
|
169 |
|
170 /* |
|
171 * check we read 40 bits (8bit x 5 ) + verify checksum in the last byte |
|
172 * print it out if data is good |
|
173 */ |
|
174 if ((j >= 40) && (dht11_dat[4] == ((dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF))) { |
|
175 got_correct_data = 1; |
|
176 |
|
177 int h = dht11_dat[0] + dht11_dat[1]; |
|
178 int t = (dht11_dat[2] & 0x7F) + dht11_dat[3]; |
|
179 |
|
180 if ((dht11_dat[2] & 0x80) != 0) |
|
181 t *= -1; |
|
182 |
|
183 dht11_temperature = t; |
|
184 dht11_humidity = h; |
|
185 dht11_valid = TRUE; |
|
186 syslog(LOG_NOTICE, "dht11 t:%d h:%d tries:%d", t, h, 6-tries); |
|
187 } else { |
115 } else { |
188 tries--; |
116 sscanf(buffer, "%d", &hum); |
189 if (tries == 0) |
117 syslog(LOG_NOTICE, "read hum rc=%d %f", rc, hum / 1000.0); |
190 syslog(LOG_NOTICE, "dht11 data checksum was wrong 5 times"); |
118 dht11_humidity = hum; |
191 usleep(100000); |
119 } |
192 } |
120 close(fd); |
193 } |
121 |
|
122 tries = 0; |
|
123 } |
|
124 |
|
125 dht11_valid = TRUE; |
|
126 syslog(LOG_NOTICE, "dht11 t:%d h:%d tries:%d", dht11_temperature, dht11_humidity, 6-tries); |
194 } |
127 } |
195 |
128 |
196 #endif |
|
197 |
129 |
198 |
130 |
199 /* |
131 /* |
200 * Read one byte from a 1-wire device like a DS2413 |
132 * Read one byte from a 1-wire device like a DS2413 |
201 */ |
133 */ |
543 } |
481 } |
544 |
482 |
545 /* |
483 /* |
546 * DHT11 as kernel module. |
484 * DHT11 as kernel module. |
547 */ |
485 */ |
|
486 if ((fi = open((char *)"/sys/bus/iio/devices/iio:device0/name", O_RDONLY))) { |
|
487 char buffer[25]; |
|
488 |
|
489 memset(&buffer, 0, 25); |
|
490 read(fi, buffer, 25); |
|
491 close(fi); |
|
492 buffer[strlen(buffer) - 1] = '\0'; |
|
493 |
|
494 found = FALSE; |
|
495 for (device = Config.devices; device; device = device->next) { |
|
496 if (strcmp(device->address, buffer) == 0) { |
|
497 found = TRUE; |
|
498 break; |
|
499 } |
|
500 } |
|
501 |
|
502 if (found == FALSE) { |
|
503 for (i = 0; i < 2; i++) { |
|
504 ndev = (devices_list *)malloc(sizeof(devices_list)); |
|
505 ndev->next = NULL; |
|
506 ndev->uuid = malloc(37); |
|
507 uuid_generate(uu); |
|
508 uuid_unparse(uu, ndev->uuid); |
|
509 ndev->type = DEVTYPE_DHT; |
|
510 ndev->direction = DEVDIR_IN_ANALOG; |
|
511 if (i == 0) |
|
512 ndev->description = xstrcpy((char *)"DHT11 temperature sensor"); |
|
513 else |
|
514 ndev->description = xstrcpy((char *)"DHT11 humidity sensor"); |
|
515 ndev->value = ndev->offset = ndev->inuse = 0; |
|
516 ndev->present = DEVPRESENT_YES; |
|
517 ndev->address = xstrcpy(buffer); |
|
518 ndev->subdevice = i; |
|
519 ndev->gpiopin = -1; |
|
520 ndev->comment = xstrcpy((char *)"Auto detected device"); |
|
521 ndev->timestamp = time(NULL); |
|
522 |
|
523 if (Config.devices == NULL) { |
|
524 Config.devices = ndev; |
|
525 } else { |
|
526 for (device = Config.devices; device; device = device->next) { |
|
527 if (device->next == NULL) { |
|
528 device->next = ndev; |
|
529 break; |
|
530 } |
|
531 } |
|
532 } |
|
533 rc++; |
|
534 } |
|
535 } |
|
536 } |
548 |
537 |
549 #ifdef HAVE_WIRINGPI_H |
538 #ifdef HAVE_WIRINGPI_H |
550 if (piBoardRev() == 2) { |
539 if (piBoardRev() == 2) { |
551 /* |
540 /* |
552 * Support rev B and newer boards only |
541 * Support rev B and newer boards only |
905 addr = NULL; |
892 addr = NULL; |
906 } |
893 } |
907 |
894 |
908 break; |
895 break; |
909 |
896 |
910 #ifdef HAVE_WIRINGPI_H |
|
911 case DEVTYPE_DHT: |
897 case DEVTYPE_DHT: |
912 /* |
898 /* |
913 * Make sure we don't read the sensor within 2 seconds. |
899 * Make sure we don't read the sensor within 2 seconds. |
914 * But we use 30 seconds interval. |
900 * But we use 30 seconds interval. |
915 */ |
901 */ |
916 now = time(NULL); |
902 now = time(NULL); |
917 if ((int)(now - dht11_last) > 30) { |
903 if ((int)(now - dht11_last) > 30) { |
918 if (device->subdevice == 0) { |
904 if (device->subdevice == 0) { |
919 /* Read once during subdevice 0 */ |
905 /* Read once during subdevice 0 */ |
920 dht11_pin = device->gpiopin; |
|
921 dht11Read(); |
906 dht11Read(); |
922 pthread_mutex_lock(&mutexes[LOCK_DEVICES]); |
907 pthread_mutex_lock(&mutexes[LOCK_DEVICES]); |
923 if (dht11_valid) { |
908 if (dht11_valid) { |
924 device->value = dht11_temperature * 1000; |
909 device->value = dht11_temperature; |
925 device->timestamp = time(NULL); |
910 device->timestamp = time(NULL); |
926 device->present = DEVPRESENT_YES; |
911 device->present = DEVPRESENT_YES; |
927 } else { |
912 } else { |
928 device->present = DEVPRESENT_ERROR; |
913 device->present = DEVPRESENT_ERROR; |
929 } |
914 } |
930 pthread_mutex_unlock(&mutexes[LOCK_DEVICES]); |
915 pthread_mutex_unlock(&mutexes[LOCK_DEVICES]); |
931 } else if (device->subdevice == 1) { |
916 } else if (device->subdevice == 1) { |
932 /* Data already present */ |
917 /* Data already present */ |
933 pthread_mutex_lock(&mutexes[LOCK_DEVICES]); |
918 pthread_mutex_lock(&mutexes[LOCK_DEVICES]); |
934 if (dht11_valid) { |
919 if (dht11_valid) { |
935 device->value = dht11_humidity * 1000; |
920 device->value = dht11_humidity; |
936 device->timestamp = time(NULL); |
921 device->timestamp = time(NULL); |
937 device->present = DEVPRESENT_YES; |
922 device->present = DEVPRESENT_YES; |
938 } else { |
923 } else { |
939 device->present = DEVPRESENT_ERROR; |
924 device->present = DEVPRESENT_ERROR; |
940 } |
925 } |