강좌,팁

허창원 *.94.119.73

8. 진폭, Add Noise 콜백 함수 작성
이제 진폭, Add Noise 콜백 함수기능을 구현해야 됩니다. 우선 진폭 기능부터 볼까요?
진폭이란 파형의 높낮이를말하는 겁니다. 파형의 최대-최소값의 폭은 Peak-to-Peak 값이라고 하고, 중심값(0)부터최대값의 크기를 Amplitude(진폭)이라고 합니다.

주기 부분과 기능이 유사하므로, 주기 콜백함수를 복사해 와서 다음과 같이 수정합니다.


그림 7.15 numAmplitude() 콜백 함수

 

이제 진폭, Amp값을 선언을 해주어야겠죠? L007_Data_IO_common.h에 선언합니다.


그림 7.16 Amp 변수의 선언

 

변수 선언을 했으면, 초기화도 필요하죠! main() 함수 내를 다음과 같이 수정합니다.


그림 7.16 Amp 변수의 초기화


이제 마지막으로 신호를 발생시키는 부분에 Amp값을 반영시키도록 해야겠죠? L007_Data_IO_common.c파일 내를 아래와 같이 수정합니다.


그림 7.17 Generate_sin_data() 함수의 수정

 

이제 실행파일을 생성하여, 실행해봅시다. 그리고 주기와 진폭을 변경시켜봅시다.


그림 7.18 두 번째 실행, 주기와 진폭의 변경 기능 검사


이제 Add Noise 기능을 추가해야겠군요. 역시 이 기능을 위한 변수가 하나 필요합니다.chkNoise라고 할까요? 1이냐 0이냐에 따라 난수를 발생시켜 더해 주느냐, 그렇지않느냐를 판단합니다. chkNoise의 초기값은 0, 즉 체크가 안된 것으로 합시다. 그리고Generate_sin_data() 함수를 다시 수정합니다. 난수는 0부터 1사이의 값으로 발생시키도록합시다.

그럼, 수정되는 소스를 하나씩 볼까요?


그림 7.19 chkNoise 변수의 선언(L007_Data_IO_common.h)


 

그림 7.20 chkNoise 변수의 초기화(L007_Data_IO.c)


 

그림 7.21 chkAddNoise() 콜백 함수 작성(L007_Data_IO.c)


 

그림 7.22 Generate_sin_data() 함수의 수정


이제 실행파일을 만들고 실행해봅시다. 그리고 Add Noise 체크 박스를 체크해봅시다.주기와 진폭도 함께 변경시켜보구요. 아래 그림 7.23에 실행화면을 표시하였습니다.


그림 7.23 세 번째 실행화면, Add Noise 기능

 

(휴우~~ 강좌 파일을 작성하는 데 굉장히 시간이 많이 걸리는군요. 내일부터 1주일간에스라 성경강좌 집회에 참석해야 되는데.....
자 그럼~ 계속 빨리 진행해보겠습니다.)


9. 데이터 파일 저장 기능 구현
이제 Save 버튼을 눌렀을 때 실행되는기능입니다. 그래프에 표시되는 데이터를 파일에 저장하는 기능입니다. 그래프에표시되는 데이터는 사실 data[NUM]라는 배열에 저장되어 있으므로, 이 data에 저장된값을 파일에 저장하면 됩니다.
데이터 파일에 저장하려면 파일명을 지정해 주어야되는데,파일 저장 대화 상자(PopUP Panel)를 이용합시다.
파일명이 지정되면 별도의사용자 정의 함수 SaveData()라는 함수를 호출하도록 합시다. 그리고 이 SaveData()라는함수는 ....common.c에 정의합시다.


그림 7.24 cmdSave() 콜백 함수 작성(L007_Data_IO.c)


 

그림 7.25 SaveData() 함수 작성(L007_Data_IO_common.c)


 

그림 7.26 SaveData() 함수의 선언(L007_Data_IO_common.h)


 

그림 7.27 Save Data File

 

그림 7.28 저장된 data

 

10. 데이터 파일을 불러와서 그래프에 표시하기
이제 저장된 데이터를불러와서 그래프에 표시하는 기능입니다. SaveData() 함수를 참고로 OpenData()함수를작성하면 쉽습니다. 그리고 cmdSave()콜백 함수를 참고하여, cmdOpen() 콜백 함수를작성하면 됩니다.


