플스4를 구입한지야 2년 다되어갑니다만, 철권 타이틀의 부재로 쭈욱 패드 플레이를 해왔습니다.

그러던 중 철권7이 드디어 플스4 타이틀로 나왔지요.

부랴부랴 플스4용 조이스틱을 알아보았으나, 개당 25만원 + α 의 가격에 좌절을 했습니다.


그동안 오락기도 만들고 이것저것 만들던 손재주를 폭발시키고자 마음을 다잡고

10만원 이내의 제작비로 플스4용 조이스틱을 만들기로 했습니다.


그리하여 완성된 1.0 버전의 스틱이 바로 이것입니다.


조이스틱 케이스는 권바 Q1을 사용하였고, PCB는 Brook Fighting PCB를 사용했습니다.


Brook PCB의 경우 인풋렉을 걱정하시는 분이 더러 계시던데, 확인해보니 최신 펌웨어 기준으로 인풋렉이 4.3ms로 측정되더군요.

눈 감았다 뜨는게 보통 0.4초.. 400ms 인데 4.3ms 를 느낄만한 초인이 아니므로 인풋렉은 문제 없음!!


다음주 금요일(2017.08.10) 새 아파트로 이사하면 집에 들고갈 예정이므로 당분간 회사에서 테스트삼아 갖고놀게 되겠습니다.


1P는 빨간색, 2P는 파란색으로 스킨 디자인은 뻔뻔하게 뷰릭스 패널을 배꼈지만, 상업적 용도가 없는 개인사용이기 때문에 좀 더 뻔뻔하게 그냥 쓰겠습니다.

(근데 적용하고 나니 심심해보여서 새로 디자인할 수도...)


이제 집에서 철권7도 할 수 있고, 접대용으로 2인용 게임도 할 수 있겠네요 으흐흐




# 내용 추가 #


한시간만에 스킨 변경했습니다;;


막상 뷰릭스 디자인 배껴서 적용하니 심심하니 되게 맘에 안드네요 ㅜㅜ
 
아내는 물건에 캐릭터 그림 넣는거 안좋아한다고 했었지만, 지금 뷰릭스 카피 스킨이
지나치게 심심하고 맘에 안들어서 일전에 편집해뒀던 스킨 급 변경했습니다.


아내도 저도 엄청 즐겼고, 아직까진 플스4에서 가장 재미있었던 게임,
오딘스피어 브레이브스라시르 스킨으로 결정.



역시 저는 이쪽이 취향에 맞는듯 하다능.. 흐믓~


etc..

PS4용 조이스틱 제작

2017. 7. 13. 17:33

네이버 EddyLab의 에디님 지원으로 권바Q1SW에 듀얼쇼크3 PCB를 이식하는 작업을 어느정도 진행하던 중

치명적인 문제를 맞딱드렸었습니다.


권바 Q1의 PCB는 살려둔 채 듀얼쇼크3의 PCB를 이식하여 유선으로 사용시 듀얼쇼크3로 동작하고, 무선으로

연결 시 권바 Q1으로 동작하도록 설계했었는데요, 작업 완료 후 연결해보니 듀얼쇼크의 키가 죄다 눌려있었습니다.


이런저런 분석의 결과로, 권바 Q1의 PCB는 full-up 베이스로 동작하기 때문에 기본 입력 
대기 상태가 short, 버튼 및 레버의 입력 시 open이 되어 PCB가 이를 감지 후 신호를 보내는 방식입니다.

듀얼쇼크3나 기타 대부분의 조이스틱 PCB들은 기본적으로 full-down 베이스입니다.
입력대기 시 open, 버튼에 의해 short 되어야 신호를 전달합니다.

중간 기판을 하나 더 만들면 듀얼쇼크3를 full-up 베이스 신호로 동작하게 할 수도 있으나
이렇게 되면 배보다 배꼽이 더 커집니다 ㅜㅜ

눈물을 머금고 권바Q1의 PCB는 남자답게 포기하기로 했습니다.

때마침 제가 개인적으로 주문했던 권바 Q1 유선버전이 오늘 도착했기에, 에디님 사무실에서
진행했던 작업을 발판삼아 빠르게 한대분의 작업을 마쳤습니다.


먼저 제가 주문해 수령한 권바 Q1 유선버전을 분해해 봅니다.



Aㅏ... 역시나 우려대로 중국 내수용 부품 버전입니다.
산와 레버와 버튼이 아닌, 중국 옴론사 레버와 부품이네요.
불행중 다행일까요.. 이거 부품 설계가 산와를 배껴서 만든 제품입니다 -_- ;;
레버를 부품단위로 분해해보니 구조가 산와레버와 95% 동일합니다.

