200117StepMotorControl
Dependencies: X_NUCLEO_IHM02A1 TextLCD
Diff: main.cpp
- Revision:
- 29:d5c13978c8e9
- Parent:
- 28:ed18e436f437
diff -r ed18e436f437 -r d5c13978c8e9 main.cpp --- a/main.cpp Thu Jan 16 06:27:47 2020 +0000 +++ b/main.cpp Fri Jan 17 07:58:29 2020 +0000 @@ -43,10 +43,7 @@ DigitalIn upin(D14,PullDown); //값올림 버튼 DigitalIn downin(D2,PullDown); //값내림 버튼 -//DigitalIn set(D9); //설정버튼 -//DigitalIn mov(D8); //자릿수선택 버튼 -//DigitalIn up(D1); //값올림 버튼 -//DigitalIn down(D0); //값내림 버튼 + //LCD 출력의 현재시각 측정(단위:초) time_t NOWLCD; //LCD 출력을 조절하기 위한 이전시각(NOWLCD)저장 @@ -61,12 +58,15 @@ int SET_SV2 = 0; //설정모드에서 표시될 농도 지시값(1의 자릿수값) int SET_SV3 = 0; //설정모드에서 표시될 농도 지시값(소수점1의 자릿수값) +//lcd설정값과 밸브의 현재위치를 저장하기 위한 플래쉬메모리의 위치(LCD설정값(0x0000,0x0001), 밸브의 현재위치(0x0002,0x0003)(오일밸브현재 위치,희석수밸브현재위치 +uint16_t VirtAddVarTab[4] = {0x0000, 0x0001, 0x0002, 0x0003}; +//lcd설정값(자연수,소수점,절삭유현재위치,희석수현재위치) +uint16_t VarDataTab[] = {0, 0, 0, 0}; -uint16_t VirtAddVarTab[2] = {0x0000, 0x0001}; -uint16_t VarDataTab[] = {0, 0}; - -float PV = 0; //현재측정 절삭유 농도값 -float PPV = 0; //이전측정 절각유 농도값 +float PV = 0; //1초동안 샘플링한 절삭유 농도값 +float PPV = 0; //이전측정 절삭유 농도값 +float CPV = 0; //현재 절삭유 농도값 +float SPV = 0; //1초동안 계속 평균을 계산하여 저장하는 절삭유 농도값 int OIL_VALVE_OPEN_P = 0; //오일밸브 열림% int WATER_VALVE_OPEN_P = 0; //희석수밸브 열림% @@ -165,6 +165,15 @@ int oilhomeposition = 0; int waterhomeposition = 0; + +//샘플링 카운트 수 +int samplecnt = 0; + + +//절삭유밸브와 희석수밸브의 현재 포지션 +short oilcurrposition = 0; +short watercurrposition = 0; + //오일탱크밸브와 수탱크밸브가 오픈된 시간을 저장 Timer OIL_VALVE_TIMER; Timer WATER_VALVE_TIMER; @@ -177,6 +186,9 @@ //현재시각 time_t NOW; +//농도값 샘플링을 위한 시각비교값 저장 +time_t SAMPLE; + //오일탱크밸브와 수탱크밸브가 열려있는지 저장 bool OIL_VALVE_ON = false; bool WATER_VALVE_ON = false; @@ -193,9 +205,9 @@ void LCD_CTRL_THREAD(void const *args) { - //설정값을 FLASH메모리에서 읽고쓰기하기 위하여 락을 해제한다. - HAL_FLASH_Unlock(); - EE_Init(); + ////설정값을 FLASH메모리에서 읽고쓰기하기 위하여 락을 해제한다. + //HAL_FLASH_Unlock(); + //EE_Init(); //SV값은 총4byte float값인데 EEPROM Library는 기본적으로 2byte씩메모리를 엑세스하게 되어있음 @@ -253,7 +265,7 @@ NOWLCD = time(NULL); /*------------------------------- LCD표시 ---------------------------------------------------*/ //1.5초마다 화면을 갱신한다. - if(NOWLCD - DISPLAY_TIME >= 1.5 and !set_mode) + if(NOWLCD - DISPLAY_TIME >= 1 and !set_mode) { //현재 측정한 절삭유 농도값이 이전측정값과 다르다면 LCD화면을 갱신한다. @@ -514,14 +526,16 @@ int main() { - + //설정값을 FLASH메모리에서 읽고쓰기하기 위하여 락을 해제한다. + HAL_FLASH_Unlock(); + EE_Init(); //LCD제어를 위한 쓰레드를 호출 Thread thread(LCD_CTRL_THREAD); - //while(1); + //스텝모터 드라이브와 F401RE보드와 통신하기 위하여 SPI통신핀을 초기화 해준다. @@ -541,53 +555,97 @@ printf("Motor Control Application Example for 2 Motors\r\n\n"); + //절삭유와 희석수의 현재위치값을 가져온다. + for (int i=2; i<4; i++) + { + EE_ReadVariable(VirtAddVarTab[i], &VarDataTab[i]); + } + + //절삭유 현재위치값을 플래쉬 메모리에서 가져온다. + oilcurrposition = VarDataTab[2]; + //희석수 현재위치값을 플래쉬 메모리에서 가져온다. + watercurrposition = VarDataTab[3]; + + //만약 현재의 위치가 홈포지션(0)이 아니라면 홈포지션으로 모터를 회전시킨다. + printf("currunt oil valve position %d",oilcurrposition); + //제일처음 전원이 들어왔을경우 현재값을 초기값으로 지정한다. printf("--> Set Home position.\r\n"); motors[0]->set_home(); - oilhomeposition = motors[0]->get_position(); + //oilhomeposition = motors[0]->get_position(); + oilhomeposition = 0; motors[1]->set_home(); - waterhomeposition = motors[0]->get_position(); + //waterhomeposition = motors[0]->get_position(); + waterhomeposition = 0; //wait_ms(DELAY_1); + + + + //루프를 돌면서 농도값,밸브열림%,설정,모터제어 관련 작업을 진행한다. while(1) { - + //현재시간을 체크한다. + NOW = time(NULL); //현재 농도값을 읽는다. //아날로그 값은 0~1값으로 들어온다. (참고로 STM32F401보드는 ADC의 분해능이 12bit이다.) - //250옴 저항을 사용했을경우 아래와 같은 범위에서 값이 들어온다. - //4ma = 1V, 20ma = 5v이다. + //165옴 저항을 사용했을경우 아래와 같은 범위에서 값이 들어온다. + //4ma = 0.66V, 20ma = 3.3v이다. - //Nucleo-64보드의 아날로그read()함수는 값을 아두이노처럼 0~5v사이의 값을 분해능값으로 (즉 0~4095)로 + //Nucleo-64보드의 아날로그read()함수는 값을 아두이노처럼 0~3.3v사이의 값을 분해능값으로 (즉 0~4095)로 //리턴하는것이 아니라 Voltage값으로 리턴한다.(내부적으로 아날로그값을 Voltage로 바꾸어준다.) - //0~1 사이의 값을 리턴하는데 그값을 보드의 기준전압인 5.0을 곱해주면 현재 아날로그 입력으로 들어오는 전압값을 알수 있다. - //따라서 4ma의 전압값은 1.0v이고 20ma의 값은 5.0v이므로 (입력값-최저값)*100/(최대값-최저값) 계산으로 농도가 몇%인지 계산이 가능하다. + //0~1 사이의 값을 리턴하는데 그값을 보드의 기준전압인 3.3을 곱해주면 현재 아날로그 입력으로 들어오는 전압값을 알수 있다. + //따라서 4ma의 전압값은 0.66v이고 20ma의 값은 3.3v이므로 (입력값-최저값)*100/(최대값-최저값) 계산으로 농도가 몇%인지 계산이 가능하다. float cc = CurCon.read()* 3.3; + //float cc = CurCon.read()* 3.3; printf("CC = %f \r\n",cc); - //5V시그널을 사용할것이므로 250옴의 저항을 연결하면 4ma = 1.0V, 20ma = 5.0v가된다. + //3.3v신호를 사용할것이므로 165옴의 저항을 연결하면 4ma = 0.66V, 20ma = 3.3v가된다. //따라서 현재들어오는 전압값을 100분율로 계산하면 몇%의 절삭유농도인지 알수가 있다. + //4ma = -2.0% ~ 20ma = 33.5% //PV = ((cc - 1)*100.0)/(5.0 - 1); - //3.3V로 계산 - PV = ((cc - 0.66)*100.0)/(3.3 - 0.66); - printf("PV = %f \r\n",PV); + //0V ~ 3.3V를 백분율로 계산한다. + CPV = ((cc - 0.66)*35.5)/(3.3 - 0.66) - 2.0; + //printf("PV = %f \r\n",PV); + + + //샘플링 시간을 비교한다. + //샘플링 시간 1초를 지나면 평균값으로 PV값을 입력한다. + if(NOW - SAMPLE >=2) + { + PV = SPV; + samplecnt = 0; + SPV = 0; + SAMPLE = NOW; + } + //샘플링 시간이 지나가지 않았다면 계속 평균값을 구한다. + else + { + + if(samplecnt == 0) SPV = CPV; + else + { + SPV = (SPV + CPV) / 2; + } + samplecnt++; + } - //현재시간을 체크한다. - NOW = time(NULL); + //만약 절삭유 농도가 10%(기준농도) 미만이라면 절삭유탱크 밸브를 연다. @@ -602,6 +660,10 @@ //수탱크 밸브가 HOME 위치로 갈때까지 대기 motors[1]->wait_while_active(); + //플래시메모리에 현재의 희석수 밸브 포지션을 저장한다. + VarDataTab[3] = 0; + EE_WriteVariable(VirtAddVarTab[3],VarDataTab[3] ); + WATER_VALVE_ON = false; //현재밸브가 열린%를 계산한다. @@ -619,6 +681,14 @@ //모터의 회전이 완료될때까지 기다린다. motors[0]->wait_while_active(); + //절삭유모터의 2바퀴회전후의 포지션을 가져온다. + short oilcurrposition = motors[0]->get_position(); + printf("--> Oil Tank Valve Position %d \r\n", oilcurrposition); + + //플래시메모리에 현재의 절삭유 밸브 포지션을 저장한다. + VarDataTab[2] = oilcurrposition; + EE_WriteVariable(VirtAddVarTab[2],VarDataTab[2] ); + OIL_VALVE_ON = true; //오일밸브 타이머 시작 @@ -654,7 +724,7 @@ } - //만약 절삭유 농도가 10%(기준농도) < 현재농도 < 12% 라면 수탱크 밸브를 연다. + //만약 절삭유 농도가 10%(기준농도) < 현재농도 < 10.5% 라면 수탱크 밸브를 연다. else if(SV + 0.5 <= PV ) { //절삭유 탱크 밸브가 열려있다면