그림 7.29 OpenData() 함수 정의(L007_Data_IO_common.c)

 

그림 7.30 cmdOpen() 콜백 함수 정의(L007_Data_IO.c)

 

그림 7.31 OpenData() 함수의 선언(L007_Data_IO_common.h)


그림 7.32 Open 버튼을 눌러 Load할 데이터 파일 선택

 

그림 7.33 데이터를 불러와서 그래프로 보여줌

 

11. 메뉴 콜백 정의
이제는 명령 버튼으로 실행된 기능을 메뉴 콜백함수에다가지정하도록 하겠습니다. 해당 메뉴 콜백함수도 버튼의 콜백 함수와 같은 소스 코드를넣어도 되겠지만, 좀 비합리적인 방법입니다. 메뉴를 선택하면 해당 버튼의 콜백함수를호출하도록 하면 간단합니다. 그림 7.34에 메뉴 콜백함수를 보였습니다.


그림 7.34 메뉴 콜백함수에서 버튼의 콜백함수를 호출


이 과정에 컴파일을 하게 되면, NULL이 선언되어 있지 않다는 엄살 메시지를 띄우는군요.
그러면,그 파일의 첫부분에
#include <ansi_c.h>
를 추가해 주세요.

 

이제 프로그램이 어느 정도 갖추어졌군요. 하지만 완벽하지는 않습니다. 좀더완벽하게 만드는 것은 연습문제로 드리도록 하고, 오늘의 강좌를 다시 정리해보겠습니다.

주된 목표는 데이터 파일을 저장하고, 다시 불러와서 그래프에보여주는 것이었습니다.
그리고 메뉴의 활용에 대해서도 예를 보였습니다.
 

연습문제를 드리겠습니다.

연습문제
1.메뉴의 Add Noise 기능은 잘못된 것입니다. 바로 잡아 보세요.
원래는 AddNoise 메뉴를 선택하면 그 메뉴 앞에 체크 표시를 하고, 한번 더 그 메뉴를 선택하면체크가 없어지는 것을 생각했었는데, 딴데로 빠졌습니다. 그와 동시에 체크 박스의체크도 연동되어야겠지요.
힌트요? 헤헤
GetMenuBarAttribute (, , ATTR_CHECKED,);
SetMenuBarAttribute (, , ATTR_CHECKED, );
함수들을 이용하면 될 것 같군요.
 

2. 이번에는 조금 어려운건데요, 데이터 파일에다가 주기와 진폭, 그리고 Noise추가 여부 정보도 함께 저장해 두었다가, 불러왔을 때, 해당 컨트롤을 세팅할 수있도록 해보세요.
그러니까, 그림 7.33에는 신호발생 파라미터 정보와 그래프의그림이 맞지 않잖습니까? 불러왔을 때에도 그 파라미터가 제대로 될 수 있도록 해보세요.
이번문제는 힌트가 없습니다. 왜냐하면 말이죠, 이건 CVI의 기능을 알아야되는 것이 아니고,순전히 C 프로그래밍 테크닉이기 때문입니다. 저장형식은 여러분들이 나름대로 결정해보세요.좀더 융통성이 있는 형식을 정의할 수 있는 능력을 키우세요.

 

강좌에서 실수한 걸 갖고 연습문제를 만들다니,.... 이렇게 생각하지 마시고,역경을 발전의 기회로 만들어 보시기 바랍니다.


박주성

2004.09.03 16:14:57
*.193.173.146

강좌 잘보고 있습니다.
따라하는데도 오래 걸리네요..
ㅎㅎ

고기원

2005.01.26 17:36:25
*.102.206.218

아.. 연습문제 1번 잘 안풀리네요.. ㅡㅡ;
SetMenuBarAttribute함수를 사용해도 메뉴앞에 체크도 안되고요...
체크박스랑 연동하는것도 잘 안되네요...
오히려 2번문제가 쉬운듯한데...
힌트 좀더 주시면 안되나요... 이틀째 머리싸매고 있는중.. ㅡㅡ;

강상욱

2005.02.07 18:59:49
*.48.44.68

연습문제1번 답:

void CVICALLBACK menuAddNoise (int menuBar, int menuItem, void *callbackData,
int panel)
{
int chkmark;
GetMenuBarAttribute (menuBar, DATA_IO_RUN_ADD_NOISE, ATTR_CHECKED, &chkmark);
if (chkmark==0)
{
SetMenuBarAttribute (menuBar, DATA_IO_RUN_ADD_NOISE, ATTR_CHECKED, 1);
SetCtrlVal (panelHandle, PANEL_CHECK, 1);
}
else
{
SetMenuBarAttribute (menuBar, DATA_IO_RUN_ADD_NOISE, ATTR_CHECKED, 0);
SetCtrlVal (panelHandle, PANEL_CHECK, 0);

}
check(0,0,EVENT_COMMIT,NULL,0,0);
}

유용혁

2005.03.11 09:38:32
*.240.25.16

GetCtrlAttribute (panelHandle, PANEL_chkAddNoise, ATTR_CTRL_VAL, &chkNoise);
// GetCtrlVal (panelHandle, PANEL_chkAddNoise, &chkNoise);

if(chkNoise)
SetCtrlAttribute (panelHandle, PANEL_chkAddNoise, ATTR_CTRL_VAL, 0);
else
SetCtrlAttribute (panelHandle, PANEL_chkAddNoise, ATTR_CTRL_VAL, 1);

허창원님이 힌트로 주셨던 거 말고요
GetCtrlAttribute, SetCtrlAttribute 를 사용해서 되네요..^^
열심히 공부하세요..^^

이경수

2005.07.01 16:44:26
*.94.41.89

1번 이렇게 풀면 안될까요??
void CVICALLBACK mnuAdd_noise (int menuBar, int menuItem, void *callbackData,int panel)
{
SetCtrlVal (panelHandle, PANEL_chkAddNoise, !chkNoise);
chkAddNoise(0,0, EVENT_COMMIT, NULL, 0, 0);
}

전지훈

2006.06.02 11:59:27
*.97.148.143

C 초보입니다. 1번문제는 간단했는데;; 제가 실력이 미천한지라 2번은 감이 안오네요 시작을 델파이로 해서 그런지 잘 모르겠습니다. 2번좀 가르쳐 주세요

케이

2006.09.25 16:52:06
*.104.133.155

점점 받아쓰기 수준으로 가는군요...^^;
어쨋든 열심히 하겠습니다. 강의 잘 보았습니다.~

허준

2008.02.17 11:09:09
*.95.164.18

1번 문제 다음과 같이 했습니다.
우선 L007_Data_IO_common.h에 int menuBarHandle;을 선언하고,
L007_Data_IO.c의 main함수안에
if ((menuBarHandle = LoadMenuBar (panelHandle, "L007_Data_IO.uir", PANEL)) < 0)
return -1;
을 추가하고, chkAddNoise함수와 mnuAdd_Noise 함수를 다음과 같이 변경합니다.
int CVICALLBACK chkAddNoise (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
int chkMark;
switch (event)
{
case EVENT_COMMIT:
GetCtrlVal (panelHandle, PANEL_chkAddNoise, &chkNoise);


if (chkNoise) {
SetMenuBarAttribute (menuBarHandle, DATA_IO_Run_Add_noise, ATTR_CHECKED, 1);

}
else {
SetMenuBarAttribute (menuBarHandle, DATA_IO_Run_Add_noise, ATTR_CHECKED, 0);

}

Generate_sin_data();
Refresh_Graph();
break;

case EVENT_RIGHT_CLICK:

break;
}
return 0;
}
void CVICALLBACK mnuAdd_Noise (int menuBar, int menuItem, void *callbackData,
int panel)
{
int chkMark;
//SetCtrlVal (panelHandle, PANEL_menuHandle, menuBar);
GetMenuBarAttribute (menuBar, DATA_IO_Run_Add_noise, ATTR_CHECKED, &chkMark);

if (chkMark) {
//SetMenuBarAttribute (menuBar, DATA_IO_Run_Add_noise, ATTR_CHECKED, 0);
SetCtrlVal (panelHandle, PANEL_chkAddNoise, 0);
}
else {
//SetMenuBarAttribute (menuBar, DATA_IO_Run_Add_noise, ATTR_CHECKED, 1);
SetCtrlVal (panelHandle, PANEL_chkAddNoise, 1);
}

chkAddNoise (0,0, EVENT_COMMIT, NULL, 0, 0);
}

동헌

2008.04.24 12:26:15
*.165.73.254

