경상북도 구미시 봉곡북로 65

명품빌딩 3층, (주)네오텍

Send Your Mail At:

semineotech@gmail.com

벨 소리를 듣고 문 열어 주기

벨 소리를 인식해 문을 열어 주는 시스템을 구상했습니다.

벨 소리를 듣고 문 열어 주기

도어락

사무실 이전을 하면서 보안 업체와 계약을 하지 않고 도어락을 설치했습니다.

도어락을 사용한 후 제일 불편한 점은 손님이 방문했을 때 누군가가 자리에서 일어나 사무실을 나가 로비를 지나 현관문까지 가서 도어락의 버턴을 눌러야 하는 것입니다.

물론 우리 사무실이 너무나 넓어서 도어락을 열기 위해 엄청난 거리를 걸어 가야 하는 것은 아닙니다만 모두가 바쁠 때는 아무도 문을 열어주지 않는 경우도 있습니다.

그래서 도어락 열림 장치를 고민하게 되었습니다.

열림 버턴 누르기

도어락의 열림 버턴을 누르기 위해 사람 손을 대신할 액추에이터를 설치하는 방법이 있습니다.

하지만, 액추에이터를 사용하기에는 여러가지 문제가 있습니다.

기계장치를 도어락에 부착하는 문제, 모터 구동을 위한 전원 공급, 적당한 액추에이터 구하기, 가격 문제등 차라리 온라인 제어가 되는 최신식 도어락을 구입해 설치하는 편이 더 나아 보였습니다.

기계장치 대신 버턴을 눌렀을 때와 동일한 신호를 발생할 수 있는 전자 장치를 추가하는 방법을 생각해 봤습니다.

보통 키 입력 회로는 키를 눌렀을 때 MCU의 GPIO 입력 전압을 GND로 변경합니다.

도어락을 분해해 키 입력 부분에 트랜지스트를 추가한 후 레벨을 변경해 보았습니다.

예상대로 키 눌린 것과 동일하게 동작합니다.

벨 소리 인식 방법

누군가가 현관문에 설치된 벨을 눌렀을 때 도어락을 열어줘야 합니다.

벨을 누른 것은 소리로 인식합니다. 사무실 안쪽에 스피커가 설치되어 있으니 전기 신호를 인식할 수도 있겠지만, 천장으로 배선된 케이블을 찾아 작업하기가 쉬워 보이지 않았습니다.

소리 인식은 TensorFlow/docs 에 있는 Simple Audio Recognition 을 이용합니다. Source code는 여기에 있습니다.

샘플 코드 동작

다운로드한 샘플 코드를 Linux 시스템에서 테스트 해 봅니다. 아래 명령을 입력해 학습을 시도합니다.

$ python3 train.py

ImportError가 발생해 Tensorflow를 업그레이드 했습니다.

또한, root 디렉토리에 /tmp 를 생성하도록 설정되어 있어 퍼미션 에러 방지를 위해 ./tmp로 수정합니다.

에러를 수정하고 실행하면 dataset을 다운로드하여 학습을 진행합니다.

벨 소리 학습

학습을 위한 데이터 확보를 위해 회사 동료들에게 벨 소리 녹음을 부탁했습니다.

녹음된 파일을 받아 벨 소리 부분을 4.5초 길이로 잘라서 16KHz로 샘플링된 50개의 데이터 파일을 만듭니다.

샘플 코드에서 사용하는 데이터셋의 구조에 맞게 dingdong 디렉토리를 생성하여 학습용 데이터 파일을 복사합니다. _background_noise_와 others는 샘플 데이터셋을 그대로 사용합니다.

수정된 환경에 맞게 옵션을 조정하여 학습을 진행합니다. 데이터의 차이가 거의 없기 때문에 정확도 100%로 학습됩니다.

$ python3 train.py --data_url= --data_dir=./tmp/my_dataset/ --wanted_words=dingdong --clip_duration_ms=4500 --how_many_training_steps=1200,400 --batch_size=10

