센서값을 저장하는 서버 프로그램이 있어야 한다. 프로그램은 demodb.cpp 파일로 만든다. 아래는 전체 코드를 보여준다. 소스코드는 길지만 윗부분의 데이터베이스 설정하고 연결하는 부분만 참고한다. 라인넘버는 53, 108 라인 부근이다.
142 라인의 delay 값을 바꾸면 반복적으로 데이터베이스에 센서 데이터를 저장하는 시간을 변경할 수 있다.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <mysql/mysql.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <math.h>
#define CS_MCP3208 8 // BCM_GPIO_8
#define SPI_CHANNEL 0
#define SPI_SPEED 1000000 // 1MHz
#define VCC 4.8 // Supply Voltage
// define farm
#define MAXTIMINGS 85
#define RETRY 5
#define PUMP 21 // BCM_GPIO 5
#define FAN 22 // BCM_GPIO 6
#define DCMOTOR 23 // BCM_GPIO 13
#define RGBLEDPOWER 24 //BCM_GPIO 19
#define RED 7
#define GREEN 8
#define BLUE 9
#define LIGHTSEN_OUT 2 //gpio27 - J13 connect
int ret_humid, ret_temp;
static int DHTPIN = 11;
static int dht22_dat[5] = {0,0,0,0,0};
int read_dht22_dat_temp();
int read_dht22_dat_humid();
int get_temperature_sensor();
int get_humidity_sensor();
int get_light_sensor();
static int read_dht22_dat();
// here
//#define DBHOST "localhost"
#define DBHOST "127.0.0.1"
#define DBUSER "smartiot"
#define DBPASS "1234"
#define DBNAME "demofarmdb"
MYSQL *connector;
MYSQL_RES *result;
MYSQL_ROW row;
int read_mcp3208_adc(unsigned char adcChannel)
{
unsigned char buff[3];
int adcValue = 0;
buff[0] = 0x06 | ((adcChannel & 0x07) >> 2);
buff[1] = ((adcChannel & 0x07) << 6);
buff[2] = 0x00;
digitalWrite(CS_MCP3208, 0); // Low : CS Active
wiringPiSPIDataRW(SPI_CHANNEL, buff, 3);
buff[1] = 0x0F & buff[1];
adcValue = ( buff[1] << 8) | buff[2];
digitalWrite(CS_MCP3208, 1); // High : CS Inactive
return adcValue;
}
int main (void)
{
int adcChannel = 0;
int adcValue[8] = {0};
if (wiringPiSetup() == -1)
exit(EXIT_FAILURE) ;
if (setuid(getuid()) < 0)
{
perror("Dropping privileges failed\n");
exit(EXIT_FAILURE);
}
if(wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) == -1)
{
fprintf (stdout, "wiringPiSPISetup Failed: %s\n", strerror(errno));
return 1 ;
}
pinMode(CS_MCP3208, OUTPUT);
// MySQL connection
connector = mysql_init(NULL);
if (!mysql_real_connect(connector, DBHOST, DBUSER, DBPASS, DBNAME, 3306, NULL, 0))
{
fprintf(stderr, "%s\n", mysql_error(connector));
return 0;
}
printf("MySQL(rpidb) opened.\n");
while(1)
{
char query[1024];
adcValue[0] = get_temperature_sensor(); // Temperature Sensor
adcValue[1] = get_humidity_sensor(); // Humidity Sensor
adcValue[2] = get_light_sensor(); // Illuminance Sensor
adcValue[3] = read_mcp3208_adc(3); // Mic Sensor
adcValue[4] = read_mcp3208_adc(4); // Flame Sensor
adcValue[5] = read_mcp3208_adc(5); // Acceleration Sensor (Z-Axis)
adcValue[6] = read_mcp3208_adc(6); // Gas Sensor
adcValue[7] = read_mcp3208_adc(7); // Distace Sensor
//adcValue[7] = 27*pow((double)(adcValue[7]*VCC/4095), -1.10);
sprintf(query,"insert into thl values (now(),%d,%d,%d)", adcValue[0],adcValue[1],adcValue[2]);
if(mysql_query(connector, query))
{
fprintf(stderr, "%s\n", mysql_error(connector));
printf("Write DB error\n");
}
delay(3000); //1sec delay
}
mysql_close(connector);
return 0;
}
int get_temperature_sensor()
{
int received_temp;
int _retry = RETRY;
//DHTPIN = 11;
/*if (wiringPiSetup() == -1)
exit(EXIT_FAILURE) ;*/
if (setuid(getuid()) < 0)
{
perror("Dropping privileges failed\n");
exit(EXIT_FAILURE);
}
while (read_dht22_dat_temp() == 0 && _retry--)
{
delay(500); // wait 1sec to refresh
}
received_temp = ret_temp ;
printf("Temperature = %d\n", received_temp);
return received_temp;
}
static uint8_t sizecvt(const int read)
{
/* digitalRead() and friends from wiringpi are defined as returning a value
< 256. However, they are returned as int() types. This is a safety function */
if (read > 255 || read < 0)
{
printf("Invalid data from wiringPi library\n");
exit(EXIT_FAILURE);
}
return (uint8_t)read;
}
int read_dht22_dat_temp()
{
uint8_t laststate = HIGH;
uint8_t counter = 0;
uint8_t j = 0, i;
dht22_dat[0] = dht22_dat[1] = dht22_dat[2] = dht22_dat[3] = dht22_dat[4] = 0;
// pull pin down for 18 milliseconds
pinMode(DHTPIN, OUTPUT);
digitalWrite(DHTPIN, HIGH);
delay(10);
digitalWrite(DHTPIN, LOW);
delay(18);
// then pull it up for 40 microseconds
digitalWrite(DHTPIN, HIGH);
delayMicroseconds(40);
// prepar
pinMode(DHTPIN, INPUT);
// detect change and read data
for ( i=0; i< MAXTIMINGS; i++) {
counter = 0;
while (sizecvt(digitalRead(DHTPIN)) == laststate) {
counter++;
delayMicroseconds(1);
if (counter == 255) {
break;
}
}
laststate = sizecvt(digitalRead(DHTPIN));
if (counter == 255) break;
// ignore first 3 transitions
if ((i >= 4) && (i%2 == 0)) {
// shove each bit into the storage bytes
dht22_dat[j/8] <<= 1;
if (counter > 16)
dht22_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) &&
(dht22_dat[4] == ((dht22_dat[0] + dht22_dat[1] + dht22_dat[2] + dht22_dat[3]) & 0xFF)) ) {
float t, h;
h = (float)dht22_dat[0] * 256 + (float)dht22_dat[1];
h /= 10;
t = (float)(dht22_dat[2] & 0x7F)* 256 + (float)dht22_dat[3];
t /= 10.0;
if ((dht22_dat[2] & 0x80) != 0) t *= -1;
ret_humid = (int)h;
ret_temp = (int)t;
printf("Humidity = %.2f %% Temperature = %.2f *C \n", h, t );
printf("Humidity = %d Temperature = %d\n", ret_humid, ret_temp);
return ret_temp;
}
else
{
printf("Data not good, skip\n");
return 0;
}
}
int get_humidity_sensor()
{
int received_humid;
int _retry = RETRY;
//DHTPIN = 11;
/*if (wiringPiSetup() == -1)
exit(EXIT_FAILURE) ;*/
if (setuid(getuid()) < 0)
{
perror("Dropping privileges failed\n");
exit(EXIT_FAILURE);
}
while (read_dht22_dat_humid() == 0 && _retry--)
{
delay(500); // wait 1sec to refresh
}
received_humid = ret_humid;
printf("Humidity = %d\n", received_humid);
return received_humid;
}
int read_dht22_dat_humid()
{
uint8_t laststate = HIGH;
uint8_t counter = 0;
uint8_t j = 0, i;
dht22_dat[0] = dht22_dat[1] = dht22_dat[2] = dht22_dat[3] = dht22_dat[4] = 0;
// pull pin down for 18 milliseconds
pinMode(DHTPIN, OUTPUT);
digitalWrite(DHTPIN, HIGH);
delay(10);
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 (sizecvt(digitalRead(DHTPIN)) == laststate)
{
counter++;
delayMicroseconds(1);
if (counter == 255) {
break;
}
}
laststate = sizecvt(digitalRead(DHTPIN));
if (counter == 255) break;
// ignore first 3 transitions
if ((i >= 4) && (i%2 == 0))
{
// shove each bit into the storage bytes
dht22_dat[j/8] <<= 1;
if (counter > 16)
dht22_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) &&
(dht22_dat[4] == ((dht22_dat[0] + dht22_dat[1] + dht22_dat[2] + dht22_dat[3]) & 0xFF)) ) {
float t, h;
h = (float)dht22_dat[0] * 256 + (float)dht22_dat[1];
h /= 10;
t = (float)(dht22_dat[2] & 0x7F)* 256 + (float)dht22_dat[3];
t /= 10.0;
if ((dht22_dat[2] & 0x80) != 0) t *= -1;
ret_humid = (int)h;
ret_temp = (int)t;
printf("Humidity = %.2f %% Temperature = %.2f *C \n", h, t );
printf("Humidity = %d Temperature = %d\n", ret_humid, ret_temp);
return ret_humid;
}
else
{
printf("Data not good, skip\n");
return 0;
}
}
int wiringPicheck(void)
{
if (wiringPiSetup () == -1)
{
fprintf(stdout, "Unable to start wiringPi: %s\n", strerror(errno));
return 1 ;
}
}
int get_light_sensor(void)
{
// sets up the wiringPi library
/*if (wiringPiSetup () < 0)
{
fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror (errno));
return 1;
}*/
if(digitalRead(LIGHTSEN_OUT)) //day
return 1;
else //night
return 0;
}
위 코드를 아래와 같은 명령어를 사용해 컴파일 한다.
$ g++ -o demodb demodb.cpp -lwiringPi -mariadbclient
실행은
$ sudo ./demodb
실행하면 3초 간격으로 센서 데이터 값을 읽어 데이터베이스 demofarmdb의 적당한 테이블에 기록한다. 아래는 실행 화면이다.
pi@raspberrypi:~/demofarmdb $ sudo ./demodb
MySQL(rpidb) opened.
Humidity = 52.20 % Temperature = 27.10 *C
Humidity = 52 Temperature = 27
Temperature = 27
Humidity = 52.20 % Temperature = 27.10 *C
Humidity = 52 Temperature = 27
Humidity = 52
Humidity = 51.90 % Temperature = 27.10 *C
Humidity = 51 Temperature = 27
Temperature = 27
Humidity = 52.00 % Temperature = 27.10 *C
Humidity = 52 Temperature = 27
Humidity = 52
Humidity = 52.10 % Temperature = 27.10 *C
Humidity = 52 Temperature = 27
Temperature = 27
Humidity = 52.10 % Temperature = 27.10 *C
Humidity = 52 Temperature = 27
Humidity = 52
아래 php 파일을 실행시키느라 고생을 했는데 이전 버전에서는 아래와 같은 에러가 많이 발생했는데 다 수정하고 고쳤다.
Fatal error: Uncaught Error: Call to undefined function mysql_connect() in /var/www/html/viewfarm.php:4 Stack trace: #0 {main} thrown in /var/www/html/viewfarm.php on line 4
이 에러 해결 방법은 - mysql_connect() 함수는 php7이상부터 삭제됨(phpinfo()로 확인) mysqli_connect() 함수 써야함 구식 mysql 함수는 못 씀 pdo_mysql 이나 mysqli 둘 중에 하나 써야함
Fatal error: Uncaught Error: Call to undefined function mysql_select_db() in /var/www/html/viewfarm.php:5 Stack trace: #0 {main} thrown in /var/www/html/viewfarm.php on line 5
위 에러는 아래 그림처럼 함수가 변경되었다. 그러니까 database 연결할 때 mysql_connect 가 아니라 mysqli_connect 를 사용해야 한다.
Fatal error: Uncaught Error: Call to undefined function mysql_query() in /var/www/html/viewfarm.php:8 Stack trace: #0 {main} thrown in /var/www/html/viewfarm.php on line 8
Connect Success!
Warning: mysqli_query() expects at least 2 parameters, 1 given in /var/www/html/viewfarm.php on line 8
Warning: mysqli_error() expects exactly 1 parameter, 0 given in /var/www/html/viewfarm.php on line 8 Query Fail:
이 에러는 mysql_query($query); -> mysqli_query($conn, $query); 를 사용해서 해결한다.
Connect Success!
Fatal error: Uncaught Error: Call to undefined function mysql_fetch_array() in /var/www/html/viewfarm.php:10 Stack trace: #0 {main} thrown in /var/www/html/viewfarm.php on line 10
Time TEM HUM ILL
이 에러는
Fatal error: Uncaught Error: Call to undefined function mysql_fetch_array() 에러시
//mysql
while($row= mysql_fetch_array($result1)) { }
//mysqli
while($row= mysqli_fetch_object($result1)) { } // 이렇게 수정
Fatal error: Uncaught Error: Call to undefined function mysql_num_rows()
//mysql
$aaaa = mysql_num_rows($result_common);
//mysqli
$aaaa = mysqli_num_rows($result_common); // 이렇게 수정
Connect Success!
Warning: Use of undefined constant MYSQL_ASSOC - assumed 'MYSQL_ASSOC' (this will throw an Error in a future version of PHP) in /var/www/html/viewfarm.php on line 10
Warning: mysqli_fetch_array() expects parameter 2 to be int, string given in /var/www/html/viewfarm.php on line 10
Time TEM HUM ILL
마지막 에러는 MYSQL_ASSOC --> MYSQLI_ASSOC 로 적어서 해결한다.
다음으로 웹에서 데이터베이스를 읽어 뿌려주는 php 파일을 viewfarm.php 파일로 만들어 준다. 코드가 잘 정리되지 않았지만 라즈베리파이 변경 구문을 모두 적용하여 잘 돌아간다.
<script language='javascript'>
window.setTimeout('window.location.reload()',1000); </script>
<?php
$connect = mysqli_connect('localhost', 'smartiot', '1234', 'demofarmdb')
or die("Connect Fail: " . mysql_error()); echo "Connect Success!";
//mysql_select_db("demofarmdb") or die("Select DB Fail!");
$query = "select
* from thl order by time desc limit 10"; $result = mysqli_query($connect, $query) or die("Query Fail: " . mysqli_error()); echo "<table>\n"; echo
"<tr><td>Time</td><td>TEM</td><td>HUM</td><td>ILL</td></tr>";
while ($line = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
echo "\t<tr>\n";
foreach ($line as $col_value) {
echo "\t\t<td>$col_value</td>\n";
}
echo "\t</tr>\n";
}
echo "</table>\n"; mysqli_free_result($result); mysqli_close($connect);
?>
브라우저에서 데이터를 불러와 뿌려주는 아름다운 화면을 보게 된다. 축하한다. ^^
'개발자 > 라즈베리파이4' 카테고리의 다른 글
mq135 air quality sensor 라즈베리파이 4 공기질 센서 (0) | 2022.05.30 |
---|---|
라즈베리파이4 화염 불꽃 감지 센서 모듈 Flame Sensor (4) | 2022.05.27 |
라즈베리파이 4 조도 센서, 빛 센서 실습 (0) | 2022.05.25 |
라즈베리파이 4 근접 센서 실습 코드 (0) | 2022.05.23 |
라즈베리파이4 데이터베이스 연동 php 에러 보이게 (0) | 2022.05.22 |
라즈베리파이4 스마트 농장 액츄에이터 제어 (0) | 2022.05.20 |
라즈베리파이 4 인체감지 센서 실습 코드 (0) | 2022.05.19 |
MQ-135 Air quality hazardous gas sensor module (0) | 2022.05.18 |
더욱 좋은 정보를 제공하겠습니다.~ ^^