Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Detección de palabras clave TinyML para controlar las luces RGB

Componentes y suministros

Arduino Nano 33 BLE Sense
× 1

Aplicaciones y servicios en línea

Edge Impulse Studio

Acerca de este proyecto

La premisa

El aprendizaje automático en el borde es extremadamente útil para crear dispositivos que pueden realizar tareas "inteligentes" con mucha menos programación y diagramas de flujo lógicos en comparación con el código tradicional. Es por eso que quería incorporar la detección de palabras clave en el borde que pueda reconocer ciertas palabras y luego realizar una tarea basada en lo que se dijo.

Hardware

Este proyecto solo tiene un componente:un Arduino Nano 33 BLE Sense. La magia real ocurre en el modelo de aprendizaje automático. El Arduino Nano 33 BLE Sense está lleno de sensores, que incluyen un micrófono, una IMU de 9 ejes, un sensor ambiental y un sensor de gestos / proximidad / color / luz ambiental (APDS-9960). El microcontrolador es un nRF52840 que se ejecuta a 64MHz y contiene 1MB de memoria flash y 256KB de RAM. Este proyecto también utiliza su LED RGB integrado para mostrar el color actual.

Configuración de Edge Impulse

Comencé creando un nuevo proyecto en Edge Impulse y luego instalé la herramienta CLI de Edge Impulse. Para obtener más instrucciones sobre cómo hacerlo, visite la página de instrucciones de instalación. Esto permite que Arduino Nano se comunique con el servicio en la nube para recibir comandos y enviar datos de sensores automáticamente. Descargué el firmware de Edge Impulse más reciente y lo transmití a la placa haciendo doble clic en el botón de reinicio para que ingrese al modo de cargador de arranque. Luego ejecuté flash_windows.bat para transferirlo.

En el símbolo del sistema ejecuté edge-impulse-daemon y siguió al asistente para configurarlo. Ahora el Nano aparece en la lista de dispositivos del proyecto, lo que permite tomar y cargar muestras como parte del conjunto de datos de entrenamiento / prueba.

Recolección de muestras

El entrenamiento de un modelo de aprendizaje automático requiere datos y bastante. Quería tener los siguientes modos para la tira de LED RGB:

  • En
  • Desactivado
  • Rojo
  • Verde
  • Azul

Obtuve aproximadamente 1 minuto de sonido para cada modo en el que repetí repetidamente la palabra en intervalos de 1-2 segundos y los dividí.

Pero tener estas muestras no es suficiente, ya que el ruido de fondo y otras palabras darán una lectura falsa. Afortunadamente, Edge Impulse ya proporciona un conjunto de datos prediseñado para el ruido y las palabras "desconocidas", por lo que utilicé su herramienta "Cargar datos existentes" para cargar estos archivos de audio en los datos de entrenamiento.

Finalmente, reequilibré el conjunto de datos para tener la división recomendada 80-20 para los datos de entrenamiento y prueba, respectivamente.

Entrenamiento del modelo

Ahora, armado con una hora de datos de entrenamiento y muchas etiquetas, llegó el momento de entrenar un modelo. El impulso que diseñé toma audio como datos de series de tiempo con un tamaño de ventana de 1 segundo y un aumento de ventana de 500ms. Luego pasa a través de un bloque MFCC a un bloque de red neuronal de Keras.

El bloque MFCC permite configurar cómo se procesará el audio, junto con un espectograma que muestra las frecuencias de forma visual.

Dejé la configuración de la red neuronal como en su mayoría predeterminada, pero también hice algunas modificaciones. Primero, cambié el umbral mínimo de confianza de 0,80 a 0,70 y agregué un poco de aumento de datos en forma de ruido adicional y bandas de tiempo de enmascaramiento. Esto ayuda a la NN a evitar un ajuste excesivo del modelo, ya que tiene datos más diversos con los que trabajar.

Implementación en Arduino Nano 33 BLE Sense

El Arduino Nano 33 BLE Sense actúa como un micrófono siempre activo que muestrea continuamente el audio y detecta si se ha hablado una de las palabras clave. Una vez que se encuentra uno, la palabra clave se convierte en un índice que se utiliza para decodificar el color deseado. Para la palabra clave de encendido o apagado, el LED se establece en negro o gris claro.

Descargué el modelo como una biblioteca y lo agregué al IDE de Arduino, luego compilé y mostré el código al Nano.

Código

  • RGBLEDKeywordDetection