강좌의 제일 마지막글이 너무 재밌습니다. ㅎㅎㅎㅎㅎㅎㅎㅎ
갑자기 급공감이 되네요 ㅋㅋㅋ 농담~~~입니다

동헌

2008.04.25 11:01:58
*.165.73.254

간단하게 풀어봤습니다. 잔머리로 -.-
1번.
int chkmark=0;
GetMenuBarAttribute (menuBar, MENUBAR_Run_Add_Noise, ATTR_CHECKED, &chkmark);

if(chkmark==0)
{
SetMenuBarAttribute (menuBar, MENUBAR_Run_Add_Noise, ATTR_CHECKED, 1); //메뉴바의 값설정한뒤
SetCtrlVal (panelHandle, PANEL_chkAddNoise, 1); //패널에 값설정
GetCtrlVal(panelHandle, PANEL_chkAddNoise, &chkNoise); //패널값가져와서
Generate_sin_data( ); //파형만들고
Refresh_Graph( ); //출력
}
else
{
SetMenuBarAttribute (menuBar, MENUBAR_Run_Add_Noise, ATTR_CHECKED, 0);
SetCtrlVal (panelHandle, PANEL_chkAddNoise, 0);
GetCtrlVal(panelHandle, PANEL_chkAddNoise, &chkNoise);
Generate_sin_data( );
Refresh_Graph( );
}

메뉴바 값체크만 해주면 되겠죠.

2번.
차례로 주기, 진폭, 노이즈체크여부를 저장합니다. 그뒤 바로 데이터 저장

먼저 저장부분
fprintf(fp,"%lf\n",T);
fprintf(fp,"%lf\n",Amp);
fprintf(fp,"%lf\n",(double)chkNoise); 이걸 첨부 하면 끝

불러와서 데이터빼내고 차례로 주기,진폭,노이즈여부를 컨트롤에 대입
if((fp=fopen(filename,"rb")) !=NULL)
{

for(index=0; index<NUM+3; index++)
{ if(fscanf(fp,"%lf",&val)==EOF)
break;
Temp[index]=val;
}
fclose(fp);
ret=1;
}
for(index=0; index<NUM; index++)
Real_data[index]=Temp[index+3];

SetCtrlVal (panelHandle, PANEL_numT, Temp[0]);
SetCtrlVal (panelHandle, PANEL_numAmp, Temp[1]);
if (Temp[2]==0)
SetCtrlVal (panelHandle, PANEL_chkAddNoise, 0);
else
SetCtrlVal (panelHandle, PANEL_chkAddNoise, 1);

김중철

2009.03.27 14:06:50
*.67.190.253

허준님의 답이 제일 근접한거 같군요
List of Articles
번호 제목 글쓴이 날짜 조회 수
» [강좌:007] 따라하기 4. 데이터 파일 입출력 및 메뉴의 이용 (2) [11] 허창원 2002-08-05 34327
13 [강좌:007] 따라하기 4. 데이터 파일 입출력 및 메뉴의 이용 (1) [2] 허창원 2002-08-05 25131
12 [강좌:006] 따라하기 3. Timer 컨트롤의 이용 [12] 허창원 2002-07-26 35025
11 [강좌계획] CVI 중장기 강좌 계획 [6] 허창원 2002-07-16 14877
10 [강좌:005-1] GetCtrlVal() 함수의 사용 [2] 허창원 2002-07-10 22150
9 [강좌:005] 따라하기 2. Graph 컨트롤의 사용 [15] 허창원 2002-07-06 38905
8 강좌가 늦어져 대단히 죄송합니다. 허창원 2002-06-29 18578
7 [강좌:004] 따라하기 1. Windows용 Hello, world! [14] 허창원 2002-06-15 32434
6 [강좌:003] CVI 프로그래밍 절차 [11] [1] 허창원 2002-06-08 30110
5 [강좌:002] 콘솔 프로그램 작성 [17] 허창원 2002-06-08 35502
4 [강좌:001] LabWindows/CVI 평가판 받기 허창원 2002-06-08 19730
3 강좌 계획 및 리스트 정리 허창원 2002-06-01 14267
2 LabWindows/CVI 강좌를 시작하며... [7] 허창원 2002-06-01 19396
1 LabWindows/CVI와 LabVIEW의 차이 [1] 허창원 2002-05-27 19207