From d035c7ede4ac0a8cfed434129f164c1ce7f88b5c Mon Sep 17 00:00:00 2001 From: SeungHun Han <shhan730@gmail.com> Date: Fri, 23 Jun 2023 23:42:50 +0900 Subject: [PATCH] final --- camera/camera | Bin 0 -> 9184 bytes camera/camera_main.c | 148 +++++++ camera/picture/Sat_Jun_10_190322_202.jpg | 0 master_gps/.vscode/settings.json | 6 + master_gps/Master_GPS.c | 273 +++++++++++++ master_gps/cgps | Bin 0 -> 8408 bytes master_gps/gps.c | 70 ++++ master_gps/gps.py | 19 + master_gps/main | Bin 0 -> 14096 bytes master_gps/myMath.h | 45 ++ master_main/RF.c | 129 ++++++ master_main/c | Bin 0 -> 19804 bytes master_main/gpio.h | 263 ++++++++++++ master_main/lcd.h | 149 +++++++ master_main/lcd/WiringPi | 1 + master_main/lcd/a.out | Bin 0 -> 13196 bytes master_main/lcd/c | Bin 0 -> 18880 bytes master_main/lcd/cc.c | 235 +++++++++++ master_main/lcd/gpio.h | 263 ++++++++++++ master_main/lcd/vibration_motor.c | 318 +++++++++++++++ master_main/make | 13 + master_main/rf24libs/RF24 | 1 + master_main/rf24libs/RF24Gateway | 1 + master_main/rf24libs/RF24Mesh | 1 + master_main/rf24libs/RF24Network | 1 + master_main/vib | Bin 0 -> 24088 bytes master_main/vibration_motor.c | 406 +++++++++++++++++++ pet_main/GPS/gps | Bin 0 -> 8488 bytes pet_main/GPS/gps.c | 70 ++++ pet_main/GPS/gps.py | 19 + pet_main/Raspberry-Pi-Heartbeat-Pulse-Sensor | 1 + pet_main/main | Bin 0 -> 13736 bytes pet_main/pet_main.c | 278 +++++++++++++ 33 files changed, 2710 insertions(+) create mode 100644 camera/camera create mode 100644 camera/camera_main.c create mode 100644 camera/picture/Sat_Jun_10_190322_202.jpg create mode 100644 master_gps/.vscode/settings.json create mode 100644 master_gps/Master_GPS.c create mode 100644 master_gps/cgps create mode 100644 master_gps/gps.c create mode 100644 master_gps/gps.py create mode 100644 master_gps/main create mode 100644 master_gps/myMath.h create mode 100644 master_main/RF.c create mode 100644 master_main/c create mode 100644 master_main/gpio.h create mode 100644 master_main/lcd.h create mode 160000 master_main/lcd/WiringPi create mode 100644 master_main/lcd/a.out create mode 100644 master_main/lcd/c create mode 100644 master_main/lcd/cc.c create mode 100644 master_main/lcd/gpio.h create mode 100644 master_main/lcd/vibration_motor.c create mode 100644 master_main/make create mode 160000 master_main/rf24libs/RF24 create mode 160000 master_main/rf24libs/RF24Gateway create mode 160000 master_main/rf24libs/RF24Mesh create mode 160000 master_main/rf24libs/RF24Network create mode 100644 master_main/vib create mode 100644 master_main/vibration_motor.c create mode 100644 pet_main/GPS/gps create mode 100644 pet_main/GPS/gps.c create mode 100644 pet_main/GPS/gps.py create mode 160000 pet_main/Raspberry-Pi-Heartbeat-Pulse-Sensor create mode 100644 pet_main/main create mode 100644 pet_main/pet_main.c diff --git a/camera/camera b/camera/camera new file mode 100644 index 0000000000000000000000000000000000000000..db58c0d5b8ef28ecc21773de8dd2d49ba6d12ab4 GIT binary patch literal 9184 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 VanKkcvbsPy1_tEeKahPObpRb=?z;d0 literal 0 HcmV?d00001 diff --git a/camera/camera_main.c b/camera/camera_main.c new file mode 100644 index 0000000..dc1afb0 --- /dev/null +++ b/camera/camera_main.c @@ -0,0 +1,148 @@ +#include <pthread.h> // -lpthread +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <unistd.h> +#include <time.h> +#include <arpa/inet.h> +#include <sys/socket.h> + +#define BUF_SIZE 1024 + +char msg[32]; + +void error_handling(char *message); +void remove_spaces(char* str); +static void *recvi(void *arg); +static void *sendmaster(void *arg); + +/** + * DESCRIPTION + * This code is attached to the Raspberry Pi #3 + * this module establish connection with Raspberry Pi #4(Master's main device) through socket + * + * this device is connected with GPS Module, + * and it receives order from RP #4 to take a photo in this device + * + * In summary, + * RP #3 make an order to this device(RP #4) to take a photo, based on RP #3's heartbeat sensor data + * and if its order has sent to this device through socket, + * Camera Module takes some photos and save'em + */ +int main(int argc, char *argv[]) +{ + pthread_t p_thread_recv, p_thread_send; + + const char server_ip[] = "192.168.219.107"; + + struct sockaddr_in serv_addr; + time_t current_time; + ssize_t str_len; + int sock, cnt; + + char command[256]; + char* times; + + //socket 설정 + sock = socket(PF_INET, SOCK_STREAM, 0); + if(sock == -1) { + error_handling("socket() error"); + } + + //주소&포트 설정 + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = inet_addr(server_ip); + serv_addr.sin_port = htons(atoi("8886")); + + //socket 연결 + if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr) ) == -1 ) { + error_handling("connect() error"); + } + + pthread_create(&p_thread_recv, NULL, recvi, (void *)&sock); + pthread_create(&p_thread_send, NULL, sendmaster, NULL); + + while (true) { + // 사진촬영 명령을 받으면 1초간격으로 5번 사진촬영 + if (msg[0] == '1'){ // RF통신용 + //if (strcmp(msg, "1") == 0){ // 소켓통신용 + cnt=5; + while(cnt--) { + current_time = time(NULL); + times = ctime(¤t_time); + times[strlen(times) - 2] = '\0'; + strcat(times, ".jpg"); + remove_spaces(times); + printf("%s\n",times); + + // 현재 시간을 이름으로 picture폴더에 사진 저장 + sprintf(command, "raspistill -t 1 -o ./picture/%s", times); + system(command); + sleep(1); + } + } + } + + //파일 & 소켓 연결 해제 + close(sock); + + return(0); +} + +//오류 메시지 출력함수 +void error_handling(char *message){ + fputs(message,stderr); + fputc('\n',stderr); + exit(1); +} + +//공백을 _로 바꾸는 함수 +void remove_spaces(char* str) +{ + for (int i = 0; str[i]; i++) { + if (str[i] == ' ') { + str[i] = '_'; + } + } +} + +//메인 장치에서 정보를 받아와 변수에 저장 +static void *recvi(void *arg) +{ + int sock = *(int*)arg; + + while(true) { + read(sock, msg, sizeof(msg)); + printf("%s\n", msg); // 실행확인용 + } + return NULL; +} + +// 주인측 장치에 RF통신으로 정보 전송 +static void *sendmaster(void *arg) +{ + FILE* pipe; + char buffer[BUF_SIZE]; + + // 심박센서 신호 출력 프로그램 실행&파이프 연결 + pipe = popen("sudo ./rf24libs/RF24/examples_linux/gettingstarted", "w"); + + if (pipe == NULL) { + perror("popen"); + return NULL; + } + + // 받아온 정보 변수에 저장 + while (true) { + sleep(1); + fwrite(msg, sizeof(char), 32, pipe); + fflush(pipe); + } + + return NULL; +} \ No newline at end of file diff --git a/camera/picture/Sat_Jun_10_190322_202.jpg b/camera/picture/Sat_Jun_10_190322_202.jpg new file mode 100644 index 0000000..e69de29 diff --git a/master_gps/.vscode/settings.json b/master_gps/.vscode/settings.json new file mode 100644 index 0000000..fb365f8 --- /dev/null +++ b/master_gps/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "files.associations": { + "stdbool.h": "c", + "math.h": "c" + } +} \ No newline at end of file diff --git a/master_gps/Master_GPS.c b/master_gps/Master_GPS.c new file mode 100644 index 0000000..cfa51c9 --- /dev/null +++ b/master_gps/Master_GPS.c @@ -0,0 +1,273 @@ +#include <sys/socket.h> +#include <sys/wait.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <pthread.h> // -lpthread +#include <unistd.h> +#include <stdio.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> // -lm + +#define LOW 0 +#define HIGH 1 + +#define BUF_SIZE 1024 +#define DIST_THRESHOLD 300 + +static inline double rad(double x) { + return x * 3.14159265 / 180.0; +} + +typedef struct { + double x; + double y; + double z; +}tagPT; + +const int VIBRATION_MOTOR_PIN = 23; +const int BUTTON_PIN_IN = 20; +const int BUTTON_PIN_OUT = 21; + +static void* recv_from_Slave(void *p_sock); +static void* send_to_rp1(void *arg); +static void* gps(void *arg); +static inline double GetDistance(tagPT pt1, tagPT pt2); + +void error_handling(char *msg); + +static int buzzerMode = true; +static int vibMode = false; +static int heartbeat = 80; +static int event = 0; + +static int tookPhoto = false; +static double curDist = DIST_THRESHOLD; +static tagPT myPos = {127.123,68.56,123.56}; +static tagPT dogPos = {127.123,68.56,123.56}; + +/** + * DESCRIPTION + * This code is attached to the Raspberry Pi #2 + * this module establish connection with RP #1(Master's sub device) and RP #4 (Pet's main device) + * it is connected with RF module, and GPS module + * + * this device (RP #2) receives data from RP #4, which is + * 1) tookPhoto, 2) heartbeat rate, and 3) latitude 4)longitude of the Pet + * based on these datas, it caculates the Distance Between Master and Pet (GetDistance func) + * + * And it sends 3 datas to the RP #1, which is + * 1) tookPhoto 2) heartbeat rate, and 3) Distance data + * + * Notice that Master's latitude and longitude data comes from the GPS module + * + * In conclusion, + * this device RP #2 literally play a 'Medium' role between Master and a Pet + */ + +int main(int argc, char* argv[]) +{ + pthread_t thread, send_thread, recv_thread; + struct sockaddr_in serv_adr; + + int serv_sock, pet_sock, lcd_sock; + char buf[BUF_SIZE]; + int str_len; + + //소켓 정보 설정 + serv_sock=socket(PF_INET, SOCK_STREAM, 0); + if(serv_sock==-1) { + error_handling("socket() error"); + } + + //ARGUMENT 활용해서 서버 구성 + memset(&serv_adr, 0, sizeof(serv_adr)); + + serv_adr.sin_family=AF_INET; + serv_adr.sin_addr.s_addr=htonl(INADDR_ANY); + serv_adr.sin_port=htons(atoi("8885")); + + //소켓에 주소를 할당 + if (bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr)) == -1) { + error_handling("bind() error"); + } + + //함수를 수동 대기 상태로 설정 함. + //serv_sock 소켓을 사용하여 연결 요청을 대기하고, + //최대 5개의 연결 요청을 대기 큐에 저장할 수 있도록 설정 + if (listen(serv_sock, 5) == -1) { + error_handling("listen() error"); + } + + struct sockaddr_in clnt_adr; + socklen_t clnt_adr_sz = sizeof(clnt_adr); + + // pet_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz); + // if (pet_sock == -1 ) { + // error_handling("accept() error"); + // } else { + // printf("pet connected() ! \n"); + // } + + struct sockaddr_in clnt_adr2; + lcd_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr2, &clnt_adr_sz); + if (lcd_sock == -1) { + error_handling("accept() error"); + } else { + printf("lcd connected() ! \n"); + } + + printf("Multi-threading start\n"); + pthread_create(&thread, NULL, gps, NULL); + //pthread_create(&recv_thread, NULL, recv_from_Slave, &pet_sock); //RF 통신에서는 사용안함 + pthread_create(&send_thread, NULL, send_to_rp1, &lcd_sock); + + pthread_join(thread, NULL); + pthread_join(send_thread, NULL); + + return 0; +} + +//pet으로부터 데이터 수신하는 THREAD용 함수 +static void* recv_from_Slave(void* p_sock) +{ + int sock = *(int*)p_sock; + char buffer[1024]; + ssize_t n; + + while ((n = read(sock, buffer, sizeof(buffer))) > 0) { + int data_cnt = atoi(buffer); + printf("read buffer : %s\n", buffer); + + char* p_delims = "_"; + char* p_tok = strtok(buffer, p_delims); + tookPhoto = atoi(p_tok); + p_tok = strtok(NULL, p_delims); + heartbeat = atoi(p_tok); + + p_tok = strtok(NULL, p_delims); + dogPos.x = atof(p_tok); + p_tok = strtok(NULL, p_delims); + dogPos.y = atof(p_tok); + + curDist = GetDistance(myPos, dogPos); + printf("Dist : %lf\n", curDist); + printf("TookPhoto : %d Heart : %d Position : %lf %lf\n", tookPhoto, heartbeat, dogPos.x, dogPos.y); + } + + close(sock); //소켓을 닫아주고 + write(STDOUT_FILENO, "[*] session closed\n", 19); //세션이 닫혔다고 print해준다. + exit(0); +} + +// GPS module Thread 관련 함수 +static void* gps(void *arg) +{ + FILE *pipe; + char buffer[BUF_SIZE]; + char msg[] = "1"; + + // gps 정보를 읽어 경도와 위도를 출력하는 프로그램 실행&파이프 연결 + pipe = popen("python3 -u gps.py", "r"); + if (pipe == NULL) { + perror("popen"); + return NULL; + } + + // 파이프에서 받은 경도와 위도를 변수에 저장 + while (fgets(buffer, BUF_SIZE, pipe) != NULL) { + myPos.y = atof(strtok(buffer, " ")); + myPos.x = atof(strtok(NULL, " ")); + + //실행확인용 + printf("Master latitude : %f\n", myPos.x); + printf("Master longitude : %f\n", myPos.y); + + } + + // 파이프 닫음 + if ( pclose(pipe) == -1 ) { + perror("pclose"); + return NULL; + } + + return NULL; +} + +// 두 위치정보를 바탕으로 거리를 계산하는 함수 +static inline double GetDistance(tagPT pt1, tagPT pt2 ) +{ + const int radius = 6371; + + double dLat = rad( (pt2.y-pt1.y) ); + double dLon = rad( (pt2.x-pt1.x) ); + + pt1.y = rad( pt1.y ); + pt2.y = rad( pt2.y ); + + double a = sin(dLat/2) * sin(dLat/2) + sin(dLon/2) * sin(dLon/2) * cos(pt1.y) * cos(pt2.y); + double c = 2 * atan2f(sqrtf(a), sqrtf(1-a)); + double dDistance = radius * c; + + // dDistance*=1000; + + return dDistance; +} + +// RP #1 (주인측 sub 장치)로 데이터를 보내는 Thread 함수 +static void* send_to_rp1(void *arg) +{ + int sock = *(int*)arg; + char msg[100]; + char str[20]; + + // 1초마다 정보표시 장치에 정보 보냄 + while (true) { + // // 촬영여부 + // sprintf(str, "%d", tookPhoto); + // strcpy(msg, str); + // msg[strcspn(msg, "\n")] = 0; + // strcat(msg, "_"); + + // // 심박수 + // sprintf(str, "%d", heartbeat); + // strcat(msg, str); + // msg[strcspn(msg, "\n")] = 0; + // strcat(msg, "_"); + + // // 거리 + // sprintf(str, "%f", curDist); + // strcat(msg, str); + // msg[strcspn(msg, "\n")] = 0; + + //경도 + sprintf(str, "%.3lf", myPos.y); + strcat(msg, str); + msg[strcspn(msg, "\n")] = 0; + strcat(msg, "_"); + + //위도 + sprintf(str, "%.3lf", myPos.x); + strcat(msg, str); + msg[strcspn(msg, "\n")] = 0; + + // 전송 + write(sock, msg, strlen(msg)); + + // rintf("Dist : %lf\n", curDist); + printf("latitude : %lf longitude : %lf\n", myPos.x, myPos.y); + + sleep(1); + } + return NULL; +} + +//에러 핸들링 용 함수 +void error_handling(char *message) +{ + fputs(message, stderr); + fputc('\n', stderr); + exit(1); +} \ No newline at end of file diff --git a/master_gps/cgps b/master_gps/cgps new file mode 100644 index 0000000000000000000000000000000000000000..36723eea61207cee79bc873a36662b25b6935130 GIT binary patch literal 8408 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 DqBHP5 literal 0 HcmV?d00001 diff --git a/master_gps/gps.c b/master_gps/gps.c new file mode 100644 index 0000000..e3020a2 --- /dev/null +++ b/master_gps/gps.c @@ -0,0 +1,70 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <termios.h> + +#define GPS_MSG_SIZE 128 + +int main() { + int serial_port; + char *port = "/dev/ttyAMA0"; + struct termios options; + + serial_port = open(port, O_RDWR | O_NOCTTY | O_NDELAY); + if (serial_port == -1) { + printf("Failed to open the serial port.\n"); + return -1; + } + + tcgetattr(serial_port, &options); + cfsetispeed(&options, B9600); + cfsetospeed(&options, B9600); + options.c_cflag |= (CLOCAL | CREAD); + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + options.c_cflag &= ~CSIZE; + options.c_cflag |= CS8; + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_iflag &= ~(IXON | IXOFF | IXANY); + options.c_oflag &= ~OPOST; + options.c_cc[VMIN] = 0; + options.c_cc[VTIME] = 5; + tcsetattr(serial_port, TCSANOW, &options); + + char gps_msg[GPS_MSG_SIZE]; + memset(gps_msg, 0, sizeof(gps_msg)); + + while (1) { + ssize_t newdata = read(serial_port, gps_msg, sizeof(gps_msg)); + if (newdata > 0) { + // Process the GPS data + if (strncmp(gps_msg, "$GPRMC", 6) == 0) { + // printf("%s\n",gps_msg); + char *token; + char *latitude; + char *longitude; + token = strtok(gps_msg, ","); + int token_count = 0; + while (token != NULL) { + if (token_count == 2) { + latitude = token; + } else if (token_count == 4) { + longitude = token; + } + token = strtok(NULL, ","); + token_count++; + } + printf("Latitude: %s\n", latitude); + printf("Longitude: %s\n", longitude); + } + } + memset(gps_msg, 0, sizeof(gps_msg)); + usleep(500000); + } + + close(serial_port); + + return 0; +} \ No newline at end of file diff --git a/master_gps/gps.py b/master_gps/gps.py new file mode 100644 index 0000000..e051d0b --- /dev/null +++ b/master_gps/gps.py @@ -0,0 +1,19 @@ +import serial +import time +import string +import pynmea2 + +while True: + port="/dev/ttyAMA0" + ser=serial.Serial(port, baudrate=9600, timeout=0.5) + dataout = pynmea2.NMEAStreamReader() + newdata=ser.readline() + #print(newdata) + + if newdata[0:6] == b"$GPRMC": + newmsg=pynmea2.parse(newdata.decode('ascii')) + lat=newmsg.latitude + lng=newmsg.longitude + gps = str(round(lat, 12)) + " " + str(round(lng, 12)) + print(gps) + \ No newline at end of file diff --git a/master_gps/main b/master_gps/main new file mode 100644 index 0000000000000000000000000000000000000000..41fcf6bbed4aa2cf269c9671cd23ac576a380c41 GIT binary patch literal 14096 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 Oh71g>AWJ}!Na_Ik@P-5c literal 0 HcmV?d00001 diff --git a/master_gps/myMath.h b/master_gps/myMath.h new file mode 100644 index 0000000..d99dfe0 --- /dev/null +++ b/master_gps/myMath.h @@ -0,0 +1,45 @@ +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +int fd; // seen by all subroutines + +void itoa(int n, char* s); +void reverse(char* s); +void ftoa(float f, char* buf); + +/* itoa: convert n to characters in s */ +void itoa(int n, char* s) +{ + int i, sign; + + if ((sign = n) < 0) /* record sign */ + n = -n; /* make n positive */ + i = 0; + do { /* generate digits in reverse order */ + s[i++] = n % 10 + '0'; /* get next digit */ + } while ((n /= 10) > 0); /* delete it */ + if (sign < 0) + s[i++] = '-'; + s[i] = '\0'; + reverse(s); +} + +void ftoa(float f, char* buf) +{ + sprintf(buf, "%f", f); + // return buf; +} + +/* reverse: reverse string s in place */ +void reverse(char* s) +{ + int i, j; + char c; + + for (i = 0, j = strlen(s)-1; i<j; i++, j--) { + c = s[i]; + s[i] = s[j]; + s[j] = c; + } +} \ No newline at end of file diff --git a/master_main/RF.c b/master_main/RF.c new file mode 100644 index 0000000..4519f51 --- /dev/null +++ b/master_main/RF.c @@ -0,0 +1,129 @@ +// 아래 헤더들을 추가해준다 +#include <SPI.h> +#include <RF24.h> + +// 0 번과 1번 아두이노(nRF모듈)를 나누어서 주고받기위한 용도 +// 하나는 0으로, 하나는 1로 설정하고 컴파일 해야 한다 +bool radioNumber = 0; + +// 7 : CE , 8: CSN +RF24 radio(7,8); + +// Pipe Address 를 설정하기 위한 값 +byte addresses[][6] = {"1Node","2Node"}; + +// 누가 Ping 하고 Pong 할 것인지 결정 위함 +bool role = 0; + +void setup() { + Serial.begin(115200); + Serial.println(F("RF24/examples/GettingStarted")); + Serial.println(F("*** PRESS 'T' to begin transmitting to the other node")); + + // RF24 모듈 초기화 + radio.begin(); + // PA 세기를 LOW 로 한다. 입력 전류 불안정을 감안함 + radio.setPALevel(RF24_PA_LOW); + + // radioNumber 에 따라 Write Pipe - Read Pipe 쌍의 주소를 지정해서 Open 한다 + if(radioNumber){ + radio.openWritingPipe(addresses[1]); + radio.openReadingPipe(1,addresses[0]); + }else{ + radio.openWritingPipe(addresses[0]); + radio.openReadingPipe(1,addresses[1]); + } + + // Reading Pipe 주소의 Listening 을 시작한다 + radio.startListening(); +} + +void loop() { + +// Ping 보내는 역할 +if (role == 1) { + + // Write 를 하기 전에 반드시 Listening 을 Stop 해야한다 + radio.stopListening(); + + + Serial.println(F("Now sending")); + unsigned long time = micros(); + + // 데이터를 Write 한다. 이때 채널 내의 해당 주소로 Listen 하는 녀석이 없으면 Fail 떨어진다 + if (!radio.write( &time, sizeof(unsigned long) )){ + Serial.println(F("failed")); + } + + // 보내고 나서 다시 LIsten 한다 + radio.startListening(); + + unsigned long started_waiting_at = micros(); + boolean timeout = false; + + // 수신 로직이다. Ping Timeout 을 200ms 로 잡고, Timeout 내에서 수신한다 + while ( ! radio.available() ){ + if (micros() - started_waiting_at > 200000 ){ + timeout = true; + break; + } + } + + if ( timeout ){ + Serial.println(F("Failed, response timed out.")); + }else{ + unsigned long got_time; + // Pong 이 왔을 때 데이터를 읽어온다 + radio.read( &got_time, sizeof(unsigned long) ); + unsigned long time = micros(); + + // Ping 의 Round-Trip 시간을 계산하여 알려준다 + Serial.print(F("Sent ")); + Serial.print(time); + Serial.print(F(", Got response ")); + Serial.print(got_time); + Serial.print(F(", Round-trip delay ")); + Serial.print(time-got_time); + Serial.println(F(" microseconds")); + } + + delay(1000); + } + +// Pong 쳐주는 역할 + if ( role == 0 ) + { + unsigned long got_time; + + // 데이터가 있으면 데이터를 모두 읽어서 FIFO 버퍼 소진한다 + if( radio.available()){ + while (radio.available()) { + radio.read( &got_time, sizeof(unsigned long) ); + } + + // Listening 멈추고 Pong 을 Write 한다 + radio.stopListening(); + radio.write( &got_time, sizeof(unsigned long) ); + radio.startListening(); + Serial.print(F("Sent response ")); + Serial.println(got_time); + } + } + +// Serial 을 통해서 T 와 R 에 따라 역할을 바꾼다 + if ( Serial.available() ) + { + char c = toupper(Serial.read()); + if ( c == 'T' && role == 0 ){ + Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK")); + role = 1; // Become the primary transmitter (ping out) + + }else + if ( c == 'R' && role == 1 ){ + Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK")); + role = 0; // Become the primary receiver (pong back) + radio.startListening(); + + } + } +} \ No newline at end of file diff --git a/master_main/c b/master_main/c new file mode 100644 index 0000000000000000000000000000000000000000..add82256e8c1f6f1e63e8e53529fe5f4050263f9 GIT binary patch literal 19804 zcmb<-^>JflWMqH=CI$@#5N`rEBZCP81H%;$1_lNe238XW1qMzA4F*{T8IXK|g)Rew zg)So)b1*P4fG`VKDFXu=0|QvE2?NLsMg|2&1~7)nGczzSgfN0IBSQ!yBZDLZ0~mwk zL3V>M#62JuBZG@B0~oV{1sOs1GyKqFVECcO1jYhP3=Aqv5PKOI7#WyA>hu{H81$JS z7-9_AT_8I^xPXy?p@5MQj9nNQ7(f^#4#I&?OHx2apkt7~1Q-|?f}WP7AluKu$iM)? zAiW@~^m8(k^m9^lb29TvD|8c!ax>EOiu3i1LFR$fh%hiPfWpAtFO;FuQRGF#wN<JL z&C&LIda|QbFU%AMsR7voG7F>zqz|MX>@Nle232S{gTfqy8+$H!bR?L5W-?jL!?2*m zfPsNQgMlld(WxbXfmMJb31l9~?d%K;44e!M3|t@sp_rS2fq{pCfq@Uo2iYsgz`!8P zz`y`<rzlh$M2RslFi1e-N{WGjK^i2;z`!8Gz`&ruz`&ryz`&pabstDd4MZ?7FsMUm z4F(1VO$G)AEd~aL2Qx42D!)FvX6wtSj{)Vg`1h9`ohGhd!he0rWSO1X*`f}<b88;Y zoKmCbXZ!7RS_ik~r*0X$xrMV2_V<3OeJjWxJ<FPZ?(WGlc6HNg^qCE140kl~2KQ(v z%72RyFg@$ZZ}Y_>$mDIj0GoaZf4<F>8opH>+<{wH2)wyBS%#Z`>(XMIDK(-FmE3<n z&z0~lpT+-ECt{yq^_&{9S7rZf*{?v78r0n&3KSP08iYZ9%>pr?7{r%_vOyGx?+ju< zu@D0TLp+oXqCk8b5Ce)q{MS%6hywAKfEZ8=;;SJ!0L0fp<ENqV&7pch6iB@^ntTu% z|2#+`6ob?ogVMAi69Xvi2r`H>On}OPD3JUS5Ce)qd~l{j;v;7ukUTG%eGi~&K@>>- zCWryWAifBidMh-(H5$JXsux6o^lt(&pcurz3}u5T5Fb<~f!H7n;(MT(cN!!C#UObn zG<h~O{zs@<5Cu~2izfdQBmu=B`FbcDM1lBEK@2Dc@l(+BtE2H9(fC17y&wvtpCR5e z#5X=AwJ0?`v$!O+D8$z}CqFMWBrz!`6(WaKrYJQrg&{FHIkljKp`auK#EnlbN=+<D zg>$p=GxHeo3sUnKl5_HlQyJpp({uCl;)_cXi%R0-8B$Vn5-S<XGmA3w(gQL*jhus1 zOG*on1%gr&Q-V^{E#P7h6=03NnaM@@#i_~pc`3yVi6x17MrjPinRyJ!`Na&yg+(Q4 z48{4$*{LNAsTG+e3>hW)c{yORn4!3!C^N4ljUfl*-8_cGr2L{1hT@W<lKgBCm6Mvs zkeixYoLa(=l$n>pkXBGyk_;w`LDI>IAjK)EMMVsy#W|^|1q^BBMVTe342dQAX&@q# zAwE7QGbtJB&)me!Jci;txSdJRzyg)?1`IiwNw5IWE6xXTb3qbjAXYMj<?iF@<Q#9L z2dZO1aR#apm>HPCbr%x@2!hz4{0A!aSs0kWav*UC2I&Ebf>c0Mg2WlXIzcQ@eF3T| zdl(rQKxI0pOcKe=<ONmc3!rHSB%g~R&&+@<KMg7mvJax42`<0JfQdnriGhK`kcmM= zfPsO>fQdnjn}I<9MDs8(h=6D*1_lWbt;WD01ESd(7!*J>8v}z1h?Zes&;Zd|3=BFT znu~$K07T0&FqnX7Nd^WB5Y58CU<0D185kTuv?c?C3y9`pVDJFZObiS@AexndApk^+ zF))OHXaxp_2oNpGzz_qX1sNC;K(qz}LkfuIWnjnv(Gm;{IUrh*fuR6Ib1*QJfM_KK zh6)g^&cILuqE#6f8bGu*149dlmSbS(0MW_}3_T!Pg@IuLh!$sHm;$1O7#L=NXn6*P zIUt&ofnfoN7G_{r0-{A27*>F2eg*~(2i=#w3=FS18uq?md7%50<-z=?d=L5`aD3SJ zGy+rs9P581bgJi3#J4?98KCR{B(?_<+X0Dffy6dIVrw9=6_D5xNNfQlHU|=$0g3(N zE5bb=kk~Jf*bk7{H;~vDkk}`X*awi<JCN8Lkk~7b*b9)@GmzL5kk}na>;@!u1roae ziJgJOPC#NuAh83G*d9o12PC!y659ZYt%1Z=0I@-tY{P=b3=bAOW)YbCgjZp~Lly<y zrz{M*PX!Llf68(|_bCs<{HHty^PevL|Nr&N|Nmbrs53HTNHH=TP-A2eF_`~UL}C6@ zW`q6*ObU~qGcW`_miw>IIQRemS1Kxu3~RvcxA{*c4CX&&U<iH)k`sWi!Rmzn>pukL zWe^5AMTKGhQx$>vPZ<mxA1sz%@X%SX@xeiX4FvTGIOx8VZ~*DM0<!0^K*L^%2mk-S zW;9svn8D!4Q-OxPFL(@@7@qzA|BAsw_a)1Q-bWG_d>=_La6e@fSn#-nVgA$N|Nmce zFmONRFpz%A$WZ*4oq<6r0pwPL$xoFP7CZ*23t^c5)bIcQ*9-;^9`iCVyb@sWek5Ta z{nP;z1_BEn7ykeMnume=DUX8mQvn0-N6Z2X9&#{9KP>^9E&X&3Snq<z%nS=2vRv?f z#L%(##Q}9jaCvq^osr=WsM5vZK5wuY*xjd&<UTd99oXIHiNk$9V6!3aWH3N=AA<(O zeKH!T?sK@{`^bTT`>Bfn_fsCj`A;nlct2u(u;3v-!@d{%3~OG%Xa<9MPZ<o(JQX+a ze#D@#;4y<j^HUau=BFGA%}*^DydOCjNI$)xF#oBpz=Fq$|Np<XFz|i^3Tsdp@qyii z>gN^EIMIgsc@D$;r!W6O;zW*t;gySlG&l_~GB8Mi{KCM%@QT@B!Q%>r`A?Yynjav` zGl9|vRGwJ@5?7qy@LTW@mIf@K_DMqRGhvwj^eogqCI*IAp!kJ^Icm6V&|qY6fred% z1|!1+9Y%&J8jK9E^e1@F_mKc2_fsc+??(cL(oa_?%zw%#v*7WAfB#=Q*?T`?5P+Bm zvI{+3HbC73i+51^T>*8IC<DVQXM68Q%nA!0!_r?rSPtPQ2dI8AsGlqt=0BYQR`cL7 zE7VUP|NVarHiu!s!#iNP1rI@S0!z0KpnhY}WMt6L#PpYlAi{4upnh8k^&2dHr~Sjs za}%I$gZZt6VgA!Xu>B7nOENIL5;26vufYOg27?96#Rl)6f#MF7SD6i(9xx*L8)QC% z0m$FMp#02b0ySG4>Td&v`A?&uX2argGnfwvdvw2o^1uuoMg|8Y|00(oH4O8gCSvhZ z2Gm|DsJ$@^^Pk#)?RoH+AE_MifR-ci|FD-MNno?3pLYHG|C*6u!DAV)8K`cJ(1hgI z3Qg4fitbKxuvw^i3+7H4BzFpd?ZEC%QylKJ0GloSGy&?)Pk%xA6V;tlpzhp(=1y3- z0xKKtK+6WHf2d^xJJ=3X_isT9=M@a|pFRTH{ot_@1H&s&S-}MM&w_`bG}9w6|0yW{ z@_@~ferked$Gg9n=`#S$4i|>`PftSa;ACKUWdkaYz<h`uI#4@4gUynDDh;t8r4G0O z4GRV>Mus^$j0_7voo#46fF2&8atu^fUi*t09*4o^qlO1Ix6T8*?ZIP^TS57LAD9nu zs|M7qC%|S&Km7oa!|B!~NbXbwm1j)cPep{dpEiTaG$ZM!d!YG#_22)mo9z+h`V6r7 zsBWEt7OowjIvH&LgU3>!GL7H+k%*D>(-MXGPq_pZJf8L!kw?Jg6tu3L3DyJ3^Ti-P zO4&foRfMK#ke_40_DetA0ap9qF)Z(I0rOGQsf-pRKe=c@@>7BqqO3#qvoo5X^Zr80 zPgq$O4Ym`zpXH!#1Nqqu>;{ORLE(t(=SU<!gTfP5zQ=&|VES1VYA(pn3Sj%CpH_p_ zBK%wq=A-(#1?uMwP(NQl^0UGP-$xu=+;2ImqTfER+Wt<0!TXW8cJLbsf%#AU|Neh1 z0c!U!EO=<l!0?&@sh#r!%?t$w?x!HN3JTIsWd!Cw1=TI~Ncxr0^dq;8Ky@Ri{L=%e z5m@k;iDAKGZ4jGb!9!4+3RcH*fZWQ!{S>4gl+Tr*YGCC$vN}*b!D`_Bl+_>_+$IFM zM+}d8P@T*Msw+Y5MTO=^917e|84NDN^|FKdRiL(r!DVoJ<jep6QlRhvVRZWiF8DqY zVBmf#BEbDrz(D%x2L<LwA_me=nGKpAau_r}<}iSWGaD^<Sgi2=8L}LY0ryi_8s`v@ z28ZLBKcI3;`Y9I!!)pa-`sabl9sL8!Hz0MW@grc!1aF(b!mXBn!Q=iv|6lun%utvN zZX2^0G=tj}ObiPiZu;~8HAqd{pZ~8lP}CfTt62$EQ~T#XN_s%H4-`Mf3=1Cb0=2ya z7Cbg$Snzl|l+DJl;PDnHn}=b+<Bd?Z2E&5K>!55<T3G!b;+ABnJ;><*J$yl7#si8Q zhG0<MUj+(t27}~B0tTQsTmT7g1?i_p4CX(bEOhvRv*3b<hwK+TWEOCIz-X}GA+zCv zhl~cz51K)20jCFr3h$qR`warkk2nOlpMvrwD2_mC3>2Ck6)C)b#-MN*9Jd7u^Pf%< zKJ>szalymGATte|9)RoxyMZD2@q_>WPr=;A&cLt=Y%Vl?f$A)fxl9Jl4|Kt8>BHbS z5m5lAl?Raa_2H)?4AM`9(9&*tT3Q-%dS~L|ehccWFhTP%C=Uw=%zw(mApJBJ8iw$6 zs*Nb~VC@J{+ZvQEB^aci>VnjR+F1t9k3eB74$T)5Fn1YTe#&d${S@Rcu$V&A1CYNY zKxxvT@d1OvrKh0qfy)~-J>XS{28)5zF&Z>K0@($UXN20pp&$)5kC`Fp;p6}RcY*R1 z2*ceBtv_Aw`92C@;eHw-!u^!XV8LSr1Ma5*Celxt7=j<OF)(n2m`FcmFqjOEGZv=# zPY?cvw5>k<{{I>jo}ls@RKCc8^Aw`|2K6s)FwTGal8NE9lb!b?7O=aV9|?fs1=@E1 z{QLiF76b1`PIjPhael<4u;B3qg~JaS7#2MK0W#lU!9yJr?x!F(uoyHy0=olLhC#!# z*x>&&P&u>$sumRg$mVTQIQ$UZZcy3-m30@PdO-ackXsEH=Re)Y#PFI`V8LUM{B1OO z5ytsXw=pri7BE=w*u#YTsh};yPauB@%6dOy5pV?cDZu^NcBozx6Yi%bCXoIz69a?P z6^8jwmohQDW@KP^b%tU7)2YAzzg95te#FDz{pf(gd~iA3_51&8P`??Jel|eGTA}Jh z7`z`XfQmIh#X$AT1gKc`@Bgozp<yk<;QgouDqi~g|7%d%0F@)4@LCSC1C+m^@v!*! z|JR^=1CyWs8&pq8gWUsCKO5p7ly(k_HY0<CHY0<EHY0<DHY0<FHX}oXHY39ZMMj1U zB}RrEWk!Yra*PaDWDt47`JV411s3k73eYqKO0%I146huaZU%)V$i5Dc`xv;NqKFGD zcv!+X|Ec2d|E~)S=RXxOK$RB(<rRhn57R+z2i2Vn(of4E?tbW^2paondJ0klN?UPA zYI31!RM6CfqN#DH-tdmaaQ;(<>gKmFb9|80r2PK>8l>id!ThI8)y;2jfXaL8$#0pw zC%<Khp8WO<h_5~QEmQX7w=C6@-#T$`c;_a);hnqohIh*u8NhnifYekszg=Q5|LFyV z!w(lQ%zygy*Z<coAn^l}pMv|f4<<jYfy$Q%%zt`=;o!p`3}+vHP&oULPhr7B9)Sf9 za~S47z5eU}Yvk}_)JF7oFaHA7aophYfq^0T@x1^4Pl3|B&F}xOg%uV&HV~Nq6jW#M zfx?Di!Q=10{=d%9W@M-V#knC9!wCZ>h7Sfz3^xpz7%mtvF*Im1GW2LOGVDPr2QOUk zeZ&aT4=VQ<iXVgW7|6^gzy7~gXISuf$1iZ7=V6W#ByODl{eOM#@Bh~cMj-y=r;H52 zk69QPq#76&Jihez|7#zn`A?ty{r{RBG=_nsh8e2n<lq0V4VdOXz5Dn7>jMl69v}Vt z|MeMYTdR?4{@eC{|6hw3LBjQn0BHQ6_bCU{{HMLY5b6#?-2^H}Kzc#-$P2~!Pd5l$ zddQ@3>FEZ6!w;Dh4nMsCN(Tm$pJpg{KVlMq^!v5{{eOJ`D$Xph;NcF&`A^G0;ilmI z2y7NqT_=)#%dyzk0!oJrlb$j#G(QFD1LcPmfB(P!#lPTj8^}DU9iZ@GWnkcP0P(9Q zzje!=|Mpn*mUjZbKEC5;V7LWp$AZGH8PpGAod0w>G+gTc{(r5*IREM7zyDv?@-28= z`0M}cg1`S?3xLc4mCXvxPmLHDUNM0929v?{05byv*B?+CG=Rj55Cel$^56fjLFQ-w z{r~z2!~CZpb3x&r{`ddu8w~To?P!qsk-z@Gj`;ik^#+iBsQJijP+bV?+b}ag#vv*| zY7HhotzZa#%*?=W3fAv7WC(s-`v3na7pUDnfB(NOV3_|j0qQr8zyDvSFwB1nYVU*W zw)*w|wdLRcuQNd7nxFyH14RxD3?5FPw$%|(+SO)c5HVz8xTDPoPRDPw85uZq7{TeA zM~9I?M2C^#i~$pagbpKviVh=#gdr1yjt(P(jSeG&j}9Y43{w9N)`pq`bvr2DR{#3{ zx(CV!)srBxZ@>P(hWQUBRt_rfK;^Lks13>e6x2>-R9Nt^Nom1DMg^w_OvVcyG8s5O zXoj|{n2jN6?$6KvuXUj2!^&<@IRqY02G!Z1HYg;Gp_JV_3{cy$;Iay;z7Cu|A$btw z-l|{!U++M(<LIyduVLeiFh3ml_5U?29${jRzyH4ml~u5MoBcPa-3@6YfXW?y1_r4V zsM(-43`mU8fcX)FLGmUaP~BzF^wa}~ya7~R1}YEAv!HO30gcuD{Qp{lVgA!CKmWhJ z`Tzf`JqAn+2Mm}PKyeO=?;Ow=l@mX_J&)XG1GhC9q@Viz{{Q-q!2G8I4AM_|LG2BJ z1&={&_dn3O(O@#T4!Q%iACw;r7#O5LY9>R<JxDtl)Yemwe#&I9;9;{7BpyNSV^G<` ztO(*aKLGVxKxGC<ul^rMUT^*R|21;k4#fV&AN=_B|Npyw*)MnuYDWq%FudX+!E6br z*?B)9?EzR@5!^Ol0Goa4)c^mlK<-%f`~U0XpnRii$OsBIaND?B_pQi=-bV=+d>^@F zZ+Pcgz2TiWH}_jnY3{ee+T3qtt-0SyXLG-mtmb~Z!VomC!TnS^Tl%eNwe(x}YO{B- z+4JABWvjo7jh_FOwYu#cXEpa**=*^z;!ycesC+0?p1YbGtk)kZ?hh3gt>%6!T`m3A z6DsZr6_>8&e#;3m3&hWEf9J-%;hp!-|F0doH@pLhJ0gj@g2bygykqayc*k8W{niRe z&JH9udjnY91WDWiBo5LuTk{>*Puv^c6(Na%+~m%^;ax6FtXlIOd$q+o-fHf*yw%cg zk5_+xm(I1}9XCk6Yr{MF?D=4EP}soaSU_@BAKs;NeR$`=1$BSbhj+`X%HKV&+WwBe zn)@wiPGy1>`@84WJKphUOTT5WR(mH{&HeU@iuXftZRa;2H;7#De#Fwf_YJt8$FShx zmut=;zZE$hK*b<KLmGr;V1Uve>>q;`5<&X}u>LK$&k8CRpkqgRKSAw8XxSjJ;2{^o zg2&=NA^m}OKmNZ4%~O4F*L}%Qu;8Ib!u+Qm0rQ`-CG<aF4d{Qsn&9?;v0=eOrU?rk zuK4l)wOitbhacMaaxge7c+6rj^$90venDWtLw1G*4;dX=9vT1Ff5^fR_VD}v|56{? z_r6f!U}TWtU}TU3&51eaz68z5f>xGUF)%RLLf24%XnrUkwC)MSH-hp(v-Ti9Xdw}Z z2Cb(8(Y#Q3(3&d{Um3~=t+@j6L2IT!G-!$*M2kb^LF>Fge9-zW5DgAj&=R-e%3}TG zoW$Z{{q%y&eErml0?@(-2Dik_oYWMBl6(cwQVj)&utHjXkpgI4LuOvOA{T>d3Il^a zn*P!}h*FUGXl8)SS13!&DNRK)2i**iLe&)gl+2>k<dV$%JX~hM6`+}iu(vq1L;<c! z5wvcN7`s6B!7vW>U~hobAnXE%6UgaEek@8%O@V|JLLF#L3`7aYK?reBxTeA-knAle z&($v|&rQzAEHJ<oKbd*ZC<2*@OD~?d$;?xL$%0HkiB}Z+3(9j<Q}k2w!0Uh*7|_!R z$Q@ugkSVy_0WqT>wJ0+myvz#`2H-Hv%u|5Kfy_Y2A%%|uiW1~Bh{dfbr6rZ|$(6}D zsc7+)T95}a2qBNtK1Eb@pmd~aqGyx_TC14Gzz|xTn4YR&rJ!1@U<1lMc3ce5WkwpB z3aLd!`9%!iMMDT419X`YLIkpA3c*j#&&x|qE=f(%&{R-VU|;~JnxxXSwA3Q7O&~Xb z)&#m_7MFkoa?-dMLh|#o12XbU@<9SA3LdG6MPRuUg@F9xOi)e&N#vv{sDe~8Fhpy` zDio&{7iZ?@DS+2vrEoDMl~z@y7Ag4Vr=&8JWhNCRg0<y>xC}YTDGDi2`}B;`bU+-C ziN#zD4895s3<|0#AZIZo734Cc<fkiS7AvIZ=cO_f<fJARr!s)W(o$1%6fzPE3Mv^G zN)od(^U@UxGLuV6i&7aF%2P9oQWP>k&Q3~AEMZ8_NKMXGD9K2Lh%q>YhJ^V0DYyrC z`YV7Ifr0E!QAjJw&s8YM%!AktT3c3H!oXl)$iM(v$ZE&{p$A*J8*%S{J*bQZrO8n| z^g^J9hmj$K2ebl?fdRAz4iuNQjG)!y3=E((b09uw?Hj0`?%`x)0M*+n>X5bSpmpb< zwa=inv7mL(fApBZYoI~=umAq%Z((F)0M+|9SQ)`<&Lx-`!E3HpF)}cK)?0(t<H6Qd zgVyOW7=TvnF)%nVGJw}ygW3Y1df$hGkpaZE;b3F{t?2~m1GOVSZGnIP|L5OfXJq*Q z|9?Knj1T|+=Qpu~TuowJfY!)EwanmTWEjjC>P#>N3Ln_|bdawD7$9*6mON18ARCop zegAm8!;%79uItKy5c+W(PH}f<XDbDbpv2;Wq|C%T1w#WpBRxZ1Gwq^+OhZj5SHZ}@ z$k4#h(15{FkAZ<9F*PwMlYtS`@?$k)U}NK8<YeSx5@Hc%6k!x)6la!Tlw_1*l3`Q= zxex3vGy=5u0VKo>T|5oij{xC=T8|72Q=t1YK<h$5;-GW|qM5;~vKbga=?cOJr8Wiz zP<n&#L96{47+~pvnE|x&pMe3CULf+I6vV&)N>>m*s8z|p07`EVKDZiS0Hu2fACzht zz-a@*2jvO|2GAZ62p^O?7#KkL1Hy;wCeQ(`p91f70JV}K`$Zt~pp?wO;Ghc$8D?-Q zhwSHo$b(Wl0|O{uLHM9l4{Gc}!i5=}OF$I^j1S388$ja>VEaHj6(H+UA^Jh71;m12 zX7DZs2pdE)Ge|;X0K@~Wkp1}IlK~O_ptZR^3<&=+Fz_;f<U#viAUXuV`~%z&|G?y7 z{%2s|2g}3U$G{-Q;1AIVCRrFh{s)<V21);P1_lNgp9yN;3nY1vdRY8`N)-?v7XF~! z9LW0zVCGNZgt?EK0i<378b2WQZ@?~r5Fqs+{~5sL`5C^0f*Z<bWZ(zu|A6EkkkK$c z%)J6UF#CAH>Sd7lAgwSyOuYw^Jjnhn(D(#}7s$P!@*3hoUIsbP{voJ(nEnbV9~Ay3 zj0_B*HHIJ;FfxdP!ylHOK)YK&Wi5=)$RG@MAE-`%nV-(czyRaJ%m<bG5P2bnVn#%I z1(nVq_k!$$$cr;f0$B{<Fu=kSw6+i;1PQ+eB=;_1WMBaC7chX<a6{6U0DRK~B>WVR z`0GJ?s(2Y0kkxNMk_Uy?0VMt&Mg|5DALMVCe_rsx9LdXYije`lCJt0mz~YyIA0dAi z#N=mWxPj!p6G-wP`)(ldpD{8pfcPJf)Nc_083GCcUWN~h3=E*PTcElNX5R@U`TvXz z3?TjrB>f432>l@Y3Xu4mObiSlKC*faAyoAeNPN(`br2t9B`iEdgc0iHnHa!pe?TP+ z$bF!s2wDdO<AdziKvHkd#J~XJBinxfN#2u*fdRBW2U-6GB>4y?1_luS3zB~~z&F7_ z;{ON|Kb?tz0mMgEzeE(_eo%S@jXQ%vn}I<boW6IU$^Ss&gZ%Rci4W3mA%-vyByWSn z2g%P6N0pz0#0SZ9NTAB|An`%+6_Tj(HAsAr{1zlW$o?Hje2_eNTp8>^F>wA~0h;>* z^C95{o(qKXLF#9K3JoY9WFBa~5X^;^uMvu<?g7m$BFm@1YjTMBpm|4R`4DAP{h&EX zWcdjysPZ$A_#pRz*Z6}qK+LZJt@(%YLGpW$_?4i91eSx;S784j$%E8OK+9`Tc?gmR ztrdr8;bp*9-md`7FMt(5%6k|el>R~H!Rl)U20?~aCPe)WX{CZSf(cN0H<<}he={%$ zF)RVO7uwcjWDsFk%Y-ODLGlMc@}NuxZpVp&(<`Vg3O0~|2NJ)aN(L;z1D0Qd#J|SG zzyR_es0}W}z{~KAi2*z(4Du3)|BZ=(0hE3=Fo101W%$R$z`!HU2;SEQl4oaT0ME^U z^n>=h@iQ}k$L}G0F$O76K?SxOvez+>g@FN9pDQqkF_<wkfajrE7$N58Lz-k@9iY~X z6EmVcBETTd5Wvg;p6h{`ABJQ;NPQ|Z0|O}kLgd96GME_{K<VWP)conp3=A@$H9`yw z3?TDLP|O!&umEWU+YWLM14A{M`42#QW})drh>4G(hnWF94+YXD$RNfr4bA*TX!<uX zGcfECV`KoeyFuZ%lbHcL_x=XzzEjK$;5l2+FfYiwi)i{Eq4B>!-4C%}oPia@Kytqr z8ebiaZ;r<IK;tK(@zYrt7(nF>XdfoX{W(bSDZn7c@D9?12D<<hAC+kOr-IZgGBWId zrl&P54B+``n144RsR!-7I*7yvnRkJOfdSUO5o8i$xQizL295uVg@FOoo&*UCGVn8S zqNOh>RtAP1F-Gv13CKUntPBjG@&mN58N@eYWnci6zX?$HTBGUrXJr8IA%V%qvobJ% z=CL65i817&sc%5z_oML_fXp)h?M?%g7GezZnNZVf5euR{4RRkF$RcoPL(=PdRt5%8 zeFNGv43gi*imHDfntf+jQS;XgRtE6Cm>edMdAtmFSs55W^&4mc0%YD(H2vRL85ltI zR{=D9IM^7#>q$O9_4A;m2N^WJE*jqjjUU3s0G{&&^}Im&AqGu84~<{T#=roo-$20v zQa=$*ei0kOzo7K94o!YP8vh&;ACw+nurV;?NH8*h+CQN1c#9+tN}qqx_`K{4;Q45X zd&C*U*%=s8#26W1@nZ@~f6($+h>4p)4%CoDicdW>z70DA1E@U$OP>t-rNu?yjq~Zr z$@+;!xzOG7>3OA~ZgxhRzM+A>o*ooolTR)xG1SXvP)T7>Nu-KtnR@vQ$%#2R@#U$B z+3{(4R53IUWN1-IaY<=fnqD#k$oS0Mf}G6Ml=!ry%#vaT#FpLolHB-Y(5BsDhWPlD z{P^^o{G`O3_>_|TqT=|((h7#;{M>?^)RNQ`Jp=42;?pwoGUF4AiV`d1Q}arSDjCv> z5_41IQ%ZAlD;eVBk$CZ$d6^|BO5vl&@wxdW`9*rk44{EqSIGPlh#3l-Dgtp_;FCSY z@$ea&;`ri{B0UqZM$mvSm=O-%S6duk2AWBNs4!*-2=|4W91!jcHy9)eo{eBAjxWti z1v9}$8Zi{dBXJEu`a{9eV3nZB4X`=`kObJm0LW}bK)5fM>rz@$=?tDzNX<#p1^Hbs zKbRpt-Yv+{*EQbN&m}&dAs#hMQW)Z0BK;hFJ)Kcyz#E?#;@y4xog97Q{oUMxT|?qS z9G!ezK}LZ03?~<tf}?^VF}WnOEU_dt9x_bNP?TDhT2!108kvtzsw@Ey*@K7fA@X2m zJf4l*pjn0Zq|%a-{5*#E_@rV`a6-0Wr<SGWm4Ig*91vTL(^44RQ%gWo4vBfmsSNR{ zDTyVC@NL-ez1oNoe2AH;c`5PnkZsmThLuznq~_!?6s0DY#e>H1<CAkTL3XC(rw8O0 zLpPBlsmI*kU0ed%aE+t{vgaB}ptz(cIk5y;ps=VU4T%rgtc@f9-G>d`w2mYJww@ua zBtH?9R}xDSAv?J-w{;`w0Y_JAJX%g*$gKo<5N+RkenDy;lGgb6l;ZsOjKsW@oK)~; zbtJjsOca%#{_({nDVcfkrNyZ!pv~wxC?<iz**PPzhygqk1u-%+FCCm_KnWK){y>=w zytN*>Ssj${z-k~<FYy7Me(|1u@Qv$8ZUSwJN8&=Z$|DIN8Q>op!r+`!<ddAj5FZao z8?fE(ke&RHR0GKu;EnPiFL>sGcG!cq<0F}xlbjM?lAoTQlM2nwAYXw~S`M-*@Roig z0azr1jv_!32Jh)d;wP6DfzmqcXaFRc#FG3>ByO0eQ;=hbr@vpkuYZVt5Ga_S6M#sH z;^RYnouNeo<YWRQNzgF?NL+B9#d^R(CMW@d99oQ|9DG;-62AmC5eNznpZsLVNef5{ zlJk+ZgM!yBCqJ=-fkCghGPfi#i9ru^@&TC6fUz?3N>Ymo81(Y;OH%dH^GfxSN;7j( zbTd<+LXJ+Jx+RI}3}Cs8#NrGFy_Cwl;>uhIT~Y**0To!FIeoA)C?~#%L9Zw^2c#at zD99;c&;utty^_?55(Yg`MZ}<2ln*X&^c;hH^-?P`Qz{trQZpd65JWko0)i-qu~RDZ z5_2<?8T8WgOBnPZ1|$_1Gw3Df=jMV69I$bTB_&0fNu?#J#n46v5fo?+2h<}6bv;32 z@ga;1;B$yzT0wFkHfW6osQCg?2O6UXogD-k^#{p;FsMxgqRki>z$5J-b)d2PDWEYr zkOUON)PdSO-~Rv42dM*%>2G0VU;v%>0c(<i)Pb-c188IyG#&^U>z80=U;y=#K}|D| z+dyhSBk5t_F>i=E&>R4$?F*V~f?5k7+m2&k0M8eJ>;=sYG_f-<L@+Rb=c+(zLE<2s z&A`9_nqLC3L30Lo*cli={Q{7^pl%z;UXc1K=y^gQb)dNf8xBxk6k#4n9jLwA3{~gE z0GVU(;egC_f&2>^xreFi0r&kO=Qx4JwtF}sXA^<!0%4Fk5Z#WX4m3tEgOh>b3n)N9 zlF+k}Kx!u;sRPYbOyFi<m;#D)s5+3_K+G9P>Of=YD(aB)tUz)g3^EHu&x5K1`4`j| z(@|$&-~j~+ND^u<h`9`+uAqqlGUs8T3o#EeO9C3N0jXkO*a%SvKJx=Kw&I|RkOQfJ z*}EHhJ`*VHL1WOMv!`HkFm)jQaR$BAaGWPOE57Ru5I?!1-AZLTjgPf5CaR^8Z zW*#VP?m&dWXH|jbC_$Y|(D(^R4G4qG0^x^9>Of;68w?=n3Zw>vL1uyI=g@P)K=y*x zZgChw<~u=hAPiFn8k+(|Cusg3EN;la0Ge<Eu|XIl2f|+==^oT&0|_&j88R?{j{O32 zpl$-OL25y924aJ7h9Luk0zc&Zs%g-81LY%5h<P9-VBF!rz~BbT_+TDlei1Y$3-SY0 RnBkl|0|P6_5~u)-2>^lXtM32+ literal 0 HcmV?d00001 diff --git a/master_main/gpio.h b/master_main/gpio.h new file mode 100644 index 0000000..a22428f --- /dev/null +++ b/master_main/gpio.h @@ -0,0 +1,263 @@ +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#define IN 0 +#define OUT 1 +#define LOW 0 +#define HIGH 1 + +#define VALUE_MAX 256 +#define BUFFER_MAX 3 +#define DIRECTION_MAX 45 + +static int GPIOExport(int pin); +static int GPIOUnexport(int pin); +static int GPIODirection(int pin, int dir); +static int GPIORead(int pin); +static int GPIOWrite(int pin, int value); + +static int PWMWriteDutyCycle(int pwmnum, int value); +static int PWMWritePeriod(int pwmnum, int value); +static int PWMEnable(int pwmnum); +static int PWMUnexport(int pwmnum); +static int PWMExport(int pwmnum); +static int PWMUnable(int pwmnum); + +static int GPIOExport(int pin) +{ + char buffer[BUFFER_MAX]; + ssize_t bytes_written; + int fd; + + fd = open("/sys/class/gpio/export", O_WRONLY); + if (-1 == fd){ + fprintf(stderr, "Failed to open export for writing!\n"); + return(-1); + } + + bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin); + write(fd, buffer, bytes_written); + close(fd); + return(0); +} + +static int GPIOUnexport(int pin) +{ + char buffer[BUFFER_MAX]; + ssize_t bytes_written; + int fd; + + fd = open("/sys/class/gpio/unexport", O_WRONLY); + if (-1 == fd){ + fprintf(stderr, "Failed to open gpio value for writing!\n"); + return (-1); + } + bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin); + write(fd, buffer, bytes_written); + close(fd); + return(0); +} + +static int GPIODirection(int pin, int dir) +{ + static const char s_directions_str[] = "in\0out"; + + char path[DIRECTION_MAX] = "/sys/class/gpio/gpio%d/direction"; + int fd; + + snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", pin); + + fd = open(path, O_WRONLY); + if (-1 == fd){ + fprintf(stderr, "Failed to open gpio direction for writing!\n"); + return(-1); + } + + if(-1 == write(fd, &s_directions_str[IN == dir ? 0 : 3], IN == dir ? 2 : 3)){ + fprintf(stderr, "Failed to set direction!\n"); + // close(fd); + return(-1); + } + + close(fd); + return(0); +} + +static int GPIORead(int pin) +{ + char path[VALUE_MAX]; + char value_str[3]; + int fd; + + snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin); + fd = open(path, O_RDONLY); + if (-1 == fd){ + fprintf(stderr, "Failed to open gpio value for raeding!\n"); + return (-1); + } + + if (-1 == read(fd, value_str, 3)){ + fprintf(stderr, "Failed to read value!\n"); + // close(fd); + return(-1); + } + + close(fd); + return(atoi(value_str)); +} + +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[LOW == value ? 0 : 1], 1)){ + fprintf(stderr, "Failed to write value!\n"); + // close(fd); + return(-1); + } + + close(fd); + return(0); +} + +static int PWMExport(int pwmnum){ + #define BUFFER_MAX 3 + char buffer[BUFFER_MAX]; + int bytes_written; + int fd; + + fd = open("/sys/class/pwm/pwmchip0/export", O_WRONLY); + if(-1==fd){ + fprintf(stderr, "Failed to open in export!\n"); + return(-1); + } + bytes_written=snprintf(buffer, BUFFER_MAX, "%d", pwmnum); + write(fd, buffer, bytes_written); + close(fd); + sleep(1); + return(0); +} + +static int PWMUnexport(int pwmnum) +{ + char buffer[BUFFER_MAX]; + ssize_t bytes_written; + int fd; + + fd = open("/sys/class/pwm/pwmchip0/unexport", O_WRONLY); + if(-1==fd){ + fprintf(stderr, "Failed to open in unexport!\n"); + return(-1); + } + bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pwmnum); + write(fd, buffer, bytes_written); + close(fd); + sleep(1); + return(0); +} + +static int PWMEnable(int pwmnum){ + static const char s_unenable_str[] = "0"; + static const char s_enable_str[] = "1"; + char path[DIRECTION_MAX]; + int fd; + + snprintf(path, DIRECTION_MAX, "/sys/class/pwm/pwmchip0/pwm%d/enable", pwmnum); + fd=open(path,O_WRONLY); + if(-1==fd){ + fprintf(stderr, "Failed to open in enable!\n"); + return -1; + } + + write(fd,s_unenable_str,strlen(s_unenable_str)); + close(fd); + + fd=open(path,O_WRONLY); + if(-1==fd){ + fprintf(stderr, "Failed to open in enable!\n"); + return -1; + } + + write(fd,s_enable_str,strlen(s_enable_str)); + close(fd); + return 0; +} + + +static int PWMUnable(int pwmnum){ + static const char s_unable_str[] = "0"; + char path[DIRECTION_MAX]; + int fd; + + snprintf(path, DIRECTION_MAX, "/sys/class/pwm/pwmchip0/pwm%d/enable", pwmnum); + fd=open(path,O_WRONLY); + if(-1==fd){ + fprintf(stderr, "Failed to open in enable!\n"); + return -1; + } + + write(fd,s_unable_str,strlen(s_unable_str)); + close(fd); + return 0; +} + +static int PWMWritePeriod(int pwmnum, int value){ + char s_values_str[VALUE_MAX]; + char path[VALUE_MAX]; + int fd,byte; + + snprintf(path, VALUE_MAX, "/sys/class/pwm/pwmchip0/pwm%d/period",pwmnum); + fd=open(path,O_WRONLY); + if(-1==fd){ + fprintf(stderr, "Failed to open in period!\n"); + return(-1); + } + + byte=snprintf(s_values_str,10,"%d",value); + + if(-1==write(fd,s_values_str,byte)){ + fprintf(stderr, "Failed to write value in period!\n"); + close(fd); + return(-1); + } + + close(fd); + return(0); +} + +static int PWMWriteDutyCycle(int pwmnum, int value){ + char path[VALUE_MAX]; + char s_values_str[VALUE_MAX]; + int fd,byte; + + snprintf(path, VALUE_MAX, "/sys/class/pwm/pwmchip0/pwm%d/duty_cycle",pwmnum); + fd=open(path,O_WRONLY); + if(-1==fd){ + fprintf(stderr,"Failed to oepn in duty_cycle!\n"); + return(-1); + } + + byte=snprintf(s_values_str, 10,"%d",value); + + if(-1==write(fd,s_values_str,byte)){ + fprintf(stderr, "Failed to write value! in duty_cycle\n"); + close(fd); + return(-1); + } + + close(fd); + return(0); +} \ No newline at end of file diff --git a/master_main/lcd.h b/master_main/lcd.h new file mode 100644 index 0000000..849d30e --- /dev/null +++ b/master_main/lcd.h @@ -0,0 +1,149 @@ +#include <wiringPiI2C.h> +#include <wiringPi.h> // -lwiringPi +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +// Define some device parameters +#define I2C_ADDR 0x27 // I2C device address + +// Define some device constants +#define LCD_CHR 1 // Mode - Sending data +#define LCD_CMD 0 // Mode - Sending command + +#define LINE1 0x80 // 1st line +#define LINE2 0xC0 // 2nd line + +#define LCD_BACKLIGHT 0x08 // On +// LCD_BACKLIGHT = 0x00 # Off + +#define ENABLE 0b00000100 // Enable bit + +int fd; // seen by all subroutines + + +void typeFloat(float myFloat); +void typeInt(int i); +void ClrLcd(void); +void lcdLoc(int line); +void typeChar(char val); +void typeln(const char *s); +void lcd_byte(int bits, int mode); +void lcd_toggle_enable(int bits); +void lcd_init(); +void itoa(int n, char* s); +void reverse(char* s); +void ftoa(float f, char* buf); + +// float to string +void typeFloat(float myFloat) { + char buffer[20]; + sprintf(buffer, "%4.2f", myFloat); + typeln(buffer); +} + +// int to string +void typeInt(int i) { + char array1[20]; + sprintf(array1, "%d", i); + typeln(array1); +} + +// clr lcd go home loc 0x80 +void ClrLcd(void) { + lcd_byte(0x01, LCD_CMD); + lcd_byte(0x02, LCD_CMD); +} + +// go to location on LCD +void lcdLoc(int line) { + lcd_byte(line, LCD_CMD); +} + +// out char to LCD at current position +void typeChar(char val) { + + lcd_byte(val, LCD_CHR); +} + + +// this allows use of any size string +void typeln(const char *s) { + + while ( *s ) lcd_byte(*(s++), LCD_CHR); + +} + +void lcd_byte(int bits, int mode) { + + //Send byte to data pins + // bits = the data + // mode = 1 for data, 0 for command + int bits_high; + int bits_low; + // uses the two half byte writes to LCD + bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT ; + bits_low = mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT ; + + // High bits + wiringPiI2CReadReg8(fd, bits_high); + lcd_toggle_enable(bits_high); + + // Low bits + wiringPiI2CReadReg8(fd, bits_low); + lcd_toggle_enable(bits_low); +} + +void lcd_toggle_enable(int bits) { + // Toggle enable pin on LCD display + delayMicroseconds(500); + wiringPiI2CReadReg8(fd, (bits | ENABLE)); + delayMicroseconds(500); + wiringPiI2CReadReg8(fd, (bits & ~ENABLE)); + delayMicroseconds(500); +} + + +void lcd_init() { + // Initialise display + lcd_byte(0x33, LCD_CMD); // Initialise + lcd_byte(0x32, LCD_CMD); // Initialise + lcd_byte(0x06, LCD_CMD); // Cursor move direction + lcd_byte(0x0C, LCD_CMD); // 0x0F On, Blink Off + lcd_byte(0x28, LCD_CMD); // Data length, number of lines, font size + lcd_byte(0x01, LCD_CMD); // Clear display + delayMicroseconds(500); +} + +/* itoa: convert n to characters in s */ +void itoa(int n, char* s) +{ + int i, sign; + + if ((sign = n) < 0) /* record sign */ + n = -n; /* make n positive */ + i = 0; + do { /* generate digits in reverse order */ + s[i++] = n % 10 + '0'; /* get next digit */ + } while ((n /= 10) > 0); /* delete it */ + if (sign < 0) + s[i++] = '-'; + s[i] = '\0'; + reverse(s); +} +void ftoa(float f, char* buf) { + sprintf(buf, "%f", f); + // return buf; +} + /* reverse: reverse string s in place */ + void reverse(char* s) + { + int i, j; + char c; + + for (i = 0, j = strlen(s)-1; i<j; i++, j--) { + c = s[i]; + s[i] = s[j]; + s[j] = c; + } + } \ No newline at end of file diff --git a/master_main/lcd/WiringPi b/master_main/lcd/WiringPi new file mode 160000 index 0000000..f97a623 --- /dev/null +++ b/master_main/lcd/WiringPi @@ -0,0 +1 @@ +Subproject commit f97a6230160b819e6daea7eb242404afa708e421 diff --git a/master_main/lcd/a.out b/master_main/lcd/a.out new file mode 100644 index 0000000000000000000000000000000000000000..2e905a86f20c01eaca643435c98f5f92230c3af2 GIT binary patch literal 13196 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 literal 0 HcmV?d00001 diff --git a/master_main/lcd/c b/master_main/lcd/c new file mode 100644 index 0000000000000000000000000000000000000000..462fec7d0c157db5bb0c71975ce7a8def77b17c7 GIT binary patch literal 18880 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 ZGDQFuftd#yg-2Fr?83l+JiP-`2LN1+u=oG~ literal 0 HcmV?d00001 diff --git a/master_main/lcd/cc.c b/master_main/lcd/cc.c new file mode 100644 index 0000000..d16d087 --- /dev/null +++ b/master_main/lcd/cc.c @@ -0,0 +1,235 @@ +#include <wiringPiI2C.h> +#include <wiringPi.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdbool.h> + +// Define some device parameters +#define I2C_ADDR 0x27 // I2C device address + +// Define some device constants +#define LCD_CHR 1 // Mode - Sending data +#define LCD_CMD 0 // Mode - Sending command + +#define LINE1 0x80 // 1st line +#define LINE2 0xC0 // 2nd line + +#define LCD_BACKLIGHT 0x08 // On +// LCD_BACKLIGHT = 0x00 # Off + +#define ENABLE 0b00000100 // Enable bit + +void lcd_init(void); +void lcd_byte(int bits, int mode); +void lcd_toggle_enable(int bits); + +// added by Lewis +void typeInt(int i); +void typeFloat(float myFloat); +void lcdLoc(int line); //move cursor +void ClrLcd(void); // clr LCD return home +void typeln(const char *s); +void typeChar(char val); + +void itoa(int n, char s[]); +void reverse(char s[]); + + +int fd; // seen by all subroutines + +int buzzerMode = true; +int vibMode = false; +int distance = 100; +int heartbeat = 80; +int event=1; + +void* lcd(){ + if (wiringPiSetup () == -1) exit (1); + fd = wiringPiI2CSetup(I2C_ADDR); + lcd_init(); // setup LCD + while (1) { + // 처음 시작할 때 LCD 한 번 비우고 감 + + // 부저모드인지, 진동 모드인지 + if(buzzerMode == 1){ + lcdLoc(LINE1); + typeln("buzzer Mode"); + } + else if(vibMode == 1){ + lcdLoc(LINE1); + typeln("vibration mode"); + } + + // 거리가 나와야하고 + lcdLoc(LINE2); + char dis[10]; + itoa(distance,dis); + strcat(dis,"M "); + + // 심박수가 나와야하고 + char htb[100]; + itoa(heartbeat,htb); + strcat(dis, htb); + strcat(dis,"bpm"); + typeln(dis); + + delay(2000); + // 이벤트가 발생하면 화면이 바뀌어야 함 + // 특이사항 : + if(event == 1){ + // 반려동물이 멀어지면 -> 이탈 경보 + ClrLcd(); + lcdLoc(LINE1); + typeln("dog is gone"); + lcdLoc(LINE2); + typeln("please"); + delay(2000); + ClrLcd(); + event=0; + } + else if(event==2){ + // 사진 촬영하면 -> 촬영했어용 + ClrLcd(); + lcdLoc(LINE1); + typeln("dog feel happy"); + lcdLoc(LINE2); + typeln("taking picture"); + delay(2000); + ClrLcd(); + event=0; + } + else if(event==3){ + // 심박수 측정해서 이상값이 있으면 -> 건강 이상해용 + ClrLcd(); + lcdLoc(LINE1); + typeln("weird heartbeat"); + lcdLoc(LINE2); + typeln("check the heart"); + delay(2000); + ClrLcd(); + } + } +} + +int main() { + + + // char array1[] = "Hello world!"; + // char array2[] = "Smart Class!"; + + + return 0; + +} + + +// float to string +void typeFloat(float myFloat) { + char buffer[20]; + sprintf(buffer, "%4.2f", myFloat); + typeln(buffer); +} + +// int to string +void typeInt(int i) { + char array1[20]; + sprintf(array1, "%d", i); + typeln(array1); +} + +// clr lcd go home loc 0x80 +void ClrLcd(void) { + lcd_byte(0x01, LCD_CMD); + lcd_byte(0x02, LCD_CMD); +} + +// go to location on LCD +void lcdLoc(int line) { + lcd_byte(line, LCD_CMD); +} + +// out char to LCD at current position +void typeChar(char val) { + + lcd_byte(val, LCD_CHR); +} + + +// this allows use of any size string +void typeln(const char *s) { + + while ( *s ) lcd_byte(*(s++), LCD_CHR); + +} + +void lcd_byte(int bits, int mode) { + + //Send byte to data pins + // bits = the data + // mode = 1 for data, 0 for command + int bits_high; + int bits_low; + // uses the two half byte writes to LCD + bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT ; + bits_low = mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT ; + + // High bits + wiringPiI2CReadReg8(fd, bits_high); + lcd_toggle_enable(bits_high); + + // Low bits + wiringPiI2CReadReg8(fd, bits_low); + lcd_toggle_enable(bits_low); +} + +void lcd_toggle_enable(int bits) { + // Toggle enable pin on LCD display + delayMicroseconds(500); + wiringPiI2CReadReg8(fd, (bits | ENABLE)); + delayMicroseconds(500); + wiringPiI2CReadReg8(fd, (bits & ~ENABLE)); + delayMicroseconds(500); +} + + +void lcd_init() { + // Initialise display + lcd_byte(0x33, LCD_CMD); // Initialise + lcd_byte(0x32, LCD_CMD); // Initialise + lcd_byte(0x06, LCD_CMD); // Cursor move direction + lcd_byte(0x0C, LCD_CMD); // 0x0F On, Blink Off + lcd_byte(0x28, LCD_CMD); // Data length, number of lines, font size + lcd_byte(0x01, LCD_CMD); // Clear display + delayMicroseconds(500); +} + +/* itoa: convert n to characters in s */ + void itoa(int n, char* s) + { + int i, sign; + + if ((sign = n) < 0) /* record sign */ + n = -n; /* make n positive */ + i = 0; + do { /* generate digits in reverse order */ + s[i++] = n % 10 + '0'; /* get next digit */ + } while ((n /= 10) > 0); /* delete it */ + if (sign < 0) + s[i++] = '-'; + s[i] = '\0'; + reverse(s); + } + + /* reverse: reverse string s in place */ + void reverse(char* s) + { + int i, j; + char c; + + for (i = 0, j = strlen(s)-1; i<j; i++, j--) { + c = s[i]; + s[i] = s[j]; + s[j] = c; + } + } \ No newline at end of file diff --git a/master_main/lcd/gpio.h b/master_main/lcd/gpio.h new file mode 100644 index 0000000..8c850c5 --- /dev/null +++ b/master_main/lcd/gpio.h @@ -0,0 +1,263 @@ +#include <stdio.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> + +#define IN 0 +#define OUT 1 +#define LOW 0 +#define HIGH 1 + +#define VALUE_MAX 256 +#define BUFFER_MAX 3 +#define DIRECTION_MAX 45 + +static int GPIOExport(int pin); +static int GPIOUnexport(int pin); +static int GPIODirection(int pin, int dir); +static int GPIORead(int pin); +static int GPIOWrite(int pin, int value); + +static int PWMWriteDutyCycle(int pwmnum, int value); +static int PWMWritePeriod(int pwmnum, int value); +static int PWMEnable(int pwmnum); +static int PWMUnexport(int pwmnum); +static int PWMExport(int pwmnum); +static int PWMUnable(int pwmnum); + +static int GPIOExport(int pin) +{ + char buffer[BUFFER_MAX]; + ssize_t bytes_written; + int fd; + + fd = open("/sys/class/gpio/export", O_WRONLY); + if (-1 == fd){ + fprintf(stderr, "Failed to open export for writing!\n"); + return(-1); + } + + bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin); + write(fd, buffer, bytes_written); + close(fd); + return(0); +} + +static int GPIOUnexport(int pin) +{ + char buffer[BUFFER_MAX]; + ssize_t bytes_written; + int fd; + + fd = open("/sys/class/gpio/unexport", O_WRONLY); + if (-1 == fd){ + fprintf(stderr, "Failed to open gpio value for writing!\n"); + return (-1); + } + bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin); + write(fd, buffer, bytes_written); + close(fd); + return(0); +} + +static int GPIODirection(int pin, int dir) +{ + static const char s_directions_str[] = "in\0out"; + + char path[DIRECTION_MAX] = "/sys/class/gpio/gpio%d/direction"; + int fd; + + snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", pin); + + fd = open(path, O_WRONLY); + if (-1 == fd){ + fprintf(stderr, "Failed to open gpio direction for writing!\n"); + return(-1); + } + + if(-1 == write(fd, &s_directions_str[IN == dir ? 0 : 3], IN == dir ? 2 : 3)){ + fprintf(stderr, "Failed to set direction!\n"); + // close(fd); + return(-1); + } + + close(fd); + return(0); +} + +static int GPIORead(int pin) +{ + char path[VALUE_MAX]; + char value_str[3]; + int fd; + + snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin); + fd = open(path, O_RDONLY); + if (-1 == fd){ + fprintf(stderr, "Failed to open gpio value for raeding!\n"); + return (-1); + } + + if (-1 == read(fd, value_str, 3)){ + fprintf(stderr, "Failed to read value!\n"); + // close(fd); + return(-1); + } + + close(fd); + return(atoi(value_str)); +} + +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[LOW == value ? 0 : 1], 1)){ + fprintf(stderr, "Failed to write value!\n"); + // close(fd); + return(-1); + } + + close(fd); + return(0); +} + +static int PWMExport(int pwmnum){ + #define BUFFER_MAX 3 + char buffer[BUFFER_MAX]; + int bytes_written; + int fd; + + fd = open("/sys/class/pwm/pwmchip0/export", O_WRONLY); + if(-1==fd){ + fprintf(stderr, "Failed to open in export!\n"); + return(-1); + } + bytes_written=snprintf(buffer, BUFFER_MAX, "%d", pwmnum); + write(fd, buffer, bytes_written); + close(fd); + sleep(1); + return(0); +} + +static int PWMUnexport(int pwmnum) +{ + char buffer[BUFFER_MAX]; + ssize_t bytes_written; + int fd; + + fd = open("/sys/class/pwm/pwmchip0/unexport", O_WRONLY); + if(-1==fd){ + fprintf(stderr, "Failed to open in unexport!\n"); + return(-1); + } + bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pwmnum); + write(fd, buffer, bytes_written); + close(fd); + sleep(1); + return(0); +} + +static int PWMEnable(int pwmnum){ + static const char s_unenable_str[] = "0"; + static const char s_enable_str[] = "1"; + char path[DIRECTION_MAX]; + int fd; + + snprintf(path, DIRECTION_MAX, "/sys/class/pwm/pwmchip0/pwm%d/enable", pwmnum); + fd=open(path,O_WRONLY); + if(-1==fd){ + fprintf(stderr, "Failed to open in enable!\n"); + return -1; + } + + write(fd,s_unenable_str,strlen(s_unenable_str)); + close(fd); + + fd=open(path,O_WRONLY); + if(-1==fd){ + fprintf(stderr, "Failed to open in enable!\n"); + return -1; + } + + write(fd,s_enable_str,strlen(s_enable_str)); + close(fd); + return 0; +} + + +static int PWMUnable(int pwmnum){ + static const char s_unable_str[] = "0"; + char path[DIRECTION_MAX]; + int fd; + + snprintf(path, DIRECTION_MAX, "/sys/class/pwm/pwmchip0/pwm%d/enable", pwmnum); + fd=open(path,O_WRONLY); + if(-1==fd){ + fprintf(stderr, "Failed to open in enable!\n"); + return -1; + } + + write(fd,s_unable_str,strlen(s_unable_str)); + close(fd); + return 0; +} + +static int PWMWritePeriod(int pwmnum, int value){ + char s_values_str[VALUE_MAX]; + char path[VALUE_MAX]; + int fd,byte; + + snprintf(path, VALUE_MAX, "/sys/class/pwm/pwmchip0/pwm%d/period",pwmnum); + fd=open(path,O_WRONLY); + if(-1==fd){ + fprintf(stderr, "Failed to open in period!\n"); + return(-1); + } + + byte=snprintf(s_values_str,10,"%d",value); + + if(-1==write(fd,s_values_str,byte)){ + fprintf(stderr, "Failed to write value in period!\n"); + close(fd); + return(-1); + } + + close(fd); + return(0); +} + +static int PWMWriteDutyCycle(int pwmnum, int value){ + char path[VALUE_MAX]; + char s_values_str[VALUE_MAX]; + int fd,byte; + + snprintf(path, VALUE_MAX, "/sys/class/pwm/pwmchip0/pwm%d/duty_cycle",pwmnum); + fd=open(path,O_WRONLY); + if(-1==fd){ + fprintf(stderr,"Failed to oepn in duty_cycle!\n"); + return(-1); + } + + byte=snprintf(s_values_str, 10,"%d",value); + + if(-1==write(fd,s_values_str,byte)){ + fprintf(stderr, "Failed to write value! in duty_cycle\n"); + close(fd); + return(-1); + } + + close(fd); + return(0); +} \ No newline at end of file diff --git a/master_main/lcd/vibration_motor.c b/master_main/lcd/vibration_motor.c new file mode 100644 index 0000000..e22cd99 --- /dev/null +++ b/master_main/lcd/vibration_motor.c @@ -0,0 +1,318 @@ +#include <stdio.h> +#include <pthread.h> +#include <unistd.h> +#include "gpio.h" +#include <wiringPiI2C.h> +#include <wiringPi.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +#define LOW 0 +#define HIGH 1 + +int VIBRATION_MOTOR_PIN = 23; + +int BUTTON_PIN_IN = 20; +int BUTTON_PIN_OUT = 21; + + +// Define some device parameters +#define I2C_ADDR 0x27 // I2C device address + +// Define some device constants +#define LCD_CHR 1 // Mode - Sending data +#define LCD_CMD 0 // Mode - Sending command + +#define LINE1 0x80 // 1st line +#define LINE2 0xC0 // 2nd line + +#define LCD_BACKLIGHT 0x08 // On +// LCD_BACKLIGHT = 0x00 # Off + +#define ENABLE 0b00000100 // Enable bit + +void lcd_init(void); +void lcd_byte(int bits, int mode); +void lcd_toggle_enable(int bits); + +// added by Lewis +void typeInt(int i); +void typeFloat(float myFloat); +void lcdLoc(int line); //move cursor +void ClrLcd(void); // clr LCD return home +void typeln(const char *s); +void typeChar(char val); + +void itoa(int n, char s[]); +void reverse(char s[]); + + +int fd; // seen by all subroutines + +int buzzerMode = true; +int vibMode = false; +int distance = 100; +int heartbeat = 80; +int event=1; + +void* lcd(){ + if (wiringPiSetup () == -1) exit (1); + fd = wiringPiI2CSetup(I2C_ADDR); + lcd_init(); // setup LCD + while (1) { + // 처음 시작할 때 LCD 한 번 비우고 감 + + // 부저모드인지, 진동 모드인지 + if(buzzerMode == 1){ + lcdLoc(LINE1); + typeln("buzzer Mode"); + } + else if(vibMode == 1){ + lcdLoc(LINE1); + typeln("vibration mode"); + } + + // 거리가 나와야하고 + lcdLoc(LINE2); + char dis[10]; + itoa(distance,dis); + strcat(dis,"M "); + + // 심박수가 나와야하고 + char htb[100]; + itoa(heartbeat,htb); + strcat(dis, htb); + strcat(dis,"bpm"); + typeln(dis); + + delay(2000); + // 이벤트가 발생하면 화면이 바뀌어야 함 + // 특이사항 : + if(event == 1 ){ + // 반려동물이 멀어지면 -> 이탈 경보 + ClrLcd(); + lcdLoc(LINE1); + typeln("dog is gone"); + lcdLoc(LINE2); + typeln("please"); + delay(2000); + ClrLcd(); + event=0; + } + else if(event==2){ + // 사진 촬영하면 -> 촬영했어용 + ClrLcd(); + lcdLoc(LINE1); + typeln("dog feel happy"); + lcdLoc(LINE2); + typeln("taking picture"); + delay(5000); + ClrLcd(); + event=0; + } + else if(event==3){ + // 심박수 측정해서 이상값이 있으면 -> 건강 이상해용 + ClrLcd(); + lcdLoc(LINE1); + typeln("weird heartbeat"); + lcdLoc(LINE2); + typeln("check the heart"); + delay(2000); + ClrLcd(); + } + } +} + +// float to string +void typeFloat(float myFloat) { + char buffer[20]; + sprintf(buffer, "%4.2f", myFloat); + typeln(buffer); +} + +// int to string +void typeInt(int i) { + char array1[20]; + sprintf(array1, "%d", i); + typeln(array1); +} + +// clr lcd go home loc 0x80 +void ClrLcd(void) { + lcd_byte(0x01, LCD_CMD); + lcd_byte(0x02, LCD_CMD); +} + +// go to location on LCD +void lcdLoc(int line) { + lcd_byte(line, LCD_CMD); +} + +// out char to LCD at current position +void typeChar(char val) { + + lcd_byte(val, LCD_CHR); +} + + +// this allows use of any size string +void typeln(const char *s) { + + while ( *s ) lcd_byte(*(s++), LCD_CHR); + +} + +void lcd_byte(int bits, int mode) { + + //Send byte to data pins + // bits = the data + // mode = 1 for data, 0 for command + int bits_high; + int bits_low; + // uses the two half byte writes to LCD + bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT ; + bits_low = mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT ; + + // High bits + wiringPiI2CReadReg8(fd, bits_high); + lcd_toggle_enable(bits_high); + + // Low bits + wiringPiI2CReadReg8(fd, bits_low); + lcd_toggle_enable(bits_low); +} + +void lcd_toggle_enable(int bits) { + // Toggle enable pin on LCD display + delayMicroseconds(500); + wiringPiI2CReadReg8(fd, (bits | ENABLE)); + delayMicroseconds(500); + wiringPiI2CReadReg8(fd, (bits & ~ENABLE)); + delayMicroseconds(500); +} + + +void lcd_init() { + // Initialise display + lcd_byte(0x33, LCD_CMD); // Initialise + lcd_byte(0x32, LCD_CMD); // Initialise + lcd_byte(0x06, LCD_CMD); // Cursor move direction + lcd_byte(0x0C, LCD_CMD); // 0x0F On, Blink Off + lcd_byte(0x28, LCD_CMD); // Data length, number of lines, font size + lcd_byte(0x01, LCD_CMD); // Clear display + delayMicroseconds(500); +} + +/* itoa: convert n to characters in s */ + void itoa(int n, char* s) + { + int i, sign; + + if ((sign = n) < 0) /* record sign */ + n = -n; /* make n positive */ + i = 0; + do { /* generate digits in reverse order */ + s[i++] = n % 10 + '0'; /* get next digit */ + } while ((n /= 10) > 0); /* delete it */ + if (sign < 0) + s[i++] = '-'; + s[i] = '\0'; + reverse(s); + } + + /* reverse: reverse string s in place */ + void reverse(char* s) + { + int i, j; + char c; + + for (i = 0, j = strlen(s)-1; i<j; i++, j--) { + c = s[i]; + s[i] = s[j]; + s[j] = c; + } + } + +// INPLEMENTATION +// activate_seconds: 한번 진동이 작동할 때 동작하는 시간 (초 단위) +// interval_seconds: 매 진동 사이의 간격 (초 단위) +// times: 진동을 몇번 수행할지를 결정 + +void* active_vibration_motor(void* activate_seconds){ + + GPIOExport(VIBRATION_MOTOR_PIN); + GPIODirection(VIBRATION_MOTOR_PIN, OUT); + + GPIOWrite(VIBRATION_MOTOR_PIN, HIGH); + int a = *(int*)activate_seconds; + usleep(a * 1000 * 1000); + GPIOWrite(VIBRATION_MOTOR_PIN, LOW); + + GPIOUnexport(VIBRATION_MOTOR_PIN); + + return NULL; +} + +void* read_button(){ + + GPIOExport(BUTTON_PIN_IN); + GPIOExport(BUTTON_PIN_OUT); + + GPIODirection(BUTTON_PIN_IN, IN); + GPIODirection(BUTTON_PIN_OUT, OUT); + + + while(1){ + GPIOWrite(BUTTON_PIN_OUT,1); + int data = GPIORead(BUTTON_PIN_IN); + printf("BUTTON GPIO Read : %d from pin %d\n", data, BUTTON_PIN_IN); + usleep(1000 * 1000); + } + + GPIOUnexport(BUTTON_PIN_IN); + GPIOUnexport(BUTTON_PIN_OUT); + return NULL; + +} + +void* activate_buzzer(void* activate_seconds){ + const int PNUM = 0; + + PWMExport(PNUM); //pwm0 == gpio18 + PWMWritePeriod(PNUM,20000000); + PWMWriteDutyCycle(PNUM,0); + PWMEnable(PNUM); + + int a = *(int*)activate_seconds; + //a *= (1000*1000); + while(a--){ + for(int i=0;i<1000;i++){ + PWMWriteDutyCycle(PNUM,i*10000); + usleep(1000); + } + for(int i=1000;i>0;i--){ + PWMWriteDutyCycle(PNUM,i*10000); + usleep(1000); + } + } + + PWMUnable(PNUM); + return NULL; + +} + +int main(){ + pthread_t thread_1, thread_2, thread_3, thread_4; + int a = 1; + pthread_create(&thread_1, NULL, active_vibration_motor, &a); + // pthread_create(&thread_2, NULL, read_button, NULL); + pthread_create(&thread_3, NULL, activate_buzzer, &a); + pthread_create(&thread_4, NULL, lcd, &a); + + pthread_join(thread_1, NULL); + // pthread_join(thread_2, NULL); + pthread_join(thread_3, NULL); + pthread_join(thread_4, NULL); + +} \ No newline at end of file diff --git a/master_main/make b/master_main/make new file mode 100644 index 0000000..b9c206e --- /dev/null +++ b/master_main/make @@ -0,0 +1,13 @@ +all: vivration_motor + +vivration_motor: vivration_motor.o gpio.o + gcc -o vivration_motor vivration_motor.o gpio.o + +gpio.o: gpio.h + gcc -c -o gpio.o gpio.c + +vivration_motor.o: vivration_motor.c + gcc -c -o vivration_motor.o vivration_motor.c + +clean: + rm -f vivration_motor *.o \ No newline at end of file diff --git a/master_main/rf24libs/RF24 b/master_main/rf24libs/RF24 new file mode 160000 index 0000000..a028813 --- /dev/null +++ b/master_main/rf24libs/RF24 @@ -0,0 +1 @@ +Subproject commit a028813b285d6cec3090d2c96984bd67a399c52e diff --git a/master_main/rf24libs/RF24Gateway b/master_main/rf24libs/RF24Gateway new file mode 160000 index 0000000..7bf8ec0 --- /dev/null +++ b/master_main/rf24libs/RF24Gateway @@ -0,0 +1 @@ +Subproject commit 7bf8ec0a253fd9ad1c6111f83c4d14b6d6d6f2dc diff --git a/master_main/rf24libs/RF24Mesh b/master_main/rf24libs/RF24Mesh new file mode 160000 index 0000000..38ee022 --- /dev/null +++ b/master_main/rf24libs/RF24Mesh @@ -0,0 +1 @@ +Subproject commit 38ee0225c336349fab513907f9798d308d2db497 diff --git a/master_main/rf24libs/RF24Network b/master_main/rf24libs/RF24Network new file mode 160000 index 0000000..a334fa6 --- /dev/null +++ b/master_main/rf24libs/RF24Network @@ -0,0 +1 @@ +Subproject commit a334fa6ec420b2beedaf617018c11847cea80402 diff --git a/master_main/vib b/master_main/vib new file mode 100644 index 0000000000000000000000000000000000000000..398a4b9c13b69131c76fb78b056ef008cb552be9 GIT binary patch literal 24088 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 literal 0 HcmV?d00001 diff --git a/master_main/vibration_motor.c b/master_main/vibration_motor.c new file mode 100644 index 0000000..96c92d4 --- /dev/null +++ b/master_main/vibration_motor.c @@ -0,0 +1,406 @@ +#include <sys/wait.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <pthread.h> // -lpthread +#include <math.h> // -lm + +#include "gpio.h" +#include "lcd.h" // -lwiringPi + +#define _MAX_THRESHOLD 120 +#define _MIN_THRESHOLD 50 +#define LOW 0 +#define HIGH 1 + +#define BUF_SIZE 1024 +#define DIST_THRESHOLD 300 + + +int VIBRATION_MOTOR_PIN = 23; + +int BUTTON_PIN_IN = 20; +int BUTTON_PIN_OUT = 21; + +static inline double rad(double x) { + return x * 3.14159265 / 180.0; +} + +typedef struct { + double x; + double y; + double z; +}tagPT; + +static void* lcd(); +static void* activate_buzzer(void* activate_seconds); +static void* read_button(); +static void* active_vibration_motor(void* activate_seconds); +static void* recv_from_server(void *sock_ptr); +static void *recvpet(void *arg); + +void error_handling(char *message); +static inline double GetDistance(tagPT pt1, tagPT pt2 ); + + +int buzzerMode = true; +int vibMode = false; +int heartbeat = 80; +int event=0; + +int tookPhoto = false; +double curDist = DIST_THRESHOLD; +tagPT myPos = {127.123,68.56,123.56}; +tagPT dogPos = {127.123,68.56,123.56}; + +struct sockaddr_in serv_addr; +int sock; + +/** + * DESCRIPTION + * This code is attached to the Raspberry Pi #1 + * this module establish connection with Raspberry Pi #2(Master's main device) + * it is connected with buzzer, button, Vibrator, and LCD module + * + * this device receives data from RP #2, which is + * 1) heartbeat rate, 2) tookPhoto, and 3) Distance between Master and Slave + * based on these datas, it handles the EVENT and display it through LCD Module + * + * Here's the Events + * a) Alarm if the "Distance" between Master and Pet is too far + * b) Notice Photo has taken by the Camera module (on RP #3) "tookPhoto" + * c) whether "heartbeat rate" is abnormal or not + * + * these infos are also driven by BUZZER OR VIBRATOR + * + * User can switch these two modes + * by pushing the BUTTON + * + * In conclusion, + * all the events are displayed and noticed by LCD, and (BUZZER or VIBRATOR) + */ +int main(int argc, char* argv[]) +{ + + pthread_t thread_1, thread_2, thread_3, thread_4, thread_pet; + pthread_t send_thread, recv_thread; + int a = 10; + + char buf[BUF_SIZE]; + int str_len; + + //ARGUMENT 오류 핸들링 + if (argc != 3) { + printf("Usage : <PATH> <IP> <port>\n"); + exit(1); + } + //소켓 정보 설정 + sock = socket(PF_INET, SOCK_STREAM, 0); + if(sock == -1) { + error_handling("socket() error"); + } + + //ARGUMENT 활용해서 서버 구성 + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = inet_addr(argv[1]); + serv_addr.sin_port = htons(atoi(argv[2])); + + // Master_GPS 서버 소켓과의 연결 + if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) { + error_handling("connect() error"); + } else { + puts("[SERVER CONNECTED]"); + } + + pthread_create(&thread_pet, NULL, recvpet, NULL); + + pthread_create(&thread_1, NULL, active_vibration_motor, &a); + pthread_create(&thread_2, NULL, read_button, NULL); + pthread_create(&thread_3, NULL, activate_buzzer, &a); + pthread_create(&thread_4, NULL, lcd, &a); + pthread_create(&recv_thread, NULL, recv_from_server, &sock); + + + pthread_join(thread_1, NULL); + pthread_join(thread_2, NULL); + pthread_join(thread_3, NULL); + pthread_join(thread_4, NULL); + pthread_join(recv_thread, NULL); + pthread_join(thread_pet, NULL); + +} + +//서버로 부터 데이터 수신하는 THREAD용 함수 +static void *recv_from_server(void *sock_ptr) +{ + int sock = *(int *)sock_ptr; + char buffer[1024]; + ssize_t n; + + while ((n = read(sock, buffer, sizeof(buffer))) > 0) { + int data_cnt = atoi(buffer); + printf("read me : %s\n", buffer); + + char* p_delims = "_"; + char* p_tok = strtok(buffer, p_delims); + myPos.x = atof(p_tok); + p_tok = strtok(NULL, p_delims); + myPos.y = atof(p_tok); + + + // tookPhoto = atoi(p_tok); + // p_tok = strtok(NULL, p_delims); + // heartbeat = atoi(p_tok); + + // p_tok = strtok(NULL, p_delims); + curDist = GetDistance(myPos, dogPos); + + printf("Dist : %lf\n", curDist); + printf("TookPhoto : %d Heart : %d \n", tookPhoto, heartbeat); + } + + close(sock); //소켓을 닫아주고 + write(STDOUT_FILENO, "[*] session closed\n", 19); //세션이 닫혔다고 print해준다. + exit(0); +} + +static void* lcd() +{ + if (wiringPiSetup () == -1) { + exit (1); + } + fd = wiringPiI2CSetup(I2C_ADDR); + lcd_init(); // setup LCD + while (1) { + // 처음 시작할 때 LCD 한 번 비우고 감 + ClrLcd(); + // 부저모드인지, 진동 모드인지 + if(buzzerMode == 1) { + lcdLoc(LINE1); + typeln("buzzer Mode"); + } else if(vibMode == 1) { + lcdLoc(LINE1); + typeln("vibration mode"); + } + + // 거리가 나와야하고 + lcdLoc(LINE2); + char dis[100]; + + itoa((int)curDist,dis); + printf("lcd dist : %.2f, dis : %s\n",curDist, dis); + strcat(dis,"M "); + + // 심박수가 나와야하고 + char htb[100]; + + itoa(heartbeat,htb); + printf(" %d\n",heartbeat); + strcat(dis, htb); + strcat(dis,"bpm"); + typeln(dis); + + delay(1000); + // 이벤트가 발생하면 화면이 바뀌어야 함 + // 특이사항 : + if( event == 1 || curDist > DIST_THRESHOLD){ + // 반려동물이 멀어지면 -> 이탈 경보 + event = 1; + ClrLcd(); + lcdLoc(LINE1); + typeln("dog is gone"); + lcdLoc(LINE2); + typeln("please"); + delay(2000); + ClrLcd(); + event=0; + } else if( event == 2 || tookPhoto == true){ + // 사진 촬영하면 -> 촬영했어용 + event = 2; + ClrLcd(); + lcdLoc(LINE1); + typeln("dog feel happy"); + lcdLoc(LINE2); + typeln("taking picture"); + delay(2000); + ClrLcd(); + event=0; + tookPhoto = false; + } else if( event == 3 || (heartbeat > _MAX_THRESHOLD || heartbeat < _MIN_THRESHOLD)) { + // 심박수 측정해서 이상값이 있으면 -> 건강 이상해용 + event = 3; + ClrLcd(); + lcdLoc(LINE1); + typeln("weird heartbeat"); + lcdLoc(LINE2); + typeln("check the heart"); + delay(2000); + ClrLcd(); + event = 0; + } + } +} + + + +// INPLEMENTATION +// activate_seconds: 한번 진동이 작동할 때 동작하는 시간 (초 단위) +// interval_seconds: 매 진동 사이의 간격 (초 단위) +// times: 진동을 몇번 수행할지를 결정 + +static void* active_vibration_motor(void* activate_seconds) +{ + + GPIOExport(VIBRATION_MOTOR_PIN); + GPIODirection(VIBRATION_MOTOR_PIN, OUT); + + while (true) { + if (vibMode == true && event != 0) { + GPIOWrite(VIBRATION_MOTOR_PIN, HIGH); + } + int a = *(int*)activate_seconds; + a = 1; + usleep(a * 1000 * 1000); + GPIOWrite(VIBRATION_MOTOR_PIN, LOW); + } + GPIOUnexport(VIBRATION_MOTOR_PIN); + + return NULL; +} + +static void* read_button() +{ + + GPIOExport(BUTTON_PIN_IN); + GPIOExport(BUTTON_PIN_OUT); + + GPIODirection(BUTTON_PIN_IN, IN); + GPIODirection(BUTTON_PIN_OUT, OUT); + + while(1){ + GPIOWrite(BUTTON_PIN_OUT,1); + int data = GPIORead(BUTTON_PIN_IN); + if (data == 0) { + buzzerMode = (buzzerMode + 1) % 2; + vibMode = (vibMode + 1) % 2; + } + printf("BUTTON GPIO Read : %d from pin %d\n", data, BUTTON_PIN_IN); + usleep(1000 * 1000); + } + + GPIOUnexport(BUTTON_PIN_IN); + GPIOUnexport(BUTTON_PIN_OUT); + + return NULL; +} + +static void* activate_buzzer(void* activate_seconds) +{ + const int PNUM = 0; + + PWMExport(PNUM); //pwm0 == gpio18 + PWMWritePeriod(PNUM,20000000); + PWMWriteDutyCycle(PNUM,0); + // PWMEnable(PNUM); + + int a = *(int*)activate_seconds; + //a *= (1000*1000); + while(1){ + if (buzzerMode == true && event != 0) { + PWMEnable(PNUM); + for(int i=0;i<1000;i++){ + PWMWriteDutyCycle(PNUM,i*10000); + usleep(1000); + } + for(int i=1000;i>0;i--){ + PWMWriteDutyCycle(PNUM,i*10000); + usleep(1000); + } + } else { + PWMUnable(PNUM); + } + } + + PWMUnable(PNUM); + return NULL; + +} + +//에러 핸들링 용 함수 +void error_handling(char *message) +{ + fputs(message, stderr); + fputc('\n', stderr); + exit(1); +} + +// 두 위치정보를 바탕으로 거리를 계산하는 함수 +static inline double GetDistance(tagPT pt1, tagPT pt2 ) +{ + const int radius = 6371; + + double dLat = rad( (pt2.y-pt1.y) ); + double dLon = rad( (pt2.x-pt1.x) ); + + pt1.y = rad( pt1.y ); + pt2.y = rad( pt2.y ); + + double a = sin(dLat/2) * sin(dLat/2) + sin(dLon/2) * sin(dLon/2) * cos(pt1.y) * cos(pt2.y); + double c = 2 * atan2f(sqrtf(a), sqrtf(1-a)); + double dDistance = radius * c; + + // dDistance*=1000; + + return dDistance; +} + +// pet 장치에서 RF통신으로 정보 받음 +static void *recvpet(void *arg) +{ + FILE* pipe; + char buffer[BUF_SIZE]; + + // 심박센서 신호 출력 프로그램 실행&파이프 연결 + pipe = popen("sudo ./rf24libs/RF24/examples_linux/gettingstarted", "r"); + + if (pipe == NULL) { + perror("popen"); + return NULL; + } + + // 받아온 정보 변수에 저장 + while (fgets(buffer, BUF_SIZE, pipe) != NULL) { + // if(buffer[0] == '\0') continue; + int data_cnt = atoi(buffer); + + printf("read buffer : %s\n", buffer); + + char* p_delims = "_"; + char* p_tok = strtok(buffer, p_delims); + tookPhoto = atoi(p_tok); + p_tok = strtok(NULL, p_delims); + heartbeat = atoi(p_tok); + + p_tok = strtok(NULL, p_delims); + dogPos.x = atof(p_tok); + p_tok = strtok(NULL, p_delims); + dogPos.y = atof(p_tok); + + + // tookPhoto = atoi(p_tok); + // p_tok = strtok(NULL, p_delims); + // heartbeat = atoi(p_tok); + + // p_tok = strtok(NULL, p_delims); + curDist = GetDistance(myPos, dogPos); + + printf("Dist : %lf\n", curDist); + printf("TookPhoto : %d Heart : %d \n", tookPhoto, heartbeat); + } + + return NULL; +} + + diff --git a/pet_main/GPS/gps b/pet_main/GPS/gps new file mode 100644 index 0000000000000000000000000000000000000000..6dbea4edcab1165d852a01fc460dbb1898aad7b7 GIT binary patch literal 8488 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 literal 0 HcmV?d00001 diff --git a/pet_main/GPS/gps.c b/pet_main/GPS/gps.c new file mode 100644 index 0000000..e3020a2 --- /dev/null +++ b/pet_main/GPS/gps.c @@ -0,0 +1,70 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <termios.h> + +#define GPS_MSG_SIZE 128 + +int main() { + int serial_port; + char *port = "/dev/ttyAMA0"; + struct termios options; + + serial_port = open(port, O_RDWR | O_NOCTTY | O_NDELAY); + if (serial_port == -1) { + printf("Failed to open the serial port.\n"); + return -1; + } + + tcgetattr(serial_port, &options); + cfsetispeed(&options, B9600); + cfsetospeed(&options, B9600); + options.c_cflag |= (CLOCAL | CREAD); + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + options.c_cflag &= ~CSIZE; + options.c_cflag |= CS8; + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_iflag &= ~(IXON | IXOFF | IXANY); + options.c_oflag &= ~OPOST; + options.c_cc[VMIN] = 0; + options.c_cc[VTIME] = 5; + tcsetattr(serial_port, TCSANOW, &options); + + char gps_msg[GPS_MSG_SIZE]; + memset(gps_msg, 0, sizeof(gps_msg)); + + while (1) { + ssize_t newdata = read(serial_port, gps_msg, sizeof(gps_msg)); + if (newdata > 0) { + // Process the GPS data + if (strncmp(gps_msg, "$GPRMC", 6) == 0) { + // printf("%s\n",gps_msg); + char *token; + char *latitude; + char *longitude; + token = strtok(gps_msg, ","); + int token_count = 0; + while (token != NULL) { + if (token_count == 2) { + latitude = token; + } else if (token_count == 4) { + longitude = token; + } + token = strtok(NULL, ","); + token_count++; + } + printf("Latitude: %s\n", latitude); + printf("Longitude: %s\n", longitude); + } + } + memset(gps_msg, 0, sizeof(gps_msg)); + usleep(500000); + } + + close(serial_port); + + return 0; +} \ No newline at end of file diff --git a/pet_main/GPS/gps.py b/pet_main/GPS/gps.py new file mode 100644 index 0000000..e051d0b --- /dev/null +++ b/pet_main/GPS/gps.py @@ -0,0 +1,19 @@ +import serial +import time +import string +import pynmea2 + +while True: + port="/dev/ttyAMA0" + ser=serial.Serial(port, baudrate=9600, timeout=0.5) + dataout = pynmea2.NMEAStreamReader() + newdata=ser.readline() + #print(newdata) + + if newdata[0:6] == b"$GPRMC": + newmsg=pynmea2.parse(newdata.decode('ascii')) + lat=newmsg.latitude + lng=newmsg.longitude + gps = str(round(lat, 12)) + " " + str(round(lng, 12)) + print(gps) + \ No newline at end of file diff --git a/pet_main/Raspberry-Pi-Heartbeat-Pulse-Sensor b/pet_main/Raspberry-Pi-Heartbeat-Pulse-Sensor new file mode 160000 index 0000000..8edae9f --- /dev/null +++ b/pet_main/Raspberry-Pi-Heartbeat-Pulse-Sensor @@ -0,0 +1 @@ +Subproject commit 8edae9fd2fbb283beb997e6d39b2e914c8ea7a84 diff --git a/pet_main/main b/pet_main/main new file mode 100644 index 0000000000000000000000000000000000000000..421663369e770a4f0763ae77a71ea309db0a3395 GIT binary patch literal 13736 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 E04wdi761SM literal 0 HcmV?d00001 diff --git a/pet_main/pet_main.c b/pet_main/pet_main.c new file mode 100644 index 0000000..932ab4e --- /dev/null +++ b/pet_main/pet_main.c @@ -0,0 +1,278 @@ +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <fcntl.h> +#include <unistd.h> +#include <pthread.h> // -lpthread +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <string.h> +#include <time.h> + +#define MAX_BUFFER 1024 + +char* shot = "0"; +char* heartbeat = "0"; +char* longitude = "0"; +char* latitude = "0"; + +void error_handling(char *msg); +static void* gps(void *arg); +static void* heart(void *arg); +static void* timer(void *arg); +static void* camera(void *arg); +static void* send_master(void *arg); + +/** + * DESCRIPTION + * This code is attached to the Raspberry Pi #4 + * this module would establish connection with Raspberry Pi #2(Master), Raspberry Pi #3(Slave - attached with Camera sensor) + * it is connected with hearbeat sensor, GPS sensor.. etc) + * so the datas are the heartbeat rate, GPS data + * and it decides whether the Camera sensor take a photo or not + * + * If RF communication is enabled, it sends data to RP #3 so that RP #3 can send'em to RP #2 + * if not, it sends data to RP #2 via socket connection + */ +int main() +{ + pthread_t p_thread_heart, p_thread_gps, p_thread_heartb, p_thread_send; + struct sockaddr_in serv_addr, clnt_addr, master_addr; + + socklen_t clnt_addr_size; + size_t len; + int serv_sock, clnt_sock, mastersock; + + const char master_ip[] = "192.168.219.104"; + char buf[100]; + + clnt_sock = mastersock = -1; + + //RF가 아닌 소켓으로 통신할 때 코드 + // // 주인측 소켓 생성 + // mastersock = socket(PF_INET, SOCK_STREAM, 0); + // if (mastersock == -1) { + // error_handling("socket() error"); + // } + + // // //주인측 주소&포트 설정 + // memset(&master_addr, 0, sizeof(master_addr)); + // master_addr.sin_family = AF_INET; + // master_addr.sin_addr.s_addr = inet_addr(master_ip); + // master_addr.sin_port = htons(atoi("8887")); + + // // 주인측 소켓연결 + // if (connect(mastersock, (struct sockaddr *)&master_addr, sizeof(master_addr)) == -1) { + // error_handling("connect() error"); + // } + + // printf("master connect\n"); // 실행확인용 + + // 메인 소켓 생성 + serv_sock = socket(PF_INET, SOCK_STREAM, 0); + + // 메인 소켓 생성됐는지 확인 + if (serv_sock == -1) { + error_handling("socket() error"); + } + + // 카메라 주소&포트 설정 + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(atoi("8886")); + + // 포트 열기 + if (bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) { + error_handling("bind() error"); + } + + // client 연결 대기 + if (listen(serv_sock, 5) == -1) { + error_handling("listen() error"); + } + + // 카메라 연결 + clnt_addr_size = sizeof(clnt_addr); + clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_addr_size); + if (clnt_sock == -1) { + error_handling("accept() error"); + } + printf("connect\n"); // 실행확인용 + + // 스레드들 실행 + pthread_create(&p_thread_heartb, NULL, heart, NULL); + pthread_create(&p_thread_heart, NULL, camera, (void *)&clnt_sock); + pthread_create(&p_thread_gps, NULL, gps, NULL); + // pthread_create(&p_thread_send, NULL, send_master, (void *)&mastersock); // 소켓통신용 + pthread_create(&p_thread_send, NULL, send_master, (void *)&clnt_sock); // RF통신용 + pthread_join(p_thread_heart, NULL); + // pthread_join(p_thread_heart, NULL); + + // client 연결 해제 + close(clnt_sock); + + printf("end\n"); // 실행확인용 + + close(serv_sock); + + return 0; +} + +// 오류 메시지 출력함수 +void error_handling(char *message) +{ + fputs(message, stderr); + fputc('\n', stderr); + exit(1); +} + +static void* send_master(void *arg) +{ + int mastersock = *(int*)arg; + char msg[100]; + + // 1초마다 주인측 장치에 정보 보냄 + while (true) { + // 촬영여부 + strcpy(msg, shot); + shot = "0"; + msg[strcspn(msg, "\n")] = 0; + strcat(msg, "_"); + // 심박수 + strcat(msg, heartbeat); + msg[strcspn(msg, "\n")] = 0; + strcat(msg, "_"); + // 경도 + strcat(msg, longitude); + msg[strcspn(msg, "\n")] = 0; + strcat(msg, "_"); + // 위도 + strcat(msg, latitude); + msg[strcspn(msg, "\n")] = 0; + // 전송 + write(mastersock, msg, strlen(msg)); + sleep(1); + } + return NULL; +} + +static void* heart(void *arg) +{ + FILE* pipe; + char buffer[MAX_BUFFER]; + + // 심박센서 신호 출력 프로그램 실행&파이프 연결 + pipe = popen("python3 -u Raspberry-Pi-Heartbeat-Pulse-Sensor/example.py", "r"); + + if (pipe == NULL) { + perror("popen"); + return NULL; + } + + // 받아온 정보 변수에 저장 + while (fgets(buffer, MAX_BUFFER, pipe) != NULL) { + heartbeat = buffer; + } + + return NULL; +} + +static void *timer(void *arg) +{ + char *p_t = (char *)arg; + // 60초 타이머 + sleep(60); + p_t[0] = '1'; + return NULL; +} + +static void* camera(void *arg) +{ + FILE* pipe; + pthread_t p_thread_timer; + int number, threshold = 100; + int sock = *(int*)arg; + char buffer[MAX_BUFFER]; + char msg[] = "1"; + + char *timers = malloc(sizeof(char *)); + timers[0] = '0'; + + // 1분 타이머 실행 + pthread_create(&p_thread_timer, NULL, timer, (void *)timers); + + while (1) { + sleep(1); // 1초마다 사진촬영을 결정 + printf("heartbeat : %s", heartbeat); // 실행 확인용 + + number = atoi(heartbeat); // 정수로 + + // 사진이 찍히지 않고 1분이 지난 경우 + if (timers[0] == '1') { + printf("threshold = : %d\n", threshold); // 실행확인용 + threshold = threshold * 0.8; // threshold 0.8배 + timers[0] = '0'; // 타이머초기화 + pthread_create(&p_thread_timer, NULL, timer, (void *)timers); // 타이머 다시시작 + } + + // 심박이 threshold를 넘긴 경우 + if (number > threshold) { + //write(sock, msg, strlen(msg)); // 카메라에 촬영명령, RF통신의 경우 사용 안함 + printf("shot&stop\n"); // 실행확인용 + shot = "1"; // 주인측 장치에 보낼 정보 + pthread_cancel(p_thread_timer); // 타이머 정지 + sleep(20); // 촬영 후 20초 재촬영 안함 + threshold = threshold * 1.2; // threshold 1.2배 + printf("threshold = : %d\n", threshold); // 실행확인용 + printf("restart\n"); // 실행확인용 + pthread_create(&p_thread_timer, NULL, timer, (void *)timers); // 타이머 재실행 + } + } + + return NULL; +} + + + +static void* gps(void *arg) +{ + FILE* pipe; + char buffer[MAX_BUFFER]; + char msg[] = "1"; + + // 실내에서 진행하기위한 임의의 좌표 변경 코드 + // while(1){ + // char *gps_data3[] = {"128.110","128.110","128.110","128.110","150.110","128.110","127.521","127.521","127.521","127.521","127.521","127.521","127.632","127.632","127.632","127.632","127.632","127.632","127.743","127.743","127.743","127.743","127.743","127.743","127.824","127.824","127.824","127.824","127.824","127.824","127.824"}; + // gps_data1 = gps_data3[inde++]; + // if(inde==20)inde=0; + // sleep(1); + // } + + // gps 정보를 읽어 경도와 위도를 출력하는 프로그램 실행&파이프 연결 + pipe = popen("python3 -u GPS/gps.py", "r"); + if (pipe == NULL) { + perror("popen"); + return NULL; + } + + // 파이프에서 받은 경도와 위도를 변수에 저장 + while (fgets(buffer, MAX_BUFFER, pipe) != NULL) { + latitude = strtok(buffer, " "); + longitude = strtok(NULL, " "); + + // 실행확인용 + printf("latitude : %s\n", latitude); + printf("longitude : %s\n", longitude); + } + + // 파이프 닫음 + if (pclose(pipe) == -1) { + perror("pclose"); + return NULL; + } + + return NULL; +} \ No newline at end of file -- GitLab