-
Notifications
You must be signed in to change notification settings - Fork 0
/
main_compiled.ino
219 lines (175 loc) · 6.99 KB
/
main_compiled.ino
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
/*
!!! 메인 알고리즘과 각종 선언을 담은 공간입니다.
!!! setup과 loop를 제외한 함수는 이 곳에 '선언'하되, 정의는 function_def 쪽 파일에 써주세요.
*/
#include<Arduino.h>
#include<SoftwareSerial.h>
#include <TM1637Display.h> // for 7 segment
#include <LiquidCrystal_I2C.h> // for lcd display
#include <Wire.h>
#define QUE_LENGTH 30
#define NUMBER_OF_TRAY 3
#define INVALID 255
// 설명: byte형 제어 변수에 '유효하지 않은 상태'라는 표시를 하고 싶으면 이 수를 대입합니다. (예 - trayPointer 변수에 '빈 쟁반이 존재하지 않는다'는 걸 기록하고 싶을 때.)
#define TRUE 1
#define FALSE 0
enum orderState {
no_order,
waiting_food,
waiting_customer
};
typedef struct _que
{
int orderNum[QUE_LENGTH];
unsigned long orderTime[QUE_LENGTH];
byte front; // 다음 append시 데이터를 넣을 공간을 가리킴. (front가 가리키는 위치는 비어있음)
byte rear; // 다음 delete시 삭제할 데이터를 가리킴. (rear는 마지막 데이터를 가리킴, f==r인 경우 제외)
} queue;
uint8_t data[] = { 0x0, 0x0, 0x0, 0x0 }; // all segments clear
long d;
long lcd_num;
long state;
long num;
/* 변수 선언 */
// 1. 입출력 관련 변수
const uint8_t pcell[NUMBER_OF_TRAY] = {A1, A2, A3};
const uint8_t rangeSensorPin = A0;
SoftwareSerial BTSerial(4, 5);
TM1637Display segment[NUMBER_OF_TRAY] =
{
// TM1637Display(CLK, DIO)
TM1637Display(2, 3),
TM1637Display(8, 9),
TM1637Display(12, 11)
};
LiquidCrystal_I2C lcd[NUMBER_OF_TRAY] =
{
LiquidCrystal_I2C(0x27, 16, 2),
LiquidCrystal_I2C(0x26, 16, 2),
LiquidCrystal_I2C(0x23, 16, 2)
};
// 2. 제어 관련 변수
byte trayPointer = 0;
unsigned long orderTime[NUMBER_OF_TRAY] = {0};
orderState trayOrderState[NUMBER_OF_TRAY] = {no_order};
boolean isSomethingOnTray[NUMBER_OF_TRAY] = {FALSE};
int orderNum[NUMBER_OF_TRAY] = { -1, -1, -1}; //
boolean errorTest[NUMBER_OF_TRAY] = {FALSE};
byte orderCount = 0;
byte LT[8] = { B00111, B01111, B11111, B11111, B11111, B11111, B11111, B11111 };
byte UB[8] = { B11111, B11111, B11111, B00000, B00000, B00000, B00000, B00000 };
byte RT[8] = { B11100, B11110, B11111, B11111, B11111, B11111, B11111, B11111 };
byte LL[8] = { B11111, B11111, B11111, B11111, B11111, B11111, B01111, B00111 };
byte LB[8] = { B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111 };
byte LR[8] = { B11111, B11111, B11111, B11111, B11111, B11111, B11110, B11100 };
byte MB[8] = { B11111, B11111, B11111, B00000, B00000, B00000, B11111, B11111 };
byte block[8] = { B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 }; // lcd 모양 지정
queue Q;
/* 함수 선언 */
void moveTrayPointer(); /* 빈 쟁반을 가리키는 포인터 업데이트 */
void queueToTray(); /* 큐의 가장 오래된 데이터를 빈 쟁반에 할당함 */
void deleteOrder(int); /* 쟁반의 index를 입력받아 제어 변수 처리, cookDis와 customerDis 출력.*/
void trayUpdate();
// Queue library
void initQueue(); /* 큐에 초기화 값을 넣어줍니다. */
int peekQueue_orderNum(); /* 큐에 남아있는 데이터 중 가장 오래된 데이터(즉 다음 인출 시 나올 값) 중 주문번호를 반환합니다. */
unsigned long peekQueue_orderTime(); /* 큐에 남아있는 데이터 중 가장 오래된 데이터(즉 다음 인출 시 나올 값) 중 주문시간을 반환합니다. */
void appendQueue(int ordernum, unsigned long ordertime);/* 큐에 새로운 값을 추가합니다. 주문번호와 주문시간을 입력인자로 주어야 합니다. */
void deleteQueue(); /* 큐에 남아있는 데이터 중 가장 오래된 데이터를 삭제합니다. */
void printQueue(); /* 큐 내의 전체 데이터를 한 번씩 Serial Monitor로 출력합니다. */
boolean isQueueEmpty(); /* 큐가 비어있다면 TRUE, 비어있지 않다면 FALSE를 반환합니다. */
/* 메인 알고리즘 */
// SETUP : 시작하고 한 번만 실행
void setup()
{
//Serial.begin(9600);
BTSerial.begin(9600);
//Serial.println("Connection Start!");
initQueue();
for (int i = 0; i < NUMBER_OF_TRAY; i++) {
//Serial.println((String) i + "LCD");
lcd[i].init();
lcd[i].backlight();
lcd[i].createChar(0, LT);
lcd[i].createChar(1, UB);
lcd[i].createChar(2, RT);
lcd[i].createChar(3, LL);
lcd[i].createChar(4, LB);
lcd[i].createChar(5, LR);
lcd[i].createChar(6, MB);
lcd[i].createChar(7, block);
//Serial.println((String) i + "SEG");
segment[i].setBrightness(0x0f);
segment[i].setSegments(data);
segment[i].showNumberDec(00);
//Serial.println((String) i + "RR");
}
//Serial.println("Ready to start");
//BTSerial.print("[" + (String)1 + "!" + "SP" + "]");
}
// LOOP : 전원이 꺼질 때까지 반복실행
void loop() {
int num = 0;
// 디버깅용
/*
if (Serial.available()) {
printQueue();
Serial.read();
}
*/
// 작업1 : 컴퓨터에서 주문 정보 받기
if (BTSerial.available())
{
num = BTSerial.parseInt();
//Serial.println((String)num + "받았음");
if (num)
{
//Serial.print("SYSTEM: "); Serial.print(num); Serial.println("번 주문 접수되었습니다.");
appendQueue(num, millis()); // num = =0 인 출력 무시
//printQueue();
//Serial.println("TRAY POINTER" + (String) trayPointer);
if (orderCount <= QUE_LENGTH)
{
orderCount++;
}
if (trayPointer != INVALID)
{
queueToTray();
}
waitDis(int orderCount - NUMBER_OF_TRAY);
}
}
// 작업 2 : 주문을 받은 쟁반에 음식이 준비되면 고객을 호출함
for (int i = 0; i < NUMBER_OF_TRAY ; i++)
{
if (trayOrderState[i] == waiting_food && isSomethingOnTray[i] == TRUE)
{
BTSerial.print("[" + (String)orderNum[i] + "!" + "WC" + "]");
//Serial.println("SYSTEM: " + (String)orderNum[i] + "번 고객님, 음식이 준비되었습니다!");
trayOrderState[i] = waiting_customer;
}
}
// 작업 3 : 주문을 받고 음식이 올라온 쟁반에서 고객이 음식을 가져가면 주문을 삭제함
for (int i = 0; i < NUMBER_OF_TRAY ; i++)
{
if (trayOrderState[i] == waiting_customer && isSomethingOnTray[i] == FALSE)
{
BTSerial.print("[" + (String)orderNum[i] + "!" + "DL" + "]");
//Serial.println("SYSTEM: " + (String)(i + 1) + "번 쟁반에서 고객이 음식을 가져갔습니다.");
customDis(i, 0);
deleteOrder(i);
orderCount--;
waitDis(int orderCount - NUMBER_OF_TRAY);
//디스플레이
}
}
// 작업 4 : 주문 큐에서 빈 쟁반에 주문 할당. ~ 빈 쟁반이 더이상 없거나 주문 큐가 빌 때까지 털어넣기.
while ( trayPointer != INVALID && !isQueueEmpty())
{
queueToTray();
}
// 작업 5 : 실시간 쟁반의 상태(isSomethingOnTray) 업데이트
trayError();
trayUpdate();
delay(30);
}