Skip to content
Snippets Groups Projects
Commit a6976309 authored by kim hakjun's avatar kim hakjun
Browse files

Upload New File

parent 30c04423
Branches
No related tags found
No related merge requests found
#include <wiringPi.h> // wiringPi 라이브러리 사용
#include <stdio.h> // 표준입출력용 라이브러리
#include <stdlib.h> // 표준 유틸리티용 라이브러리
#include <stdint.h> // 정수 자료형 라이브러리
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#define MAX_TIMINGS 85 // 최대 신호 추출 개수
#define DHT_PIN 4 // GPIO로 사용할 핀 번호
#define IN 0
#define OUT 1
#define LOWS 0
#define HIGH 1
#define POUT 17
#define VALUE_MAX 40
#define DIRECTION_MAX 128
#define MAX_BUFFER_SIZE 256
// 입력 및 출력을 처리하는 두 개의 스레드 생성
char buffer[MAX_BUFFER_SIZE];
char end[2]="";
int limit_temperature = 25; // 최고 온도
int limit_humidity = 40; // 최고 습도
int data[5] = { 0, 0, 0, 0, 0 }; // 온습도 및 checksum 데이터 저장용 변수 배열
// 에러 메시지 출력 및 프로그램 종료 함수
void error_handling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
static int GPIOWrite(int pin, int value) {
static const char s_values_str[] = "01";
char path[VALUE_MAX];
int fd;
snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin);
fd = open(path, O_WRONLY);
if (-1 == fd) {
// fprintf(stderr, "Failed to open gpio value for writing!\n");
return (-1);
}
if (1 != write(fd, &s_values_str[LOWS == value ? 0 : 1], 1)) {
fprintf(stderr, "Failed to write value!\n");
return (-1);
}
close(fd);
return (0);
}
void LED_GPIO(){
int repeat = 2;
do {
GPIOWrite(POUT, repeat);
usleep(1000 * 1000);
} while(repeat--);
}
void read_dht_data() { // dht데이터 읽기 함수
uint8_t laststate = HIGH; // DHT핀의 상태 저장용 변수(현재 신호가 HIGH인지 LOW인지 확인하기 위한 용도)
uint8_t counter = 0; // 신호의 길이를 측정하기 위한 카운터 변수
uint8_t j = 0, i; // 40개의 신호 인덱스 용 변수
data[0] = data[1] = data[2] = data[3] = data[4] = 0; //초기 데이터 값은 0으로 지정
/* DHT11센서와의 통신을 개시하기 위해 DATA핀을 18ms동안 LOW로 출력 */
pinMode(DHT_PIN, OUTPUT);
digitalWrite(DHT_PIN, 0);
delay(18);
digitalWrite(DHT_PIN, 1);
delayMicroseconds(40);
pinMode(DHT_PIN, INPUT);
/* 핀을 입력모드로 설정해서 DHT11로 부터 응답을 기다림 */
pinMode(DHT_PIN, INPUT);
/* DHT11에서 오는 신호 검출 및 데이터비트 추출 */
for (i = 0; i < MAX_TIMINGS; i++) // 총 85번 동안 신호를 확인
{
counter = 0; // 초기 카운터는 0
while (digitalRead( DHT_PIN ) == laststate) { //DHT핀의 신호를 읽어서 현재 지정한 DATA핀 신호와 같은 동안==즉 신호의 변환이 없는 동안
counter++;
delayMicroseconds(1);
if (counter == 255) // 즉 너무 오래 동안 대기하면==오류가 생겼다는 의미 임
{
break;
}
}
laststate = digitalRead(DHT_PIN); // 현재 핀 상태 저장
if (counter == 255) // 카운터가 255이상 도달했다면, 데이터비트 수신 중지== for문 밖으로 나가서 처음부터 새로 받겠다는 의미임
break;
/* 첫번째 3개의 신호는 무시하고 짝수번째에 해당하는 신호길이를 읽어 0인지 1인지에 따라 온습도 변수에 저장
첫번째 3개의 신호는 DHT11의 응답 용 신호로 실제 데이터 길이를 통해 정보를 수신하는 값이 아니므로 무시함.
짝수만 추출하는 이유는 짝수 번째의 신호 길이에 따라 해당 신호가 0을 의미하는지 1을 의미하는지를 나타냄.
*/
if ((i >= 4) && (i % 2 == 0))
{
/* 가각의 데이터 비트를 온도 및 습도 변수에 하나씩 넣어줌 */
data[j / 8] <<= 1; // 이진수의 자리수를 하나씩 옆으로 이동시킴
if ( counter > 16 ) // 카운터의 값이 16보다 크다면, 즉 신호의 길이가 길어서 비트 1로 인식된다면
data[j / 8] |= 1; // 해당 비트는 1을 넣어줌
j++; // 다음 데이터를 위해 인덱스 값을 하나 증가 시킴
}
}
/*
* 40비트를 다 확인했다면 (8비트 x 5 ) 체크섬 데이터와 오류체크를 해서
* 오류가 없으면 데이터를 출력함.
*/
if ((j >= 40) && (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF))) { //에러가 없으면 습도 및 온도 출력
printf( "Humidity = %d.%d %% Temperature = %d.%d C\n", data[0], data[1], data[2], data[3]);
if(data[2] >= limit_temperature){ //최고 온도 및 최고 습도를 넘을 경우, 온습도기 실행
printf("temperature over\n");
LED_GPIO();
}
if(data[0] >= limit_humidity){
printf("humidity over\n");
LED_GPIO();
}
}else {
printf("Data not good, skip\n"); //에러 발생시 Data not good 메시지 출력
}
}
void *thread_socket_to_output() {
while (1){
read_dht_data(); // 온도 및 습도 데이터 획득 및 출력
delay( 1000 ); // 다음 읽기까지 2초 대기
if(strcmp(end, "e") == 0) {
LED_GPIO();
break;
}
}
}
void *read_func(void *arg) {
int client_socket = *(int *)arg;
while(1){
int str_len = read(client_socket, buffer, sizeof(buffer));
if (strcmp(buffer, "e") == 0){
strcpy(end, "e");
break;
}
}
}
int main(int argc, char *argv[])
{
int client_socket;
struct sockaddr_in server_address;
int thr_id;
int status;
pthread_t p_thread[2];
printf( "Raspberry Pi DHT11 temperature/humidity test\n" );
if ( wiringPiSetupGpio() == -1 ) //라즈베리파이의 BCM GPIO 핀번호를 사용하겠다고 선언
exit( 1 );
// 클라이언트 소켓 생성
client_socket = socket(PF_INET, SOCK_STREAM, 0);
if (client_socket == -1) error_handling("socket() error");
// 서버 주소 설정
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr(argv[1]);
server_address.sin_port = htons(atoi(argv[2]));
// 서버에 연결
if (connect(client_socket, (struct sockaddr *)&server_address, sizeof(server_address)) == -1)
error_handling("connect() error");
printf("Connected to server\n");
while(1){
int str_len = read(client_socket, buffer, sizeof(buffer));
if (strcmp(buffer, "s") == 0){
thr_id = pthread_create(&p_thread[0], NULL, read_func, &client_socket);
if (thr_id < 0) error_handling("thread create error : ");
thr_id = pthread_create(&p_thread[1], NULL, thread_socket_to_output, NULL);
if (thr_id < 0) error_handling("thread create error : ");
// 스레드가 종료될 때까지 대기
pthread_join(p_thread[0], (void **)&status);
pthread_join(p_thread[1], (void **)&status);
break;
}
}
return(0);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment