Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: X_NUCLEO_IHM02A1 TextLCD
main.cpp
00001 /** 00002 ****************************************************************************** 00003 이프로그램은 16x2크기의 LCD표시 및 제어, 스텝모터 제어 2가지 기능을 한다. 00004 사용자에서 실시간으로 LCD와 스텝모터의 동시제어를 위하여 2개의 쓰레드로 분리시켰다. 00005 모터가 회전할때는 적어도 1~2초의 시간이 소모되는데, 싱글 쓰레드로 한다면 모터가 작동할때 00006 LCD제어는 멈추게 된다. 따라서 작은시간을 서로 쪼개어 사용하여 서로간의 제어에 00007 영향을 받지 않도록 하기 위하여 2개의 쓰레드로 분리 시켰음. 00008 ****************************************************************************** 00009 */ 00010 00011 00012 /* Includes ------------------------------------------------------------------*/ 00013 00014 // mbed의 기능을 사용하기 위한 헤더파일 00015 #include "mbed.h" 00016 #include "rtos.h" 00017 00018 00019 //텍스트LCD를 사용하기 위한 라이브러리의 헤더파일 00020 #include "TextLCD.h" 00021 00022 //내부 FLASH ROM을 사용하기 위한 라이브러리 헤더파일 00023 #include "eeprom.h" 00024 #include <ctype.h> 00025 00026 //스텝모터 드라이버와 SPI통신을 위한 헤더파일 00027 #include "DevSPI.h" 00028 00029 //스텝모터 확장보드 사용을 위한 라이브러리 헤더파일 00030 #include "XNucleoIHM02A1.h" 00031 00032 00033 00034 00035 /*----------------------------------------------LCD제어관련 변수정의 -------------------------------------------------------*/ 00036 //16x2 크기의 LCD를 제어하기 위한 객체생성 00037 TextLCD lcd(D10, D9, D8, D7, D6, D5,TextLCD::LCD16x2); // H/L Register(RS) 선택핀, Enable(E) 선택핀, D4,D5,D6,D7(LCD출력핀) 00038 //DigitalOut rw(D7); // H/L Read,Write신호핀 00039 00040 //Digital 입력핀 설정(기본으로 신호가 없을시 풀다운신호(0V)를 출력하도록 설정한다.) 00041 DigitalIn setin(A3,PullDown); //설정버튼 00042 DigitalIn movin(D15,PullDown); //자릿수선택 버튼 00043 DigitalIn upin(D14,PullDown); //값올림 버튼 00044 DigitalIn downin(D2,PullDown); //값내림 버튼 00045 00046 00047 //LCD 출력의 현재시각 측정(단위:초) 00048 time_t NOWLCD; 00049 //LCD 출력을 조절하기 위한 이전시각(NOWLCD)저장 00050 time_t DISPLAY_TIME; 00051 00052 float SV = 10.5; //절삭유 농도 지시값(기준값) 00053 int SV1 = 1; //화면에 표시될 절삭유 농도 지시값(10의 자릿수값 정수값1문자) 00054 int SV2 = 0; //화면에 표시될 절삭유 농도 지시값(1의 자릿수값 정수값1문자) 00055 int SV3 = 5; //화면에 표시될 절삭유 농도 지시값(소수점1의 자릿수값 정수값1문자) 00056 00057 int SET_SV1 = 0; //설정모드에서 표시될 농도 지시값(10의 자릿수값) 00058 int SET_SV2 = 0; //설정모드에서 표시될 농도 지시값(1의 자릿수값) 00059 int SET_SV3 = 0; //설정모드에서 표시될 농도 지시값(소수점1의 자릿수값) 00060 00061 //lcd설정값과 밸브의 현재위치를 저장하기 위한 플래쉬메모리의 위치(LCD설정값(0x0000,0x0001), 밸브의 현재위치(0x0002,0x0003)(오일밸브현재 위치,희석수밸브현재위치 00062 uint16_t VirtAddVarTab[4] = {0x0000, 0x0001, 0x0002, 0x0003}; 00063 //lcd설정값(자연수,소수점,절삭유현재위치,희석수현재위치) 00064 uint16_t VarDataTab[] = {0, 0, 0, 0}; 00065 00066 float PV = 0; //1초동안 샘플링한 절삭유 농도값 00067 float PPV = 0; //이전측정 절삭유 농도값 00068 float CPV = 0; //현재 절삭유 농도값 00069 float SPV = 0; //1초동안 계속 평균을 계산하여 저장하는 절삭유 농도값 00070 00071 int OIL_VALVE_OPEN_P = 0; //오일밸브 열림% 00072 int WATER_VALVE_OPEN_P = 0; //희석수밸브 열림% 00073 int OIL_VALVE_OPEN_PP = 0; //오일밸브 열림%(이전값) 00074 int WATER_VALVE_OPEN_PP = 0; //희석수밸브 열림%(이전값) 00075 00076 bool set_button = false; //설정버튼 눌림 플래그 00077 bool mov_button = false; //자릿수선택 버튼 눌림 플래그 00078 bool up_button = false; //값올림버튼 눌림 플래그 00079 bool down_button = false; //값내림버튼 눌림 플래그 00080 00081 bool set_mode = false; //설정버튼 ON/OFF모드 00082 int cursor_loc = 0; //SV값을 설정하기 위하여 현재cursor의 위치를 저장(2번째행 11번열, 12번열 두개값중에 하나를 저장하고 있음) 00083 00084 00085 00086 00087 /*----------------------------------------------STEP모터 제어관련 변수정의 -------------------------------------------------------*/ 00088 00089 00090 //스텝수 정의 00091 #define STEPS_1 (200 * 128) //1바퀴에 200스텝(1스텝당 1.8도)을 가지고 있는 스텝모터를 1/128정밀도의 마이크로 스텝을 제어.(1바퀴 회전정의) 00092 #define STEPS_2 (STEPS_1 * 2) //2바퀴 회전정의 00093 00094 00095 00096 //스텝모터 확장모듈 드라이버 객체생성 00097 XNucleoIHM02A1 *x_nucleo_ihm02a1; 00098 00099 //스텝모터 파라미터값 정의 00100 L6470_init_t init[L6470DAISYCHAINSIZE] = { 00101 // 첫번째 Motor.(절삭유밸브 모터) 00102 { 00103 12.0, /* Motor supply voltage in V. */ 00104 200, /* Min number of steps per revolution for the motor. */ 00105 1.7, /* Max motor phase voltage in A. */ 00106 3.06, /* Max motor phase voltage in V. */ 00107 300.0, /* Motor initial speed [step/s]. */ 00108 500.0, /* Motor acceleration [step/s^2] (comment for infinite acceleration mode). */ 00109 500.0, /* Motor deceleration [step/s^2] (comment for infinite deceleration mode). */ 00110 992.0, /* Motor maximum speed [step/s]. */ 00111 0.0, /* Motor minimum speed [step/s]. */ 00112 602.7, /* Motor full-step speed threshold [step/s]. */ 00113 3.06, /* Holding kval [V]. */ 00114 3.06, /* Constant speed kval [V]. */ 00115 3.06, /* Acceleration starting kval [V]. */ 00116 3.06, /* Deceleration starting kval [V]. */ 00117 61.52, /* Intersect speed for bemf compensation curve slope changing [step/s]. */ 00118 392.1569e-6, /* Start slope [s/step]. */ 00119 643.1372e-6, /* Acceleration final slope [s/step]. */ 00120 643.1372e-6, /* Deceleration final slope [s/step]. */ 00121 0, /* Thermal compensation factor (range [0, 15]). */ 00122 3.06 * 1000 * 1.10, /* Ocd threshold [ma] (range [375 ma, 6000 ma]). */ 00123 3.06 * 1000 * 1.00, /* Stall threshold [ma] (range [31.25 ma, 4000 ma]). */ 00124 StepperMotor::STEP_MODE_1_128, /* Step mode selection. */ 00125 0xFF, /* Alarm conditions enable. */ 00126 0x2E88 /* Ic configuration. */ 00127 }, 00128 00129 //두번째 Motor(희석수밸브 모터) 00130 { 00131 12.0, /* Motor supply voltage in V. */ 00132 200, /* Min number of steps per revolution for the motor. */ 00133 1.7, /* Max motor phase voltage in A. */ 00134 3.06, /* Max motor phase voltage in V. */ 00135 300.0, /* Motor initial speed [step/s]. */ 00136 500.0, /* Motor acceleration [step/s^2] (comment for infinite acceleration mode). */ 00137 500.0, /* Motor deceleration [step/s^2] (comment for infinite deceleration mode). */ 00138 992.0, /* Motor maximum speed [step/s]. */ 00139 0.0, /* Motor minimum speed [step/s]. */ 00140 602.7, /* Motor full-step speed threshold [step/s]. */ 00141 3.06, /* Holding kval [V]. */ 00142 3.06, /* Constant speed kval [V]. */ 00143 3.06, /* Acceleration starting kval [V]. */ 00144 3.06, /* Deceleration starting kval [V]. */ 00145 61.52, /* Intersect speed for bemf compensation curve slope changing [step/s]. */ 00146 392.1569e-6, /* Start slope [s/step]. */ 00147 643.1372e-6, /* Acceleration final slope [s/step]. */ 00148 643.1372e-6, /* Deceleration final slope [s/step]. */ 00149 0, /* Thermal compensation factor (range [0, 15]). */ 00150 3.06 * 1000 * 1.10, /* Ocd threshold [ma] (range [375 ma, 6000 ma]). */ 00151 3.06 * 1000 * 1.00, /* Stall threshold [ma] (range [31.25 ma, 4000 ma]). */ 00152 StepperMotor::STEP_MODE_1_128, /* Step mode selection. */ 00153 0xFF, /* Alarm conditions enable. */ 00154 0x2E88 /* Ic configuration. */ 00155 } 00156 }; 00157 00158 00159 00160 //현재 농도를 받아오는 Analog input 핀번호를 선택한다.(PA_0)즉 핀번호 Analog 0번핀을 선택한다. 00161 AnalogIn CurCon(A0); 00162 00163 00164 //절삭유밸브와 희석수밸브의 초기위치 00165 int oilhomeposition = 0; 00166 int waterhomeposition = 0; 00167 00168 00169 //샘플링 카운트 수 00170 int samplecnt = 0; 00171 00172 00173 //절삭유밸브와 희석수밸브의 현재 포지션 00174 short oilcurrposition = 0; 00175 short watercurrposition = 0; 00176 00177 //오일탱크밸브와 수탱크밸브가 오픈된 시간을 저장 00178 Timer OIL_VALVE_TIMER; 00179 Timer WATER_VALVE_TIMER; 00180 00181 00182 //밸브가 열린후 카운트 시간 00183 time_t OIL_VALVE_OPEN_TIME; 00184 time_t WATER_VALVE_OPEN_TIME; 00185 00186 //현재시각 00187 time_t NOW; 00188 00189 //농도값 샘플링을 위한 시각비교값 저장 00190 time_t SAMPLE; 00191 00192 //오일탱크밸브와 수탱크밸브가 열려있는지 저장 00193 bool OIL_VALVE_ON = false; 00194 bool WATER_VALVE_ON = false; 00195 00196 00197 //딜레이시간 정의 (milli seconds) 00198 #define DELAY_1 1000 00199 #define DELAY_2 2000 00200 #define DELAY_3 5000 00201 00202 00203 00204 //LCD제어를 위한 쓰레드 생성 00205 void LCD_CTRL_THREAD(void const *args) 00206 { 00207 00208 ////설정값을 FLASH메모리에서 읽고쓰기하기 위하여 락을 해제한다. 00209 //HAL_FLASH_Unlock(); 00210 //EE_Init(); 00211 00212 00213 //SV값은 총4byte float값인데 EEPROM Library는 기본적으로 2byte씩메모리를 엑세스하게 되어있음 00214 //따라서 2byte메모리를 읽어서 4byte값으로 만들것임. 00215 for (int i=0; i<2; i++) 00216 { 00217 EE_ReadVariable(VirtAddVarTab[i], &VarDataTab[i]); 00218 } 00219 00220 //읽은값을 정수자릿수 2byte + 소숫점1자릿수 2byte값을 합쳐서 4byte float값으로 변경(설정값 저장) 00221 SV = VarDataTab[0] + VarDataTab[1]*0.1; 00222 00223 00224 //SV값을 LCD에 출력하기위하여 SV1,SV2,SV3로 분리한다. 00225 SV1 = (int)(SV/10); 00226 SV2 = (int)(SV-(SV1*10)); 00227 SV3 = (int)(((SV-((SV1*10)+SV2))*10)+0.5); 00228 00229 00230 00231 00232 //rw =0; 00233 lcd.cls(); //화면을 초기화 한다. 00234 00235 00236 00237 //절삭유 공급밸브 열림% LCD출력 00238 lcd.locate(0,0); 00239 lcd.printf("P1:"); 00240 lcd.printf("%03d%%",OIL_VALVE_OPEN_P); 00241 00242 //절삭유 현재 농도값 LCD출력 00243 lcd.locate(8,0); 00244 lcd.printf("PV:"); 00245 lcd.printf("%02.1f%%",PV); 00246 00247 //희석수 공급밸브 열림% LCD출력 00248 lcd.locate(0,1); 00249 lcd.printf("P2:"); 00250 lcd.printf("%03d%%",WATER_VALVE_OPEN_P); 00251 00252 //절삭유 지시(목표) 농도값 LCD출력 00253 lcd.locate(8,1); 00254 lcd.printf("SV:"); 00255 lcd.printf("%d%d.%d%%",SV1,SV2,SV3); 00256 00257 00258 //커서표시와 깜밖임을 없앤다. 00259 lcd.setCursor(lcd.CurOff_BlkOff); 00260 00261 00262 00263 while (1) 00264 { 00265 NOWLCD = time(NULL); 00266 /*------------------------------- LCD표시 ---------------------------------------------------*/ 00267 //1.5초마다 화면을 갱신한다. 00268 if(NOWLCD - DISPLAY_TIME >= 1 and !set_mode) 00269 { 00270 00271 //현재 측정한 절삭유 농도값이 이전측정값과 다르다면 LCD화면을 갱신한다. 00272 if(PV != PPV) 00273 { 00274 lcd.locate(11,0); 00275 lcd.printf("%02.1f%%",PV); 00276 00277 //현재값을 이전값변수에 입력한다.(다음타이밍에 비교하기 위하여) 00278 PPV = PV; 00279 } 00280 00281 //현재 오일밸브의 오픈%가 이전값과 달다면 LCD화면을 갱신한다. 00282 if(OIL_VALVE_OPEN_P != OIL_VALVE_OPEN_PP) 00283 { 00284 lcd.locate(3,0); 00285 lcd.printf("%03d%%",OIL_VALVE_OPEN_P); 00286 00287 //현재값을 이전 측정값을 저장하는 변수에 복사 00288 OIL_VALVE_OPEN_PP = OIL_VALVE_OPEN_P; 00289 } 00290 00291 00292 //현재 희석수밸브의 오픈%가 이전값과 달다면 LCD화면을 갱신한다. 00293 if(WATER_VALVE_OPEN_P != WATER_VALVE_OPEN_PP) 00294 { 00295 lcd.locate(3,1); 00296 lcd.printf("%03d%%",WATER_VALVE_OPEN_P); 00297 00298 //현재값을 이전 측정값을 저장하는 변수에 복사 00299 WATER_VALVE_OPEN_PP = WATER_VALVE_OPEN_P; 00300 } 00301 00302 //다음 시간비교를 위해서 현재시각을 저장한다. 00303 DISPLAY_TIME = NOWLCD; 00304 } 00305 00306 00307 00308 00309 /*------------------------------- LCD설정 ---------------------------------------------------*/ 00310 00311 //----------농도 설정 00312 //SV(농도지시값)값 설정버튼(SET)을 눌렀을경우 플래그를 세팅한다.(정확한 세팅상태를 지정하기 위함) 00313 if(setin and set_button == false) 00314 { 00315 set_button = true; //설정버튼 플래그 활성화 00316 } 00317 00318 //SET버튼이 눌려지다가 떨어지면 세팅모드로 들어간다. 00319 if(!setin and set_button == true and set_mode == false) 00320 { 00321 printf("LCD SETTING MODE IN\r\n"); 00322 lcd.locate(14,1); //설정값 첫번째 위치로 이동 00323 cursor_loc = 14; //현재 커서위치 저장 00324 lcd.setCursor(lcd.CurOff_BlkOn); //설정위치에서 커서 깜박임 00325 00326 set_mode = true; //설정모드 활성화 00327 set_button = false; //설정버튼 플래그 초기화 00328 } 00329 00330 //만약 SV설정 버튼이 true인 상태에서 한번더 누르면 현재값을 저장하고 모드를 빠져나온다(커서의 깜박임을 멈춘다.) 00331 if(!setin and set_button == true and set_mode == true ) 00332 { 00333 printf("LCD SETTING MODE OUT\r\n"); 00334 SV = (SV1*10) + (SV2*1) + (SV3*0.1); //설정값을 float형(4byte 부동소수점형)으로 저장한다. 00335 00336 //플래쉬메모리에 설정값을 저장한다. 00337 00338 //정수자릿수와 소수점 자릿수로 나눈다. 00339 VarDataTab[0] = (uint16_t)SV; //정수자릿수 00340 VarDataTab[1] = (uint16_t)(((SV-VarDataTab[0])*10)+0.5); //소수점1자릿수(45.5라는 숫자가 45.4999999같은 값이 될수 있으므로 소수점 첫번째에서 반올림한다.) 00341 00342 //내부 플래쉬 메모리에 값을 저장한다. 00343 EE_WriteVariable(VirtAddVarTab[0],VarDataTab[0] ); 00344 EE_WriteVariable(VirtAddVarTab[1],VarDataTab[1] ); 00345 00346 lcd.setCursor(lcd.CurOff_BlkOff); //설정위치의 커버 깜박임 꺼짐 00347 00348 set_mode = false; //설정모드 종료 00349 set_button = false; //설정버튼 플래그 초기화 00350 } 00351 00352 00353 00354 00355 00356 00357 00358 00359 //-------------자릿수 설정 00360 //자릿수 지정버튼(◁)을 눌렀을경우 플래그를 세팅한다.(정확한 세팅상태를 지정하기 위함) 00361 if(movin and mov_button == false and set_mode == true) 00362 { 00363 mov_button = true; //자릿수 이동버튼 플래그 활성화 00364 } 00365 00366 //만약 현재 설정모드이고 자릿수 버튼이 눌려졌다면 커서를 앞뒤로 이동한다. 00367 if(!movin and mov_button == true and set_mode == true) 00368 { 00369 printf("LCD MOVE\r\n"); 00370 //만약 현재 cursor의 위치가 11이라면 14로 옮기고, 12라면 11로, 14라면 12로 옮긴다. 00371 if(cursor_loc == 11) 00372 { 00373 //커서의 위치를 옮긴후 현재의 위치를 저장한다. 00374 lcd.locate(14,1); 00375 cursor_loc = 14; 00376 } 00377 //만약 현재 cursor의 위치가 12라면 11로 옮긴다. 00378 else if(cursor_loc == 12) 00379 { 00380 //커서의 위치를 옮긴후 현재의 위치를 저장한다. 00381 lcd.locate(11,1); 00382 cursor_loc = 11; 00383 } 00384 //만약 현재 cursor의 위치가 14라면 12로 옮긴다. 00385 else if(cursor_loc == 14) 00386 { 00387 //커서의 위치를 옮긴후 현재의 위치를 저장한다. 00388 lcd.locate(12,1); 00389 cursor_loc = 12; 00390 } 00391 00392 00393 mov_button = false; //자릿수 이동버튼 플래그 초기화 00394 } 00395 00396 00397 00398 00399 00400 //------------지시값 설정 00401 //설정모드에서 값올림(△)버튼을 눌렀을 경우 올림버튼 플래그를 활성화 한다. 00402 if(upin and up_button == false and set_mode == true) 00403 { 00404 up_button = true; //값올림 버튼 플래그 활성화 00405 } 00406 00407 //설정모드에서 값올림 버튼을 눌렀다면 현재 커서가 깜박이는 위치의 자릿수 값을 1씩 올린다. 00408 if(!upin and up_button == true and set_mode == true) 00409 { 00410 printf("LCD UP\r\n"); 00411 //10의 자릿수에 커서가 위치해 있다면 10의자릿수 값에 1을 더한다. 00412 if(cursor_loc == 11) 00413 { 00414 SV1++; 00415 //만약 더한값이 10이상이라면 다시 0으로 바꾼다. 00416 if(SV1 >= 10) SV1 = 0; 00417 //LCD화면의 값을 바꾼다. 00418 lcd.printf("%d",SV1); 00419 //화면에 프린트하면 location이 자동으로 증가하므로 다시 원래위치로 돌린다. 00420 lcd.locate(11,1); 00421 cursor_loc == 11; 00422 00423 } 00424 //1의 자릿수에 커서가 위치해 있다면 1의자릿수 값에 1을 더한다. 00425 else if(cursor_loc == 12) 00426 { 00427 SV2++; 00428 //만약 더한값이 10이상이라면 다시 0으로 바꾼다. 00429 if(SV2 >= 10) SV2 = 0; 00430 //LCD화면의 값을 바꾼다. 00431 lcd.printf("%d",SV2); 00432 //화면에 프린트하면 location이 자동으로 증가하므로 다시 원래위치로 돌린다. 00433 lcd.locate(12,1); 00434 cursor_loc == 12; 00435 } 00436 //소수점1의 자릿수에 커서가 위치해 있다면 소수점1의자릿수 값에 1을 더한다. 00437 else if(cursor_loc == 14) 00438 { 00439 SV3++; 00440 //만약 더한값이 10이상이라면 다시 0으로 바꾼다. 00441 if(SV3 >= 10) SV3 = 0; 00442 //LCD화면의 값을 바꾼다. 00443 lcd.printf("%d",SV3); 00444 //화면에 프린트하면 location이 자동으로 증가하므로 다시 원래위치로 돌린다. 00445 lcd.locate(14,1); 00446 cursor_loc == 14; 00447 } 00448 00449 up_button = false; //값올림 버튼 플래그 초기화 00450 } 00451 00452 00453 00454 00455 //설정모드에서 값내림(▽)버튼을 눌렀을 경우 내림버튼 플래그를 활성화 한다. 00456 if(downin and down_button == false and set_mode == true) 00457 { 00458 down_button = true; //값내림 버튼 플래그 활성화 00459 } 00460 00461 //설정모드에서 값내림 버튼을 눌렀다면 현재 커서가 깜박이는 위치의 자릿수 값을 1씩 내린다. 00462 if(!downin and down_button == true and set_mode == true) 00463 { 00464 printf("LCD DOWN\r\n"); 00465 //10의 자릿수에 커서가 위치해 있다면 10의자릿수 값에 1을 뺀다. 00466 if(cursor_loc == 11) 00467 { 00468 SV1--; 00469 //만약 뺀값이 -1이하라면 값을 9로 바꾼다. 00470 if(SV1 <= -1) SV1 = 9; 00471 //LCD화면의 값을 바꾼다. 00472 lcd.printf("%d",SV1); 00473 //화면에 프린트하면 location이 자동으로 증가하므로 다시 원래위치로 돌린다. 00474 lcd.locate(11,1); 00475 cursor_loc == 11; 00476 00477 } 00478 //1의 자릿수에 커서가 위치해 있다면 1의자릿수 값에 1을 뺀다 00479 else if(cursor_loc == 12) 00480 { 00481 SV2--; 00482 //만약 뺀값이 -1이하라면 값을 9로 바꾼다. 00483 if(SV2 <= -1) SV2 = 9; 00484 //LCD화면의 값을 바꾼다. 00485 lcd.printf("%d",SV2); 00486 //화면에 프린트하면 location이 자동으로 증가하므로 다시 원래위치로 돌린다. 00487 lcd.locate(12,1); 00488 cursor_loc == 12; 00489 } 00490 //소수점1의 자릿수에 커서가 위치해 있다면 소수점1의자릿수 값에 1을 뺀다 00491 else if(cursor_loc == 14) 00492 { 00493 SV3--; 00494 //만약 뺀값이 10이하라면 값을 9로 바꾼다. 00495 if(SV3 <= -1) SV3 = 9; 00496 //LCD화면의 값을 바꾼다. 00497 lcd.printf("%d",SV3); 00498 //화면에 프린트하면 location이 자동으로 증가하므로 다시 원래위치로 돌린다. 00499 lcd.locate(14,1); 00500 cursor_loc == 14; 00501 } 00502 00503 down_button = false; //값내림 버튼 플래그 초기화 00504 } 00505 00506 00507 00508 00509 //쓰레드 대기 00510 Thread::wait(10); 00511 } 00512 } 00513 00514 00515 00516 00517 00518 00519 00520 00521 00522 00523 00524 00525 /* Main ----------------------------------------------------------------------*/ 00526 00527 int main() 00528 { 00529 //설정값을 FLASH메모리에서 읽고쓰기하기 위하여 락을 해제한다. 00530 HAL_FLASH_Unlock(); 00531 EE_Init(); 00532 00533 //LCD제어를 위한 쓰레드를 호출 00534 Thread thread(LCD_CTRL_THREAD); 00535 00536 00537 00538 00539 00540 00541 //스텝모터 드라이브와 F401RE보드와 통신하기 위하여 SPI통신핀을 초기화 해준다. 00542 #ifdef TARGET_STM32F429 00543 DevSPI dev_spi(D11, D12, D13); 00544 #else 00545 DevSPI dev_spi(D11, D12, D3); 00546 #endif 00547 00548 //확장보드 초기화 00549 x_nucleo_ihm02a1 = new XNucleoIHM02A1(&init[0], &init[1], A4, A5, D4, A2, &dev_spi); 00550 00551 //모터 컨트롤 모터리스트 객체 00552 L6470 **motors = x_nucleo_ihm02a1->get_components(); 00553 00554 //콘솔화면 프린트 00555 printf("Motor Control Application Example for 2 Motors\r\n\n"); 00556 00557 00558 //절삭유와 희석수의 현재위치값을 가져온다. 00559 for (int i=2; i<4; i++) 00560 { 00561 EE_ReadVariable(VirtAddVarTab[i], &VarDataTab[i]); 00562 } 00563 00564 //절삭유 현재위치값을 플래쉬 메모리에서 가져온다. 00565 oilcurrposition = VarDataTab[2]; 00566 //희석수 현재위치값을 플래쉬 메모리에서 가져온다. 00567 watercurrposition = VarDataTab[3]; 00568 00569 //만약 현재의 위치가 홈포지션(0)이 아니라면 홈포지션으로 모터를 회전시킨다. 00570 printf("currunt oil valve position %d",oilcurrposition); 00571 00572 //제일처음 전원이 들어왔을경우 현재값을 초기값으로 지정한다. 00573 printf("--> Set Home position.\r\n"); 00574 motors[0]->set_home(); 00575 //oilhomeposition = motors[0]->get_position(); 00576 oilhomeposition = 0; 00577 00578 00579 motors[1]->set_home(); 00580 //waterhomeposition = motors[0]->get_position(); 00581 waterhomeposition = 0; 00582 //wait_ms(DELAY_1); 00583 00584 00585 00586 00587 00588 00589 00590 00591 //루프를 돌면서 농도값,밸브열림%,설정,모터제어 관련 작업을 진행한다. 00592 while(1) 00593 { 00594 //현재시간을 체크한다. 00595 NOW = time(NULL); 00596 00597 //현재 농도값을 읽는다. 00598 //아날로그 값은 0~1값으로 들어온다. (참고로 STM32F401보드는 ADC의 분해능이 12bit이다.) 00599 //165옴 저항을 사용했을경우 아래와 같은 범위에서 값이 들어온다. 00600 //4ma = 0.66V, 20ma = 3.3v이다. 00601 00602 00603 //Nucleo-64보드의 아날로그read()함수는 값을 아두이노처럼 0~3.3v사이의 값을 분해능값으로 (즉 0~4095)로 00604 //리턴하는것이 아니라 Voltage값으로 리턴한다.(내부적으로 아날로그값을 Voltage로 바꾸어준다.) 00605 //0~1 사이의 값을 리턴하는데 그값을 보드의 기준전압인 3.3을 곱해주면 현재 아날로그 입력으로 들어오는 전압값을 알수 있다. 00606 //따라서 4ma의 전압값은 0.66v이고 20ma의 값은 3.3v이므로 (입력값-최저값)*100/(최대값-최저값) 계산으로 농도가 몇%인지 계산이 가능하다. 00607 00608 float cc = CurCon.read()* 3.3; 00609 //float cc = CurCon.read()* 3.3; 00610 printf("CC = %f \r\n",cc); 00611 00612 00613 //3.3v신호를 사용할것이므로 165옴의 저항을 연결하면 4ma = 0.66V, 20ma = 3.3v가된다. 00614 //따라서 현재들어오는 전압값을 100분율로 계산하면 몇%의 절삭유농도인지 알수가 있다. 00615 //4ma = -2.0% ~ 20ma = 33.5% 00616 //PV = ((cc - 1)*100.0)/(5.0 - 1); 00617 //0V ~ 3.3V를 백분율로 계산한다. 00618 CPV = ((cc - 0.66)*35.5)/(3.3 - 0.66) - 2.0; 00619 //printf("PV = %f \r\n",PV); 00620 00621 00622 //샘플링 시간을 비교한다. 00623 //샘플링 시간 1초를 지나면 평균값으로 PV값을 입력한다. 00624 if(NOW - SAMPLE >=2) 00625 { 00626 PV = SPV; 00627 samplecnt = 0; 00628 SPV = 0; 00629 SAMPLE = NOW; 00630 } 00631 //샘플링 시간이 지나가지 않았다면 계속 평균값을 구한다. 00632 else 00633 { 00634 00635 if(samplecnt == 0) SPV = CPV; 00636 else 00637 { 00638 SPV = (SPV + CPV) / 2; 00639 } 00640 samplecnt++; 00641 } 00642 00643 00644 00645 00646 00647 00648 00649 00650 00651 //만약 절삭유 농도가 10%(기준농도) 미만이라면 절삭유탱크 밸브를 연다. 00652 if(PV < SV - 0.5) 00653 { 00654 //수탱크 밸브가 열려있다면 00655 if(waterhomeposition != motors[1]->get_position()) 00656 { 00657 //수탱크 밸브를 원상복귀 시킨다. 00658 printf("--> Going Home Position Water Tank Value.\r\n"); 00659 motors[1]->go_home(); 00660 //수탱크 밸브가 HOME 위치로 갈때까지 대기 00661 motors[1]->wait_while_active(); 00662 00663 //플래시메모리에 현재의 희석수 밸브 포지션을 저장한다. 00664 VarDataTab[3] = 0; 00665 EE_WriteVariable(VirtAddVarTab[3],VarDataTab[3] ); 00666 00667 WATER_VALVE_ON = false; 00668 00669 //현재밸브가 열린%를 계산한다. 00670 WATER_VALVE_OPEN_P = 0.0; 00671 } 00672 00673 00674 //만약 절삭유밸브가 열려있지 않다면 밸브를 연다. 00675 if(oilhomeposition == motors[0]->get_position()) 00676 { 00677 //밸브를 앞방향으로 90도(모터2바퀴) 돌린다. 00678 printf("--> Moving forward Oil Tank Valve %d steps.\r\n", STEPS_2); 00679 //모터회전 명령을 내린다. 00680 motors[0]->move(StepperMotor::FWD, STEPS_2); 00681 //모터의 회전이 완료될때까지 기다린다. 00682 motors[0]->wait_while_active(); 00683 00684 //절삭유모터의 2바퀴회전후의 포지션을 가져온다. 00685 short oilcurrposition = motors[0]->get_position(); 00686 printf("--> Oil Tank Valve Position %d \r\n", oilcurrposition); 00687 00688 //플래시메모리에 현재의 절삭유 밸브 포지션을 저장한다. 00689 VarDataTab[2] = oilcurrposition; 00690 EE_WriteVariable(VirtAddVarTab[2],VarDataTab[2] ); 00691 00692 OIL_VALVE_ON = true; 00693 00694 //오일밸브 타이머 시작 00695 //OIL_VALVE_TIMER.start(); 00696 OIL_VALVE_OPEN_TIME = time(NULL); 00697 00698 //현재밸브가 열린%를 계산한다. 00699 OIL_VALVE_OPEN_P = (STEPS_2*100)/STEPS_2; 00700 00701 } 00702 00703 //만약 오일밸브 타이머가 시작되어 있다면 시간을 체크한다. 00704 if(OIL_VALVE_ON == true) 00705 { 00706 00707 //만약 절삭유의 현재값이 목표값(설정값) - 0.5 이상이고 절삭유밸브가 OPEN되고 2초이상 지났다면 절삭유가 파이프를 통해서 흘러가는 잔류량을 고려하여 밸브를 닫는다. 00708 if(PV >= SV - 0.5) 00709 { 00710 if((NOW - OIL_VALVE_OPEN_TIME) > 2) 00711 { 00712 printf("--> Going Home Position Oil Tank Value.\r\n"); 00713 motors[0]->go_home(); 00714 //절삭유탱크 밸브가 HOME 위치로 갈때까지 대기 00715 motors[0]->wait_while_active(); 00716 00717 OIL_VALVE_ON = false; 00718 } 00719 } 00720 //printf("--> Aready Oil Tank Valve Opened\r\n"); 00721 } 00722 00723 00724 00725 00726 } 00727 //만약 절삭유 농도가 10%(기준농도) < 현재농도 < 10.5% 라면 수탱크 밸브를 연다. 00728 else if(SV + 0.5 <= PV ) 00729 { 00730 //절삭유 탱크 밸브가 열려있다면 00731 if(waterhomeposition != motors[0]->get_position()) 00732 { 00733 //절삭유 탱크 밸브를 원상복귀 시킨다. 00734 printf("--> Going Home Position Oil Tank Valve\r\n"); 00735 motors[0]->go_home(); 00736 //절삭유탱크 밸브가 HOME 위치로 갈때까지 대기 00737 motors[0]->wait_while_active(); 00738 00739 OIL_VALVE_ON = false; 00740 00741 //현재밸브가 열린%를 계산한다. 00742 OIL_VALVE_OPEN_P = 0.0; 00743 } 00744 00745 00746 //만약 절삭유밸브가 열려있지 않다면 밸브를 연다. 00747 if(waterhomeposition == motors[1]->get_position()) 00748 { 00749 //밸브를 앞방향으로 45도(1바퀴) 돌린다. 00750 printf("--> Moving forward Water Tank Valve %d steps.\r\n", STEPS_2); 00751 //모터회전 명령을 내린다. 00752 motors[1]->move(StepperMotor::FWD, STEPS_2); 00753 //모터의 회전이 완료될때까지 기다린다. 00754 motors[1]->wait_while_active(); 00755 00756 WATER_VALVE_ON = true; 00757 00758 //희석수탱크밸브 타이머 시작 00759 //WATER_VALVE_TIMER.start() 00760 WATER_VALVE_OPEN_TIME = time(NULL); 00761 00762 //현재밸브가 열린%를 계산한다. 00763 WATER_VALVE_OPEN_P = (STEPS_2*100)/STEPS_2; 00764 00765 } 00766 00767 //만약 수탱크 타이머가 시작되어 있다면 시간을 체크한다. 00768 if(WATER_VALVE_ON == true) 00769 { 00770 //만약 절삭유의 현재값이 기준값(목표값)+ 0.5 이하이고 절삭유밸브가 OPEN되고 2초이상 지났다면 절삭유가 파이프를 통해서 흘러가는 잔류량을 고려하여 밸브를 닫는다. 00771 if(PV <= SV + 0.5) 00772 { 00773 if((NOW - WATER_VALVE_OPEN_TIME) > 2) 00774 { 00775 printf("--> Going Home Position Oil Tank Value.\r\n"); 00776 motors[1]->go_home(); 00777 //희석수탱크 밸브가 HOME 위치로 갈때까지 대기 00778 motors[1]->wait_while_active(); 00779 00780 OIL_VALVE_ON = false; 00781 } 00782 } 00783 } 00784 00785 } 00786 //정상이라면 절삭유탱크밸브 및 수탱크밸브를 HOME위치로 이동시킨다. 00787 else 00788 { 00789 //절삭유 탱크 밸브를 원상복귀 시킨다. 00790 //절삭유 탱크 밸브가 열려있다면 00791 if(waterhomeposition != motors[0]->get_position()) 00792 { 00793 printf("--> Going Home Position Oil Tank Value.\r\n"); 00794 motors[0]->go_home(); 00795 //절삭유탱크 밸브가 HOME 위치로 갈때까지 대기 00796 motors[0]->wait_while_active(); 00797 00798 OIL_VALVE_ON = false; 00799 00800 //현재밸브가 열린%를 계산한다. 00801 OIL_VALVE_OPEN_P = 0.0; 00802 } 00803 00804 00805 //희석수탱크 밸브가 열려있다면 00806 if(waterhomeposition != motors[1]->get_position()) 00807 { 00808 //수탱크 밸브를 원상복귀 시킨다. 00809 printf("--> Going Home Position Water Tank Value.\r\n"); 00810 motors[1]->go_home(); 00811 //희석수탱크 밸브가 HOME 위치로 갈때까지 대기 00812 motors[1]->wait_while_active(); 00813 00814 WATER_VALVE_ON = false; 00815 00816 //현재밸브가 열린%를 계산한다. 00817 WATER_VALVE_OPEN_P = 0.0; 00818 } 00819 } 00820 00821 00822 00823 00824 00825 00826 00827 00828 00829 //내부적인 프로세스 처리를 우해서 반드시 일정시간 멈추어야한다. 00830 Thread::wait(10); 00831 00832 //wait_ms(100); 00833 00834 00835 00836 } 00837 00838 00839 00840 }
Generated on Wed Jul 20 2022 01:37:54 by
1.7.2