건전 융자란 무엇인지 알려 주마!

앞의 글에 이어 오늘은 집을 살 때 은행대출을 끼고 사는 것이 과연 합리적인 것인지 얘기해 보겠습니다.

1.  은행융자를 끼고 집을 살 때의 투자가치

먼저 융자끼고 사는 집의 자본이득률을 먼저 계산해 봅시다. 이전 글에서 밝혔듯이 자본이득률은 실수익/실투자액입니다. 실투자액, 소위 '총알'은 집값에서 전세보증금과 은행대출액을 뺀 것입니다. 그리고 분자의 실수익부분은 집값상승분에서 대출이자를 빼줘야 합니다. 즉,

실투자액 = 집값 - 전세보증금 - 대출액 = H - D - L
실수익 = 집값상승분 - 대출이자 = H*ra - L*rl
투자수익률 = 실수익/실투자액 = (H*ra - L*rl) / (H-D-L)

이제부터 다소 어려워지는데 너무 어렵다 생각하시면 수식 부분은 생략하고 결과 설명만 보시면 됩니다. 일단 위 식을 대출금(L)에 대해 미분해 보겠습니다. 항상 양수인 분모 부분은 생략하고 분자만 나타냅니다.

dr/dL = H * (ra - rl) + D * rl

왜 미분을 하느냐 하면 대출이 수익률에 도움이 되는 건지 아닌지 판단할 수 있기 때문입니다. 미분값이 0보다 커지면 대출을 통해 수익률이 높아진다는 얘기고, 미분값이 0보다 작아지면 대출이자 때문에 수익률이 오히려 낮아진다는 얘기입니다. 일단 미분 결과값에서 L이 사라져 버렸습니다. 그 의미는 투자율을 극대화 할 수 있는 최적의 대출금 규모라는 것은 존재하지 않고, 시장조건에 따라 대출이 투자수익률을 높이는 약이 되거나, 반대로 독이 되거나 둘 중 하나가 된다는 겁니다.

2. 대출이 투자에 약이 되는 경우

위의 식에서 미분값이 0보다 커지는 조건을 정리하면 다음과 같이 됩니다.

ra / rl > 1 - D/H

아싸, 이전 글에서 봤던 전세가비율(D/H)이 다시 나왔군요! 반갑네요. 인사 한번 해줍니다. (^_^)/ 방가~
자.. 이제 그 의미를 살펴봅니다. 일단 전세가 비율(D/H)을 대략 0.5로 놓고, 집값상승률을 2%로 놓고 봅시다. 그러면 위 식은 이렇게 정리됩니다.

2% / rl > 1- 0.5   ====>  rl < 4%

집값상승률이 연 2%로 예상되고, 전세가 비율이 50%인 집을 융자끼고 사는 경우에는 대출이자가 4%보다 작아야 수익률에 도움이 된다는 뜻입니다. 대출이자가 4%보다 커지면 수익률을 까먹는 독이 됩니다. 그럼 실질적인 몇 가지 시나리오에 대해 계산을 해 볼까요? (표가 잘 안 올라가네요.. 그냥 텍스트로 올립니다.)

집값상승률(ra)    2%                3%                4% 
전세금비율(D/H) 0.4   0.5   0.6   0.4   0.5   0.6 0.4    0.5    0.6
임계대출이율(rl) 3.3% 4.0% 5.0% 5.0% 6.0% 7.5% 6.7% 8.0% 10.0%

 집값상승률이 높고, 전세값비율이 높을 때는 높은 대출이율에도 불구하고 투자수익률에 도움이 됩니다. 하지만 그 반대의 경우 요즘처럼 집값상승률이 계속 마이너스로 간다면 대출은 항상 독이 되게 되어 있습니다. 집을 사실 때는 여러분께서 사시고자 하는 집의 전세가 비율, 집값상승률 기대값 그리고 대출이자를 위의 식에 넣고 비교해서 대출을 받아 집을 사는 것이 정말로 다탕한 선택인지 반드시 따져 보셔야 합니다.

3. 자가주택에서 융자의 중요성

이전 글에서 자가주택을 사는 거랑, 전세 살면서 전세끼고 다른 집을 사는 거랑 투자 면에서 차이가 없다고 말씀드렸는데요. 그건 융자가 없을 때 얘기고, 융자라는 면에서는 분명히 차이가 발생합니다. 본인이 사는 자가주택에 대해서는 집값 전체를 담보로 보기 때문에 전세끼고 산 집보다 더 많은 대출을 받을 수 있기 때문이죠. 투자 측면에서는 이걸 굉장히 조심해야 합니다.

전세보증금과 은행융자금은 둘 다 집값을 담보로 하는 대출금입니다. 대출금이 담보액인 집값보다 클 수는 없으므로 실투자액 H-D-L은 항상 0보다 커야 합니다. 즉 다른 세입자가 살고 있는 집을 살 때는 반드시 내 돈이 들어가기 마련입니다. 하지만, 자가주택을 살 경우에는 개념적인 투자수익률 계산에서 실투자액인 H-D-L를 마이너스로 만들 수 있습니다. 다시 말해 순전히 남의 돈으로 투자하는 게 가능해 진다는 거죠. 본인이 살고 있는 집의 전세값이 개념적으로 빠지기 때문입니다. 그렇게 되면 위 수익률 식에서 집값 상승률 (ra)가 마이너스가 되면 오히려 본인의 투자수익률이 높아진다는 역설이 발생합니다. 어찌된 일일까요?

이건 그냥 빌려온 돈을 수학적으로 마이너스로 놓다 보니 발생한 역설이고, 실제로는 남의 돈 빌려서 투자했다가 그 돈 다 날리고, 추가로 투자손실금까지 따따블로 날린다는 뜻입니다. 그러니 융자규모를 정할 때는 적어도 집값과 전세값의 차액 이내에서 빌려야 최악의 경우에도 집 날리고 전세금도 모자라 거리로 나앉는 경우를 피할 수 있는 겁니다.

by stal | 2010/09/16 16:39 | 투자 | 트랙백 | 덧글(0)

집값/전세값 비율에 대한 투자이론적 해석

근2년반 만에 글을 씁니다. 그동안 MBA과정을 수학했고, 회사를 옮겼고, 대만에서 파견근무를 시작했습니다. 재정적으로도 많은 변화가 있어 가진 집 하나를 팔고, 두 개를 새로 샀습니다. 고위험채권에 투자해 큰 손실을 보기도 했습니다. 개인적으로 재테크에 많은 관심을 갖고 실제로 실행하고 있지만 주식에는 손대지 않고 있습니다. 회사일 하면서 주식투자를 병행하기엔 시간관리 면에 무리라고 생각합니다. 양쪽 다 제대로 수행하지 못할 거라 믿고 있죠. 부동산 투자는 회사일 하면서 병행해도 큰 무리가 없기에 여기에 집중하는 편입니다.

최근 집값이 하락추세를 보이기 시작하자 향후 부동산 투자를 어떻게 해야 할 지 여러 가지 주장들이 난무하고 있습니다. 특히 짒값이 곧 폭락할 거란 주장과 아직 상승여력이 남았다는 주장 사이에서 본인의 주택 매도/매수 여부와 그 타이밍을 결정하기 위해 고민하시는 분들이 많은 것 같습니다. 저 역시 향후 투자방향을 결정하기 위해 어느 쪽 주장이 맞는 것인지 상당한 고민을 하고 있는데요. 몇 주일 동안 포털싸이트 Daum의 부동산 토론방에서 진행되는 논란들을 지켜보면서 나름대로 생각을 정리할 수 있었습니다. 저 나름대로 최대한 가치중립적인 시각을 유지하기 위해 노력했습니다. 투자의 성공 여부는 현실을 얼마나 제대로 보고, 미래를 얼마나 제대로 예측하느냐에 달린 것이니까요. 시작합니다.

1. 자가주택과 전세의 전환

많은 분들이 주택 거래를 전세와 매매, 주거와 투자 등 양분적 시각으로 보시는 것 같습니다. 그래서 자가주택 수요와 전세 수요를 대체적인 것으로 인식하고 있죠. 자가주택 수요가 줄어들면 대신 전세수요가 늘어난다고 생각합니다. 하지만 엄밀히 재무적인 시각에서 보면 자가주택은 "내 집에 전세 사는 것"입니다.

예를 들어 어떤 가구가 2억짜리 A아파트 101호에 자가주택으로 산다고 합시다. 이 아파트의 전세가는 1억이라 합시다. 이 가구가 101호를 전세 주고, 그 돈으로 구조와 시세가 완전히 동일한 102호에 전세를 살기로 했습니다. 당연한 얘기지만 이렇게 이사를 하든 안 하든 개인적 측면에서 재무적으로 변하는 건 하나도 없습니다. 102호 집값이 오르는 만큼 101호도 오르는 것이고, 102호 전세값이 오르면 똑같이 101호 올려받아서 주면 됩니다. 이 거래는 전체 시장에 대해서도 영향력이 전혀 없습니다. 전세집 하나가 공급되고 대신 하나가 소멸한 것이니까요. 즉, 자가주택에 산다는 것은 그 집 전세주고, 다른 집에 전세사는 것과 완전히 등가입니다. 이 때 소유한 집은 순전히 투자적 의미를 갖고, 전세로 사는 집은 순전히 주거적 의미를 갖습니다.

자.. 그럼 자가주택을 사고자 하는 사람이 줄어들고, 모두 전세만 찾는다고 하면 그게 정말로 전세수요가 늘어난 걸까요? 앞에서 설명한 대로 자가주택 수요라는 것은 본질적으로 자기가 살고자 하는 전세집을 하나 구함과 동시에 전세끼고 투자할 다른 집을 하나 구하는 것과 완전히 등가입니다. 자가주택을 사려던 사람이 전세를 살기로 했다는 것은 '전세끼고 투자할 다른 집'만을 포기한 것이죠. 따라서 시장 전체의 전세 수요에는 아무런 영향을 주지 않습니다. 최근 전세값이 상승하는 이유는 집값 하락 때문에 전세살려는 사람이 늘어서가 아니고 전혀 다른 이유에서라는 뜻이죠.

