mulll

[Sparkfun Edge] Himax - HM01B0 카메라를 이용한 Snap Shot 찍기 본문

TinyML Project

[Sparkfun Edge] Himax - HM01B0 카메라를 이용한 Snap Shot 찍기

dongha 2023. 4. 2. 11:52

재미있어 보이는 Sparkfun Edge 카메라 관련 예제 프로젝트가 있어서 실행해 보았고 실행과정 및 실행 도중 해결한 문제점을 위주로 포스팅을 통해 정리하고자 한다. Himax 카메라가 읽은 프레임을 호스트 PC에 비트맵 형식으로 Serial 유선전송하는 간단하지만 새로운 프로젝트 수행에 기반이 되는 흥미로운 프로젝트인 것 같다. 

 

개발 OS: Ubuntu 20.04.3 LTS / 64-bit

하드웨어 구성

SparkFun Edge Development Board - Apollo3 Blue Himax CMOS Imaging Camera - HM01B0 Reversible USB A to C Cable - 2m SparkFun Serial Basic Breakout - CH340C and USB-C

 

 

 

0. Arduino IDE 설치 및 실행

 

https://www.arduino.cc/en/software

 

Software

Open-source electronic prototyping platform enabling users to create interactive electronic objects.

www.arduino.cc

 

 

Linux AppImage 64 bits 를 선택을 하고 다운로드한다.

다운로드한 파일을 우클릭하여 속성 -> Allow excuting file as program을 체크해 준다.

 

이후 다운로드한 파일을 더블클릭하여 실행해 준다.

 

 

실행화면이 나타나게 된다.

 

1. Arduino ide 환경설정 및 라이브러리 설치

- File -> Settings -> Additional boards manager URLs 칸에 아래의 URL을 추가한다.

https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json

 

- Tools -> Manage Libraries에서 himax 검색 후 아래의 해당 라이브러리를 설치한다.

 - Tools -> Board -> Boards Manager에서 apollo3 검색 후 아래의 보드 패키지를 설치한다.

 

 

- Bootloader는 Default인 Ambiq Secure Bootloader를 선택한다. 다른 부트로더로 선택가능한 Sparkfun Variable Bootloader로 업로드를 계속 시도해 보았지만 잘 안된다...

- Tools -> Ambiq Secure Bootloader Baud Rate921600 인지 확인한다.

- Tools -> SVL Baud Rate460800 인지 확인한다.

- Tools -> ProgrammerAmbiq Secure Bootloader 인지 확인한다.

 

2. Example 코드 불러오기

다음은 Himax 라이브러리의 Example을 불러올 것이다.

File -> Examples -> Sparkfun Himax HM01B0 Camera -> Sparkfun_Edge -> Example1_StopMotion을 클릭하면 새로운 창이 나타나게 되며 Example 코드가 나타난다. 한 프레임이 완성되면 Serial Port로 프레임을 전송하는 코드이다.

 

3. 프로젝트 코드 살펴보기

- 프로젝트의 코드를 살펴보자. 먼저 setup 과 loop 함수가 큰 틀을 구성한다. 함수명에서도 알 수 있듯이 setup 함수는 프로세스 실행 시 가장 처음 실행되는 함수이며 loop 함수는 프로세스가 종료될 때가지 무한히 반복하는 구조로 함수의 내부를 구현함으로써 보드의 기능을 SW적으로 설계할 수 있다.

void setup() {
...


}


void loop() {
...
}

 

- setup 부분은 아래와 같이 구현되어있다. 시리얼 포트 설정을 하고, 카메라 켈리브레이팅 및 파이썬 스크립트와 동기화를 하는 단계이다. 

void setup() {

  // 460800의 BAUD RATE로 시리얼 포트 연결 후 SERIAL_PORT가 활성화 될때까지 대기 
  SERIAL_PORT.begin(BAUD_RATE);
  do {
    delay(500);
  }while(!SERIAL_PORT);


  // Turn on camera regulator if using Edge board
#if defined (ARDUINO_SFE_EDGE)
  pinMode(AM_BSP_GPIO_CAMERA_HM01B0_DVDDEN, OUTPUT);
  digitalWrite(AM_BSP_GPIO_CAMERA_HM01B0_DVDDEN, HIGH);
  SERIAL_PORT.println("Turned on Edge camera regulator");
#endif

  // Start the camera
  if(myCamera.begin() != HM01B0_ERR_OK){
    SERIAL_PORT.print("Camera.begin() failed with code: " + String(myCamera.status) + "\n");
  }else{
    SERIAL_PORT.print("Camera started successfully\n");
  }

  // Calibrate Autoexposure
  SERIAL_PORT.println("Calibrating Auto Exposure..."); 
  myCamera.calibrateAutoExposure();
  if(myCamera.status != HM01B0_ERR_OK){
    SERIAL_PORT.println("\tnot converged"); 
  }else{
    SERIAL_PORT.println("\tconverged!");
  }
  
#ifdef DEMO_HM01B0_TEST_MODE_ENABLE
  // Enable test mode (generates a 'walking 1s' pattern to verify interface function
  SERIAL_PORT.print("Enabling test mode...\n");
  myCamera.enableTestMode();
  if(myCamera.status != HM01B0_ERR_OK){
    SERIAL_PORT.print("\tfailed\n");
  }else{
    SERIAL_PORT.print("\tsucceeded!\n");
  }

  // In test mode capturing a frame fills the buffer with the test pattern
  myCamera.capture();

  uint32_t mismatches = myCamera.countTestMismatches();
  SERIAL_PORT.print("Self-test mismatches: 0x");
  printWord(mismatches);
  SERIAL_PORT.print("\n");
#endif

  SERIAL_PORT.write(0x55);                                                    // 나중에 실행할 파이썬 스크립트와 맞춰주기 위한 특수값 전송
  SERIAL_PORT.print("\n\n");                                                  // Newlines allow Python script to find frame start
}

 