다른점이라면 각 마이크로 스위치의 입력을 모아 5핀으로 변환해주는 기판이
산와 정품은 레버 최 하단에 있는데, 이 제품은 안쪽에 들어가있다는 정도 차이가 있고,
아무래도 산와 정품이 아니기 때문에 레버 부품의 내구도가 걱정된다는 점이 있네요.

버튼은 아무래도 좀 시끄럽습니다. 덜그럭 거리는 느낌이 아주 살~짝 있네요.
일단은 쓰다가 나중에 여유자금이 좀 생기면 버튼부터 교체해줘야겠습니다 ㅜㅜ



시간을 훅 건너뛰어, PS4용 PCB 기판을 작업 완료한 모습입니다.

조그마한 정사각형의 녹색 PCB가 PS3 / PS4용 조이스틱 기판인 Brook Fighting PCB 입니다.
복각 오락기의 경우 듀얼쇼크3 PCB를 사용하지만, 사진의 물건은 제 개인 용도로써 집에서 PS4 게임을
즐기기 위해 만든 것입니다. 기본적으로 PCB만 다를 뿐 작업 자체는 프로세스상 90% 동일합니다.

작업 내용으로는..

1. 레버 및 버튼 입력에 Brook Fighting PCB 사용
2. 버튼 레이아웃 변경. ( X, Y, A, B를 가운데로, 좌측에 L1, L2, 우측에 R1, R2로 재배열)
3. Function키 변경.

이 중 3번 펑션 키의 경우 기존 PCB의 접점에 납땜할 경우 full-up이 걸려 상시 눌림으로 입력됩니다.
그러면 이 펑션키를 버려야 하느냐??
그럴리가요..



넵. 잔머리 대마왕의 편법이 폭발했습니다.

권바 Q1 PCB의 접점 위를 넓은 투명테이프로 막아서 절연해주고, 그 위에 테프론와이어 피복을 길게 벗겨
스카치테잎으로 위치를 맞춰 얹어놓았습니다.

Function 버튼을 누르면, 버튼 뒤에 있는 접점이 각 테프론 와이어를 short 시켜 버튼 입력을 발생시킵니다.
현재까지 테스트로는 매우 만족스럽게 작동중입니다.

권바 Q1의 PCB를 포기하니 일이 이렇게 쉬워지네요;;


권바 Q1을 사용한 PS4용 조이스틱 제작의 총 제작 단가는


1. 권바 Q1 : 싯가(저는 5만원 후반대에 구입했습니다.)

2. Brook Fighting PCB : 약 4만원


조이스틱 하나에 총 \95,000 정도가 소모되었네요.

물론 레버와 버튼이 맘에 안들기 때문에 추가 경비가 조금 더 들어갈 예정이긴 하지만, 유통중인 플4용 조이스틱에 비하면

매우 저렴하게 제작할 수 있었습니다.


이제 저도 패드 철권의 지옥에서 벗어날 수 있겠네요 ㅜㅜ

오늘부터 철권7을 열심히 연습해야겠습니다.


고인물 유져가 되는 그날까지 연습!! 연습!!


에.. 뭐 보통은 모형질이나 프로그래밍에 관한 포스팅이 메인이지만..

제 인생에 몇 되지않을 큰 소비가 될 주택구매에 관해서 글을 하나쯤 쓰고싶었습니다.


저희 부부는 연애 시작과 동시에 결혼 준비를 시작했습니다.

전문을 옮기기는 좀 그렇고.. 고백 내용 자체가 '너랑 결혼하고 싶으니 사귀자.' 였습니다;;;;

그도 그럴게, 처음 만나서 같이 밥먹으면서 이미 '아 이여자랑 결혼할꺼같은데?' 하는 느낌이 들었거든요.

아내도 같은 느낌을 받았다는건 나중에 들었습니다.

특이하게도 '이여자랑 연애하고싶다'가 아니라 '결혼할것 같다'라는 느낌이 먼저 들었습니다.


해서 사귀게 되고부터는 데이트 코스의 대부분은 결혼 준비였습니다.

모델 하우스를 구경다니고, 가구들을 보러다니고..


그러다가 아파트 분양에 성공하여 계약서를 쓴 그날, 바로 아내의 집에 가서 장모님, 장인어른께 결혼 허락을 받고

당일 예식장 계약까지 하루만에 다 해치웠습니다.


임시 신혼집에서 2년을 알콩달콩 재미나게 지내다보니 어느새 분양받은 아파트도 거의 다 지어졌고

6월 말 경 사전점검을 다녀왔습니다.