2. 주택의 투자적 가치

모두들 아시다시피 전세는 순전히 주거적 목적만을 갖고 있어 향후 집값이 오르던 내리던 그 집에 살고 있는 세입자는 전혀 신경쓰지 않습니다. 본인이 그 집을 살 생각이 있거나, 집의 담보력이 떨어져 전세보증금을 떼일 우려가 없다면 말이죠. 전세값을 결정하는 것은 집값의 미래전망이 아니라 순전히 현재 시점에서의 수요/공급량입니다. 그럼 집값은 어떻게 결정될까요? 당연히 미래가치 즉, 투자가치가 반영되겠죠. 그런데 그걸 어떻게 정량화할 수 있을까요? 앞서 설명한 대로 자가주택에 대한 순수한 투자가치는 '내가 살고 있는 전세집'이 아니라 '전세끼고 투자한 다른 집'을 보고 계산하여야 합니다. 이제 하나하나 풀어가 봅시다.

집에 투자한 이득은 크게 자본이득율과 임대수익률로 구분할 수 있습니다. 자본이득률은 실투자액 대비 집값의 상승분이 됩니다. 그리고 임대수익률은 실투자비 대비 연간 월세수익을 뜻합니다. 은행융자 없이 자기자본만 들였다고 가정하고, 세금 및 거래수수료를 제외하면 각 수익률은 다음과 같은 식으로 나타낼 수 있습니다.

자본이득률 = 집값 * 연간집값상승률 / (집값-임차보증금) = H * ra / (H - D)
임대수익률 = (시장전세가 - 임차보증금) * 전월세전환비율 * 12개월 / (집값-임차보증금) = (Do - D) * rd * 12 / (H-D)
총수익률 = 자본이득률 + 임대수익률 = [H * ra + (Do-D)*rd*12]/(H-D)

두번째 식이 조금 복잡해 보이니 설명이 좀 필요하겠네요. 월세 거래해 보신 분을 아시겠지만 월세는 전세가를 기준으로 합니다. 전세가가 1억인 집을 구하면서 보증금이 9천밖에 없으면 그 차액인 1천만원에 대해 그 1%인 월10만원을 내는 식이죠. 만일 보증금이 3천만원 밖에 없다면 그 차액인 7천만원에 대한 이자로서 70만원의 월세를 내게 됩니다. 이 때 1%가 전월세전환비율인데 지역에 따라 그 값이 다릅니다. 부동산114에 따르면 2009년 전국평균은 0.87%라고 합니다.

3. 순수 전세일 경우

순수 전세의 경우 임대수익률을 무시하고, 자본수익률만 보면 됩니다. 따라서 주택구매의 기대수익률 r은 다음과 같이 나타낼 수 있습니다.

r = H * ra / (H-D)

위 식의 분자, 분모를 H로 나누어 다시 정리하면 이렇게 나타낼 수 있지요.

r = ra / ( 1 - D/H )

이 식이 중요한 식입니다. 이제부터 그 의미를 음미해 보도록 하겠습니다. 먼저 연간집값상승률(ra)에 관한 신문기사를 하나 보죠.

----------------------------------------------------------------------------------------------------

작년 집값상승률 대전.부산 최고..서울 5위

by stal | 2010/09/15 20:15 | 투자 | 트랙백 | 덧글(3)

떠돌이 인생

4년간의 외국생활을 마치고 한국으로 돌아왔습니다. 공돌이가 돌아온 곳은 역시 공장이네요. 이번엔 품질 업무를 하게 되었습니다. 매번 그렇듯 이사짐 보내고 받고, 새로운 사람들과 인사하고, 새 업무에 적응해 나가고 있습니다. 제 인생에는 이사가 정말 많았습니다. 언젠가 한번 어디다 써서 세보려고 했는데 오늘 한번 해 보죠.

1. 서울출생: 시골 내려가기 전에도 서울 안에서 몇 번인가 이사다녔다고 하는데 제가 기억 못하니까 그냥 하나로만 칩니다.
2. 경북 문경군 산북면 - 가좌목: 아버님 고향입니다. 부모님이 누에농사짓던 기억이 납니다.
3. 산북면 - 시장 생선가게 뒷집: 어머님이 동지라고 팥죽을 끓여주시던 기억
4. 산북면 - 초등학교 옆집: 눈사람 만들던 기억
5. 산북면 - 교회 옆집: 집 앞 개울에서 우리 형 포함해서 동네 형들이랑 가재 잡던 기억
6. 산북면 - 오매기: 초등학교 입학
7. 가은읍 - 학교옆: 초등학교 2학년, 이 집에서 홍역을 앓았습니다.
8. 가은읍 - 탄광촌: 여기서 '오시오상회'(구멍가게)를 했지요.
9. 가은읍 - 읍사무소옆: 집 앞뒤로 개울과 산이 있었습니다. 염소, 개, 토끼도 키웠죠.
10. 서울 신길동 - 교회옆: 초등학교 4학년
11. 신길동 - 언덕 위집: 초등학교 5학년
12. 신길동 - '태양의 집' 근처 가게집: 초등학교 6학년
13. 신길동 - 가게/집 분리: 중1
14. 화곡동 - 헌책방옆: 중2-대2. 제 인생에서 가장 오래 산 집이네요. 7년?
15. 화곡동 - 연립 2층: 대2-3
16. 화곡동 - 언덕위: 대-석사-취직. 이 집도 꽤 오래 살았습니다. 4년? 5년?

취직 후부터는 부모님의 필요가 아닌 제 자신의 필요에 의해 옮겨다닌거죠.

17. 수원 기숙사: 한 6개월. 95년
18. 구미 기숙사: 2년. 96-97년
19. 구미 전세: 2년. 97-98년
10. 수원 매탄동: 2년. 99-2000년
21. 호주 Perth - Nedland: 6개월
22. 호주 Perth - Victoria Park: 1년
23. 수원 영통동: 2년반. 2001.10-2004.3.

결혼 2003.12. 이직 2004.3

24. 일본 우쯔노미야: 10개월. 2004.3-2004.12
25. 일본 가와사키: 8개월. 2005.1-2005.8
26. 대만 타이빼이: 2년반. 2005-2008.1
27. 울산 굴화리 강변그린빌: 26개월. 2008.2-2010.4
28. 대만 신죽: 2010.5- (업데이트 2010년 9월 16일)

만 37세가 되는 동안 27곳에 살았으니 장소당 평균 1.4년 살았네요. (업데이트 2010.9월. 만39세/28곳 = 평균 1.4년 동일) 
그동안 제가 탓던 제 소유의 차도 한번 세어 봅니다.

1. 엑셀: 95년
2. 캐피탈: 99년
3. 소나타: 2000년
4. 토요타 코로나: 2000년 2nd car
5. 캐피탈: 2001년
6. 에스페로: 2003년
7. 닛산 마치: 2004년. 렌탈 7개월
8. 닛산 티아나: 2005년. 리스 2년5개월
9. 카스타: 2008년
10. 닛산 티나: 2010년(업데이트)

95년부터 13년동안 9대(2010년 15년 동안 10대)를 탓네요. 제 의지이던 아니던 간에 평균 1.4년당 한번씩 집도 바꾸고, 차도 바꾸고 살아왔네요. 이제는 이사와 이동이 너무 익숙해져서 한 곳에서 같은 일을 2년 넘게 하면 지겹게 느껴집니다. 대만에서 돌아온 것도 그런 이유가 좀 있었죠.

인생이 여행입니다. 낯선 곳에 가고, 그곳을 탐험하고, 익숙해질만 하면 떠나고... 그렇게 살아왔고 앞으로도 그렇게 살겠지요. 그동안은 어딘가 새로운 곳에 가는게 신나는 일이었는데 이제는 왠지 좀 서글프네요. 나이가 들었나봅니다. 추가: 그러고도 또 대만으로 파견근무 나온 걸 보면 전 확실히 역마살이 있는 것 같습니다.

by stal | 2008/04/12 02:01 | 트랙백 | 덧글(3)

세리아 CMP의 선택비 조절 메카니즘

CMP(chemical mechanical planarization)라는 공정은 램/CPU 등의 다층 고집적 회로를 만드는 반도체 공정 중 하나입니다. 고집적 반도체는 여러 개의 박막층으로 이루어지는데, 각 층을 만들 때마다 여기저기 울퉁불퉁해지기 때문에 다음 층을 올리기 전에 평평하게 연마해 줍니다. 이걸 CMP라고 합니다. 근데 각 층의 두께가 끽해야 수 미크론에 불과하기 때문에 이걸 깍는 연마재의 입경은 겨우 0.1-0.2 미크론 단위입니다. 그리고 기껏 만든 막을 몽땅 깍어버리면 안 되기 때문에 막이 평평해지고 나면 더이상 깍이지 않도록 해주는 메커니즘이 있어야 합니다. 그 중 한 가지 방법이 아래 층의 물질이 노출되면 연마가 진행되지 않도록 하는 겁니다. 특정물질에 선택적으로 흡착하는 계면활성제를 연마액에 넣어놓으면, 연마가 진행되어 해당 물질이 노출되었을 때 그 표면을 계면활성제가 보호하여 더 이상 연마가 진행되지 않도록 할 수 있습니다. 이 방법은 세리아(산화세륨) 연마제를 이용하는 STI(shallow trench insulation) CMP에도 이용됩니다. 그런데 특정 계면활성제가 왜 특정 조건(ph 및 농도)에서 최적의 선택비(연마속도 비율)를 갖는 지에 대한 이론적인 근거가 좀 빈약합니다. 이제부터 하려는 얘기는 흡착이 왜 일어나는지, 그리고 어떤 조건에서 가장 강한 흡착이 일어나 연마속도비(산화실리콘 vs 산화질소)를 최대로 만들 수 있는지에 관한 것입니다.

1. 이론

1.1. Langmuir Isotherm
LI이론은 고체표면 상의 기체분자 흡착을 정량적으로 설명하는 이론으로서 대부분의 물리화학 개론서에 소개되어 있는 기초이론이다(참조: P.W. Atkins, Physical Chemistry 6th ed., pp 858-861). 이 이론은 다음과 같은 세 가지 가정을 만족하는 경우 적용이 가능하다.

