forked from Min-su-Jeong/Embedded_System_Team_Project
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.c
More file actions
343 lines (297 loc) · 10.1 KB
/
main.c
File metadata and controls
343 lines (297 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <wiringSerial.h>
// Pin 번호 설정
#define CLK 19
#define DT 26 // 로터리 엔코더(Rotary encoder)
#define TRIG 15
#define ECHO 18 // 초음파(Ultrasonic)
#define LED1 20
#define LED2 21 // LED(Light-emitting diode)
#define BAUD_RATE 115200 // UART 통신(Bluetooth baud rate)
#define SLAVE_ADDR_01 0x48 // 조도 센서(slave address)
// 전역변수 정의 및 초기화
int curVal = 0; // 현재 값(조도 센서)
int digital[10] = { 0 }; // 디지털관 주차장 생성을 위한 1차원 배열
int global[10] = { 0 }; // 글로벌관 주차장 생성을 위한 1차원 배열
int library[10] = { 0 }; // 도서관 주차장 생성을 위한 1차원 배열
int segmentSelect = 1; // 로터리 엔코더를 통해 각 건물을 선택하기 위한 변수
int dn[] = { 4,22,10,23 }; // 4-digit 7-segment display 자리마다의 GPIO 번호
int segment_pin[] = { 17,9,25,7,13,27,24,8 }; // 4-digit 7-segment별 GPIO 번호
short digits_data1[14] = { 0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE4,0xFE,0xE6,0xFC,0xBC,0x1C,0x02 }; // 숫자, 문자, 모양 표기(16진수)
static const char* I2C_DEV = "/dev/i2c-1"; // I2C 연결을 위한 장치 파일
static const char* UART2_DEV = "/dev/ttyAMA1"; // UART2 연결을 위한 장치 파일
// 함수 프로토타입 선언
void* ultraSonic(void* number); // 초음파 센서 제어 함수
void* bluetooth(); // UART 통신(Blutetooth) 제어 함수
void* photoresistor(); // 조도 센서 제어 함수
void* rotaryEncoder(); // 로터리 엔코더 제어 함수
void* digitSegment(); // 4-digit 7-segment display 제어 함수
void pinInit(); // Pin Mode 초기화 함수
void ledControl(int i, int index); // LED 제어 함수
int calEmpty(int select); // 남은 주차자리 수 계산 함수
void displaySegment(int pos, int num); // Digit segment display에 값 출력 함수
unsigned char serialRead(const int fd); // 1byte 데이터 읽기 함수
void serialWriteBytes(const int fd, const char* s); // Multi byte 데이터 쓰기 함수
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // Mutex 초기화
int main()
{
int sonicNumber = 0;
pthread_t th1, th2, th3, th4, th5;
if (wiringPiSetupGpio() < 0) { // BCM 기반 PIN 번호 사용
fprintf(stderr, "Unable to setup wiringPi:%s\n", strerror(errno));
return 1;
}
pinInit();
pthread_create(&th1, NULL, ultraSonic, (void*)sonicNumber++);
pthread_create(&th2, NULL, bluetooth, NULL);
pthread_create(&th3, NULL, photoresistor, NULL);
pthread_create(&th4, NULL, rotaryEncoder, NULL);
pthread_create(&th5, NULL, digitSegment, NULL);
pthread_join(th1, NULL);
pthread_join(th2, NULL);
pthread_join(th3, NULL);
pthread_join(th4, NULL);
pthread_join(th5, NULL);
pthread_mutex_destroy(&mutex); // Mutex 해제
return 0;
}
// 초음파 센서 제어 함수
void* ultraSonic(void* number)
{
int n = (int)number;
int distance = 0;
long start, end;
while (1) { // TRIG: 초음파를 보냄, ECHO: 초음파를 받음
digitalWrite(TRIG, 0);
delayMicroseconds(10);
digitalWrite(TRIG, 1);
delayMicroseconds(10);
digitalWrite(TRIG, 0);
while (digitalRead(ECHO) == 0)
start = micros();
while (digitalRead(ECHO) == 1)
end = micros();
distance = (end - start) / 58; // 거리 계산 식(cm)
if (distance < 25 && curVal > 40)
ledControl(0, n); // 주차 O 상태
else
ledControl(1, n); // 주차 X 상태
printf("Distance(cm): %d\n", distance);
delay(1000);
}
}
// UART 통신(Blutetooth) 제어 함수
void* bluetooth()
{
int fd_serial;
char str[50] = "=========================\n";
unsigned char dat, buffer[500];
if ((fd_serial = serialOpen(UART2_DEV, BAUD_RATE)) < 0)
{
printf("Unable to open serial device.\n");
exit(1);
}
while (1)
{
fflush(stdout); // 버퍼 비우기
switch (serialRead(fd_serial))
{
case 'D':
sprintf(buffer, "%s| 디지털관 남은 주차자리 수 : %d |\n%s",str, calEmpty(1), str);
break;
case 'G':
sprintf(buffer, "%s| 글로벌관 남은 주차자리 수 : %d |\n%s",str, calEmpty(2), str);
break;
case 'L':
sprintf(buffer, "%s| 도서관 남은 주차자리 수 : %2d |\n%s",str, calEmpty(3), str);
break;
default:
continue;
}
serialWriteBytes(fd_serial, buffer); // 버퍼 쓰기
delay(10);
}
}
// 조도 센서 제어 함수
void* photoresistor()
{
int i2c_fd;
int threshold = 50, adcChannel = 2; // 조도 임계 값 및 채널 설정(외부)
if ((i2c_fd = wiringPiI2CSetupInterface(I2C_DEV, SLAVE_ADDR_01)) < 0) {
printf("wiringPi2CSetup Failed: \n");
exit(1);
}
while (1)
{
wiringPiI2CWrite(i2c_fd, 0x40 | adcChannel);
curVal = wiringPiI2CRead(i2c_fd); // 현재 조도 센서 값 읽기
if (curVal < threshold) // 임계 값보다 낮으면(밝으면)
printf("Bright\n");
else // 임계 값보다 높으면(어두우면)
printf("Dark\n");
delay(1000);
}
}
// 로터리 엔코더 제어 함수
void* rotaryEncoder()
{
unsigned char fl, p, crr;
while (1)
{
p = digitalRead(CLK);
while (!digitalRead(DT)) {
crr = digitalRead(CLK);
fl = 1;
}
if (fl == 1) {
fl = 0;
if ((p == 0) && (crr == 1)) { // 시계 방향(CW)
if (segmentSelect < 3) segmentSelect++;
printf("%d\n", segmentSelect);
}
if ((p == 1) && (crr == 0)) { // 반시계 방향(CCW)
if (segmentSelect > 1) segmentSelect--;
printf("%d\n", segmentSelect);
}
}
}
}
// 4-digit 7-segment display 제어 함수
void* digitSegment()
{
// 1번 segment : segmentSelect 값에 따라 'D, G, L' 표시(변동)
// 2번 segment : '-' 표시(고정)
// 3,4번 segment : 선택된 건물에 해당하는 남은 주차자리 수 표시(변동)
while (1)
{
displaySegment(1, 9 + segmentSelect); // 1번 segment 표시
delay(1);
displaySegment(2, 13); // 2번 segment 표시
delay(1);
if (calEmpty(segmentSelect) == 10)
{
displaySegment(3, 1); // 3번 segment 표시
delay(1);
displaySegment(4, 0); // 4번 segment 표시
delay(1);
}
else
{
displaySegment(3, 0); // 3번 segment 표시
delay(1);
displaySegment(4, calEmpty(segmentSelect)); // 4번 segment 표시
delay(1);
}
}
}
// Pin Mode 초기화 함수
void pinInit()
{
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
pinMode(TRIG, OUTPUT);
pinMode(ECHO, INPUT);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
for (int i = 0; i < 8; i++)
{
if (i < 4)
{
pinMode(dn[i], OUTPUT);
}
pinMode(segment_pin[i], OUTPUT);
}
}
// LED 제어 함수
void ledControl(int i, int index)
{
if (i == 0) // 주차 O 상태
{
digitalWrite(LED1, LOW); // 파란색 LED OFF
digitalWrite(LED2, HIGH); // 빨간색 LED ON
switch (segmentSelect) // 현재 선택된 건물
{
case 1: // 디지털관
digital[index] = 1; // 해당 배열 index 자리가 주차 상태임을 나타냄
break;
case 2: // 글로벌관
global[index] = 1; // 해당 배열 index 자리가 주차 상태임을 나타냄
break;
case 3: // 도서관
library[index] = 1; // 해당 배열 index 자리가 주차 상태임을 나타냄
break;
default:
break;
}
}
else if (i == 1) // 주차 X 상태
{
digitalWrite(LED1, HIGH); // 파란색 LED ON
digitalWrite(LED2, LOW); // 빨간색 LED OFF
switch (segmentSelect) // 현재 선택된 건물
{
case 1: // 디지털관
digital[index] = 0; // 해당 배열 index 자리가 출차 상태임을 나타냄
break;
case 2: // 글로벌관
global[index] = 0; // 해당 배열 index 자리가 출차 상태임을 나타냄
break;
case 3: // 도서관
library[index] = 0; // 해당 배열 index 자리가 출차 상태임을 나타냄
break;
default:
break;
}
}
}
// 남은 주차자리 수 계산 함수
int calEmpty(int select)
{
int cnt = 0;
// 남은 자리 계산 중 접근 차단
pthread_mutex_lock(&mutex); //Mutex Lock
for (int i = 0; i < 10; i++)
{
if (select == 1) cnt += digital[i];
else if (select == 2) cnt += global[i];
else if (select == 3) cnt += library[i];
}
pthread_mutex_unlock(&mutex); //Mutex Unlock
return 10 - cnt;
}
// Digit segment display에 값 출력 함수
void displaySegment(int pos, int num)
{
for (int i = 0; i < 4; i++)
{
if (i + 1 == pos) digitalWrite(dn[i], LOW);
else digitalWrite(dn[i], HIGH);
}
for (int i = 0; i < 8; i++)
{
short segmentData = (digits_data1[num] & (0x01 << i)) >> i;
if (segmentData == 1) digitalWrite(segment_pin[7 - i], HIGH);
else digitalWrite(segment_pin[7 - i], LOW);
}
}
// 1byte 데이터 읽기 함수
unsigned char serialRead(const int fd)
{
unsigned char x;
if (read(fd, &x, 1) != 1) return -1;
return x;
}
// Multi byte 데이터 쓰기 함수
void serialWriteBytes(const int fd, const char* s)
{
write(fd, s, strlen(s));
}