Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Manufacturing Technology >> Proses manufaktur

Kontrol Lampu RGB dengan Deteksi Kata Kunci TinyML

Komponen dan Perlengkapan

Aplikasi dan Layanan Online

Tentang Proyek Ini

Premis

Pembelajaran mesin di tepi sangat berguna untuk membuat perangkat yang dapat menyelesaikan tugas "cerdas" dengan jauh lebih sedikit pemrograman dan diagram alur logika dibandingkan kode tradisional. Itulah sebabnya saya ingin mengintegrasikan deteksi kata kunci di tepi yang dapat mengenali kata-kata tertentu dan kemudian melakukan tugas berdasarkan apa yang dikatakan.

Hardware

Proyek ini hanya memiliki satu komponen: Arduino Nano 33 BLE Sense. Keajaiban sebenarnya terjadi dalam model pembelajaran mesin. Arduino Nano 33 BLE Sense penuh dengan sensor, termasuk mikrofon, IMU 9-sumbu, sensor lingkungan, dan sensor gerak/dekat/warna/cahaya lingkungan (APDS-9960). Mikrokontroler padanya adalah nRF52840 yang berjalan pada 64MHz dan memiliki memori flash 1MB dan RAM 256KB. Proyek ini juga menggunakan LED RGB papannya untuk menampilkan warna saat ini.

Kontrol Lampu RGB dengan Deteksi Kata Kunci TinyML
Kontrol Lampu RGB dengan Deteksi Kata Kunci TinyML

Menyiapkan Edge Impulse

Saya memulai dengan membuat proyek baru di Edge Impulse dan kemudian menginstal alat CLI Edge Impulse. Untuk instruksi lebih lanjut cara melakukannya, kunjungi halaman instruksi pemasangan. Ini memungkinkan Arduino Nano berkomunikasi dengan layanan cloud untuk menerima perintah dan mengirim data sensor secara otomatis. Saya mengunduh firmware Edge Impulse terbaru dan memflashnya ke papan dengan double-klik tombol reset untuk membuatnya memasuki mode bootloader. Lalu saya menjalankan flash_windows.bat untuk mentransfernya.

Kontrol Lampu RGB dengan Deteksi Kata Kunci TinyML

Di command prompt saya menjalankan edge-impulse-daemon dan mengikuti wizard untuk menyiapkannya. Sekarang Nano muncul dalam daftar perangkat proyek, yang memungkinkan sampel diambil dan diunggah sebagai bagian dari dataset pelatihan/pengujian.

Kontrol Lampu RGB dengan Deteksi Kata Kunci TinyML

Mengumpulkan Sampel

Pelatihan model pembelajaran mesin membutuhkan data, dan cukup banyak. Saya ingin memiliki mode berikut untuk strip LED RGB:

Saya mendapat sekitar 1 menit suara untuk setiap mode di mana saya berulang kali mengucapkan kata pada interval 1-2 detik dan memisahkannya.

Kontrol Lampu RGB dengan Deteksi Kata Kunci TinyML
Kontrol Lampu RGB dengan Deteksi Kata Kunci TinyML

Namun hanya memiliki sampel ini tidak cukup, karena kebisingan latar belakang dan kata-kata lain akan menghasilkan pembacaan palsu. Untungnya, Edge Impulse sudah menyediakan dataset bawaan untuk kebisingan dan kata 'tidak diketahui', jadi saya menggunakan alat "Upload Existing Data" mereka untuk mengunggah file audio ini ke data pelatihan.

Kontrol Lampu RGB dengan Deteksi Kata Kunci TinyML

Terakhir, saya menyeimbangkan kembali dataset untuk memiliki pembagian 80-20 yang direkomendasikan untuk data pelatihan dan pengujian, masing-masing.

Kontrol Lampu RGB dengan Deteksi Kata Kunci TinyML

Melatih Model

Sekarang dengan satu jam data pelatihan dan banyak label, saatnya melatih model. Impulse yang saya desain mengambil suara sebagai data time-series dengan ukuran jendela 1 detik dan peningkatan jendela 500ms. Kemudian melalui blok MFCC ke dalam blok jaringan saraf Keras.

Kontrol Lampu RGB dengan Deteksi Kata Kunci TinyML