1. Adsorption cannot proceed beyond monolayer coverage.
   흡착은 단층막 이상으로 진행되지 않는다.
2. All sites are equivalent and the surface is uniform(that is, the surface
   is perfectly flat on a microscopic scale).
   모든 흡착사이트는 동등하며, 표면은 균일하다(미세스케일에서 표면은
   완벽하게 평탄하다).
3. The ability of a molecule to adsorb at a given site is independent of
    the occupation of neighbouring sites.
   특정사이트에 흡착이 일어나는 것은 이웃한 사이트의 흡착여부에
   대한 영향을 받지 않는다.

표면상의 흡착은 다음과 같은 동적평형에 의해 그 흡착율이 결정된다.

A(g) + M(surface) = AM(surface) 
정반응 속도상수: ka
역반응 속도상수: kd
평형상수: K = ka/kd

흡착가능한 싸이트의 개수를 N이라 할 때, 표면의 커버리지(θ) 증가속도는 흡착기체의 분압(p) 및 vacant site의 개수인 N(1-θ)에 비례한다. 반면, 탈착에 의한 커버리지 감소속도는 흡착된 사이트의 개수Nθ에 비례하므로,
dθ/dt = ka×p×N×(1-θ) -kd×N×(1-θ)

동적평형이 이루어지면 커버리지의 변화가 제로가 되므로, 위 식의 좌변을 0으로 놓고 정리하면 다음과 같은 Lanmuir isotherm을 얻을 수 있다. 고체-기체의 경우,

 

위 식에서 흡착기체 분압을 선택비 약액(additive)의 농도(c)로 대체하면 선택비 약액의 커버리지를 얻을 수 있다. 즉, 고체-액체의 경우,
1.2. 대전된 표면에서의 평형상수

액상과 접촉한 고체표면은 hydration/dehydration 등에 의해 표면전위(제타전위)를 갖게 되므로 이를 고려하여야 한다. 단위전하(e)의 제타전위(E)에 의한 포텐셜에너지는 e*E로 나타낼 수 있으며, 이 경우 포텐셜에너지에 의한 볼쯔만 분포(Boltzmann distribution)항인 exp(-zeE/kT)을 K에 다음과 같이 반영할 수 있다.

Ko: 표면전위가 0일 경우의 평형상수
z: 흡착분자의 유효전하량(effective charge)
eE: 표면전위(제타전위)에 의한 단위전하의 포텐셜에너지
kT: 열에너지

위 식에서 z는 선택비를 나타내도록 하는 계면활성제의 각 분자의 평균적인 유효전하량을 나타내는 수치이다. 하나의 -COOH기를 갖는 단분자 유기산의 경우 명백히 z=1이 되나, 선택비 약액에 주로 사용되는 고분자 계면활성제는 단위 분자에 여러 개의 -COOH기를 가지므로 z는 대개 2 이상의 값을 갖는다. 고분자의 경우 z를 결정하는 것은 해리도 뿐만 아니라 크기효과도 있다. 즉, 단위분자가 4개의 이온화된 카르복실기를 갖는다 하더라도 흡착표면의 반대쪽에 있는 그룹은 온전한 -eE의 포텐셜에너지를 갖지 못하므로 z는 다소 낮아진다. z는 단위분자에 해리도가 높은 functional group을 많이 가진 물질일수록 큰 값을 갖는다. 이후 논의에서 z값의 크기에 따라 선택비 효과가 확연히 차이남을 볼 수 있다. 한편 Ko는 표면전위가 제로일 경우의 평형상수인데 실제 측정은 어렵고, 계산상으로 결과를 가장 잘 설명하는 값을 임의로 대입하였다. 농도의 단위보정상수로 볼 수도 있다.

1.3. 웨이퍼 연마속도

연마속도가 커버리지θ와 선형적인 비례관계가 있다고 가정하면, 계면활성제가 흡착되지 않은 표면의 연마속도를 Ru, 흡착된 표면의 연마속도를 Rc라 할 때, 연마속도 RR은 다음과 같이 나타낼 수 있다.

이 식에 LI식을 대입하고, K를 보정하면 연마속도를 다음과 같이 정량적으로 얻을 수 있다.

이것이 Langmuir Isotherm 적용모델의 연마속도식이다.

1.4. 계산의 편의를 위한 가정 및 approximation

- STI CMP에 있어 oxide와 nitride의 특성은 표면전위 이외에는 완전히 동일하다. 즉, oxide와 nitride의 Ko, Ru, Rc는 동일하다.

- abrasive입자는 pH 및 additive 함량/종류에 관계없이 동일한 분산상태를 유지하며, additive와의 상호작용(흡착)을 하지 않는다. 즉, c는 pH 및 제타전위에 대해 독립변수이다.

- additive분자의 유효전하량은 pH 및 농도영향을 받지 않는다. 즉, z는 constant이다. 이 가정은 낮은 pH에서 고분자 내 카르복실기의 해리도가 낮아지므로 유효하지 않게 되는데 필요시 pH에 따른 유효전하량 변화를 고려해 계산할 수 있다.

1.5. 상수의 결정

Ru: 선택비 약액을 첨가하지 않았을 때의 연마속도. oxide 최대연마속도인 5000Å/min 대입.
Rc: 완전한 coverage가 일어났을 경우의 연마속도. additive 첨가시 nitride연마속도 90Å/min
c: 선택비 약액의 농도는 abrasive함량(1wt%)에 대한 비율로 나타내었음. 퍼센트 단위.
e/kT: e=1.60E-19 C, k=1.38E-23 JK-1, 연마시 슬러리 온도 50℃ ⇒ 0.03594/mV
Ko: RR vs c 관계로부터 유추. 5.0 %-1 대입.
E: pH별 oxide, nitride 제타전위 측정 및 대입.


2. 모델 적용 계산 결과

2.1. additive의 종류에 따른 연마특성 영향
다음은 60% 동일농도에서 additive의 유효전하 z값을 -2, -3, -4로 대입하였을 때 나타나는 coverage, 연마속도, 선택비의 변화를 나타낸 것이다.
그래프에서 볼 수 있는 바와 같이 z값의 변화에 따른 nitride의 커버리지는 큰 변화가 없는 반면 oxide의 커버리지는 급격히 변한다. 그 이유는 oxide 및 nitride표면에 계면활성제가 흡착되었을 때의 포테션에너지 차이가 z값이 클수록 확실히 벌어지기 때문이다. 결과적으로 z값이 큰 물질은 oxide표면에는 붙지 않고, nitride표면에만 붙기 때문에 높은 oxide연마속도와 선택비를 나타내게 된다.

한편, 최대의 선택비를 나타내는 pH는 z값에 따라 조금씩 달라지는데 z=-2일 때 pH7, z=-3일때 pH6.5, z=-4일때 pH5.5와 같이 z가 커질수록 낮은 pH에서 최대선택비를 나타낸다.

2.2. 농도영향

다음 그래프는 pH7에서 농도에 따른 연마특성 변화를 z값 별로 나타낸 것이다.

그래프에서 볼 수 있는 바와 같이 선택비 약액은 특정농도에서 최대값을 가지며, 그 이상의 농도를 사용하면 oxide연마속도가 감소되어 선택비가 감소하게 된다. z값이 클수록 최대값을 나타내는 함량은 커지게 된다. 그러나, 이것은 최적농도의 위치를 나타내는 것일뿐 z값이 클수록 동일농도에서 더 높은 선택비와 연마속도를 가진다는 것에 주의할 필요가 있다.

한편, pH에 따라서도 최적농도는 변하게 되는데 다음은 z=-4일 때의 pH별 농도영향을 나타낸 것이다.

위 그래프로부터 pH가 낮을수록 적은 양의 약액만으로 높은 선택비를 얻을 수 있음을 볼 수 있다. 특히, pH별로 최고선택비가 나타나는 농도에서의 oxide연마속도를 비교해보면 낮은 pH에서 더 높은 선택비와 연마속도가 나타난다. 그러나, 낮은 pH에서는 약액혼합비율에 따라 급격한 연마속도 변화가 일어나는 단점이 있으므로 정량투입이 중요해진다.

3. 결론
① 표면흡착이론으로부터 세리아 STI CMP 선택비 구현시 고려할 인자별 특성을 설명하는 수학적 모델을 구성하였다.
② 선택비 구현 고분자 계면활성제는 유효전하량이 클수록 연마속도, 선택비 면에서 유리하다.
③ 유효전하량이 큰 물질은 낮은 pH에서 최적의 성능을 나타낸다.
④ 선택비 약액은 특정농도에서 최대의 선택비를 나타내며, 추가투입시 연마속도/선택비가 감소한다.

맺음말

이 이론의 타당성을 검증해 줄 수 있는 실제 실험데이터는 게재하지 않습니다. 이런 재미없는 포스트를 열심히 읽어 줄 사람들은 아무래도 반도체 업계에 계신 분들 뿐일 거 같은데, 아무쪼록 하시는 일에 조금이나마 도움이 되었으면 합니다. 참고로 저는 이미 반도체 업계 떠난지 오래됐습니다.

by stal | 2007/12/16 03:02 | 전자재료/공정 | 트랙백 | 덧글(4)

Torque feedback을 통한 서보 제어

아직은 순전히 아이디어뿐인 개념입니다만 조종자의 행동을 따라하는 로봇제어 메카니즘으로 써먹을 수 있지 않을까 하고 구상하고 있습니다. 제가 하고 싶은 건 서보모터 혹은 엔코더와 결합된 스텝모터 두 개를 가지고 한 쪽의 움직임을 다른 한 쪽이 따라 하게 하는 것입니다. 구체적으로는 두 모터의 위치 차이를 서로 피드백하여 교정하는 방향으로 토크를 가하는 겁니다.