평생 살며 1천만원도 현금으로 만져본 적이 없는데, 수억(반은 은행빚이지만...)의 아파트를 구입하다니 기분이 묘했습니다.

또, 이곳에서 최소 10년 이상 살게될거란 생각에 기분도 상당히 업됐었네요.


아래 사진은 사전점검하러 들어가서 찍어본 우리 부부의 집입니다.




우선은 거실입니다.



거실 창가쪽 의자는 원래 제가 만든 오락기(http://cloudtree.tistory.com/243)에 사용하던 접이식 의자였는데, 사전점검 하다가 쉬고싶을때 앉으려고 챙겨갔습니다.


발코니 확장형에 로이창호로 개방감이 좋은 거실입니다.

아트월에 TV및 인터넷 단자, 컨트롤 디스플레이, 에어컨 배관 등이 설치되어 있네요.

25평형 작은 아파트이다보니 거실장이나 TV장은 두지 않고 TV는 벽걸이로 설치하고 아래쪽에 간단하게 벽체선반 하나를 설치할까 생각중입니다.




다음은 제가 가장 중요하게 생각하는 주방입니다.



바리바리 싸들고간 짐더미가 아일랜드 식탁을 점령하고 있네요;;

ㄷ자 형태로 일체감이 있는 아일랜드식 주방입니다.

현재 살고있는 임시 신혼집은 주방이 너무 좁아서 요리할때 재료를 미리 준비해놓으려고 하면 조리대가 부족해

식탁까지 동원해서 재료를 벌려놔야 했는데, 이제 그럴 걱정이 없겠네요. Nice !!


주방 펜트리가 따로 없는 설계인데, 다행히 주방 바로 옆에 에어컨 실외기실이 있습니다.

실외기 설치 후 추가 시공을 통해 실외기 주위를 슬라이딩 도어 같은거로 막고, 그 외 공간을 주방 펜트리로 쓰려고 합니다.


주방 창으로 내다보면 바로 앞에 수원 어린이 교통공원이 보여서 뷰가 좋습니다.

거실 뷰는 단지 내부를 향하고 있고, 공원뷰가 작은 주방창인게 아쉽긴 하지만 이건 이거대로 또 좋습니다.

어차피 퇴근하고 집에오면 늦은 저녁이라 공원뷰가 소용이 없다능.. ㅜㅜ

칼퇴근을 꼬박꼬박 하는 능력있는 개발자가 되고싶네요.




다음은 안방입니다.



발코니 확장 시 안방 발코니만 그대로 두고 나머지를 확장했습니다.

안방 발코니에는 전동접이식 빨래건조대가 있고, 세탁기 설치구가 있습니다.

거실과 마찬가지로 로이창호라서 채광과 단열이 좋아요.


최근 아내와 안방 커튼을 보러 다니고 있습니다.

안방은 가능한 침대 외에는 아무것도 들여놓지 않고 미니멀리즘으로 가고 싶습니다.

뭐 일단 살면서 하나 둘 증식하는게 살림세간이라고 하긴 하지만요...


안방에서 왼쪽 보시면 트인곳이 있는데, 안방 화장실과 화장대가 있고, 그 너머로 드레스룸이 있습니다.

거실과 안방 화장실, 화장대는 아내 폰으로 찍어서 저는 안갖고있네요;;


다음은 안방 안쪽에 위치한 드레스룸입니다.



시스템장이 기본으로 설치되어 있는 드레스룸입니다. 드레스룸 크기가 큰 편은 아닌데, 구성이 좋아요.

사진에 보이는 드레스룸 오른편은 상의, 하의, 코드를 걸어놓을 수 있는 행거와 수납장이 위치하고 있고, 사진에 안나온 왼편에는 

모자나 악세사리를 걸 수 있는 형태의 행거(?) 랄까.. 정확한 명칭을 모르겠는 그게 있습니다.


드레스룸 저 안쪽에 문이 하나 더 있는데, 화재시 대피공간이 있습니다.

큰 창과 위급시 타고 내려갈 수 있는 승강대가 있지요.


의복의 색이 바래는걸 방지하기 위해 드레스룸 창에는 코팅 필름을 시공하고, 블라인드도 시공하기로 했습니다.


저는 사실 드레스룸 안쪽 화재시 대피공간을 모형 도색공간으로 쓰고싶었는데, 아내와 아직 합의가 안됐습니다.

솔찍히 허가가 안날 확률이 더 높다는게 현실.. 또르르.. ㅜㅜ




다음은 작은방 1 입니다.



이 방은 서재로 사용할 방입니다.

아내도 그렇고 저도 그렇고 끈임없이 공부하며 자기개발을 해야 하는 직종이다 보니 서재는 꼭 필요하더군요.

책상과 책장, 블라인드까지 전부 원목가구로 준비했습니다.

아무래도 서재는 너무 가벼운 분위기보다는 좀 묵직한 분위기가 집중이 잘되니까요.


아내는 100% 공부를 위한 서재이겠지만, 저에게는 공부 겸 모형 작업을 할 공간이 될것입니다.

.. 사실 공부보다 모형 작업쪽이 지분이 더 높겠지요. 네 인정합니다.




마지막으로 작은방 2 입니다.



이 방은 운동방 겸 보조 드레스룸이 될 예정입니다.

확장시 기본 제공되는 붙박이장이 이 방에 있기에 계절에 맞지않는 옷은 이 방의 붙박이장에 수납될 예정입니다.

또, 이것저것 운동기구도 이 방에 배정되겠지요.


헬스장도 다녀보고 했는데, 저는 솔찍히 홈트레이닝이 더 맞더군요.

사정상 집과 직장이 멀어 출퇴근시간이 편도 1시간 40분입니다. 하루에 최소 3시간 20분 정도를 지하철에서 이동에 쓰다보니

아무래도 헬스장에 꾸준히 다니기가 힘들더라구요.


예전 92Kg까지 살이 쪘다가 홈트레이닝으로 72Kg까지 감량한 경험도 있고, 기본적으로 공을 쓰지 않는 맨몸운동은 어디가서

빠지지 않을 정도는 하기때문에, 집에 트레이닝룸을 만들어 두고 운동하는걸 계속 원해왔습니다.

현재 예상하는 운동방 구성 항목은 아령 Kg 별로 2 set, 덤벨, 턱걸이용 암스트롱바, 요가매트 입니다만 살면서 조금씩 늘겠지요.

턱걸이바는 이불빨래 전용 건조대가 되기 십상이라던데.. 일단 들여놓으면 아내 눈치가 보여서라도 열심히 해봐야겠습니다.




영통역 + 망포역 더블 역세권에 주변 상권도 좋고, 학군도 좋은데다 근처에 삼성전자가 있어 수요도 많아 재테크 투자용으로

구입하신 분들도 많다고 들었는데, 저는 어차피 주거용이고 이번 아파트 구매로 인해 당분간은 꼼짝없이 빚갚는 인생입니다.


아직 아이가 없어 앞일은 모르나, 적어도 둘은 낳고싶으니 나중에 첫째아이가 왠만큼 크면 그땐 더 큰 아파트로 갈 수 있도록

지금까지보다 더 열심히 일해야겠지요 ㅜㅜ


그래도 결혼하고 2년, 새집으로 이사가면 왠지 새로운 신혼같은 느낌♡

생각보다 하자 보수할 곳도 많지 않았고, 경기도에서 파견나온 검수단의 의견도 최근 지어진 아파트들 중 단연 으뜸으로 잘

지어졌다는 평가라니 기분이 상당히 좋습니다.


늦어도 8월 말에는 이사가게 될텐데, 빨리 지금 사는 집 전세가 나가서 이사가고 싶네요 으히힛~

※ 결론보다 문제점 설명이 더 길기에 미리 쓰는 해결방법 : 풀 다운 저항


아두이노의 디지털 핀 확장을 위해 많은 분들께서 74HC595나 74HC165 IC 등을 주로 사용하곤 합니다.
제 경우에는 업무상 필요에 의해 디지털 입력확장 보드를 제작할 필요가 있었는데, 회사에 4051 아날로그 MUX가 많더군요.

이 아날로그 MUX를 디지털 MUX로 사용할 수 있는지 알아봤는데 딱히 이렇게 쓰면 된다 하는 글을 못찾겠더군요.
제 검색 실력이 형편없었을 수도 있고, 그냥 74HC595/165를 쓰는게 효율적이기에 제가 찾는 글이 없었을 수도 있지요.

허나, 업무상 한정적인 자원으로 급하게 진행해야 하는 제 경우엔 또 새로운 IC를 적용해서 테스트를 하고 PCB를 설계할
시간적 여유가 없었기에 결국 4051 아날로그 MUX를 디지털 MUX로 사용하게 되었습니다.




4051 IC는 기본적으로 아날로그 멀티플렉서이며, 9~11번 핀의 A, B, C 컨트롤을 High/Low로 변경하며, 이를 이진법으로 0번에서 7번까지의 채널I/O핀을 제어해 COM I/O핀으로 데이터를 읽던가 보내던가 할 수 있습니다.


다음 그림은 4051 IC를 사용하는 간단한 예제입니다.




# 아두이노 핀 맵핑

- 22 : Ctrl A ( IC 11번핀 )

- 24 : Ctrl B ( IC 10번핀 )

- 26 : Ctrl C ( IC 9번핀 )

- A0 : 0ch I/O ( IC 13번핀 )

- A1 : 1ch I/O ( IC 14번핀 )

- A2 : 2ch I/O ( IC 15번핀 )

- A3 : 3ch I/O ( IC 12번핀 )

- A4 : 4ch I/O ( IC 1번핀 )

- A5 : 5ch I/O ( IC 5번핀 )

- A6 : 6ch I/O ( IC 2번핀 )

- A7 : 7ch I/O ( IC 4번핀 )

- A15 : COM I/O ( IC 3번핀)


위와 같이 회로를 구성하면, 0~7Ch I/O(아두이노 A0~A7핀)중 하나에 analogWrite() 함수로 값을 쓰고, Ctrl A~C(아두이노 22, 24, 26핀)을 사용하여 특정 채널에 써진 값을 COM_I/O(아두이노 A15핀)로 읽어올 수 있고, 반대로 COM_I/O핀에 analogWrite() 함수로 값을 쓰고 Ctrl A~C를 제어하여 특정 채널 I/O에 값을 보낼 수도 있습니다.


예를 들어 A3에 200의 값을 쓰고, Ctrl A(22)에 Low, Ctrl B(24)에 High, Ctrl C(26)에 High를 주면 COM_I/O핀에 200의 값이 전달됩니다. int value = analogRead(A3); 한 후 시리얼 모니터에 찍어보면 200이란 값이 나오겠지요.


여기서 analogRead 대신 digitalRead를 사용하면 High가 나올까요 Low가 나올까요.


결과는 '장담 못한다.' 입니다. 저는 루즈하게 analogRead/Write의 값 범위가 0~1023 이니까 적당히 512를 기준으로 낮으면 Low, 높으면 High가 나오겠지하고 생각했으나, 그렇지 않았습니다.

아날로그 값과 디지털 값을 다 읽어보았으나 어쩔땐 700~800이 나와도 Low일 때가 있고, 어쩔땐 50~100이 나와도 High일 때가 있더군요. 너무 안일했습니다.


제가 제작한 회로의 경우, 4051의 각 채널I/O 핀에 스위치를 통해 5v 전압이 걸리면 High로 인식하여 COM_IO로 HIGH를 가져와야 했으나, 5v 전압을 걸어도 High가 제대로 걸리지 않고, 인접한 다른핀의 5v 인가에도 영향을 받아 High-Low가 지멋대로 바뀌더군요.


이런 저런 시도끝에 4051의 0~7ch 핀에 각 10K옴 풀다운 저항을 걸어주니 값을 정확히 High/Low로 받을 수 있었습니다.


제 회로는 (하나의 4051 IC의 각 채널 I/O를 8개의 또다른 4051 IC의 COM_I/O로 연결) x 2 하여 최종적으로는 A0, A1 두개의 아두이노 핀과 컨트롤신호핀 6개, 총 8개의 아두이노 핀을 사용하여 128개의 디지털 인풋을 입력받을 수 있도록 확장했습니다.

이 경우 스위치와 연결되어 5v를 직접 받는 16개의 4051에는 풀 다운 저항을 달아줄 필요가 없으며, 8개의 4051 IC가 모이는 허브 역할을 하는 4051 IC의 각 채널 I/O에만 풀 다운 저항을 사용하면 인풋을 High/Low 디지털로 읽을 수 있습니다.


이하는 제가 사용한 PCB 설계도 입니다.


무료 설계툴인 Fritzing에서는 2레이어 PCB까지밖에 설계할 수가 없기에 점프 와이어를 꽤 많이 날려야 하지만, 일단 동작은 확실하게 검증하였습니다.


Ctrl A,B,C는 허브 역할을 하는 4051의 채널을 제어하며, Ctrl 1,2,3은 5v가 인가되는 말단 4051을 제어합니다.

Slot 0,1을 아두이노 A0, A1에 연결하여 디지털 High/Low를 가져오도록 되어있습니다.


이하는 위 PCB로 디지털 입력을 확장한 소스코드입니다.


 

#define DigitIn_enable 0x01
#define DigitIn_disable 0x00

// 공용 함수 및 변수
bool DebugMode = true;
int nDelay = 1;
int nSerialBaudrate = 9600;
bool breakWhile;
bool onLock ;

// Digital Input 관련 함수 및 변수
void DigitalInputProcessing();  // Digital Input 상태 변화를 감지
bool CheckChanged_DigitInput();  // Digital Input 상태가 변화한 경우 데이터 배열에 적용
void Init_DigitalPin();
void Init_ControlPin();
void Setup_DataPin();
void Setup_ControlPin();

int DigitIn_DATA_PIN[2];  // Digital Input 상태 가져올 핀
int DigitIn_CONTROL_PIN[6]; // Digital Input Board 제어할 컨트롤  핀
byte DigitIn_DATA[2][8][8];  // Digital Input 상태 저장할 배열
byte PREV_DigitIn_DATA[8][8][8]; // Digital Input 상태 변화 비교용 버퍼
int DigitIn_nCtrlSignal1 = 0; // DigitIn_nCtrlSignal1 = 말단 pin 나오는 MUX 8개 중 하나 선택
int DigitIn_nCtrlSignal2 = 0; // DigitIn_nCtrlSignal2 = 선택된 MUX중 In/Out Pin 8개 중 하나 선택
int DigitIn_nSlot = 0;        // DigitIn_nSlot = IO보드 넘버(0~7).

                                   // DigitIn_DATA_PIN[0][DigitIn_nSlot]에 각 Slot에서 들어온 값 넣음.
int CtrlA, CtrlB, CtrlC; // 허브 Mux 컨트롤 신호. 8개의 Mux 중 하나 선택.
int Ctrl1, Ctrl2, Ctrl3; // 말단 MUX 컨트롤 신호. Mux의 8개 데이터 핀 중 하나 선택.

void setup()
{
  if(DebugMode)
  {
    Serial.begin(nSerialBaudrate);
    while (!Serial) {;} // 시리얼 포트 오픈되기까지 대기
  }

  // 공용 설정
  breakWhile = false;
  onLock = false;

  // Digital Input 관련 설정
  Init_DigitalPin();
  Init_ControlPin();
  init_AnalogInputPin();
  Setup_ControlPin();
  Setup_DataPin();
 
  if(DebugMode)
    Serial.println("Setup done."); 
}

int cnt = 0;
unsigned long currentMillis = 0;
void loop()
{
  // Digital Input Process
  DigitalInputProcessing(); // Digital Input 상태변화 감지
 
  bool bIsChanged_DigitInput = CheckChanged_DigitInput(); // 상태변화가 있으면 현재상태를 저장
  if(bIsChanged_DigitInput && !onLock)
  {
    onLock = true;
    // 변화상태 전송
    // Send_MSG_0x4008(); // 상태변화 TCP 전송
    bIsChanged_DigitInput = false;
    onLock = false;
  }
  delay(1);
}

void Init_DigitalPin()
{
  // 데이터핀 하나에서 8*8=64개 인풋 받아옴.
  DigitIn_DATA_PIN[0] = A0;
  DigitIn_DATA_PIN[1] = A1;
}

void Init_ControlPin()
{
  // [0]~[2] : Control신호1. (MUX 1~8번 선택)
  // [3]~[5] : Control신호2. (Data Pin 선택)
  DigitIn_CONTROL_PIN[0] = 22;
  DigitIn_CONTROL_PIN[1] = 23;
  DigitIn_CONTROL_PIN[2] = 24;
  DigitIn_CONTROL_PIN[3] = 25;
  DigitIn_CONTROL_PIN[4] = 26;
  DigitIn_CONTROL_PIN[5] = 27;
}

void Setup_ControlPin()
{
  for (int nControl = 0; nControl < 6; nControl++)
    pinMode(DigitIn_CONTROL_PIN[nControl], OUTPUT);
}

void Setup_DataPin()
{
  for (int nControl = 0; nControl < 2; nControl++)
    pinMode(DigitIn_DATA_PIN[nControl], INPUT);
}

bool CheckChanged_DigitInput()
{
  bool rtn = false;
 
  for(int i=0;i<8;i++)  // DigitIn_nCtrlSignal1
  {
    for(int j=0;j<8;j++)  // DigitIn_nCtrlSignal2
    {
      for(int k=0;k<2;k++)  // DigitIn_nSlot
      {
        if(DigitIn_DATA[k][i][j] != PREV_DigitIn_DATA[k][i][j])
        {
          rtn = true;
        }
        PREV_DigitIn_DATA[k][i][j] = DigitIn_DATA[k][i][j];
      }
    }
  }       
  return rtn;
}

void DigitalInputProcessing()
{
  for (DigitIn_nCtrlSignal1 = 0; DigitIn_nCtrlSignal1 < 8; DigitIn_nCtrlSignal1++)
  {
    // Control signal 1을 변경하며 MUX 선택
    CtrlA = bitRead(DigitIn_nCtrlSignal1, 0);
    CtrlB = bitRead(DigitIn_nCtrlSignal1, 1);
    CtrlC = bitRead(DigitIn_nCtrlSignal1, 2);
    digitalWrite(DigitIn_CONTROL_PIN[0], CtrlA);
    digitalWrite(DigitIn_CONTROL_PIN[1], CtrlB);
    digitalWrite(DigitIn_CONTROL_PIN[2], CtrlC);
   
    for (DigitIn_nCtrlSignal2 = 0; DigitIn_nCtrlSignal2 < 8; DigitIn_nCtrlSignal2++)
    {
      // 선택한 MUX에서 Control signal 2를 변경하며 말단 I/O 핀 선택
      Ctrl1 = bitRead(DigitIn_nCtrlSignal2, 0);
      Ctrl2 = bitRead(DigitIn_nCtrlSignal2, 1);
      Ctrl3 = bitRead(DigitIn_nCtrlSignal2, 2);
      digitalWrite(DigitIn_CONTROL_PIN[3], Ctrl1);
      digitalWrite(DigitIn_CONTROL_PIN[4], Ctrl2);
      digitalWrite(DigitIn_CONTROL_PIN[5], Ctrl3);

      // 8개 I/O보드의 1~64번 I/O 핀 상태를 동시에 가져와 데이터 배열에 저장.
      for (DigitIn_nSlot = 0; DigitIn_nSlot < 2; DigitIn_nSlot++)
      {
        if(digitalRead(DigitIn_DATA_PIN[DigitIn_nSlot]))
        {
          DigitIn_DATA[DigitIn_nSlot][DigitIn_nCtrlSignal1][DigitIn_nCtrlSignal2] = DigitIn_enable;
          //Serial.println("input[" + String(DigitIn_nCtrlSignal1) + "][" + String(DigitIn_nCtrlSignal2) + "] is " + String(digitalRead(DigitIn_DATA_PIN[DigitIn_nSlot])));
        }
        else
        {
          DigitIn_DATA[DigitIn_nSlot][DigitIn_nCtrlSignal1][DigitIn_nCtrlSignal2] = DigitIn_disable;
          //Serial.println("input[" + String(DigitIn_nCtrlSignal1) + "][" + String(DigitIn_nCtrlSignal2) + "] is " + String(digitalRead(DigitIn_DATA_PIN[DigitIn_nSlot])));
        }
      }
    }
  }
}


원래 소스코드에는 192개 LED 개별 밝기조절/점등 부분과 TCP/IP 서버 생성하여 클라이언트에 변화감지 시 메세지 날리는 부분도 함께 있었으나, 포스팅의 깔끔함을 위해 편집을 가하였습니다. 편집 과정에서 불필요한 부분이 남아있을 수 있다는 점 미리 양해를 구합니다.


아마도 저처럼 사용하실 분이 계시긴 할런지 의문이긴 한데, 혹시나 4051 아날로그 MUX를 보유중인데, 디지털 MUX가 따로 더 필요하다 하시는 분이 계시다면 풀 다운 저항을 이용하여 디지털 MUX로 유용할 수 있다는 정보를 공유하고 싶었습니다 ㅎㅎ


그럼 오늘의 포스팅은 여기까지!! 휘리릭 뿅~

차회 갱신은 비동기 TCP 통신이 될것같다고 예고해놓고는, 비동기 통신이 아닌 보간곡선때문에 버전업을 하게되었네요.

최근 완료된 업무에서 필요해서 모듈을 만들어뒀던게 급 생각나서 추가하게 되었습니다.


이번 업데이트에 추가된 내용은 보간 곡선 생성 기능입니다.


제가 사용하는 보간 곡선은 경우에 따라 두가지를 용도에 맞게 적용하는데,

베지어 곡선과 캣멀롬 곡선이 그 두가지입니다.


베지어 곡선은 다음 그림과 같은 방식으로 그려지며, 부드러운 곡선을 만드는데 유용합니다.



< 베지어 4점 곡선 >


하지만 베지어 곡선은 지정한 웨이포인트를 지나지 않으며 최대한 부드럽게 유사 경로로 지나가게 되지요.


캣멀롬 곡선은 베지어 곡선보다 부드러운 곡이 나오진 않지만, 베지어 곡선과의 가장 큰 차이점으로 지정한 웨이포인트를 반드시 지나도록 구성됩니다. 다음 그림과 같이요.


< 캣멀롬 5점 곡선 >


위 두 보간곡선의 기능을 기존 레퍼런스에 추가하였습니다.

추가된 기능을 포함하여 제 개인 레퍼런스 클래스의 기능을 종합해보면 다음 표와 같습니다.


TCP/IP

서버

클라이언트

UDP

UDP

수학함수

Euclidean distance 2D

Euclidean distance 3D

가우시안 랜덤수 생성

좌표계

위경도 방위각 계산

위경도 거리 계산

ECEF-위경도 좌표계 변환

시간경과

시간경과 체크

공유메모리

쓰기

읽기

보간곡선

베지어 곡선

캣멀롬 곡선


레퍼런스 클래스 DLL을 적용한 샘플 윈도우 어플리케이션의 구성중 보간곡선 부분의 GUI만 추가로 설명합니다.

다른 기능의 GUI는 이전글(http://cloudtree.tistory.com/294)을 참고해 주시면 감사하겠습니다.


그리기 영역에 임의의 점을 2개 이상 찍어줍니다.

웨이포인트로써 곡선 생성의 기준이 됩니다.



베지어 곡선을 생성한 모습입니다.

웨이포인트를 최대한 부드럽게 접근하는 곡선이 생성됩니다.



캣멀롬 곡선을 생성한 모습입니다.

지정된 웨이포인트를 반드시 지나치는 최적 경로가 생성됩니다.



이전 글에서의 언급과 마찬가지로 최대한 쉽게 적용할 수 있도록 짜려 노력했으며, C#에 어느정도 익숙하신 분이라면 DLL 적용을 위한 샘플 폼 어플리케이션의 코드만 보셔도 큰 어려움 없이 적용이 가능하시리라 생각합니다.



CloudtreeReference_sample_v1.0.1.zip



소스코드의 편집 및 재배포는 자유롭게 허용되며, 혹시나 레퍼런스 샘플에 치명적 오류가 있을 시 알려주시면 빠르게 수정 반영하도록 하겠습니다.


오랜만에 프로그래밍 카테고리에 게시물을 포스팅하네요 ^^;;


예전에 VC++ 용으로 만들어두었던 레퍼런스 클래스가 있었습니다만, 최근 C# 코딩을 더 많이 하는 관계로

오랜만에 레퍼런스를 재정비 하여 C#용 레퍼런스 클래스를 작성했습니다.


C# 전용 레퍼런스로 넘어오며 가장 큰 변경점이라면...

이전에는 소스코드를 복&붙 하여 쓰도록 해놨던것을 클래스 라이브러리로 변경하여, 앞으로 C# 프로젝트에서 사용 시 DLL 파일만 복&붙 하면 쓸 수 있도록 수정하였습니다.


또한, TCP/IP와 UDP 소켓 통신의 경우 기존 레퍼런스에서는 소스 코드 안에 리시브 스레드를 만들어두었기에 적용할 때 마다 각 프로젝트에 맞도록 레퍼런스 소스 코드를 수정해야 했습니다. 하지만 이는 레퍼런스로서의 의미가 많이 퇴색된다 생각되어 이번  C#용 레퍼런스 클래스에서는 각 리시브 스레드를 레퍼런스 클래스 외부에서 작성하여 붙일 수 있도록 만들었습니다.


그 외에는 딱히 변경이나 추가사항 없이 기존의 레퍼런스와 같습니다.


작업 환경은 .Net Framework 4.0 기반, VS2010 기준으로 작성했으며, 솔루션 파일을 열면 두개의 프로젝트가 있습니다.


1. CloudtreeReference 프로젝트 : dll 파일을 생성하는 레퍼런스 클래스

2. CloudtreeReference_SampleForm 프로젝트 : 레퍼런스 적용 예시 윈도우 폼 어플리케이션



다음은 레퍼런스 클래스에 구현되어 있는 함수 내역입니다.

생각할 수 있는 최대한 쓰기 편하도록 짜보긴 했는데, 쓰면서 불편한 점이 생기면 그때마다 버전업 해 갈 예정입니다.



TCP/IP

서버

클라이언트

UDP

 UDP

수학함수

Euclidean distance 2D

Euclidean distance 3D

가우시안 랜덤수 생성

좌표계

위경도 방위각 계산

위경도 거리 계산

ECEF-위경도 좌표계 변환

시간경과

시간경과 체크 

공유메모리

공유메모리 생성

쓰기

읽기




레퍼런스 클래스 DLL을 적용한 샘플 윈도우 폼 어플리케이션 구성은 다음 그림과 같습니다.










C#에 어느정도 익숙하신 분이라면 코드만 봐도 큰 어려움 없이 적용이 가능하시리라 생각합니다.

원본 소스코드 및 바이너리가 포함된 압축파일을 첨부합니다.



CloudtreeReference_sample_v1.0.0.zip



ps. 차후 업데이트는 TCP 소켓 통신을 현재의 1:1 접속에서 1:n 다중 접속 방식으로 변경하기 위해 비동기 소켓 통신으로 변경하는 작업이 되지 않을까 합니다.