RGBLEDKeywordDetection C / C ++
 / * Ejemplos de Edge Impulse Arduino * Copyright (c) 2020 EdgeImpulse Inc. * * Por la presente se otorga permiso, sin cargo, a cualquier persona que obtenga una copia * de este software y los archivos de documentación asociados (el "Software"), negociar * en el Software sin restricciones, incluidos, entre otros, los derechos * de uso, copia, modificar, fusionar, publicar, distribuir, sublicenciar y / o vender * copias del Software, y permitir a las personas a las que pertenece el Software * proporcionado para hacerlo, sujeto a las siguientes condiciones:* * El aviso de copyright anterior y este aviso de permiso se incluirán en * todas las copias o partes sustanciales del Software. * * EL SOFTWARE SE PROPORCIONA "TAL CUAL", SIN GARANTÍA DE NINGÚN TIPO, EXPRESA O * IMPLÍCITA, INCLUYENDO PERO NO LIMITADO A LAS GARANTÍAS DE COMERCIABILIDAD, * IDONEIDAD PARA UN PROPÓSITO PARTICULAR Y NO INFRACCIÓN. EN NINGÚN CASO LOS * AUTORES O TITULARES DE LOS DERECHOS DE AUTOR SERÁN RESPONSABLES DE CUALQUIER RECLAMO, DAÑOS U OTRA * RESPONSABILIDAD, YA SEA EN UNA ACCIÓN DE CONTRATO, AGRAVIO O DE OTRO MODO, QUE SURJA DE, * FUERA DE O EN RELACIÓN CON EL SOFTWARE O EL USO U OTROS NEGOCIACIONES EN EL SOFTWARE *. * /// Si su objetivo tiene memoria limitada, elimine esta macro para ahorrar 10K de RAM. # Defina EIDSP_QUANTIZE_FILTERBANK 0 / ** * Defina el número de cortes por ventana de modelo. P.ej. una ventana de modelo de 1000 ms * con cortes por ventana de modelo establecida en 4. Da como resultado un tamaño de corte de 250 ms. * Para más información:https://docs.edgeimpulse.com/docs/continuous-audio-sampling * / # define EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW 3 / * Incluye ------------------- --------------------------------------------- * / # incluir  #include  #include 
 #define CONFIDENCE_THRESHOLD 0.7static const uint32_t colors [] ={0x00ff0000, 0x0000ff00, 0x000000ff}; // rojo, verde, blueenum Acciones {LED_ON =1, LED_OFF =0, LED_RED =2, LED_GREEN =3, LED_BLUE =4, NONE =5}; Funciones de enumeración {CHANGE_LED_ON_OFF =0, CHANGE_LED_COLOR =1, CHANGE_LEDONE =2}; static 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_GORLED_CAMBIO }, {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}}; / ** Búferes de audio, punteros y selectores * / typedef struct {búferes cortos * firmados [2]; char sin firmar buf_select; char sin firmar buf_ready; unsigned int buf_count; unsigned int n_samples;} inference_t; static inference_t inference; static bool record_ready =false; static firmó corto * sampleBuffer; static bool debug_nn =false; // Establezca esto en verdadero para ver, por ejemplo, características generadas a partir de signalstatic sin procesar int print_results =- (EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW); / ** * @brief función de configuración de Arduino * / void setup () {// ponga su código de configuración aquí, para que se ejecute una vez:Serial.begin (115200); Serial.println ("Inferencia de impulso de borde"); setPixelColor (0xaeae00); // resumen de la configuración de inferencia (de model_metadata.h) ei_printf ("Configuración de inferencia:\ n"); ei_printf ("\ tIntervalo:% .2f ms. \ n", (flotante) EI_CLASSIFIER_INTERVAL_MS); ei_printf ("\ tTamaño del marco:% d \ n", EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE); ei_printf ("\ tLongitud de la muestra:% d ms. \ n", EI_CLASSIFIER_RAW_SAMPLE_COUNT / 16); ei_printf ("\ tNo. de clases:% d \ n", sizeof (ei_classifier_inferencing_categories) / sizeof (ei_classifier_inferencing_categories [0])); run_classifier_init (); if (inicio_inferencia_de_micrófono (EI_CLASSIFIER_SLICE_SIZE) ==false) {ei_printf ("ERR:No se pudo configurar el muestreo de audio \ r \ n"); regreso; }} / ** * @brief Función principal de Arduino. Ejecuta el ciclo de inferencia. * / bucle vacío () {bool m =registro_inferencia_micrófono (); if (! m) {ei_printf ("ERR:Error al grabar audio ... \ n"); regreso; } señal_t señal; signal.total_length =EI_CLASSIFIER_SLICE_SIZE; signal.get_data =&micrófono_audio_signal_get_data; ei_impulse_result_t result ={0}; EI_IMPULSE_ERROR r =run_classifier_continuous (&señal, &resultado, debug_nn); if (r! =EI_IMPULSE_OK) {ei_printf ("ERR:No se pudo ejecutar el clasificador (% d) \ n", r); regreso; } if (++ print_results> =(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)) {// imprime las predicciones ei_printf ("Predictions"); ei_printf ("(DSP:% d ms., Clasificación:% d ms., Anomalía:% d ms.)", result.timing.dsp, result.timing.classification, result.timing.anomaly); ei_printf (":\ n"); para (tamaño_t ix =0; ix  CONFIDENCE_THRESHOLD) {realizarAcción (resultado.clasificación [ix] .etiqueta); } ei_printf ("% s:% .5f \ n", resultado.clasificación [ix] .etiqueta, resultado.clasificación [ix] .valor); } #if EI_CLASSIFIER_HAS_ANOMALY ==1 ei_printf ("puntuación de anomalía:% .3f \ n", result.anomaly); # endif print_results =0; }} void setPixelColor (uint32_t c) {analogWrite (redPin, 255 - (c>> 16)); analogWrite (greenPin, 255 - ((c>> 8) y 0xff)); analogWrite (bluePin, 255 - (c &0xff));} void performAction (const char * clasificacionLabel) {auto itr =labelToActionMap.find (clasificacionLabel); if (itr ==labelToActionMap.end ()) return; auto itr2 =actionToFunctionMap.find (itr-> segundo); if (itr2 ==actionToFunctionMap.end ()) return; switch (itr2-> segundo) {case CHANGE_LED_ON_OFF:setPixelColor ((itr-> second)? 0x5c5c5c:0x00); descanso; case CHANGE_LED_COLOR:{uint32_t pixelColor =colors [itr-> second - 2]; setPixelColor (pixelColor); } descanso; case CHANGE_LED_NONE:romper; }} / ** * La función @brief Printf usa vsnprintf y la salida usa Arduino Serial * * @param [in] format Lista de argumentos variables * / void ei_printf (const char * format, ...) {static char print_buf [1024] ={0}; va_list args; va_start (argumentos, formato); int r =vsnprintf (print_buf, sizeof (print_buf), formato, argumentos); va_end (argumentos); if (r> 0) {Serial.write (print_buf); }} / ** * @brief Devolución de llamada completa del búfer de PDM * Obtener datos y llamar a la devolución de llamada del hilo de audio * / static void pdm_data_ready_inference_callback (void) {int bytesAvailable =PDM.available (); // leer en el búfer de muestra 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; inference.buf_count =0; inference.buf_ready =1; }}}} / ** * @brief Inicializar estructura de inferencia y configurar / iniciar PDM * * @param [in] n_samples Las n muestras * * @return {description_of_the_return_value} * / static bool micrófono_inference_start (uint32_t n_samples) {inference.buffers [ 0] =(con signo corto *) malloc (n_samples * sizeof (con signo corto)); if (inference.buffers [0] ==NULL) {return false; } inference.buffers [1] =(signo corto *) malloc (n_samples * sizeof (firmado corto)); if (inference.buffers [0] ==NULL) {free (inference.buffers [0]); falso retorno; } sampleBuffer =(short firmado *) malloc ((n_samples>> 1) * sizeof (short firmado)); if (sampleBuffer ==NULL) {free (inference.buffers [0]); libre (inferencia.buffers [1]); falso retorno; } inference.buf_select =0; inference.buf_count =0; inference.n_samples =n_samples; inference.buf_ready =0; // configurar la devolución de llamada de recepción de datos PDM.onReceive (&pdm_data_ready_inference_callback); // establece opcionalmente la ganancia, por defecto es 20 PDM.setGain (80); PDM.setBufferSize ((n_samples>> 1) * sizeof (int16_t)); // inicializar PDM con:// - un canal (modo mono) // - una frecuencia de muestreo de 16 kHz if (! PDM.begin (1, EI_CLASSIFIER_FREQUENCY)) {ei_printf ("¡Error al iniciar PDM!"); } record_ready =true; return true;} / ** * @brief Esperar nuevos datos * * @return True cuando termine * / static bool micrófono_inferencia_record (void) {bool ret =true; if (inference.buf_ready ==1) {ei_printf ("Error de saturación del búfer de muestra. Disminuir el número de cortes por ventana de modelo" "(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW) \ n"); ret =falso; } while (inference.buf_ready ==0) {delay (1); } inference.buf_ready =0; return ret;} / ** * Obtener datos de señales de audio sin procesar * / static int micrófono_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 , longitud); return 0;} / ** * @brief Detener PDM y liberar búferes * / static void micrófono_inferencia_end (void) {PDM.end (); libre (inferencia.buffers [0]); libre (inferencia.buffers [1]); free (sampleBuffer);} # si! definido (EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR! =EI_CLASSIFIER_SENSOR_MICROPHONE # error "Modelo no válido para sensor actual". # Endif 

Proceso de manufactura

  1. Tendencias y consejos de seguridad de IIoT para 2020
  2. Computación perimetral y en la nube para IoT:una breve historia
  3. ¿Por qué Edge Computing para IoT?
  4. Kontrons KBox A-150-WKL para aplicaciones IoT Edge con uso intensivo de datos
  5. Núcleos de brazo diseñados para dispositivos TinyML
  6. Beneficios del Edge Computing para la cristalización de la IA
  7. Cuatro pasos para garantizar el éxito en Edge Computing
  8. Microsoft lanza Azure Edge Zones para aplicaciones 5G
  9. La necesidad del código abierto en el perímetro (eBook)
  10. Sistema de detección química para bajos niveles de concentración
  11. 3 razones para mantener los dispositivos de detección de gas