Polymor!

카메라 듀얼 센서 프로그램 본문

Embedded

카메라 듀얼 센서 프로그램

Megan Kim 2020. 5. 28. 15:48

인턴 생활을 하면서 내가 주로 참여 했던 프로젝트는  "듀얼 센서 (Dual Sensor)" 프로그램 제작이 주된 업무였다.

카메라 하나가 최대 320*240 = 76,800픽셀의 그래픽 디스플레이가 지원되었고, 이를 확장하기 위해선 두가지 측면에서 접근이 가능하다.

하나는 하드웨어적인 관점에서 보드를 확장 수정하는 방법이고, 둘째는 소프트웨어적으로 두대의 카메라를 서로 통신을 시켜 서버를 확장하는 방향이었다. 첫번째 방법은 아무래도 물리적인 비용이 훨씬 많이 들게 되니 SW적으로 수정하기로 결정되었다. 

 

고해상도의 디스플레이를 위해서는 물리적으로 일단 센서가 두개가 필요했다.  하지만 카메라 두개를 병렬적으로 동시에 실행 시키면, 카메라의 조명끼리 서로 충돌이 일어나 간섭 현상으로 깜빡임이 끊임없이 출력되었다. 

듀얼 센서의 핵심은 서로의 조명을 제어하는 일이었다.

처음엔 우선 기본적으로 두 카메라 사이에 "통신" 하는 프로그램을 만들어야했다. 이 카메라는 UART 시리얼 포트와 USB 이더넷 포트 두가지가 있다. UART 직렬 통신 프로토콜이 TCP/IP보다 간단하긴 했으나, UART는 본질적으로 주 쓰임새가 콘솔(터미널)과의 통신이기도 하고, 고질적으로 하드웨어적으로 문제가 좀 있어서 TCP/IP 통신 프로그램을 제작하게 됬다.  

 

두 대의 카메라를 제어하는 서버를 별도의 PC에 올리고, 이 서버가 두 대의 카메라 조명을 컨트롤 해주는 1:N 다중 클라이언트 모델로 구현을 하게 되었다 . 또한 두대의 카메라를 컨트롤하는데에 비동기적으로 통신하기 위해 멀티 쓰레드 기반이 되어야한다. 

 

 

 

 

 

서버(PC)는 두 클라이언트를 각각의 쓰레드로 생성하여(phtead_create) 두 클라이언트의 중계 역할을 맡고, 

카메라는 윈도우 gui(client)와 연결되있는 내부 서버프로그램과 PC와 연결되는 클라이언트 프로그램 두개를 멀티 쓰레딩 시킨다. 

물론 PC 와 연결되는 그 client 프로그램 내에도 멀티쓰레드로 read()와 write() 부를 나눴다. 

결국 조명 on/off 에 대한 flag로 1바이트 신호로 주거니 받거니 하는 건데...  생각보다 복잡했다. 

 

나름의 고민의 결과로 첫번째 프로그램이 완성되었다. 그리고 테스트 결과, 예상대로 잘 되지 않았다. 

다행히 빠르게 원인을 찾아냈다. 문제는 내가 flag 값에 대한 임계 영역을 제대로 설정해주지 않은 탓에, 두 쓰레드가 동시에 같은 값을 접근하여 읽고 쓰는 바람에 꼬이게 된 것이다. 이런 경우는 뮤텍스(pthead_mutex) 로 해결을 하면 되어서, 이를 바탕으로 조금 더 방어적이고 견고하게 코드를 수정했다. 

최종 결과로 두 카메라를 동시에 켜고 조명 충돌없이 깔끔하게 두배 큰 화면으로 출력되는 걸 눈으로 확인 할 수있었다. 

앞으로 해야 하는 것은 이제 클라이언트 측에서 두개의 프레임을 잘 이어 붙여 출력해줘야하는 작업을 해줘야한다. 클라이언트 서버는 Python이어서 파노라마 기법등을 잘 찾아보면 있지 않을까하는 생각이다. 

 

 

 

** 멀티쓰레드 관련 트러블슈팅 

보통 우리가 쓰는 PC의 경우, 요즘 같은 시대에는 메모리 용량이 넘치기때문에 메모리 누수와같은 자원관리에 큰 신경을 쓰지않고 개발자들이 프로그램을 작성한다. 하지만 임베디드 시스템의 경우엔 다르다. 메모리용량이 8GB 정도밖에 안되는 초소형 메모리 내에서는 운영체제도 프로그램도 모두 신경을 써야한다. 

 

유닉스계열에서 쓰레드를 생성하는 인터페이스는 pthread_create() 이다. 내가 만든 멀티 쓰레드 기반 듀얼센서가 여러번 테스트를 해봤는데 약 5분정도 지나면 끊기는 문제가 발생했다. 이를 해결하기 위해서 주요 부분에 디버깅 메세지 출력을 걸어두고 테스트해본 결과 , 어느 시점부터 

pthread_create가 제대로 안되고 있다는 것을 알게되었다. 

 

pthread_create 가 error를 반환하는 경우중 나의 프로그램은 자원부족 문제인 것 같았다. 

내 프로그램의 쓰레드는 아래와 같이 구성되어있다.

  • Thread 1 : main server    1회 생성
  • Thread 2 : Sub server  1회 생성 
  • Thread 3 : Image processing  매번 생성 --> 일정 시간 지나면 더이상 쓰레드 생성되지않음. 

문제는 Thread3 를 계속 생성한다는 점인건데,  그렇지만 매번 thread_exit이 되기때문에 상관이 없을 것 같았다. 

(thread start_point 함수가 while loop에서 빠져나와 return 을 하고 나면 암묵적으로 thread_exit의 효과가 있다고 한다.)결론적으로는 thread3를 한번만 생성하는 방향으로 다시 프로그램을 짰더니, run time이 10분이상 지속되어 문제가 해결된듯했다. 

 

정리를하자면,

1. 메모리 자원은 무한하지않다. 임베디드 환경에서 개발할 때에는, 자원을 최대한 아껴쓰고 재활용할 수 있는 코드를 만들어야한다.  PC 환경에선 그런 고려가 없어도 문제가 없었을 수 있으나 임베디드 환경에선 피부로 와닿게 중요하다. 

  

2.  매번 thread를 반복적으로 생성-파괴하는 코드는 피하는게 좋다. 시스템적으로 큰 부하가 걸릴 수 있다.  

 

 

 

 

 

 

 

https://github.com/kimjungsun/TOFproject

'Embedded' 카테고리의 다른 글

image data streaming  (0) 2020.05.30
Comments