산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

RGB 조명 제어를 위한 TinyML 키워드 감지

구성품 및 소모품

Arduino Nano 33 BLE 감지
× 1

앱 및 온라인 서비스

Edge Impulse Studio

이 프로젝트 정보

전제

에지에서의 머신 러닝은 기존 코드에 비해 훨씬 적은 프로그래밍 및 논리적 흐름도로 "지능적" 작업을 수행할 수 있는 장치를 만드는 데 매우 유용합니다. 그래서 특정 단어를 인식하고 말한 내용을 기반으로 작업을 수행할 수 있는 최첨단 키워드 감지 기능을 통합하고 싶었습니다.

하드웨어

이 프로젝트에는 Arduino Nano 33 BLE Sense라는 하나의 구성 요소만 있습니다. 실제 마법은 기계 학습 모델에서 발생합니다. Arduino Nano 33 BLE Sense는 마이크, 9축 IMU, 환경 센서 및 제스처/근접/색상/주변광 센서(APDS-9960)를 포함한 센서로 가득합니다. 마이크로컨트롤러는 64MHz에서 실행되고 1MB의 플래시 메모리와 256KB의 RAM을 포함하는 nRF52840입니다. 이 프로젝트는 또한 온보드 RGB LED를 사용하여 현재 색상을 표시합니다.

Edge Impulse 설정

Edge Impulse에서 새 프로젝트를 생성한 다음 Edge Impulse CLI 도구를 설치했습니다. 설치 방법에 대한 자세한 내용은 설치 지침 페이지를 참조하십시오. 이를 통해 Arduino Nano는 클라우드 서비스와 통신하여 명령을 수신하고 센서 데이터를 자동으로 보낼 수 있습니다. 최신 Edge Impulse 펌웨어를 다운로드하고 리셋 버튼을 두 번 클릭하여 부트로더 모드로 전환하여 보드에 플래시했습니다. 그런 다음 flash_windows.bat를 실행했습니다. 전송합니다.

명령 프롬프트에서 edge-impulse-daemon을 실행했습니다. 마법사를 따라 설정했습니다. 이제 Nano가 프로젝트의 장치 목록에 표시되어 샘플을 채취하고 훈련/테스트 데이터 세트의 일부로 업로드할 수 있습니다.

샘플 수집

머신 러닝 모델을 훈련하려면 데이터와 상당한 양의 데이터가 필요합니다. RGB LED 스트립에 대해 다음 모드를 원했습니다.

