Daha önce burada DHT11’in C kodları ile nasıl okunacağını anlatmıştım. Şimdi de bu kodları biraz daha geliştirip, okunan sıcaklık ve nem değerlerini bir MySQL tablosuna kaydedeceğiz.
Tablomuzun yapısı şöyle:
1 2 3 4 5 6 7 |
CREATE TABLE `logs` ( `id` int(11) NOT NULL AUTO_INCREMENT, `date` int(11) DEFAULT NULL, `temp` int(255) DEFAULT NULL, `rh` int(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; |
Veritabanı tablosunu oluşturduktan sonra aşağıdaki paketlerin sistemde yüklü olduğu teyit edin. Yüklemek için apt-get komutunu kullanabilirsiniz:
- mysql: MySQL client programs and shared library
- mysqlclient: Backlevel MySQL shared libraries (old libs)
- mysql-devel: Files for development of MySQL applications (a must have)
- mysql-server: Mysql server itself
- gcc, make and other development libs: GNU C compiler
algilayici.h kütüphanesinden bahsetmek gerekirse; DHT11’i okuyan kodu dht11.h isimli ayrı bir dosyaya kaydettim. Böylece diğer sensörleri de gerektiğinde include ile ana programa dahil edebileceğiz. dht11.h kodunda, DHT11 sensörünü bağladığınız wiringPi numarasını doğru tanımlamaya dikkat edin, varsayılan olarak önceki yazımda da kullandığım 7 numaralı wiringPi pinini kullanmaya devam ettim.
dht11.h: DHT11 sıcaklık ve nem sensörünü okuyan C kodları
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
[crayon-66cbd2c3f02cf195375129 lang="c" ] /* * Simple test program to test the wiringPi functions * DHT11 test */ #include <wiringPi.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> #define MAXTIMINGS 85 #define DHTPIN 7 int dht11_dat[5] = { 0, 0, 0, 0, 0 }; int read_dht11_dat() { uint8_t laststate = HIGH; uint8_t counter = 0; uint8_t j = 0, i; dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0; /* pull pin down for 18 milliseconds */ pinMode( DHTPIN, OUTPUT ); digitalWrite( DHTPIN, LOW ); delay( 18 ); /* then pull it up for 40 microseconds */ digitalWrite( DHTPIN, HIGH ); delayMicroseconds( 40 ); /* prepare to read the pin */ pinMode( DHTPIN, INPUT ); /* detect change and read data */ for ( i = 0; i < MAXTIMINGS; i++ ) { counter = 0; while ( digitalRead( DHTPIN ) == laststate ) { counter++; delayMicroseconds( 1 ); if ( counter == 255 ) { break; } } laststate = digitalRead( DHTPIN ); if ( counter == 255 ) break; /* ignore first 3 transitions */ if ( (i >= 4) && (i % 2 == 0) ) { /* shove each bit into the storage bytes */ dht11_dat[j / 8] <<= 1; if ( counter > 16 ) dht11_dat[j / 8] |= 1; j++; } } /* * check we read 40 bits (8bit x 5 ) + verify checksum in the last byte * print it out if data is good */ if ( (j >= 40) && (dht11_dat[4] == ( (dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF) ) ) { //printf( "Sicaklik = %d.%d *C Nem = %d.%d %%\n", //dht11_dat[2], dht11_dat[3], dht11_dat[0], dht11_dat[1] ); return 1; }else { //printf( "Veri alinamadi, geciliyor\n" ); return 0; } } |
algilayici.c ana programımızın yer aldığı dosyamız. Dosyanın tanım kısmında yer alan veritabanı adı ve ve kullanıcı bilgilerini kendinize göre düzenlemeyi unutmayın. Kodları incelerseniz her saniye okunan sıcaklık ve nem verisi sadece bir önceki okumadan farklı ise veritabanına kaydediliyor. Böylece veritabanının gereksiz yere veri ile dolmasının önüne geçmiş oluyoruz.
algilayici.c Ana programımızın C kaynak dosyası
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
[crayon-66cbd2c3f02db362868003 lang="c" ] #include <mysql.h> #include <stdio.h> #include <time.h> #include "dht11.h" MYSQL *conn; int mysql_baglan(void) { MYSQL_RES *res; MYSQL_ROW row; // Veritabani parametreleri char *server = "localhost"; char *user = "root"; char *password = "root"; char *database = "sensor"; // Mysql hazirla conn = mysql_init(NULL); if (conn == NULL) { fprintf(stderr, "%s\n", mysql_error(conn)); return 0; } // Veritabanina baglan if (!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) { fprintf(stderr, "%s\n", mysql_error(conn)); return 0; } return 1; } int main(void) { char sql[100]; int last_temp, last_rh; int timestamp; // Veritabanı baglantisini kur if (!mysql_baglan()) { printf("MySQL connection error!"); exit(3306); } // wiringPi'yi hazirla if ( wiringPiSetup() == -1 ) { printf("wiringPiSetup error!"); exit(3307); } // Sonsuz donguye gir while ( 1 ) { // ----------------------------- // DHT11 sensorunu oku // ----------------------------- if (read_dht11_dat()) { // Sicalik veya nem degismis mi? if ((last_temp != dht11_dat[2]) || (last_rh != dht11_dat[0])) { // SQL sorgusunu calistir sprintf (sql, "insert into logs (date, temp, rh) values (%d, %d,%d)", (int)time(NULL), dht11_dat[2], dht11_dat[0]); printf("%s\n", sql); if (mysql_query(conn, sql)) { fprintf(stderr, "%s\n", mysql_error(conn)); } last_temp = dht11_dat[2]; last_rh = dht11_dat[0]; } } // Tekrar okumak icin bekle delay(1 * 1000 ); } return 0; } |
Kodu derleyip çalıştırmak için derle.sh adında bir betik oluşturdum. Betiğin içeriği şöyle:
1 2 3 4 5 6 7 |
[crayon-66cbd2c3f02f1630949489 lang="bash" ] gcc -o algilayici $(mysql_config --cflags) algilayici.c $(mysql_config --libs) -l wiringPi chmod 755 algilayici ./algilayici |
Betiği ./derle.sh komutu vererek çalıştırdığınızda aşağıdaki gibi bir ekran görüntüsü ile karşılaşacaksınız.
Kodu bir süre çalıştırdığınızda aşağıdaki gibi bir veri listesine sahip olacaksınız.
Kodu sürekli olarak arka planda çalıştırmak için ./algilayici & komutunu vererek arka plana atın (& ampersant işareti programı interaktif konsoldan ayırıp geri planda çalıştırır)
Burada anlattığım konuya ait tüm dosyaları indirmek için aşağıdaki indirme bağlantısını kullanabilirsiniz.
Hata Ayıklama (Şubat 2015)
Algilayici’nin bu sürümü hatalara karşı pek dayanıklı değil. Daha da geliştirilmesi gerektiğini belirtmem gerekiyor. Özellikle programı arka planda çalıştırıyorsanız muhtemel program çökmelerinden ve nedenlerinden haberiniz olamayacaktır.
fprintf ile stderr çıktısına yazılan hata mesajlarını kayıt altına alabilirsiniz. Böylece konsola geri döndüğünüzde olası çökmenin nedeni hakkında elinizde bir veri olacaktır. Algılayıcı programı tarafından stderr çıktısına yönlendirilen mesajları almak için programı aşağıdaki şekilde çalıştırarak kullanabilirsiniz.
1 2 3 4 5 |
[crayon-66cbd2c3f02fc812665733 lang="bash" ] ./algilayici  > sensor.txt 2> sensor_err.txt & |
sensor.txt dosyasında ekrana yazılan SQL satırları, sensor_err.txt dosyasında ise hata mesajları kayıt alına alınacaktır. Tahmin edebileceğiniz gibi 2> belirteci, stderr hata çıktısını belirtilen dosyaya yönlendirmektedir. Hem standart çıktıları hem de hata çıktılarını aynı dosyaya yönlendirmek isterseniz aşağıdaki komut satırı numarasını kullanabilirsiniz.
1 2 3 |
[crayon-66cbd2c3f0302093702414 lang="bash" ] ./algilayici > sensor.txt 2>&1 |
Kaynaklar:
http://www.cyberciti.biz/tips/linux-unix-connect-mysql-c-api-program.html
http://www.cyberciti.biz/faq/linux-redirect-error-output-to-file/
bu kod ile eksi değer alamıyoruz sanırım? nasıl bir yöntem izleyebiliriz eksi değerler için?
Merhaba,
Bu durum kod ile ilgili değil. DHT11 sensörü veri sayfasında 0-50 derece arasında ölçüm yapabildiği yazmış. DHT22 sensörünü kullanarak ile -40 ile 100 arasını ölçebilirsiniz.