현재 로봇들은 서보(RC servo)모터를 주로 사용하는데, 일정 주파수의 on/off duty ratio로 위치를 제어하는 방식이지요. 자세한 건 생략하고.. 하여튼 RC서보로는 조정하는 사람이 제어신호만 내보낼 뿐, 로봇이 어떤 저항으로 인해 지시한대로 움직이지 못하고 있다는 정보를 받아들이지 못합니다. 굳이 하려면 입력신호(위치, 압력 등)를 별도의 센서를 통해 처리를 해야 합니다. 태권브이가 마징가를 밀어붙일 때, 태권브이가 느끼는 마징가의 힘이 태권브이 조종사 훈이에게 전달되어야 합니다. 근데 그 힘을 센서를 통해 화면에 표시되게 한다? 이건 아니죠. 훈이는 마징가가 얼마나 힘이 센 지 몸으로 느낄 수 있어야 합니다. 즉, 훈이는 만화에서처럼 방처럼 생긴 곳에서 혼자 허공에다 발길질 하는 것이 아니고, 신체의 움직임을 제한하는 어떤 수트가 필요하다는 겁니다.

그러면 그런 수트를 어떻게 구현하느냐... 우선 훈이의 팔 관절에 서보모터를 하나 붙여 보죠. 이 서보모터의 엔코더는 훈이의 팔관절이 지금 몇 도로 구부러져 있는지 측정해 태권브이에게 알려줍니다. 태권브이는 현재 자신의 팔 관절 각도와 비교한 후 모자란 만큼을 움직이기 위해 모터의 토크를 증가시킵니다. 한편 태권브이의 팔관절 모터에도 서보모터 및 엔코더가 붙어있고, 이 엔코더의 신호는 훈이 팔관절에 붙어 있는 모터에 태권브이의 현재 팔 관절 각도에 해당하는 토크를 걸어줍니다. 수식으로 표현하면 다음과 같습니다.

훈이 관절 각도 = xi
태권브이 관절 각도 = xo

훈이 관절 모터 피드백 = a*(xo-xi)    
태권브이 관절 모터 피드백 = b*(xi-xo)    * a, b는 증폭율

이렇게 되면 훈이의 관절과 태권브이의 관절을 입력과 출력을 교차시켜 서로의 관절을 동기화하려는 방향으로 힘이 작용하게 됩니다. 즉, 조종사 훈이는 자기가 팔을 굽힌 만큼 태권브이가 굽히지 못하고 있는 것을, 증가하는 저항을 통해 알 수 있게 되는 거죠. 이렇게 두 개의 서보모터를 동기화하는 방식을 확장하혀 조종사의 수트와 로봇을 동기화하면 조종사의 동작을 로봇이 따라하고, 로봇의 동작저항을 조종사가 느끼도록 할 수 있을 것 같습니다. 근데 만일 위에 제시한 방식으로 완전히 비례(proportional)제어만을 하게 되면, 이건 용수철로 연결된 인형을 조작하는 것과 마찬가지가 되므로 진동이 일어날 수 있습니다. 가능하면 어느 한 쪽 혹은 둘 다 PID제어를 이용하는 편이 좋겠지요.

이상이 공상의 바다에 허우적거리고 있는 스탈의 아이디어입니다. 이런 게 실제로 구현되고 있는지 인터넷에서 대충 검색해 봤는데 아직 찾지 못했습니다. 너무 간단한 아이디어라 어딘가 실제로 이용되고 있을 것 같은데 말이죠...

by stal | 2007/11/08 01:01 | 메카트로닉스 | 트랙백 | 덧글(4)

로봇 격투기

최근의 로봇 연구 결과들에 자극을 많이 받고 있는데요.. 저는 로봇과 전혀 관계없는 일을 하는 사람이지만, 이 분야가 앞으로의 산업을 이끌어갈 중추 중 하나라고 생각하여 관심있게 지켜보고 있습니다. 저는 앞으로 로봇과 관련해 가장 발전할 분야가 로봇 격투기라고 생각합니다. 그렇게 생각하는 이유가 몇 가지 있습니다.

첫째. 인간은 전투본능을 갖고 있습니다.
인간이 만들어낸 수많은 스포츠는 인류가 사냥과 전쟁 등 적자생존 과정 중에 축적한 전투적 본능을 평화적 방법으로 해소하고 있는 것이라고 봅니다. 만일 인간과 같이 움직이는, 비슷하게 생긴 두 휴머노이드 로보트가 있으면 여러분께서는 무슨 일을 시키고 싶습니까? 많은 분들은 저와 마찬가지로 싸움을 붙여보고 싶어할 겁니다. 소, 개, 닭 등 인간이 키우는 대부분의 동물들은 한편으로 싸움을 시켜 구경거리로 삼기도 하지요. 하다못해 벌레들까지 싸움시켜놓고 구경하는 게 인간입니다. 이제 인간을 닮은 5톤짜리 로봇들이 격투기를 한다고 상상해 보죠. 경기장엔 부서진 쇳조각들이 날라다닐 거고, 부러진 팔에서 기름이 흘러나올지도 모르지요. 그러나 다치는 사람은 아무도 없습니다. 다 깨부시라고 응원해도 잔인하다고 비난하는 사람은 아무도 없습니다. 무지 재밌을 것 같지 않습니까?

둘째. 돈이 됩니다.
많은 자동차 회사들이 레이싱카를 만들고 경기를 벌입니다. 싸우는 것도 아닙니다. 그냥 달릴 뿐이지요. 그래도 수많은 사람들이 몰려들어 구경하고, 이 경기를 통해 광고를 유치하고, 돈을 법니다. 혼다, 토요타, 소니, 삼성 등 대기업에서 5톤짜리 로봇들을 만들어서 쌈박질로 누구 기술이 더 대단한지 겨룬다고 합시다. 스포츠단을 운영하듯 기업에서는 이미지 홍보를 위해 돈을 투자할 거고, 일반인들은 이 재미있는 경기를 보고 싶어 할 겁니다. 방송국은 중계를 하면서 광고수익을 얻겠죠. 제 생각에는 이거 되는 장사입니다. 로봇 가격이 너무 비싸 못 할 이유는 없습니다. 휴보는 겨우 1억5천짜리 연구비 만들어 1년만에 만들었다고 하더군요. 개발비가 들어봐야 유명 프로 운동선수들 연봉 정도 밖에 안 될 거고, 로봇 몇 대 깨져나가도 부품값이 많이 드는 건 아니니까요.

세째. 기술은 이미 있습니다.
겨우 몇 년 전 혼다의 아시모가 처음 걸었을 때 그 부드러운 움직임에 세계는 경악했습니다. 요즘은 로봇들이 뛰어다니고, 물구나무를 서도 별로 감흥이 안 옵니다. 근데 이런 휴머노이드 개발해 봐야 당장 써먹을 데가 없습니다. 기업들은 이걸 어디다 써먹을까 고민하고 있지요. 시장을 억지로라도 만들어야 합니다.

저런 이런 여러 이유로 조만간 휴머노이드 로봇 격투가 상용화되어 TV에 중계될 거라고 예상하고 있습니다. 요즘 케이블 TV에 가끔 보이는 페이로더 비스무레한 장난감들은 사실 인간의 전투 본능을 자극해 주지 못합니다. 인간답게 치고 받고 싸워야 제 맛이죠. 근데 전 사실 권투나 격투기 같은 거 별로 안 좋아합니다. 선수들이 불쌍하고, 잔인해 보여서 싫습니다. 하지만 태권브이가 마징가랑 싸우면 아주 재미있게 볼 거 같습니다. 어서 그런 날이 오길 기대해 봅니다.  

by stal | 2007/11/04 15:40 | 메카트로닉스 | 트랙백 | 덧글(0)

엑셀로 curve fitting 하기

전공이 화학이지만 보다 많은 독자에게 도움이 될만한 주제에 대해 글을 쓰다보니 자꾸 컴퓨터 관련된 것만 쓰게 됩니다. 이번 주제는 엑셀을 이용하여 커브 피팅(curve fitting)하기 입니다. 엑셀에 이미 선형함수, 지수로그함수, 다항식 함수 등의 추세선을 수식과 함께 그래프 상에 추가하는 기능이 있고, trend, forcast 등의 함수도 있습니다. 이런 엑셀 내장 기능들이 단순한 형태의 데이터를 피팅하는데 유용하고 대부분의 경우 충분합니다만 때때로 기본으로 제공하지 않는 형태의 함수에 대해 피팅이 필요한 경우가 있습니다. 예를 들어 다음과 같은 지수함수를 한번 생각해 보죠.

y = A*exp(-B/(x-C))   : x=C 일 때 y=0, x=무한대 일때 y=A인 1/x에 대한 지수 감쇄 곡선. 
              온도에 대한 유리의 점도값이 이 함수를 따릅니다. VTF equation이라고도 합니다.

아니면 이런 건 어떨까요?

y = A*(1-exp(-B*(x-C))) : x=무한대 일 때 y=A에 수렴하는 지수 곡선. 
              눈막힘(clogging) 현상이 있을 때, 필터/스크린을 통과하는 분체의 중량이 이 함수를 따릅니다.

이런 건 엑셀 내장 추세선으로는 피팅할 수 없습니다. 커브피팅이 안 된다는 건 실험으로 구한 x,y 데이타가 있어도 특정 지점/시점의 y값을 수학적으로 예측하지 못한다는 뜻이지요. 물론 엑셀이 아닌 오리진이나 매트랩 같은 고급 수학 소프트웨어를 쓰면 되겠지요. 그러나, 저는 15년 가까이 대학원/연구소 생활하면서 그런 소프트웨어 턱턱 사 주는 보스 만나본 적 한번도 없었습니다. 그거 사느라고 기안 올리고, 구매 절차 밟는 것보다 만만한 엑셀을 조지는 게 빠르지요. 엑셀에서 저런 복잡한 형태의 함수를 피팅하는 게 가능하냐구요? 가능합니다.

우선 기본적인 개념을 잡아보죠. 우리가 실험으로 얻는 데이타는 아래와 같이 대개 (xi, yi)의 쌍으로 이루어져 있습니다. 이걸 그래프(분산형)으로 그려보면 우리가 피팅하고자 하는 그래프의 모양이 대충 나오죠.

 
피팅을 하기 위해서는 우선 어떤 곡선에 피팅할 지 y=f(x)의 형태를 모델링을 해야 합니다. 우선 위의 그래프를 척~ 보면 지수적으로 감소하고 있음을 알 수 있습니다. 그럼, 엑셀의 추세선을 쓸 수 있지 않을까요? 한번 해보죠.