<울>
  • 켜기
  • 꺼짐
  • 빨간색
  • 녹색
  • 파란색
  • 1~2초 간격으로 단어를 반복해서 말하고 쪼개는 모드마다 1분 정도의 소리가 났어요.

    그러나 이러한 샘플을 갖는 것만으로는 충분하지 않습니다. 배경 소음 및 기타 단어가 잘못된 판독을 제공하기 때문입니다. 고맙게도 Edge Impulse는 이미 노이즈 및 '알 수 없는' 단어에 대한 사전 구축된 데이터 세트를 제공하므로 "기존 데이터 업로드" 도구를 사용하여 이러한 오디오 파일을 교육 데이터에 업로드했습니다.

    마지막으로 데이터 세트를 재조정하여 교육 데이터와 테스트 데이터에 대해 각각 권장되는 80-20 분할을 갖도록 했습니다.

    모델 훈련

    이제 한 시간 분량의 훈련 데이터와 많은 레이블로 무장하고 모델을 훈련할 때입니다. 내가 디자인한 임펄스는 1초의 윈도우 크기와 500ms의 윈도우 증가를 가진 시계열 데이터로 오디오를 받아들입니다. 그런 다음 MFCC 블록을 통해 Keras 신경망 블록으로 전달됩니다.

    MFCC 블록을 사용하면 시각적으로 주파수를 보여주는 스펙토그램과 함께 오디오가 처리되는 방식을 구성할 수 있습니다.

    신경망 설정을 대부분 기본값으로 두었지만 몇 가지 수정도 했습니다. 먼저 최소 신뢰도 임계값을 0.80에서 0.70으로 변경하고 추가 노이즈 및 마스킹 시간 대역의 형태로 약간의 데이터 증대를 추가했습니다. 이것은 작업할 데이터가 더 다양하기 때문에 NN이 모델을 과적합하는 것을 방지하는 데 도움이 됩니다.

    Arduino Nano 33 BLE Sense에 배포

    Arduino Nano 33 BLE Sense는 오디오를 지속적으로 샘플링하고 키워드 중 하나가 말했는지 감지하는 상시 작동 마이크 역할을 합니다. 키워드를 찾으면 원하는 색상을 디코딩하는 데 사용되는 색인으로 키워드가 변환됩니다. on 또는 off 키워드의 경우 LED는 검정색 또는 밝은 회색으로 설정됩니다.

    모델을 라이브러리로 다운로드하여 Arduino IDE에 추가한 다음 코드를 컴파일하여 Nano에 플래시했습니다.

    <섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

    코드

    <울>
  • RGBLED키워드 감지
  • RGBLED키워드 감지C/C++
    /* Edge Impulse Arduino 예제 * Copyright (c) 2020 EdgeImpulse Inc. * * 이 소프트웨어 및 관련 문서 파일("소프트웨어")의 사본 *을 얻는 모든 사람에게 무료로 권한이 부여됩니다. * 소프트웨어의 사본을 사용, 복사, 수정, 병합, 출판, 배포, 2차 라이선스 및/또는 판매할 수 있는 * 권리를 포함하되 이에 국한되지 않는 * 제한 없이 소프트웨어를 거래하고 * 소프트웨어를 받는 사람에게 허용하는 * 다음 조건에 따라 제공됩니다. * * 위의 저작권 표시 및 이 허가 표시는 * 소프트웨어의 모든 사본 또는 상당 부분에 포함됩니다. * * 소프트웨어는 상품성, * 특정 목적에의 적합성 및 비침해에 대한 보증을 포함하되 이에 국한되지 않는 어떠한 종류의 명시적 또는 * 묵시적 보증 없이 "있는 그대로" 제공됩니다. 어떤 경우에도 * 저자 또는 저작권 소유자는 계약, 불법 행위 또는 기타 행위로 인해 발생하는 청구, 손해 또는 기타 책임에 대해 책임을 지지 않습니다. * 소프트웨어 거래. */// 타겟이 메모리에 제한이 있는 경우 이 매크로를 제거하여 10K RAM을 저장합니다.#define EIDSP_QUANTIZE_FILTERBANK 0/** * 모델 창당 슬라이스 수를 정의합니다. 예를 들어 모델 창당 슬라이스가 4로 설정된 1000ms *의 모델 창. 결과는 250ms의 슬라이스 크기입니다. * 추가 정보:https://docs.edgeimpulse.com/docs/continuous-audio-sampling */#define EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW 3/* 포함 ------------------- --------------------------------------------- */#포함 #include #include 
    #define CONFIDENCE_THRESHOLD 0.7정적 const uint32_t 색상[] ={0x00ff0000, 0x0000ff00, 0x000000ff}; // 빨강, 초록, 파랑색 Actions { LED_ON =1, LED_OFF =0, LED_RED =2, LED_GREEN =3, LED_BLUE =4, NONE =5};enum 함수{ CHANGE_LED_ON_OFF =0, CHANGE_LED_COLOR =1, CHANGE_LED_NONE =COLG const uint8_t redPin =22, greenPin =23, bluePin =24;const std::map<작업, 함수> actionToFunctionMap ={ {LED_ON, CHANGE_LED_ON_OFF}, {LED_OFF, CHANGE_LED_ON_OFF}, {LED_RED, CHANGE_LED_OFF} }, {LED_BLUE, CHANGE_LED_COLOR}, {NONE, CHANGE_LED_NONE}};const std::map labelToActionMap ={ {"on", LED_ON}, {"off", LED_OFF}, {"red" , LED_RED}, {"green", LED_GREEN}, {"blue", LED_BLUE}, {"unknown", NONE}, {"noise", NONE}};/** 오디오 버퍼, 포인터 및 선택기 */typedef struct { 서명된 짧은 *버퍼[2]; 서명되지 않은 문자 buf_select; 서명되지 않은 문자 buf_ready; 서명되지 않은 int buf_count; unsigned int n_samples;} inference_t;static inference_t 추론;static bool record_ready =false; static signed short *sampleBuffer;static bool debug_nn =false; // 이를 true로 설정하면 예를 들어 원시 신호에서 생성된 기능static int print_results =-(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW);/** * @brief Arduino setup function */void setup(){ // 여기에 설정 코드를 입력하여 한 번 실행:Serial.begin(115200); Serial.println("에지 임펄스 추론"); setPixelColor(0xaeae00); // 추론 설정 요약(model_metadata.h에서) ei_printf("추론 설정:\n"); ei_printf("\t간격:%.2f ms.\n", (float)EI_CLASSIFIER_INTERVAL_MS); ei_printf("\t프레임 크기:%d\n", EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE); ei_printf("\t샘플 길이:%dms.\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT / 16); ei_printf("\t클래스 수:%d\n", sizeof(ei_classifier_inferencing_categories) / sizeof(ei_classifier_inferencing_categories[0])); run_classifier_init(); if (microphone_inference_start(EI_CLASSIFIER_SLICE_SIZE) ==false) { ei_printf("ERR:오디오 샘플링 설정 실패\r\n"); 반품; }}/** * @brief Arduino 주요 기능. 추론 루프를 실행합니다. */void 루프(){ bool m =마이크 추론_기록(); if (!m) { ei_printf("오류:오디오 녹음 실패...\n"); 반품; } signal_t ​​신호; signal.total_length =EI_CLASSIFIER_SLICE_SIZE; signal.get_data =µphone_audio_signal_get_data; ei_impulse_result_t 결과 ={0}; EI_IMPULSE_ERROR r =run_classifier_continuous(&signal, &result, debug_nn); if (r !=EI_IMPULSE_OK) { ei_printf("오류:분류기(%d)를 실행하지 못했습니다.\n", r); 반품; } if (++print_results>=(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)) { // 예측 출력 ei_printf("Predictions "); ei_printf("(DSP:%d ms., 분류:%d ms., 이상:%d ms.)", result.timing.dsp, result.timing.classification, result.timing.anomaly); ei_printf(":\n"); (크기_t ix =0; ix  CONFIDENCE_THRESHOLD) { performAction(result.classification[ix].label); } ei_printf(" %s:%.5f\n", result.classification[ix].label, result.classification[ix].value); }#if EI_CLASSIFIER_HAS_ANOMALY ==1 ei_printf("이상 점수:%.3f\n", result.anomaly);#endif print_results =0; }} 무효 setPixelColor(uint32_t c){ analogWrite(redPin, 255 - (c>> 16)); analogWrite(greenPin, 255 - ((c>> 8) &0xff)); analogWrite(bluePin, 255 - (c &0xff));} void performAction(const char* classificationLabel){ auto itr =labelToActionMap.find(classificationLabel); if(itr ==labelToActionMap.end()) 반환; 자동 itr2 =actionToFunctionMap.find(itr->초); if(itr2 ==actionToFunctionMap.end()) 반환; switch(itr2->second) { case CHANGE_LED_ON_OFF:setPixelColor((itr->second) ? 0x5c5c5c :0x00); 부서지다; 경우 CHANGE_LED_COLOR:{ uint32_t pixelColor =색상[itr->초 - 2]; setPixelColor(픽셀 색상); } 부서지다; case CHANGE_LED_NONE:중단; }}/** * @brief Printf 함수는 vsnprintf를 사용하고 Arduino 직렬을 사용하여 출력합니다. * * @param[in] 형식 변수 인수 목록 */void ei_printf(const char *format, ...) { static char print_buf[1024] ={0}; va_list 인수; va_start(인수, 형식); int r =vsnprintf(print_buf, sizeof(print_buf), 형식, 인수); va_end(인수); if (r> 0) { Serial.write(print_buf); }}/** * @brief PDM 버퍼 전체 콜백 * 데이터 가져오기 및 오디오 스레드 콜백 호출 */static void pdm_data_ready_inference_callback(void){ int bytesAvailable =PDM.available(); // 샘플 버퍼로 읽습니다. int bytesRead =PDM.read((char *)&sampleBuffer[0], bytesAvailable); if (record_ready ==true) { for (int i =0; i> 1; i++) { inference.buffers[inference.buf_select][inference.buf_count++] =sampleBuffer[i]; if (inference.buf_count>=inference.n_samples) { inference.buf_select ^=1; 추론.buf_count =0; inference.buf_ready =1; } } }}/** * @brief 초기화 구조 및 PDM 설정/시작 * * @param[in] n_samples n개의 샘플 * * @return { description_of_the_return_value } */static bool 마이크_inference_start(uint32_t n_samples){ inference.buffers[ 0] =(짧은 부호 *)malloc(n_samples * sizeof(짧은 부호)); if (inference.buffers[0] ==NULL) { 반환 거짓; } inference.buffers[1] =(signed short *)malloc(n_samples * sizeof(signed short)); if (inference.buffers[0] ==NULL) { 무료(inference.buffers[0]); 거짓을 반환합니다. } sampleBuffer =(짧은 부호 *)malloc((n_samples>> 1) * sizeof(짧은 부호)); if (sampleBuffer ==NULL) { 무료(inference.buffers[0]); 무료(inference.buffers[1]); 거짓을 반환합니다. } 추론.buf_select =0; 추론.buf_count =0; inference.n_samples =n_samples; inference.buf_ready =0; // 데이터 수신 콜백 구성 PDM.onReceive(&pdm_data_ready_inference_callback); // 선택적으로 게인을 설정합니다. 기본값은 20입니다. PDM.setGain(80); PDM.setBufferSize((n_samples>> 1) * sizeof(int16_t)); // 다음을 사용하여 PDM을 초기화합니다. // - 하나의 채널(모노 모드) // - 16kHz 샘플 속도 if (!PDM.begin(1, EI_CLASSIFIER_FREQUENCY)) { ei_printf("PDM을 시작하지 못했습니다!"); } 레코드 준비 =참; return true;}/** * @brief 새 데이터 대기 * * @return 완료되면 True */static bool 마이크_inference_record(void){ bool ret =true; if (inference.buf_ready ==1) { ei_printf( "오류 샘플 버퍼 오버런. 모델 창당 슬라이스 수 감소 " "(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)\n"); ret =거짓; } 동안 (inference.buf_ready ==0) { 지연(1); } 추론.buf_ready =0; return ret;}/** * 원시 오디오 신호 데이터 가져오기 */static int Mike_audio_signal_get_data(size_t offset, size_t length, float *out_ptr){ numpy::int16_to_float(&inference.buffers[inference.buf_select ^ 1][offset], out_ptr , 길이); return 0;}/** * @brief PDM을 중지하고 버퍼를 해제합니다. */static void 마이크_inference_end(void){ PDM.end(); 무료(inference.buffers[0]); 무료(inference.buffers[1]); free(sampleBuffer);}#if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR !=EI_CLASSIFIER_SENSOR_MICROPHONE#error "현재 센서의 모델이 잘못되었습니다.#endif

    제조공정

    1. 2020년 IIoT 보안 팁 및 동향
    2. IoT용 클라우드 및 에지 컴퓨팅:짧은 역사
    3. IoT용 에지 컴퓨팅이 필요한 이유
    4. 데이터 집약적인 IoT Edge 애플리케이션을 위한 Kontrons KBox A-150-WKL
    5. AI 결정화를 위한 에지 컴퓨팅 이점
    6. 에지 컴퓨팅의 성공을 보장하기 위한 4단계
    7. Microsoft, 5G 애플리케이션을 위한 Azure Edge Zone 출시
    8. 엣지에서 오픈 소스의 필요성(eBook)
    9. 저농도용 화학물질 검출 시스템
    10. 가스 감지 장치를 유지 관리해야 하는 3가지 이유