Blok MFCC memungkinkan Anda mengonfigurasi bagaimana audio akan diproses, beserta spektrogram yang menunjukkan frekuensi secara visual.

Kontrol Lampu RGB dengan Deteksi Kata Kunci TinyML

Saya membiarkan pengaturan jaringan saraf sebagian besar default, tetapi melakukan beberapa modifikasi. Pertama, saya mengubah ambang kepercayaan minimum dari 0.80 menjadi 0.70, dan menambahkan augmentasi data dalam bentuk kebisingan tambahan dan masking pita waktu. Ini membantu NN untuk menghindari overfitting model, karena memiliki data yang lebih bervariasi untuk bekerja.

Kontrol Lampu RGB dengan Deteksi Kata Kunci TinyML

Meluncurkan pada Arduino Nano 33 BLE Sense

Arduino Nano 33 BLE Sense bertindak sebagai mikrofon selalu aktif yang terus-menerus mengambil sampel audio dan mendeteksi apakah salah satu kata kunci telah diucapkan. Setelah satu ditemukan, kata kunci dikonversi menjadi indeks yang digunakan untuk mengdekode warna yang diinginkan. Untuk kata kunci nyala atau mati, LED diatur menjadi hitam atau abu-abu terang.

Saya mengunduh model sebagai library dan menambahkannya ke Arduino IDE, lalu mengompilasi dan memflash kode ke Nano.

Kontrol Lampu RGB dengan Deteksi Kata Kunci TinyML

Kode