피팅이 잘 되었나요? 아닙니다. 실험데이타에서 y는 5 근처의 값으로 수렴하고 있는데, 엑셀은 0으로 수렴하는 것으로 가정하기 때문에 적절한 피팅곡선을 얻을 수 없습니다. 그럼, 실제 곡선은 어떤 형태를 갖고 있을까요? 아마도 이런 형태가 될 듯 싶습니다.

y = A * exp(-B * x) + C

이와 같이 모델은 기초적인 곡선의 형태(지수함수) 및 여러 개의 인자들(A, B, C)로 구성됩니다. 커브피팅은 주어진 실험데이타(xi, yi)에 가장 잘 들어맞는 곡선을 만들기 위한 인자들(A, B, C)의 값을 결정하는 과정을 말합니다. 그럼 A, B, C 값을 임의로 넣어서 피팅 곡선을 만들어 보기로 하죠.

Y_fitting 컬럼은 그 위에 있는 A, B, C 값을 이용해 모델값을 계산한 것입니다. 실험값과 많이 가까워졌죠? A, B, C 값을 수동으로 적절히 조절하면 실험곡선에 꽤 가까운 곡선을 얻을 수 있습니다. 그런데 우리가 원하는 것은 "꽤" 가까운 곡선이 아니고 "가장" 가까운 곡선입니다. 그러기 위해서는 실험값과 모델값이 가까운 정도를 수치로 정량화해야 합니다.

피팅이 잘 들어맞는다는 것은 실험값(yi)과 모델값(y_model)의 차, 즉 sum of error 가 작다는 뜻입니다. 이러한 차이는 (yi-y_model)^2 으로 수치화할 수 있고, 커브피팅은 이 누적오차를 최소화하기 위한 인자들의 값을 결정하는 것이죠. 제곱이 아닌 절대값의 합을 구해 최소화해도 되지만, 제곱을 이용하는 편이 수학적 다루기 편하기 때문에 전통적으로 제곱법(자승법)을 이용해 왔습니다.

엑셀에는 이런 목적으로 사용할 수 있는 sumxmy2라는 함수가 있습니다. 영문 엑셀에서는 함수 설명이 이렇게 나와 있군요. Sums the squares of the differences in two corresponding range or arrays. 한글 엑셀에서의 설명은 직접 찾아 보시기 바랍니다. 이 함수를 이용하여 테이블 맨 밑에 SumErrSqr라는 항목을 하나 넣어봤습니다. 실험값 및 모델값이 B, C 컬럼의 10행에서 20행까지라고 할 때 셀의 수식은 =SUMXMY2(B10:B20,C10:C20)가 됩니다.


 그럼, 이제 우리가 해야 할 일은 SumErrSqr를 최소화시키기 위한 A, B, C 값을 구하는 것입니다. 엑셀에는 이런 문제를 풀어주는 해찾기(Solver, '목표값 찾기'와는 다른 기능입니다)라고 하는 기능이 있습니다. 이 기능은 추가기능(add-in)이라서 평소에는 메뉴에 나타나지 않습니다. 도구(Tools) 메뉴를 열어보면 추가기능...(Add-ins...)라는 항목이 있습니다. 그걸 선택하면 추가할 수 있는 기능목록이 나타나는데 거기서 해찾기(Solver)를 체크하시고 확인(OK) 버튼을 누르시면 설치됩니다. 처음 엑셀을 어떻게 설치했느냐에 따라 인스톨 CD를 요구하는 경우도 있고, 아닌 경우도 있습니다. 설치가 끝나고 나면 도구 메뉴에 [해찾기...] 항목이 나타납니다. 그걸 선택하면 아래와 같은 대화창이 나타납니다. 


목표셀은 SumErrSqr 값을 갖고 있는 셀을 선택합니다. 예제에서는 C21 입니다. 그리고 찾고자 하는 값으로서 최소값을 선택합니다. 마지막으로 변경시킬 셀의 범위로서 A, B, C 값을 담고 있는 셀을 선택합니다. 예제에서는 C5:C7이 되겠네요. 그 다음 실행(Solve) 버튼을 누르면 해찾기 기능이 실행되어 순식간에 새로운 A, B, C 값을 찾아 줍니다. 마지막으로 대화창에 변경된 값을 저장한다고 선택하시면 변경된 A, B, C값 및 그래프를 보실 수 있습니다.


정말로 실험값에 매우 가까운 곡선이 얻어졌죠? 오차제곱합이 43.6에서 0.61으로 줄어들었습니다. 위 예제의 실험값은 실제 데이타가 아니라 A=21, B=0.5, C=4.0 을 대입한 모델함수식에 일부러 +/- 0.5 범위의 랜덤 오차를 더해서 만든 가상의 실험데이타입니다. 피팅을 통해 실제값에 매우 가까운 피팅값이 얻어짐을 확인하실 수 있습니다. 랜덤 오차를 일부러 더하지 않으면 정확한 A, B, C 값을 찾아냅니다. 같은 방법으로 이보다 복잡한 모델함수도 얼마든지 피팅할 수 있습니다.

아래 화일은 위의 예제를 담은 것입니다. 매크로를 하나 넣어 놨는데 새로운 가상 실험데이타를 만들어 주는 것으로서 피팅과는 전혀 관계없으니 개념치 마시기 바랍니다. 피팅은 위에서 설명한 대로 해찾기 기능을 추가하신 후 메뉴에서 실행하시기 바랍니다.

Fitting_Example.xls

이상에서 보신 것처럼 엑셀은 잘만 활용하면 상당한 수준의 수치해석 기법도 수행할 수 있습니다. 분석적 해(analytical solution)을 얻기 어려운 미분방정식도 그래프, 목표값 찾기, 해찾기 등의 기능을 이용하면 대략의 근사값은 얻을 수 있습니다. 거기다가 VBA까지 곁들이면 웬만한 실제 공학문제는 거의 다 다룰 수 있습니다. 아직 사용해 본 적 없는 함수나 메뉴가 있으면 도움말을 띄워 한번 살펴보시기 바랍니다.

by stal | 2007/10/04 01:30 | 메카트로닉스 | 트랙백(1) | 덧글(10)

Generic RS232 Communicator V.05

'엑셀에서 RS232기기 연결/제어하기' 시리즈의 마지막 편으로 Generic RS232 Communicator V.05를 업로드합니다.

Generic_RS232_Communicator_Ver05.xls

이번 버젼은 아래 포스트에서 설명한 Win32Comm을 사용하여 외부 ActiveX 모듈이 필요하지 않습니다. 자세한 내용은 아래의 포스트를 참조하시기 바랍니다. 이번 버젼에서는 01/02 버젼의 간단한 인터페이스를 되살리고, 필요없는 부분은 다 삭제해 버렸습니다. 버튼도 세 개에서 두 개로 줄여버렸습니다. 필요한 부분은 사용자들께서 직접 추가/수정하여 사용하시기 바랍니다. 사용방법은 이전버젼과 대동소이하지만 다시 한번 설명합니다.

1. RS232기기를 케이블을 이용해 PC에 연결합니다. USB-RS232 컨버터를 사용하셔도 됩니다.

2. 엑셀을 띄우고, 화일을 엽니다. 매크로를 사용할 지 묻는 질문에 '예'를 선택해 주세요.

3. Serial Port Settings라고 되어 있는 곳에 통신조건을 기입합니다. Port부분은 COM1~COM4 중 실제로 연결된 포트를 선택하시고, 만일 USB-RS232 컨버터를 사용하셨을 경우에는 컨버터의 설정과 동일한 포트로 지정해야 합니다. 다른 통신조건은 접속하고자 하는 기기에 따라 다르므로 해당 기기의 메뉴얼을 참조하셔서 설정해 주시기 바랍니다.

4. Command & Data Format이라고 되어 있는 부분을 설정합니다. AddToCommand는 보낼 문자열에 붙일 제어문자입니다. 대부분의 기기가 CR, LF 또는 CR+LF를 이용하여 문장이 끝났음을 표시합니다. 어떤 문자를 붙여야 되는지는 해당기기의 메뉴얼을 참조하시기 바랍니다. RemoveCR/LF는 받은 문자열을 그대로 셀에 넣을지 설정하는 곳입니다. 문자열에 섞여들어 온 CR, LF 등의 제어문자을 그대로 셀에 넣어 버리면 기능상의 문제는 없지만 셀높이가 늘어나 엑셀화면이 지저분해집니다.

5. 오른쪽의 Commands라고 써진 컬럼에 기기에 보낼 명령어를 기입합니다. 보낼 명령어는 기기 및 여러분이 하고자 하는 작업에 따라 다르므로 기기 메뉴얼을 참조하세요. 디폴트로 써있는 "Q"는 제가 쓰고 있는 전자저울의 값을 읽어오는 명령어로서 여러분의 기기와는 아무 상관없는 것입니다. 모든 스텝의 명령어가 반드시 같아야 할 필요는 없습니다. 두 가지 동작을 교대로 반복한다던지, 어떤 값을 읽어온 후 엑셀의 if()함수를 써서 다음 스텝의 명령을 결정한다든지 하는 것도 가능합니다.

6. Time(s)라고 써있는 컬럼에 각 스텝의 시작시간을 기입합니다. 시간은 0.1초 단위로 자유로이 설정가능합니다. 기본으로 100 밀리초 주기로 체크하므로 0.1초 이하 단위의 설정을 해도 의미가 없습니다. 1주기 범위 내에서 시간지터(jitter)가 다소 있을 수 있음에 유념하시기 바랍니다. 만일 0.1초 이하의 시간지터나 초고속 처리를 원하시면 매크로 내부의 TIMER_INTERVAL(=100)을 더 작은 값으로 줄이시기 바랍니다. 그래도 윈도우즈 타이머 자체의 지터가 있으므로 정밀도의 한계가 있습니다. 정말 정밀한 시간간격 제어를 원하시면 아예 루프 내에서 GetTickCount() 함수를 이용해 제어하시든지, 외부 모듈을 이용하셔야 할 겁니다.

