재료별 리스트
온도를 디스플레이에 표시하는 것 까지 완료하였습니다. 이제는 설정 온도를 재료별로 리스트를 만들고, 버튼을 누르면 설정바뀌고 화면에 표시하는 코드를 작성하는 것 이 목표입니다.
먼저 재료별로 온도, 속도 항목을 포함할 수 있는 구조체를 선언 과 초기화를 해주는 코드를 추가합니다.
1int material_index = 0; // 재료 구조체 배열의 위치를 가리키는 인덱스
2int setTemperature = 0; // 설정된 온도
3
4struct setting {
5 int temperature;
6 char* materialName;
7};
8
9struct setting materials[] = {{0, "OFF"}, {60, "PCL"}, {200, "PLA"}};
구조체에는 서로 다른 자료형을 포함할 수 있습니다. 따라서 구조체 배열을 통해
OFF 일 경우 설정온도와 속도가 0
PCL 재료일 경우 온도는 50, 속도는 100
PLA 재료일 경우 온도는 200, 속도는 90
으로 설정이 입력된 것입니다.
1#include "ssd1306.h" // 라이브러리 포함
2
3#define BTN_A 8 // A버튼
4#define BTN_B 7 // B버튼
5#define BTN_C 11 // C버튼
6#define BTN_D 12 // D버튼
7
8#define MOTOR_EN 5 // 모터 활성화 핀
9#define MOTOR_DIR 6 // 모터 방향 핀
10#define MOTOR_SPEED 10 // 모터 속도 핀
11
12#define HEATER_EN 9 // 열선 핀
13
14#define TEMP_IN A0 // 온도 읽는 핀
15
16#define VALUE_TEMPTB 0 // 온도 테이블의 신호 값 인덱스
17#define CELSIUS_TEMPTB 1 // 온도 테이블의 온도 값 인덱스
18
19#define MATERIAL_COUNT 3 // material 구조체 배열의 갯수
20
21String strToShow; // 디스플레이에 보여줄 문자열을 저장하는 변수
22
23int curTemp = 0; // 현재온도
24
25long timeInterval = millis(); // 50ms 에 1회씩 작동하기 위한 시간 변수
26
27int material_index = 0; // 재료 구조체 배열의 위치를 가리키는 인덱스
28int setTemperature = 0; // 설정된 온도
29
30// 온도, 속도, 재료명을 포함한 구조체 선언
31struct setting {
32 int temperature;
33 char* materialName;
34};
35
36struct setting materials[] = {{0, "OFF"}, {60, "PCL"}, {200, "PLA"}};
37
38/*
39 * 온도 테이블 배열
40 * 첫번째 항목은 신호 값, 두번째 항목은 온도 값
41 */
42int temptable[23][2] = {
43 {1023,0},
44 {1022,10},
45 {1020,20},
46 {1016,30},
47 {1011,40},
48 {1009,50},
49 {1006,60},
50 {1004,70},
51 {1000,80},
52 {990,90},
53 {983,100},
54 {976,110},
55 {972,120},
56 {964,130},
57 {955,140},
58 {942,150},
59 {929,160},
60 {910,170},
61 {895,180},
62 {864,190},
63 {839,200},
64 {800,210},
65 {744,220}
66};
67
68/*
69 * 입력받은 문자를 디스플레이 좌표에 표시
70 */
71void showTextToScreen(int x, int y, String text)
72{
73 text = text + "\n";
74 char ch[10];
75 text.toCharArray(ch,text.length());
76 ssd1306_printFixedN(x, y, ch, STYLE_NORMAL, FONT_SIZE_2X);
77}
78
79/*
80 * 온도를 읽고, 정확한 온도로 계산 후 결과 값을 화면에 표시하고 반환하는 함수
81 * VALUE_TEMPTB = 0, CELSIUS_TEMPTB = 1 으로 온도표의 각 항목을 지시함
82 */
83int getTemperature()
84{
85 float ratioTemp;
86 float tempADU = analogRead(A0);
87 int result;
88
89 for(int i=1; i<23; i++){
90 if(tempADU >= temptable[i][VALUE_TEMPTB])
91 {
92 ratioTemp = (tempADU - temptable[i][VALUE_TEMPTB])/(temptable[i-1][VALUE_TEMPTB] - temptable[i][VALUE_TEMPTB]);
93
94 result = temptable[i][CELSIUS_TEMPTB] - ratioTemp*(temptable[i][CELSIUS_TEMPTB] - temptable[i-1][CELSIUS_TEMPTB]);
95
96 strToShow = String(result);
97
98 showTextToScreen(0,16,strToShow);
99
100 return result;
101 }
102 }
103
104 return ;
105}
106
107void setup()
108{
109 pinMode(BTN_A, INPUT_PULLUP);
110 pinMode(BTN_B, INPUT_PULLUP);
111 pinMode(BTN_C, INPUT_PULLUP);
112 pinMode(BTN_D, INPUT_PULLUP);
113
114 pinMode(MOTOR_EN, OUTPUT);
115 pinMode(MOTOR_DIR, OUTPUT);
116 pinMode(MOTOR_SPEED, OUTPUT);
117
118 pinMode(HEATER_EN, OUTPUT);
119
120 digitalWrite(MOTOR_EN, HIGH); // 모터 활성화
121
122 ssd1306_128x32_i2c_init(); // 32로 변경
123 ssd1306_fillScreen(0x00); // 화면 초기화
124 ssd1306_setFixedFont(ssd1306xled_font6x8); // 폰트 설정
125 ssd1306_flipHorizontal(1); // x 화면 대칭 회전
126 ssd1306_flipVertical(1); // y 화면 대칭 회전
127}
128
129void loop()
130{
131 if(millis() - timeInterval > 50)
132 {
133 curTemp = getTemperature();
134
135 timeInterval = millis();
136 }
137}
구조체 선언 과 초기화를 하였고, getTemperature 함수의 온도가 표시되는 좌표 위치도 조정하였습니다.
이어서 materials 의 값들을 디스플레이에 표시해보도록 하고
materials 의 현재 인덱스의 값을 디스플레이에 표시해주는 함수를 만들어 보겠습니다.
※ 작성된 코드가 길기 때문에 추가할 함수만 따로 작성합니다.
1// 업데이트가 필요한지 확인하는 bool 변수 생성
2bool isNeedUpdateScreen = true;
3
4void updateMaterial(int index)
5{
6 // isNeedUpdate 변수가 false 이면 함수를 종료함
7 if(!isNeedUpdateScreen) return;
8
9 // 목표 온도, 속도 항목에 현재 인덱스의 구조체 값을 저장
10 setTemperature = materials[index].temperature;
11
12 // 화면 클리어
13 ssd1306_clearScreen();
14
15 // 화면에 목표 온도, 재료 명, 속도를 표시
16 // 재료명은 좌표 0,0 에 표시
17 // 목표 온도는 좌표 52, 16 에 표시
18 strToShow = materials[index].materialName;
19 showTextToScreen(0,0, strToShow);
20
21 strToShow = "/" + String(setTemperature);
22 showTextToScreen(52,16,strToShow);
23
24 // 화면을 계속해서 업데이트 하지 않도록 방지하는 bool 변수 변경
25 isNeedUpdateScreen = false;
26}
위 함수는 isNeedUpdate 변수가 true 일 때마다 화면의 문자들을 현재의 값으로 변경해줍니다.
materials 구조체에서 현재 index의 값을 목표 온도, 목표 속도 변수에 저장합니다.
isNeedUpdate 는 버튼을 누를 때마다 변경되게 해야합니다. 따라서 버튼을 누르면 isNeedUpdate 변수와 updateMaterial 함수의 index를 매개변수 로 전달될 변수를 변경해주어야 합니다.
C, D 버튼을 누를 때 마다 변경하도록 합니다.
1// 버튼이 눌러져 있는지 확인하는 bool 변수 생성
2bool isPressedC_BTN, isPressedD_BTN;
3
4void checkBtnPressed()
5{
6 // C버튼이 눌리고, D버튼이 눌리지 않았을 경우 실행
7 if(!digitalRead(BTN_C) && digitalRead(BTN_D))
8 {
9 // C 버튼이 눌러져 있으면(isPressedC_BTN 가 true), 아래 코드 건너뜀
10 if(!isPressedC_BTN)
11 {
12 // 구조체 배열의 인덱스로 사용될 변수 값 1 증가
13 material_index++;
14 if(material_index > MATERIAL_COUNT-1)
15 {
16 material_index = 0;
17 }
18
19 // 디스플레이 업데이트를 할 수 있도록 변수 변경
20 isNeedUpdateScreen = true;
21 }
22 }
23 // D버튼이 눌리고, C버튼이 눌리지 않았을 경우 실행
24 else if(digitalRead(BTN_C) && !digitalRead(BTN_D))
25 {
26 // D 버튼이 눌러져 있으면(isPressedD_BTN 가 true), 아래 코드 건너뜀
27 if(!isPressedD_BTN)
28 {
29 // 구조체 배열의 인덱스로 사용될 변수 값 1 감소
30 material_index--;
31 if(material_index < 0)
32 {
33 material_index = MATERIAL_COUNT-1;
34 }
35
36 // 디스플레이 업데이트를 할 수 있도록 변수 변경
37 isNeedUpdateScreen = true;
38 }
39 }
40 else
41 {
42 // C, D 버튼 모두 눌리지 않을 경우, 변수 값 변경
43 isPressedC_BTN = false;
44 isPressedD_BTN = false;
45 }
46
47}
버튼이 눌러졌는지 체크하는 함수를 작성하였습니다. 추후 A,B 버튼에 대한 코드도 작성이 되겠지만, 이번 단계에서는 C,D 버튼에 해당되는 코드만 작성하였습니다.
버튼이 눌러져 있는 경우에도 계속해서 코드가 실행되면 안되니, bool 변수를 추가하였습니다.
또한 구조체의 배열 인덱스를 증감시키고, isNeedUpdateScreen 변수의 값을 변경시켜, loop의 코드가 반복수행 하면서 디스플레이를 업데이트 시킵니다.
그렇다면, 코드를 합치고, 이번 단계에서의 최종 코드를 작성해보겠습니다.
1#include "ssd1306.h" // 라이브러리 포함
2
3#define BTN_A 8 // A버튼
4#define BTN_B 7 // B버튼
5#define BTN_C 11 // C버튼
6#define BTN_D 12 // D버튼
7
8#define MOTOR_EN 5 // 모터 활성화 핀
9#define MOTOR_DIR 6 // 모터 방향 핀
10#define MOTOR_SPEED 10 // 모터 속도 핀
11
12#define HEATER_EN 9 // 열선 핀
13
14#define TEMP_IN A0 // 온도 읽는 핀
15
16#define VALUE_TEMPTB 0 // 온도 테이블의 신호 값 인덱스
17#define CELSIUS_TEMPTB 1 // 온도 테이블의 온도 값 인덱스
18
19#define MATERIAL_COUNT 3 // material 구조체 배열의 갯수
20
21String strToShow; // 디스플레이에 보여줄 문자열을 저장하는 변수
22
23bool isNeedUpdateScreen = true; // 업데이트가 필요한지 확인하는 bool 변수 생성
24bool isPressedC_BTN, isPressedD_BTN; // 버튼이 눌러져 있는지 확인하는 bool 변수 생성
25
26int curTemp = 0; // 현재온도
27
28long timeInterval = millis(); // 50ms 에 1회씩 작동하기 위한 시간 변수
29
30int material_index = 0; // 재료 구조체 배열의 위치를 가리키는 인덱스
31int setTemperature = 0; // 설정된 온도
32
33// 온도, 속도, 재료명을 포함한 구조체 선언
34struct setting {
35 int temperature;
36 char* materialName;
37};
38
39struct setting materials[] = {{0, "OFF"}, {60, "PCL"}, {200,"PLA"}};
40
41/*
42 * 온도 테이블 배열
43 * 첫번째 항목은 신호 값, 두번째 항목은 온도 값
44 */
45int temptable[23][2] = {
46 {1023,0},
47 {1022,10},
48 {1020,20},
49 {1016,30},
50 {1011,40},
51 {1009,50},
52 {1006,60},
53 {1004,70},
54 {1000,80},
55 {990,90},
56 {983,100},
57 {976,110},
58 {972,120},
59 {964,130},
60 {955,140},
61 {942,150},
62 {929,160},
63 {910,170},
64 {895,180},
65 {864,190},
66 {839,200},
67 {800,210},
68 {744,220}
69};
70
71/*
72 * 입력받은 문자를 디스플레이 좌표에 표시
73 */
74void showTextToScreen(int x, int y, String text)
75{
76 text = text + "\n";
77 char ch[10];
78 text.toCharArray(ch,text.length());
79 ssd1306_printFixedN(x, y, ch, STYLE_NORMAL, FONT_SIZE_2X);
80}
81
82/*
83 * 온도를 읽고, 정확한 온도로 계산 후 결과 값을 화면에 표시하고 반환하는 함수
84 * VALUE_TEMPTB = 0, CELSIUS_TEMPTB = 1 으로 온도표의 각 항목을 지시함
85 */
86int getTemperature()
87{
88 float ratioTemp;
89 float tempADU = analogRead(A0);
90 int result;
91
92 for(int i=1; i<23; i++){
93 if(tempADU >= temptable[i][VALUE_TEMPTB])
94 {
95 ratioTemp = (tempADU - temptable[i][VALUE_TEMPTB])/(temptable[i-1][VALUE_TEMPTB] - temptable[i][VALUE_TEMPTB]);
96
97 result = temptable[i][CELSIUS_TEMPTB] - ratioTemp*(temptable[i][CELSIUS_TEMPTB] - temptable[i-1][CELSIUS_TEMPTB]);
98
99 strToShow = String(result);
100
101 showTextToScreen(0,16,strToShow);
102
103 return result;
104 }
105 }
106
107 return ;
108}
109
110/*
111 * 버튼이 눌러졌는지 확인하고, 해당버튼에 맞는 코드 실행
112 */
113void checkBtnPressed()
114{
115 // C버튼이 눌리고, D버튼이 눌리지 않았을 경우 실행
116 if(!digitalRead(BTN_C) && digitalRead(BTN_D))
117 {
118 // C 버튼이 눌러져 있으면(isPressedC_BTN 가 true), 아래 코드 건너뜀
119 if(!isPressedC_BTN)
120 {
121 // 구조체 배열의 인덱스로 사용될 변수 값 1 증가
122 material_index++;
123 if(material_index > MATERIAL_COUNT-1)
124 {
125 material_index = 0;
126 }
127
128 // 디스플레이 업데이트를 할 수 있도록 변수 변경
129 isNeedUpdateScreen = true;
130
131 // 버튼 상태 변수 변경
132 isPressedC_BTN = true;
133 }
134 }
135 // D버튼이 눌리고, C버튼이 눌리지 않았을 경우 실행
136 else if(digitalRead(BTN_C) && !digitalRead(BTN_D))
137 {
138 // D 버튼이 눌러져 있으면(isPressedD_BTN 가 true), 아래 코드 건너뜀
139 if(!isPressedD_BTN)
140 {
141 // 구조체 배열의 인덱스로 사용될 변수 값 1 감소
142 material_index--;
143 if(material_index < 0)
144 {
145 material_index = MATERIAL_COUNT-1;
146 }
147
148 // 디스플레이 업데이트를 할 수 있도록 변수 변경
149 isNeedUpdateScreen = true;
150
151 // 버튼 상태 변수 변경
152 isPressedD_BTN = true;
153 }
154 }
155 else
156 {
157 // C, D 버튼 모두 눌리지 않을 경우, 변수 값 변경
158 isPressedC_BTN = false;
159 isPressedD_BTN = false;
160 }
161
162}
163
164/*
165 * 화면에 표시될 재료명, 목표속도, 목표온도를 업데이트
166 */
167void updateMaterial(int index)
168{
169 // isNeedUpdate 변수가 false 이면 함수를 종료함
170 if(!isNeedUpdateScreen) return;
171
172 // 목표 온도, 속도 항목에 현재 인덱스의 구조체 값을 저장
173 setTemperature = materials[index].temperature;
174 setMotorSpeed = materials[index].motorSpeed;
175
176 // 화면 클리어
177 ssd1306_clearScreen();
178
179 // 화면에 목표 온도, 재료 명, 속도를 표시
180 // 재료명은 좌표 0,0 에 표시
181 // 목표 온도는 좌표 52, 16 에 표시
182 strToShow = materials[index].materialName;
183 showTextToScreen(0,0, strToShow);
184
185 strToShow = "/" + String(setTemperature);
186 showTextToScreen(52,16,strToShow);
187
188 // 화면을 계속해서 업데이트 하지 않도록 방지하는 bool 변수 변경
189 isNeedUpdateScreen = false;
190}
191
192void setup()
193{
194 pinMode(BTN_A, INPUT_PULLUP);
195 pinMode(BTN_B, INPUT_PULLUP);
196 pinMode(BTN_C, INPUT_PULLUP);
197 pinMode(BTN_D, INPUT_PULLUP);
198
199 pinMode(MOTOR_EN, OUTPUT);
200 pinMode(MOTOR_DIR, OUTPUT);
201 pinMode(MOTOR_SPEED, OUTPUT);
202
203 pinMode(HEATER_EN, OUTPUT);
204
205 digitalWrite(MOTOR_EN, HIGH); // 모터 활성화
206
207 ssd1306_128x32_i2c_init(); // 32로 변경
208 ssd1306_fillScreen(0x00); // 화면 초기화
209 ssd1306_setFixedFont(ssd1306xled_font6x8); // 폰트 설정
210 ssd1306_flipHorizontal(1); // x 화면 대칭 회전
211 ssd1306_flipVertical(1); // y 화면 대칭 회전
212}
213
214void loop()
215{
216 if(millis() - timeInterval > 50)
217 {
218 curTemp = getTemperature();
219 updateMaterial(material_index);
220 checkBtnPressed();
221
222 timeInterval = millis();
223 }
224}