Android App에서 사용할 파일을 생성할 옵션도 환경에 맞게 조정합니다.

$ python3 freeze.py  --sample_rate=16000 --wanted_words=dingdong --clip_duration_ms=4500 --how_many_training_steps=1200,400 --batch_size=10 --start_checkpoint=./tmp/speech_commands_train/conv.ckpt-1600 --output_file=./tmp/dingdong_graph.pb

Android App 동작

안드로이드 앱에서 학습한 결과를 이용하여 벨 소리를 인식하기 위해 Tensorflow ExampleTF Speech를 이용합니다.

이 클래스가 오디오 스트림을 입력받아 판별하는 방식을 요약하면 아래와 같습니다.

  • recording thread에서 recordingBuffer에 입력된 오디오 데이터를 기록한다.
  • recordingBuffer는 원형 큐로 동작하며, bufferOffset이 저장할 위치를 지정한다.
  • recordingBuffer의 크기는 training에 사용한 dataset의 길이와 샘플링 주파수로 결정된다.
    • recordingBuffer의 크기 = dataset의 길이(초) * 샘플링 주파수
  • 녹음된 데이터 버퍼는 recordingBuffer에 비해 작다.
  • 인식하는 thread에서는 recordingBuffer의 bufferOffset 부터 시작해 전체 데이터를 읽어 다른 버퍼에 저장한다.
  • 따라서 전체 데이터의 길이는 dataset의 길이와 같다.
  • 이 데이터를 TF로 보내 판별한다.

앱에서 벨 소리 학습 데이터를 사용해 벨 소리를 인식하기 위해서 몇 가지 인수를 조정해야 합니다. 아래는 조정한 인수에 대한 설명입니다.

이름기본값변경값설명
minimumTime
Between
SamplesMs
30ms짧은 시간동안 테스트를 많이 하는 것을 방지하기 위해, 테스트한 후 이 시간동안 테스트를 하지 않고 기다립니다.
averageWindow
DurationMs
500ms1500ms이 시간동안 테스트 한 결과를 평균해 최종 판단을 합니다.
minimumCount3최종 결과를 얻기위해 averageWindowDurationMs 동안 minimumCount 이상 테스트를 해야합니다. 너무 짧은 시간동안 테스트를 마치는 경우를 방지하기 위해 총 테스트 시간은 (averageWindowDurationMs / 4) 이상이어야 합니다. 이것은 minimumTimeBetweenSamplesMs를 이용해 조정 할 수 있습니다.
detectionThreshold 0.7TF에서 테스트한 점수의 평균이 이 값 이상이어야 인식된 것으로 판단합니다.
suppressionMs 1500ms인식된 결과를 전달한 후 다음 결과를 전달하기 까지의 대기 시간입니다.
동일한 결과가 연속해서 전달되는 것을 방지합니다.

시스템 구성

동작 시스템은 단순합니다. 벨 소리가 나면 안드로이드 앱에서 인식을 하고 블루투스 모듈로 문을 열라는 신호를 보낸니다. 블루투스 모듈은 도어락의 버턴을 전기 신호로 제어하여 문을 엽니다.

그런데, 이 구성도는 소비 전력 문제가 있습니다. 블루투스 모듈은 수신 대기를 해야 하므로 항상 액티브 상태에 있어야 합니다. 이 경우 블루투스 모듈의 소비전류는 20mA 정도입니다. 1000mAh 건전지를 사용한다면 이틀마다 교체해야 합니다.

이 글을 쓰면서 같은 칲셋을 사용하는 모듈을 찾아 보았습니다. 20mA 정도면 열심히 데이터를 주고 받을 때의 소비전류입니다. S/W가 뭔가 다른가 봅니다.

블루투스 모듈의 소비 전력 문제는 좀 더 검토를 해 봐야겠습니다. 그런 후에 도어락에 부착할 수 있을 것 같습니다.

denis