RGBLEDKeywordDetectionC/C++
/* Edge Impulse Arduino examples * Copyright (c) 2020 EdgeImpulse Inc. * ... */ #define EIDSP_QUANTIZE_FILTERBANK 0 #define EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW 3 #include <PDM.h> #include <keyword_detection_inference.h> #include <map> #define CONFIDENCE_THRESHOLD 0.7 static const uint32_t colors[] = {0x00ff0000, 0x0000ff00, 0x000000ff}; // merah, hijau, biru enum Actions { LED_ON = 1, LED_OFF = 0, LED_RED = 2, LED_GREEN = 3, LED_BLUE = 4, NONE = 5 }; enum Functions { CHANGE_LED_ON_OFF = 0, CHANGE_LED_COLOR = 1, CHANGE_LED_NONE = 2 }; static const uint8_t redPin = 22, greenPin = 23, bluePin = 24; const std::map<Actions, Functions> actionToFunctionMap = { {LED_ON, CHANGE_LED_ON_OFF}, {LED_OFF, CHANGE_LED_ON_OFF}, {LED_RED, CHANGE_LED_COLOR}, {LED_GREEN, CHANGE_LED_COLOR}, {LED_BLUE, CHANGE_LED_COLOR}, {NONE, CHANGE_LED_NONE} }; const std::map<const char*, Actions> labelToActionMap = { {"on", LED_ON}, {"off", LED_OFF}, {"red", LED_RED}, {"green", LED_GREEN}, {"blue", LED_BLUE}, {"unknown", NONE}, {"noise", NONE} }; typedef struct { signed short *buffers[2]; unsigned char buf_select; unsigned char buf_ready; unsigned int buf_count; unsigned int n_samples; } inference_t; static inference_t inference; static bool record_ready = false; static signed short *sampleBuffer; static bool debug_nn = false; static int print_results = -(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW); void setup() { Serial.begin(115200); Serial.println("Edge Impulse Inferencing"); setPixelColor(0xaeae00); ei_printf("Inferencing settings:\n"); ei_printf("\tInterval: %.2f ms.\n", (float)EI_CLASSIFIER_INTERVAL_MS); ei_printf("\tFrame size: %d\n", EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE); ei_printf("\tSample length: %d ms.\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT / 16); ei_printf("\tNo. of classes: %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: Failed to setup audio sampling\r\n"); return; } } void loop() { bool m = microphone_inference_record(); if (!m) { ei_printf("ERR: Failed to record audio...\n"); return; } signal_t signal; signal.total_length = EI_CLASSIFIER_SLICE_SIZE; signal.get_data = µphone_audio_signal_get_data; ei_impulse_result_t result = {0}; EI_IMPULSE_ERROR r = run_classifier_continuous(&signal, &result, debug_nn); if (r != EI_IMPULSE_OK) { ei_printf("ERR: Failed to run classifier (%d)\n", r); return; } if (++print_results >= (EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)) { ei_printf("Predictions "); ei_printf("(DSP: %d ms., Classification: %d ms., Anomaly: %d ms.)", result.timing.dsp, result.timing.classification, result.timing.anomaly); ei_printf(": \n"); for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) { if(result.classification[ix].value > 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(" anomaly score: %.3f\n", result.anomaly); #endif print_results = 0; } } void 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()) return; auto itr2 = actionToFunctionMap.find(itr->second); if(itr2 == actionToFunctionMap.end()) return; switch(itr2->second) { case CHANGE_LED_ON_OFF: setPixelColor((itr->second) ? 0x5c5c5c : 0x00); break; case CHANGE_LED_COLOR: { uint32_t pixelColor = colors[itr->second - 2]; setPixelColor(pixelColor); } break; case CHANGE_LED_NONE: break; } } void ei_printf(const char *format, ...) { static char print_buf[1024] = { 0 }; va_list args; va_start(args, format); int r = vsnprintf(print_buf, sizeof(print_buf), format, args); va_end(args); if (r > 0) { Serial.write(print_buf); } } 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<bytesRead>> 1; i++) { inference.buffers[inference.buf_select][inference.buf_count++] = sampleBuffer[i]; if (inference.buf_count >= inference.n_samples) { inference.buf_select ^= 1; inference.buf_count = 0; inference.buf_ready = 1; } } } } static bool microphone_inference_start(uint32_t n_samples) { inference.buffers[0] = (signed short *)malloc(n_samples * sizeof(signed short)); if (inference.buffers[0] == NULL) { return false; } inference.buffers[1] = (signed short *)malloc(n_samples * sizeof(signed short)); if (inference.buffers[0] == NULL) { free(inference.buffers[0]); return false; } sampleBuffer = (signed short *)malloc((n_samples >> 1) * sizeof(signed short)); if (sampleBuffer == NULL) { free(inference.buffers[0]); free(inference.buffers[1]); return false; } inference.buf_select = 0; inference.buf_count = 0; inference.n_samples = n_samples; inference.buf_ready = 0; PDM.onReceive(&pdm_data_ready_inference_callback); PDM.setGain(80); PDM.setBufferSize((n_samples >> 1) * sizeof(int16_t)); if (!PDM.begin(1, EI_CLASSIFIER_FREQUENCY)) { ei_printf("Failed to start PDM!"); } record_ready = true; return true; } static bool microphone_inference_record(void) { bool ret = true; if (inference.buf_ready == 1) { ei_printf( "Error sample buffer overrun. Decrease the number of slices per model window "(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)\n"); ret = false; } while (inference.buf_ready == 0) { delay(1); } inference.buf_ready = 0; return ret; } static int microphone_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, length); return 0; } static void microphone_inference_end(void) { PDM.end(); free(inference.buffers[0]); free(inference.buffers[1]); free(sampleBuffer); } #if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR != EI_CLASSIFIER_SENSOR_MICROPHONE #error "Invalid model for current sensor." #endif 

Proses manufaktur

  1. Keamanan IoT Industri: Tren Utama dan Praktik Terbaik untuk 2020
  2. Edge & Cloud Computing dalam IoT: Gambaran Evolusi Ringkas
  3. Mengapa Edge Computing Esensial untuk Keberhasilan IoT
  4. Kontron KBox A-150-WKL: IoT Edge PC Tinggi Performa, Daya Rendah untuk Otomasi Industri
  5. Komputasi Edge: Mempercepat Penerapan AI di Tepi Jaringan
  6. Empat Langkah Terbukti untuk Memaksimalkan Keberhasilan Edge Computing di Pabrik Cerdas
  7. Microsoft Meluncurkan Azure Edge Zones untuk Beban Kerja IoT dan AI yang Didukung 5G
  8. Mengapa Open Source Mendorong Inovasi di Edge – eBook Esensial
  9. Sistem Deteksi Senjata Kimia Ultra-Sensitif untuk Ancaman Tingkat Rendah
  10. Mengapa Anda Harus Memelihara Alat Deteksi Gas dalam Kondisi Terbaik: 3 Alasan Esensial