본문 바로가기

언어/기타

시리얼 통신에서는 노이즈를 반드시 염두에 둬야만 합니다

http://www.delmadang.com/community/bbs_view.asp?bbsNo=3&bbsCat=0&indx=450856&page=2


저는 그동안 시리얼통신을 참 많이 했습니다. 
그 중에 일반 프로그래머가 간과하는 부분을 짚고 넘어가고 싶습니다.

2003년 정도였을 것입니다. 인터넷에서 다운받은 시리얼 통신 로직을 아무생각없이 그대로 가져와서
변형하여 프로젝트를 수행하고 있었습니다. 그 로직은 전에도 몇번 사용해본 것이었기 때문에 어느정도 
자신감마져 있었습니다. (로직이라고 할지, 아니면 그냥 전체적인 클래스 구조라고 할지.. .모르겠습니다. 
아무튼... 일반적인 구조라고 보시면 될것 같습니다.)

그런데 참 이상한 일이 벌어졌습니다. 지금까지 잘 돌았고, 하물며 어젯밤까지도 잘 작동되었던 로직이 아침에
출근하자마자부터 작동을 하지 않는 것이었습니다. 이런 해괴망측한 일이 있나... 하고 생각하면서 하나하나 추적해 들어가기 시작하였습니다. 

그런데 이상하게 규칙적으로 들어오던 프로토콜의 명령어가 중간이 잘리거나 아니면 공백문자가 들어오곤 하는 것을 발견하였습니다. 일단 원인을 알았으니 점심먹고 다시 시작하자라고 생각했는데요, 다녀와서 보니 아니 이게 웬일인가요, 또다시 정상작동을 하는 것이었습니다. 

이 미스테리한 일은 제가 베니어합판 위에 미니로 만들어놓았던 장치와 배선들이 위치가 약간 바뀌어서 일어난 것이었습니다. 0.5Cm가 넘는 두꺼운 베니어 합판 위에 나사못으로 견고하게 장치들을 고정했지만, 전선은 그렇지 않고 아무렇게나 끌려 다녔던 것입니다. 

제가 그동안 시리얼 통신로직의 수정의뢰를 받아서 다른사람이 만든 로직을 보면 10에 10은 전부다 동일하게 노이즈를 전혀 생각하지 않고 만들어진 로직이었습니다. 

예를 들면...

  프로토콜에서 ABC가 헤더이고, 00/08/02/04가 명령어이고 나머지 꼬리 부분이... XXX라고 하면은...
  대부분의 로직이 버퍼에서 가져온 그 문자열 그대로 잘라서 첫 머리 글자가 ABC이면 이라는 if 문장으로 
  시작되는 것입니다. 

  그러나 그런식으로 하면 안되고 노이즈를 생각한다면 이중 버퍼링을 하셔야 합니다. 즉... 계속해서 문자열을
  가지고 오면서 한쪽에 쌓아두고는 이 문자가 'A'인가, 이 문자가 'A'인가 하고 연속적으로 물어야 합니다. 
  그러다가 'A'이면 그 다음에 문자열 세개를 잘라서 'ABC'인가라고 확인해야만 합니다. 

  이 단순한 차이는 조금 더 복잡한 구조를 만들어야하는 수고를 일으킵니다. 
  게다가 기계를 만지는 사람들은 컴퓨터 쪽을 전혀 모르기 때문에 잘 작동하다가 이상하게 한두번 에러가 
  발생하면 자신들이 잘못 동작시켰는지 알고 그냥 컴퓨터를 껏다가 다시 켜보는 식입니다.

물론 대부분의 현장에서 통신에 노이즈가 갑자기 발생할 가능성은 상당히 없습니다. 그러나 이런 경험을 한번 하고 난 뒤에도 예전의 단순한 로직을 그대로 사용한다면 마음 가득한 죄책감이 들 수밖에는 없을 것입니다. 

이 직전에 쓰레드에 관한 글을 올렸습니다. 저는 이벤트 방식을 추천해 드리고자 하였고 기존에 사용하던 델파이 로직에 문제가 있었다는 점을 알려드리고자 하였습니다. 물론 기존의 로직을 활용해도 쓰레드를 사용하는데는 거의 문제가 없을 것이라는 생각이 듭니다. 

그러나 사실 이런 문제는 후배들을 위한 배려라고 생각합니다. 
아직도 현장에는 시리얼 통신 로직에 단순히 프로토콜을 잘라서 확인하는 식의 코드가 수없이 반복되고 있습니다. 왜냐하면 저 또한 그렇게 인터넷에서 퍼왔거나 책을 통해서 배워왔기 때문입니다. 

아직도 개발 5,6년 차에게 객체지향을 좀 익히라는 소리를 하면 오히려 눈을 힐겨 뜨고는 합니다. 
상황이 상황인데 줄코딩 안하고 어떻게 배기냐고 도리어 묻는 것입니다. 
물론 우리나라의 열악한 개발환경은 저도 잘 알고는 있습니다. 
하지만 미래를 잠시 눈감고 있는 것과 미래를 아예 부정하는 것과는 큰 차이가 있지 않나 하는 생각입니다.  

저도 현재 프로젝트 중이라 마음이 많이 바빠서 저의 생각을 이정도에서 마무리 하였으면 좋겠다는 생각입니다.
쓰레드와 시리얼통신 문제는 언젠가는 한번 짚고 넘어가야지 하고 마음에 두고는 있었던 것이었습니다. 
부디 좋은 의도로 받아주시면 대단히 감사하겠습니다

reply

좋은 내용입니다. 

굳이 사족을 달면, 노이즈는 항상 발생을 한다고 염두를 하고, 작성을 해야 할것 같고, 통신 속도가 높고, 거리가 멀수록 오류 발생 확률은 높아집니다.

최근에 Uart TTL 3V (RS-232)를 10Mbps로 만들어 사용한 적이 있는데, 이런 경우, 30cm도 오류 없이 통신하기가 어려웠던 경험이 있습니다.

하드웨어가 안정되어야 하는 것이 기본이지만, 소프트웨어서도 보안을 해주어야 하는 것이 정석인 것 같습니다.

특히 고정형 사이즈가 아니고, STX + Len (Word) + Data (n Data) + ETX 같은 포맷일 경우, 내부 통신 버퍼가 100KBytes 이고, Len가 Word 같은 경우, Len에서 오류가 발생하면, 최대 64KB까지로 인식할 수도 있어서, Buffer Overflow가 발생하여 프로그램이 죽을 수도 있습니다. 

윈도우는 프로그램만 죽어버리지만, Firmware같은 경우에는 전체 시스템이 멈출 수도 있기 때문에, 항상 State Zero로 돌아갈 수 있도록 신경을 써주어서 작업을 해야 합니다.

공장 FA같은 경우, 해외(?) 메이저 회사 제품들은 이런 부분들 잘 처리하고 있지만, 무명 회사에서, 제작한 제품들 중 일부분은 이런 처리를 안하는 경우도 있어서, 꺼꾸로 제어 시스템에서 충분한 시간 여유를 두고 제어해야 하는 경우도 발생됩니다.