7. Program Variables의 EndStep은 어느 스텝까지 실행하고 멈출 것인지 결정하는 곳입니다. 적절한 값을 넣으시기 바랍니다. 레코딩이 시작된 후에도 이 값은 변경할 수 있습니다.

모든 설정이 끝나셨으면 [Record] 버튼을 눌러보시기 바랍니다. 포트의 문제가 없으면 스텝컬럼의 색이 바뀌면서 프로그램이 진행하는 것을 보실 수 있습니다. [Record] 버튼을 다시 한번 누르시면 프로그램의 진행이 멈춥니다. 포트를 열 수 없다는 메세지가 뜰 경우, 해당 포트가 존재하지 않거나 아니면 다른 프로그램에서 사용하고 있는 겁니다. 만일 Responses 부분에 아무런 변화가 없으면 기기가 꺼져 있거나, 연결에 문제가 있을 가능성이 높습니다. 읽을 수 없는 쓰레기 값이라도 뭔가 들어오면 연결은 확립된 겁니다. 통신설정이나 제어문자 설정 등이 올바른지 다시 한번 체크해 보세요. 연결은 잘 됐는데 원하는 동작을 하지 않는 경우는 명령을 잘못 설정한 것일테니 메뉴얼을 보고 적절한 명령을 써주시면 됩니다.

받은 데이타의 포맷은 기기에 따라 다릅니다. 가끔은 원하는 데이타(예를 들면 중량) 뿐만 아니라 다른 데이타(시간 등)이 함께 들어오는 경우도 있습니다. 이런 경우 인접한 셀에 필요한 데이타를 추출하는 엑셀함수식(mid, value 등)을 미리 만들어 놓으면 편리합니다. 다량의 데이타가 한꺼번에 들어오는 경우도 있는데, 참고로 엑셀은 한 셀에 8KB의 문자열 밖에 저장하지 못합니다. 그 이상의 데이타는 매크로 레벨에서 처리해 줘야 합니다.

[Clear] 버튼을 누르시면 받아놓은 데이터를 다 지울지 확인하는 메시지가 뜹니다. '예'를 선택하시면 삭 지워버리고, 프로그램 설정을 초기화합니다. 데이터를 저장하시고 싶으시면 웍시트를 하나 더 만들어, 거기다 복사해 저장해 두시면 됩니다.

맺음말

그동안 많은 분들께서 호응해 주시기에 제 전공과 전혀 관계없는 주제에 대해 많은 시간을 할애해 이런저런 업데이트 했습니다만, 점점 재미가 없어지네요. 혹시 이 매크로를 이용하신다면 어떤 용도로 어떻게 사용하시는지 알려주시면 무척 기쁘겠습니다. 저는 일단 RS232는 일단락 짓고 다른 재미있는 걸 찾아볼까 합니다. 제 글을 찾아주신 모든 분들께 감사드립니다.

by stal | 2007/10/03 18:12 | 메카트로닉스 | 트랙백 | 덧글(30)

Win32Comm - RS232 connection module for VBA

ActiveX 방식의 문제점들

그동안 IO Control ActivX 모듈을 써서 RS232 기기와 연결하는 엑셀 매크로 프로그램들을 여러 개 만들어 쓰고 있었습니다. 그런데 이 방식은 엑셀 외부의 모듈을 사용하기 때문에 매크로를 사용하려면 미리 ActiveX 모듈을 설치해야 하고, 경우에 따라서는(다 그런지는 모르겠지만 제 동료들이 쓰는 일본어 윈도우즈 및 일본어 엑셀에서는) 외부 모듈의 참조순서를 바꿔 줘야 하는 등 여러가지 번잡한 문제가 있어서 다른 사람들과 공유해서 쓰는 것이 쉽지 않았습니다. 일일이 직접 설치해 줘야 하고 문제가 생기면 고쳐줘야 했거든요.

최근에 만든 엑셀 매크로 프로그램을 여러 나라(일본, 대만, 미국) 공장 및 실험실에 배포해야 할 일이 생겼는데 위에서 말한 문제 때문에 그대로 배포할 수가 없었습니다. 엑티브엑스 모듈이야 그냥 설치화일 주고 미리 깔으라고 하면 된다지만 외부모듈의 참조순서를 바꿔주는 것은 사용자들한테 직접 하라고 하기가 영 껄끄러운 것이었습니다. 저 자신이 해도 일본어 엑셀이나 중국어 엑셀에서는 메뉴 뒤져가며 고치는 것이 꽤 번잡한 일이었거든요. 사용자들마다 깔려있는 프로그램들이 다르기 때문에 기본순서도 다 다릅니다. 그래서 액티브엑스 방식이 아닌 DLL 방식으로 만들어 공개해 놓은 것이 없는지 찾던 중에 EasyComm을 발견하게 된 겁니다. EasyComm은 외부 모듈을 전혀 사용하지 않고, 윈도우즈 운영체제가 기본적으로 갖고 있는 kernel32.dll 내의 Win32 API만을 이용하여 시리얼 포트를 연결하여 읽고 쓸 수 있게 해 줍니다. 저도 지식이 짧아서 VBA로 Win32 API를 직접 호출할 수 있다는 걸 EasyComm 내부를 뜯어보고 나서야 알게 되었습니다.

API 호출방식

API(Application Programming Interface)라는 것이 뭐냐 하면 운영체제의 여러 기능을 일반 프로그램에서 이용할 수 있도록 열어놓은 통로라고 생각하시면 됩니다. 일반 응용프로그램들은 대개 자신이 열고자 하는 파일이 하드디스크의 몇 번째 섹터에 들어있는지 알 필요가 없습니다. 그냥 운영체제한테 파일이름을 주고 열어달라고 하면 운영체제가 다 알아서 해줍니다. 모든 운영체제는(심지어 도스에서도) 이렇게 일반 프로그램들을 위해 파일 입출력, 화면 입출력, 프로세스 제어, 메모리 관리 등의 서비스를 해 주는데 이를 API라 부르기도 하고, 시스템 호출이라고도 하고, 도스에서는 BIOS(Basic Input Output Service)라고 하기도 했습니다. 윈도우즈95 이후의 32비트 윈도우즈 버젼들은 이런 서비스를 Win32 API라고 통칭합니다. 프로그래머는 자신이 이용하고자 하는 기능을 해주는 API함수를 찾아서 이를 호출하기만 하면 됩니다. C나 베이직 등의 고급언어에서 기본으로 제공하는 화일, 화면제어, 메모리 등의 관련 함수와 기능들도 사실 내부적으로는 대부분 API함수들을 이용하고 있습니다.

그래도 맘에 들지 않는...

VBA로 Win32API를 호출하여 모든 걸 할 수 있다는 걸 알게 된 저는 엄청 기뻤고, 급히 EasyComm 메뉴얼을 번역해 아래의 포스트에 올려놓았습니다. 그런데 막상 EasyComm을 써서 그동안 짜놓은 프로그램들을 바꾸려니 역시 걸리적거리는 것이 있었습니다. 이건 기능의 문제라기 보다는 사실 취향의 문제인데요...

1. 대부분의 기능들이 함수가 아닌 프로퍼티로 되어 있다.
키노시타씨가 왜 함수를 만들지 않고, 프로퍼티만으로 입출력 기능을 구현하려 했는지 잘 모르겠습니다. 프로퍼티는 한번에 단 하나의 입출력만 가능합니다. 필요한 변수들을 한꺼번에 세팅할 수 없기 때문에 귀찮게 여러 줄을 써야 합니다.

2. 에러처리가 번잡하다.
프로퍼티(특히 쓰기 작업)로는 입출력 에러 발생여부를 직접 리턴할 수가 없으므로, 각 입출력 코드 뒤에 에러체크 루틴을 일일이 넣을 수 밖에 없는데 그러면 코드가 아주 더~리해 집니다. 물론 에러 캐치 방식을 써도 됩니다만 다른 나라에서 사용할 수 있도록 일본어(또는 제가 번역해 놓은 한글)로 설정해 놓은 에러코드 및 설명을 일일이 영문으로 바꾸려니 그것도 쉬운 작업이 아닙니다.

3. 내겐 필요없는 기능이 너무 많다.
깔끔하고 간결한 기능를 선호하는 저로서는 주렁주렁 덧붙여진 기능들이 사실 번거롭기만 합니다.

위에 나열한 그다지 중요하지 않는 이유들 때문에 저는 EasyComm을 재구성해서, 제 입맛에 맞게 모든 기능을 함수 형태로 바꾸기로 했습니다. EasyComm 내의 중요한 입출력 부분만 가져오고, RS232와 관련없는 것들이나 에러핸들링은 그냥 다 빼버렸습니다. 결과적으로 ecDef와 ec 두 모듈을 합쳐 4,000 라인이 넘던 코드를 350 라인으로 줄여 Win32Comm 모듈 하나로 만들어 버렸습니다. 그래도 실질적인 RS232관련 입출력 기능은 모두 살아 있습니다. 그만큼 EasyComm에 군살이 많았다는 뜻이죠.

Win32Comm 사용법  Win32Comm.bas

위의 텍스트 화일을 다운로드(14 kB)해서 저장하신 후, 엑셀의 VB 에디터(alt-F11)에서 [파일]-[가져오기] 메뉴를 선택해서 다운로드한 파일을 임포트하세요. 그러면 모듈 트리에 Win32Comm이라는 모듈이 나타날 겁니다. 그러면 사용준비가 끝난 겁니다. 간단하죠? 이제 자신의 프로그램 코드를 작성하시면 됩니다.

다음은 코드 작성예로서 Command1 버튼이 눌려지면 COM1 포트를 열어 그 핸들을 A1 셀에 저장한 후, A2 셀의 내용을 읽어 포트에 전송합니다. Command2 버튼이 눌려지면 시리얼포트에 들어온 값을 A3 셀에 집어넣고 포트를 닫는 작업을 수행합니다.

