thermferm/devices.c

changeset 647
fcd85176ea2e
parent 646
e3edc783006b
child 648
62c5ed1b9cfd
equal deleted inserted replaced
646:e3edc783006b 647:fcd85176ea2e
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 */
450 */ 382 */
451 int devices_detect(void) 383 int devices_detect(void)
452 { 384 {
453 struct dirent *de; 385 struct dirent *de;
454 DIR *fd; 386 DIR *fd;
387 int fi;
455 devices_list *device, *ndev; 388 devices_list *device, *ndev;
456 int found, subdevices, ival, i, rc = 0; 389 int found, subdevices, ival, i, rc = 0;
457 char buf[40]; 390 char buf[40];
458 uuid_t uu; 391 uuid_t uu;
459 #ifdef HAVE_WIRINGPI_H 392 #ifdef HAVE_WIRINGPI_H
477 if (found == FALSE) { 410 if (found == FALSE) {
478 strncpy(buf, de->d_name, 2); 411 strncpy(buf, de->d_name, 2);
479 buf[2] = '\0'; 412 buf[2] = '\0';
480 sscanf(buf, "%02x", &ival); 413 sscanf(buf, "%02x", &ival);
481 syslog(LOG_NOTICE, "Scan 1-wire %02x %d", ival, ival); 414 syslog(LOG_NOTICE, "Scan 1-wire %02x %d", ival, ival);
482 subdevices = 1; 415 subdevices = 0;
416 /*
417 * ival is zero when a ghost sensor is detected.
418 */
419 if (ival > 0)
420 subdevices = 1;
483 if (strcmp(buf, (char *)"29") == 0) 421 if (strcmp(buf, (char *)"29") == 0)
484 subdevices = 8; 422 subdevices = 8;
485 if (strcmp(buf, (char *)"3a") == 0) 423 if (strcmp(buf, (char *)"3a") == 0)
486 subdevices = 2; 424 subdevices = 2;
487 for (i = 0; i < subdevices; i++) { 425 for (i = 0; i < subdevices; i++) {
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
726 simulator_list *simulator; 715 simulator_list *simulator;
727 #endif 716 #endif
728 char *addr = NULL, line1[60], line2[60], *p = NULL; 717 char *addr = NULL, line1[60], line2[60], *p = NULL;
729 FILE *fp; 718 FILE *fp;
730 int temp, rc; 719 int temp, rc;
731 #ifdef HAVE_WIRINGPI_H
732 time_t now; 720 time_t now;
733 #endif
734 721
735 my_devices_state = 1; 722 my_devices_state = 1;
736 syslog(LOG_NOTICE, "Thread my_devices_loop started"); 723 syslog(LOG_NOTICE, "Thread my_devices_loop started");
737 724
738 #ifdef HAVE_WIRINGPI_H 725 #ifdef HAVE_WIRINGPI_H
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 }
942 dht11_last = now; /* Okay for a new reading. */ 927 dht11_last = now; /* Okay for a new reading. */
943 } 928 }
944 } 929 }
945 break; 930 break;
946 931
932 #ifdef HAVE_WIRINGPI_H
947 case DEVTYPE_GPIO: 933 case DEVTYPE_GPIO:
948 if (device->direction == DEVDIR_IN_BIN) { 934 if (device->direction == DEVDIR_IN_BIN) {
949 pthread_mutex_lock(&mutexes[LOCK_DEVICES]); 935 pthread_mutex_lock(&mutexes[LOCK_DEVICES]);
950 device->value = digitalRead(device->gpiopin); 936 device->value = digitalRead(device->gpiopin);
951 device->offset = 0; 937 device->offset = 0;

mercurial