- loop 부분은 아래와 같다. 

void loop() {
  // Take an image
  myCamera.capture();

#ifdef DEMO_HM01B0_FRAMEBUFFER_DUMP_ENABLE
  // Print out a frame for the Python script to pick up
  framebuffer_dump();
#else
  // Print auto exposure state
  SERIAL_PORT.print("AE convergance(0x");
  printByte(myCamera.aeConvergenceStatus);
  SERIAL_PORT.print(") TargetMean 0x");
  printByte(myCamera.aecfg.ui8AETargetMean);
  SERIAL_PORT.print(", ConvergeInTh 0x");
  printByte(myCamera.aecfg.ui8ConvergeInTh);
  SERIAL_PORT.print(", AEMean 0x");
  printByte(myCamera.aecfg.ui8AEMean);
  SERIAL_PORT.print("\n");
#endif
}

 

- framebuffer_dump 함수

// frame buffer dump (formatted for python script)
void framebuffer_dump( void ){  
  SERIAL_PORT.print("+++ frame +++");                                         // Mark frame start
  for (uint32_t ui32Idx = 0; ui32Idx < myCamera.frameBufferSize; ui32Idx++){  // Process all bytes in frame
    if ((ui32Idx & 0xF) == 0x00){                                             // Print address every 16 bytes
      SERIAL_PORT.print("\n0x");
      printWord(ui32Idx);
      SERIAL_PORT.print(" ");         
    }            
    printByte(myCamera.frameBuffer[ui32Idx]);                                 // Print byte value
    SERIAL_PORT.print(" ");
  }
  SERIAL_PORT.print("\n--- frame ---\n");
  memset(myCamera.frameBuffer, 0x00, sizeof(myCamera.frameBufferSize));       // Zero out frame buffer for help identifying errors
}

 

4. 포트설정

하드웨어를 완성한 뒤 PC에 부착한다. linux의 경우 /dev/ttyUSB* 으로 Sparkfun Edge가 인식된다.

업로드 버튼 옆의  Unknown을 클릭한 뒤 아래와 같이 Sparkfun Edge를 검색해서 연동한다.

 

5. 검증 및 업로드

- Tools-> Burn Bootloader를 실행한다.

- 체크 표시가 되어있는 Valifiy 버튼을 눌러 컴파일을 수행한다.

완료 시 아래와 같이 할당될 메모리정보와 기타 등등이 보인다.

 

- 화살표 표시의 Upload를 수행하기 전 

 

Sparkfun Edge의 14 버튼과 RST 버튼이 존재한다. 14 버튼을 누른 채 RST버튼을 누르고 땐다. 그 이후 upload버튼을 누른다. 이때 주의할 점은 14 버튼은 업로드가 끝날 때까지 계속 누르고 있어야 한다는 것이다.

 

이후 아래와 같이 화면이 나오면 성공한 것이다.

 

에러 대응 1.  no upload port provided 가 출력 시 

위 에러를 마주쳤다면 Permission 문제일 가능성이 크다.

Permmision 문제일 경우 아래와 같이 권한 설정을 해준 뒤 다시 업로드 과정을 수행한다.

 

sudo chmod 777 ${연결된 디바이스의 경로}

# 본인의 경우
sudo chmod 777 /dev/ttyUSB0

 

6. Util App 실행

Sparkfun Board 쪽의 업로드 및 설정은 모두 마쳤으므로 리눅스 쪽에서 스냅숏을 받기 위해 설정해주어야 할 차례다. 라이브러리의 location을 임의로 바꾸지 않았다면 설치된 아두이노 IDE의 라이브러리는 아래의 PATH에서 확인할 수 있다.

 

dongha@my-laptop:~$ cd ~/Arduino/libraries/
dongha@my-laptop:~/Arduino/libraries$ ls
Arduino_TensorFlowLite  SparkFun_Himax_HM01B0_Camera

이후 아래의 경로로 다시 한번 이동한다.

cd SparkFun_Himax_HM01B0_Camera/utils/

이후 다음 명령어를 수행한다.

sudo python3 Example1_StopMotion.py -o . -p /dev/ttyUSB0

시리얼 포트를 통해 전송된 프레임이 모여서 쌓이게 되면 비트맵 형식의 이미지를 주기적으로 보여준다.

 

 

에러 대응 2.  no module named "serial" 출력 시

계속해서 설치했음에도 없는 모듈이라고 나타나서 sudo 명령어를 붙여서 설치해 보니 잘 되었다. 아마 권한 문제였던 것 같다.

 

sudo pip3 install pyserial

 

 

 

7. 실행 결과

주기적으로 카메라로부터 받은 프레임이 전송되어 호스트 pc에 전송해 준다.

 

8. 이후 공부하고 싶은 것들

Tensorflow lite 의 CNN 모델 기반 Object Classification 과 같은 고급 영역까지 공부해서 Sparkfun Edge 보드 위에 올려보고 싶다.

Comments