Private Sub CommandButton1_Click()             ' 포트 열어 문자열 보내기 프로시져
    [a1] = CommOpen("com1", "4800, e, 7, 1")  ' 4800 bps, even parity, 7 data, 1 stop으로 COM1을 오픈. 핸들은 A1셀에 저장
    If [a1] = 0 Then                                        ' 에러일 경우 메세지
        MsgBox "Cannot open COM1.", , "Error"
        Exit Sub
    End If
    CommWrite [a1], CStr([a2])                       ' 문자열 보내기
End Sub


Private Sub CommandButton2_Click()              ' 문자열을 받아들인 후 포트 닫기 프로시져
    If [a1] = 0 Then Exit Sub                            ' 아직 포트가 열려있지 않으면 exit
    [a3] = CommReadStr([a1])                        ' 포트에서 문자열을 읽어 A3셀에 저장.
    CommClose [a1]                                      ' 포트 닫기
    [a1] = 0                                                    ' 이전 핸들값 삭제
End Sub

포트를 열 때 핸드쉐이크(default=none)나 버퍼크기(default=1024 bytes)는 CommSetFlowControl 및 CommSetBuffers 함수를 이용하여 세밀하게 설정할 수 있습니다. 자세한 사용법은 아래의 함수 설명 부분을 참조하세요.

입력 기다리기

CommRead 혹은 CommWrite계열의 입출력 함수를 호출하는 경우, 각 함수에서는 입출력 작업을 운영체제에 의뢰한 후 하드웨어적인 작업이 끝날 때까지 기다리지 않고 바로 리턴합니다. 원하는 문자열이 다 들어올 때까지 기다리는 기능은 갖고 있지 않습니다. 이런 부분은 포트에 문자가 몇 개 들어왔는지는 체크해 볼 수 있는 CommNumRcv 함수 등을 이용해 사용자가 직접 작성해 줘야 합니다. 일반적으로 입력을 기다리는 방법은 루프를 써서 계속 체크하는 방법(폴링이라고 합니다), 주기적으로 입력버퍼에 들어온 것이 있는지 체크하는 방법 그리고 이벤트(혹은 인터럽트) 방식이 있는데 Win32 API는 이벤트 방식을 지원하지 않습니다.

만일 루프를 써서 기다리는 방법을 쓰신다면 반드시 루프 내에 DoEvents 를 넣어 두세요. 안 그러면 문자열이 들어올 때까지 엑셀 전체가 무응답 상태가 되어 버립니다. 별도의 쓰레드를 만들면 이런 문제를 피할 수 있는데 VBA에서 쓰레드를 만드는 방법이 있는지는 모르겠습니다. 어쩌다 어떤 블로그에서 Win32 API로 VBA 쓰레드를 만들어 보려고 시도하는 것을 본 적이 있는데 결국 실패하더군요.  

'예
CommWrite [a1], [a2]         ' 포트로 문자열 전송. [a1]은 포트 핸들, [a2]는 기기명령어를 담고 있다고 가정.
Do While CommNumRcv([a1]) = 0   ' 포트에 들어온 문자가 없으면 기다림
    DoEvents                                  ' 무한루프 때문에 엑셀이 멈춰버리는 것을 방지
Loop
[a3] = CommReadStr([a1])             ' 입력된 문자열을 [a3]에 저장

때로는 루프를 쓰는 것보다 타이머를 이용해 주기적으로 문자열이 들어왔는지 체크하는 것이 더 유용할 수도 있습니다. 타이머를 이용하는 가장 쉬운 방법은 엑셀 내장 함수인 Application.OnTime을 쓰는 것입니다. 이 함수는 지정된 매크로를 지정된 시간에 호출하도록 설정하는데 쓰이는데, 콜백프로시져 끝부분에 자기 자신을 다시 콜백하도록 해놓으면 주기적인 작업을 할 수 있습니다. 콜백프로시져는 반드시 모듈레벨이어야 하고 시트별로 저장된 매크로는 부를 수 없습니다.

'예. Module1 내에 작성
Public Sub CheckInput()
        If [a1] = 0 Then Exit Sub              ' [a1]에 포트 핸들이 저장되어 있다고 가정. 만일 0이면 exit
        If CommNumRcv([a1]) > 0 Then  '  포트에 들어온 문자열이 있으면 
            'your handling routine              ' 필요한 작업을 합니다.
        End If
        Application.OnTime Now + TimeValue("00:00:01"), "CheckInput"    ' 1초 후에 다시 체크하도록 설정
End Sub

프로그램 어디선가 CheckInput을 한번 실행한 이후로는 스스로 계속 돌아갑니다. 그 Application.OnTime 이 편하긴 한데 시간설정의 최소 단위가 1초로 다소 길다는 점, 호출시마다 커서 모양이 화살표로 바뀐다는 점 그리고 어쩌다 시간설정을 잘못 했을 경우 이미 닫아놓았던 파일도 그 시간이 되면 자동으로 다시 열릴 수 있다는 등의 부작용이 있습니다. 보다 빠르고 부작용이 없이 타이머를 쓰는 방법도 있는데 그건 역시 Win32 API 기능을 불러다 쓰는 것입니다. 이것 역시 모듈레벨에서 만들어야 합니다. 먼저 표준모듈(Module1)을 만들고, 입력을 체크하고 필요한 작업을 수행하는 프로시져를 만듭니다.

Sub CheckInput()
    On Error Resume Next  ' 에러가 발생하면 무시하고 다음 라인으로 넘어갑니다. 고속루틴에서는 필수.

    If [a1] = 0 Then Exit Sub                           ' [a1]에 포트 핸들이 저장되어 있다고 가정. 만일 0이면 exit
    If CommNumRcv([a1]) = 0 Then Exit Sub   '  포트에 들어온 문자열이 없으면 exit
        'your handling routine                           ' 여기에 필요한 작업을 합니다.
End Sub

그 다음에는 모듈의 윗부분에 다음과 같이 Win32 타이머 API를 이용하겠다는 선언을 합니다.

Public Declare Function SetTimer Lib "user32" (ByVal hWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" (ByVal hWnd As Long, ByVal nIDEvent As Long) As Long

그리고나면 모듈뿐만 아니라 시트레벨에서도 필요할 때 아무 때나 다음과 같이 타이머를 켜거나, 끌 수 있습니다. SetTimer는 Application.OnTime과 달리, 콜백 프로시져를 한번만 부르는 것이 아니라 KillTimer를 부르기 전까지는 지정된 시간간격으로 계속 콜백한다는 것에 주의하시기 바랍니다.

SetTimer Application.hWnd, 3100, 200, AddressOf CheckInput 
KillTimer Application.hWnd, 3100  

위의 예에서 3100은 타이머ID입니다. 여러 개의 타이머가 있을 때 구분하기 위해 씁니다. 아무 값이나 자신이 정해서 쓰면 됩니다. 200은 타이머 간격을 밀리초 단위로 설정한 것입니다. 매 0.2초마다 콜백 프로시져가 불려져서 포트에 들어온 데이타가 있는지 체크합니다. 데이타가 있으면 CommReadBytes(바이너리 데이타 읽어오기) 또는 CommReadStr(아스키 문자열 데이타 읽어오기) 함수를 이용해 데이타를 읽어와 처리하면 됩니다. 

Win32Comm_Example.xls

위 엑셀 파일은 위에서 설명한 포트 여닫기, 읽고 쓰기, 타이머 사용법을 실제 화일로 만든 것입니다. 예제일 뿐이므로 실용적이지는 않습니다. 타이머는 포트가 열려 있을 때 버튼을 눌러야 동작하고, 포트를 닫으면 저절로 멈춥니다. 콜백이 일어나고 있음을 확인하기 위하여 A4 셀의 값을 하나씩 증가시킬 뿐 실제로 시리얼 포트 관련 작업은 하지 않습니다.

Win32Comm 함수 설명

CommOpen 함수

Public Function CommOpen(PortName As String, Optional Setting As String = "9600, n, 8, 1") As Long
PortName: 열고자 하는 포트이름. "COM1", "COM2" 등
Setting: 통신조건. 문법은 DOS의 mode 명령어와 동일합니다. 기본값은 9600 bps, no parity, 8 data bit, 1 stop bit 입니다.
            mode 명령어 문법
            baudrate=1200, 2400, 4800, 9600, 14400, 28800, ... , 119200 중 하나. 저는 9600이랑 4800밖에 안 써봐서..
            parity=no, even, odd, mark, space 중 하나
            data=5,6,7,8 중 하나
            stop=1,2
반환값: 성공=화일핸들, 실패=0. 화일핸들은 다른 함수들을 호출할 때 항상 첫번째 인수로 써야 합니다.
예1) [a1] = CommOpen "COM1", "9600, n, 8, 1"              '약식 표기에서는 순서를 지켜야 합니다.
예2) [a1] = CommOpen "COM1", "parity=n stop=1 data=8 baud=9600"   '변수이름을 지정하면 순서는 관계없습니다.


CommClose 함수

Public Function CommClose(Handle As Long) As Long
Handle: 포트 핸들. CommOpen의 반환값
반환값: 성공<>0, 실패=0
예) 
Dim hPort as Long
hPort = CommOpen("COM1", "9600, n, 8, 1")
...
CommClose hPort

CommSetBuffer 함수
Public Function CommSetBuffers(Handle As Long, InBufferSize As Long, OutBufferSize As Long) As Long
Handle: 포트 핸들. CommOpen의 반환값
InBufferSize/OutBufferSize: 입력 및 출력버퍼의 크기. 바이트 단위. 디폴트=1024
반환값: 성공<>0, 실패=0
예) 
Dim hPort as Long
hPort = CommOpen("COM1", "9600, n, 8, 1") ' 포트 오픈
CommSetBuffers hPort, 4096, 1024    ' 입력버퍼 4KB, 출력버퍼 1KB

CommSetFlowControl 함수

Public Function CommSetFlowControl(Handle As Long, Flow As String, _
        Optional xonChar As Byte = &H11, Optional xoffChar As Byte = &H13, _
        Optional xonlim As Integer = 128, Optional xofflim As Integer = 128) As Long
