Jaeyeol Lee / Mbed OS 200117StepMotorControl

Dependencies:   X_NUCLEO_IHM02A1 TextLCD

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }