2024년 10월 1일 화요일

lepton 3.1 개발 기행

 어느 날 회사로 부터 lepton 3.1을 이용한 열화상 네트워크 카메라를 개발하자는 결정이 내려왔다.

예전 회사에서도 사용을 위하여 타진은 한 적이 있었지만 높은 가격으로 인해 다른 모듈이 선택 되는 것이 자주 있었다. 최근 160에 한정하여 합리적인 가격이 되었다 한다.

드디어 밀당만 하던 lepton이 나와 이렇게 인연을 맺게 되었다.


합리적인 가격 제품이 목표였기 때문에 SOC는 Eyenix의 EN675로 하였다.

아직 아쉬운 점도 많지만, 그에 비해 장점 및 가격 대 성능 비가 매우 좋은 제품이다.


lepton은 80x60해상도의  1.X 대에 주로 보았기 때문에 큰 어려움이 없을 것으로 생각하였다.

하지만 오산이었다.


lepton 3.1 은 160x120 해상도인데 제어는 i2c, 데이터 전송은 spi로 한다.

lepton 1x의 경우 SYNC 인터럽트가 들어오면 데이터를 받아들이고, 그 중, 유효한 데이터 (ID 의 상위 비트를 확인하여)만 해당 온도 데이터만 사용하고 나머지는 버리면 된다.

lepton 시리즈는 SPI로 온도나 영상 데이터를 선택하여 전송할 수 있는데, 특이한 점은 데이터는 20fps가 넘게 전송하는데, 그 중에서 유효한 데이터만 골라서 사용하고 나머지는 동일한 데이터 복재이거나 불필요한 데이터라는 것이다.

아마도 원래는 20fps 넘게 출력이 가능하지만, 수출 제약으로 9fps 보다 밑으로 전송하기 위해서 나머지 프레임을 막아버린 것이 아닌가 생각이 된다.


80x60해상도의 lepton 1x는 적당히 SPI로 데이터를 받아들이면서 유효한 데이터만 골라 사용하면 되는데 lepton 3.x 는 더 큰 난관이 존재한다.

전송 단위 크기를 lepton 1x를 그대로 사용하기 때문에, 원래는 160x120 해상도인 19200 픽셀 씩 전송해줘야 하는데, 80x60 크기인 4800 pixel 씩 전송한다.

즉, 그림 한 장을 4조각으로 잘라 전송하는 것이다.


그림 4장이 연속으로 온 후 lepton 1x와 마찬가지로 불필요한 데이터를 전송하다 다시 주기가 되면 그림 4장을 연속으로 전송한다.

그러면 그림 4장을 받아 조립하여 사용하면 그만 이라 생각했지만 실수였다.

80x60은 데이터 전송 하나가 하나의 완성된 그림이기 때문에 한 프레임 정도 놓쳐도 다음 프레임을 받아 표시하면 된다. 하지만 160x120인 lepton 3.x 는 4프레임이 연속으로 받아야 한 장면이 완성되기 때문에 중간에 하나라도 빠지면 다음 4프레임 모두 잘 받을 때 까지 기다리거나 다른 프레임과 함께 조립하여야 하는데 이 경우 대상이 움직임이 있으면 영상 찢어짐 현상이 발생한다.


SPI로 그림 4개 연속으로 받아오는 것이 뭐가 그리 어렵나 생각할 수 있는데, SPI 통신 자체는 어려운 것이 아니지만, 가져오는 타이밍에 제약이 걸려 있다면 이것은 문제가 된다.

보통 lepton에서 데이터를 가져올 때 GPIO3번에 SYNC 출력으로 설정하고, SYNC 신호가 들어오면 3ms 이내에 SPI로 데이터를 가져와야 한다.

lepton의 매뉴얼을 보면, lepton은 타이밍과 통신에 매우 민감하니 lepton이 연결된 i2c와 spi에 다른 기기를 연결하지 말고 단독으로 사용하는 것을 권장한다고 써있을 정도이다.

시험 삼아 SYNC 신호 후 타이밍을 벗어나 SPI 요청을 하면 매뉴얼에서 경고한 것과 같이 0x00 이나 0xFF 데이터가 잔뜩 들어오게 된다.

타이밍이 맞지 않을 경우 SPI데이터는 깨지며, 최악의 경우 재 동기화라 하여 lepton과 SOC의 SPI 통신 간 동기화 작업을 해야 한다.

아실 분은 아시겠지만, 리눅스의 context switching 주기는 10ms 간격이다.

보통 SPI 드라이버를 개발 할 때 여러 User application으로부터 들어오는 요청들을 순차적으로 처리하기 위하여 예약을 실행하고, kernel thread에서 순차적으로 수행하는 방식을 사용한다.  즉 요청 시 10ms 의 대기를 고려하여 개발해야 한다는 뜻인데, 이는 lepton의 허용 범위를 넘는 상황이다.

ST micro와 같은 micom의 경우 user application과 kernel 과의 경계가 없어 이런 고민을 할 필요가 없지만 linux 환경에서는 달랐다.

이를 해결하기 위해, 어쩔 수 없지 linux의 기존 SPI 드라이버를 제거하고, leptop 전용 드라이버를 개발하기로 했다.

자원을 dts로 설정하는 platform 기반 드라이버로 설정하고, 리눅스에 입력할 dts에 lepton항목으로 자원을 할당했다.

자원으로는 사용할 대상의 SPI 레지스터들과 interrupt와 SYNC 입력을 받을 GPIO를 설정하였다.

user application으로 부터 요청은 ioctl로 받도록 spi 가 아닌 misc 드라이버로 등록하였고,

gpio interrupt를 설정하여 GPIO interrupt가 발생하면 예약된 버퍼 들 중 빈 버퍼로 SPI DMA 전송이 수행되고, DMA 전송이 완료되면 SPI interrupt가 발생하여, 버퍼 입력이 완성되었음을 을 marking하고 다음 SYNC 인터럽트를 대기하는 방식으로 드라이버를 개발하였다.


결과는 성공이었다. 스코프로 파형을 보면 SYNC 가 발생하고 SPI 클럭과 데이터가 1ms 가량 내에 시작되는 것을 볼 수 있었다.

데이터도 다행히 빠지지 않고 잘 들어와 문제 없이 출력 되었다.

초 당 9 fps 도 되지 않는 모듈에 이렇게 까지 공을 들이는 것은 뭔가 아이러니 하지만, 좋은 경험을 했다고 생각하기로 했다. 

댓글 없음:

댓글 쓰기