Handle: 포트 핸들. CommOpen의 반환값
Flow: "No", "XonXoff", "RTS", "DTR" 중 하나. 사실 첫 글자만 구분하므로 "N", "X", "R", "D" 만 써도 됩니다. 디폴트="N"
xonChar/xoffChar: xon/off 방식 흐름제어에 이용할 문자들입니다. 지정하지 않으면 디폴트 문자들로 지정됩니다.
xonLim/xoffLim: xon/off 방식 흐름제어시 xon/xoff를 개시할 쓰기버퍼의 잔량입니다.
반환값: 성공<>0, 실패=0
예) 
Dim hPort as Long
hPort = CommOpen("COM1", "9600, n, 8, 1") ' 포트 오픈
CommSetFlowControl hPort, "X"                  ' Xon/Xoff 흐름제어, 제어문자 및 버퍼임계선은 디폴트 사용

CommWrite 함수

Public Function CommWrite(Handle As Long, ByteData As Variant, Optional length As Long = 0) As Long

Handle: 포트 핸들. CommOpen의 반환값
ByteData: 보낼 데이타. Byte, Integer, Long, Single, Double의 경우 0-255의 범위로 truncation됩니다.
                실수형은 정수형으로 반올림됩니다. 배열은 각 개별항이 truncation 및 반올림되어 전송됩니다.
                엑셀의 문자열(유니코드)는 ANSI코드로 변환된 후 전송됩니다.
length: 데이타가 배열/문자열일 경우 보낼 데이타 개수입니다. 0 이면 모든 데이타를 전송합니다(디폴트).
반환값: 출력버퍼로 보낸 데이타 갯수. 전송성공 <> 0,  전송실패=0.
예) 
Dim hPort as Long
hPort = CommOpen("COM1", "9600, n, 8, 1") ' 포트 오픈
CommWrite hPort, "Test"

CommWriteRTS / CommWriteDTR 함수

Public Function CommWriteRTS(Handle As Long, level As Long) As Long
Public Function CommWriteDTR(Handle As Long, level As Long) As Long

Handle: 포트 핸들. CommOpen의 반환값
level:  각 라인의 설정값. 0 이면 reset(마이너스 레벨), 0 이 아니면 set(플러스 레벨)
반환값: 성공 <> 0,  실패=0.
예) 
Dim hPort as Long
hPort = CommOpen("COM1", "9600, n, 8, 1") ' 포트 오픈
CommWriteDTR hPort, 1                             ' set DTR

나중에 CommSetFlowControl함수를 써서 핸드쉐이크를 설정하면 CommWriteRTS/CommWriteDTR로 설정해 놓은 라인상태는 무효화될 수 있으니 주의하세요.
CommNumRcv 함수

Public Function CommNumRcv(Handle As Long) As Long

Handle: 포트 핸들. CommOpen의 반환값
반환값: 입력버퍼에 들어온 문자 갯수. 에러나 no data일 경우 0.
예) 
Dim hPort as Long
hPort = CommOpen("COM1", "9600, n, 8, 1") ' 포트 오픈
CommWrite hPort, Cstr([a2]) + Chr(13)        ' A2 cell의 내용을 기기로 전송
Do While CommNumRcv(hPort)=0                ' 문자가 들어올 때까지 기다림
    DoEvents                                              ' 엑셀 freeze 방지
Loop
[a3] = CommReadStr(hPort)                        ' 들어온 문자열을 A3 셀에 저장
CommReadBytes 함수

Public Function CommReadBytes(Handle As Long, Optional length As Long = 0) As Byte()

Handle: 포트 핸들. CommOpen의 반환값
length: 읽어올 문자의 개수. 0(default)이거나, CommNumRcv보다 클 경우 버퍼내의 모든 문자를 읽어옵니다.
반환값: 에러나 no data일 경우 인덱스가 0 to 0인 배열을, 데이타가 있을 경우 1 부터 시작하는 배열을 반환합니다.
예) 
Dim bdata() as Byte
bdata = CommReadBytes(hPort, 1)     ' 입력버퍼의 데이타 중 1 바이트만 읽어 옵니다.
If Ubound(bdata) Then 
    Msgbox "No data or error"          ' 반환된 배열의 인덱스 상한이 0이면 no data 또는 에러
Else
    [a3] = Cstr(bdata(1))                  ' 아스키 값을 A3 셀에 표시합니다.
End If

CommReadBytes 함수는 바이너리 데이타를 처리하기 위해 만든 것으로 일반적인 아스키 문자열을 읽어올 경우에는 아래의 CommReadStr 함수가 더 편리합니다.
CommReadStr 함수

Public Function CommReadStr(Handle As Long, Optional length As Long = 0) As String

Handle: 포트 핸들. CommOpen의 반환값
length: 읽어올 문자의 개수. 0(default)이거나, CommNumRcv보다 클 경우 버퍼내의 모든 문자를 읽어옵니다.
반환값: 버퍼 내의 데이타를 문자열로서 반환합니다. 에러나 no data일 경우 빈 문자열("")을 반환합니다.
예)  CommNumRcv 예제 참조

CommReadStr 함수는 바이너리 데이타, 특히 아스키값이 0인 데이타를 제대로 처리하지 못합니다. 윈도우즈 및 엑셀 내부에서 0을 문자열 종료로 인식하기 때문입니다. 게다가 CommReadStr함수는 자동으로 ANSI 코드를 유니코드로 변환합니다. 바이너리 데이타를 원형 그대로 입력받기 위해서는 위에서 설명한 CommReadBytes 함수를 이용하세요.
CommReadCTS / CommReadDSR / CommReadDCD / CommReadRI 함수

Public Function CommReadCTS(Handle As Long) As Long
Public Function CommReadDSR(Handle As Long) As Long
Public Function CommReadDCD(Handle As Long) As Long
Public Function CommReadRI(Handle As Long) As Long

Handle: 포트 핸들. CommOpen의 반환값
반환값: 플러스 레벨=+1, 마이너스 레벨=-1, 에러=0.

RS232의 신호라인 각각의 현재 상태를 읽어옵니다. 리턴값 0은 마이너스 레벨이 아니라, 에러를 뜻함에 주의하세요. 너무 단순해서 예는 생략합니다.
CommClear / CommClearRx / CommClearTx 함수

Public Function CommClear(Handle As Long) As Long
Public Function CommClearRx(Handle As Long) As Long
Public Function CommClearTx(Handle As Long) As Long

Handle: 포트 핸들. CommOpen의 반환값
반환값: 성공<>0, 에러=0.

입출력 버퍼를 모두 혹은 각각 초기화합니다. 너무 단순해서 예는 생략합니다.
맺음말

Win32Comm은 EasyComm을 기반으로 수정한 것입니다. 저 역시  EasyComm의 라이센스 정책에 따라 Win32Comm을 프리웨어로 공개합니다. 아무나 용도에 관계없이 자유로이 사용하실 수 있습니다. 단 Win32Comm을 사용하다 발생한 손실에 대해서는 아무런 책임도 지지 않습니다. Win32Comm은 상업용 어플리케이션의 일부로서 포함할 수 있지만, 단독으로 판매해서는 안 됩니다.

그동안 ActiveX를 사용해 오던 매크로 프로그램을, Win32Comm을 써서 바꿔봤는데 아무 이상없이 잘 작동하고 있습니다. 하지만 제가 사용하는 작동조건이 몇 개 안 되기 때문에 다른 사용조건에서는 에러가 날 수도 있습니다. 그런 부분을 알려주시면 가능한 범위 내에서 업데이트하도록 하겠습니다. 그리고, Generic RS232 Communicator도 조만간 Win32Comm용으로 업데이트하도록 하겠습니다. 아무쪼록 제 작은 노력이 여러분의 작업에 도움이 되었길 바랍니다.

by stal | 2007/09/29 02:48 | 메카트로닉스 | 트랙백 | 덧글(1)

VBA로 작성된 RS232 연결모듈 EasyComm 1.87

ActiveX를 사용하지 않고, 순전히 VBA로만 작성된 RS232 연결모듈인 EasyComm 1.87를 소개하고자 합니다. 이 모듈은 일본의 K. Kinoshita 씨가 작성한 것으로 프리웨어로서 그 이용과 배포가 자유롭습니다. 원래는 일본어로 쓰여진 것인데 제가 한국어로 바꿨습니다. 한국어판의 번역과 배포는 원작자의 허락을 구한 것임을 알려드립니다. 저작권 관련 사항은 압축화일 내에 있는 readme.txt의 내용을 참조하시기 바랍니다.

아래에 두 개의 압축화일이 있는데 하나는 원래의 일본어판 모듈이고, 다른 하나는 제가 한국어로 번역한 것입니다. 한국어판은 화일이름 끝에 Kr을 붙여 구분하였습니다.

한국어판 압축을 풀면 4개의 화일이 나옵니다.

- readmeKr.txt        간략한 소개와 저작권 관련내용
- ecManualKr.xls    메뉴얼
- ecKr.bas              EasyComm의 주 모듈  
- ecDefKr.bas         Win32 API 인터페이스용 함수 및 구조체 선언모듈

사용하실 때는 VB 에디터에서 ecKr.bas와 ecDefKr.bas 두 개의 모듈만  임포트하시면 됩니다. 자세한 사용법은 메뉴얼을 참조하시기 바랍니다.

ecKr.bas를 번역할 때 실수로 '써넣기'를 '읽어오기'로 전부 바꿔쓰기 해버려 이상하게 되어버린 곳이 꽤 있는데 일일이 찾아 고치지 못했습니다. 그리고, 번역을 끝내고 Excel에서 문법에러가 없는 것만 확인한 상태로서, 아직 동작테스트까지는 안 해 봤습니다. 조만간 실제 코딩작업을 해가면서 오류가 발견될 때마다 수정해 나갈 생각입니다. 아무쪼록 잘 사용하시고 오류나 개선사항이 있으면 원작자나 제게 알려주시면 고맙겠습니다.

by stal | 2007/09/16 02:56 | 메카트로닉스 | 트랙백(1) | 덧글(3)

<< 이전 페이지다음 페이지 >>