Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Détection de mots-clés TinyML pour contrôler les lumières RVB

Composants et fournitures

Arduino Nano 33 BLE Sense
× 1

Applications et services en ligne

Edge Impulse Studio

À propos de ce projet

La Prémisse

L'apprentissage automatique à la périphérie est extrêmement utile pour créer des appareils capables d'accomplir des tâches « intelligentes » avec beaucoup moins de programmation et d'organigrammes logiques par rapport au code traditionnel. C'est pourquoi je voulais incorporer une détection de mots clés à la pointe qui puisse reconnaître certains mots, puis effectuer une tâche en fonction de ce qui a été dit.

Matériel

Ce projet n'a qu'un seul composant :un Arduino Nano 33 BLE Sense. La magie réelle se produit dans le modèle d'apprentissage automatique. L'Arduino Nano 33 BLE Sense regorge de capteurs, notamment un microphone, une IMU à 9 axes, un capteur environnemental et un capteur de geste/proximité/couleur/lumière ambiante (APDS-9960). Le microcontrôleur est un nRF52840 qui fonctionne à 64 MHz et contient 1 Mo de mémoire flash et 256 Ko de RAM. Ce projet utilise également sa LED RVB intégrée pour afficher la couleur actuelle.

Configuration d'Edge Impulse

J'ai commencé par créer un nouveau projet sur Edge Impulse, puis j'ai installé l'outil Edge Impulse CLI. Pour plus d'instructions sur la façon de procéder, visitez la page d'instructions d'installation. Cela permet à l'Arduino Nano de communiquer avec le service cloud pour recevoir des commandes et envoyer automatiquement les données du capteur. J'ai téléchargé le firmware Edge Impulse le plus récent et je l'ai flashé sur la carte en double-cliquant sur le bouton de réinitialisation pour le faire passer en mode chargeur de démarrage. Ensuite, j'ai exécuté flash_windows.bat pour le transférer.

Sur l'invite de commande, j'ai exécuté edge-impulse-daemon et suivi l'assistant pour le configurer. Maintenant, le Nano apparaît dans la liste des appareils du projet, ce qui permet de prélever et de télécharger des échantillons dans le cadre de l'ensemble de données d'entraînement/de test.

Collecte d'échantillons

L'entraînement d'un modèle d'apprentissage automatique nécessite des données, et une grande partie de celles-ci. Je voulais avoir les modes suivants pour la bande LED RVB :

  • Activé
  • Désactivé
  • Rouge
  • Vert
  • Bleu

J'ai obtenu environ 1 minute de son pour chaque mode où j'ai répété le mot à des intervalles de 1 à 2 secondes et les ai divisés.

Mais il ne suffit pas d'avoir ces échantillons, car le bruit de fond et d'autres mots donneront une fausse lecture. Heureusement, Edge Impulse fournit déjà un ensemble de données prédéfini pour le bruit et les mots « inconnus », j'ai donc utilisé leur outil « Télécharger les données existantes » pour télécharger ces fichiers audio dans les données d'entraînement.

Enfin, j'ai rééquilibré l'ensemble de données pour avoir la division 80-20 recommandée pour les données d'entraînement et de test, respectivement.

Formation du modèle

Maintenant armé d'une heure de données d'entraînement et de nombreuses étiquettes, il était temps d'entraîner un modèle. L'impulsion que j'ai conçue prend l'audio sous forme de données de série temporelle avec une taille de fenêtre de 1 seconde et une augmentation de fenêtre de 500 ms. Il passe ensuite à travers un bloc MFCC dans un bloc de réseau neuronal Keras.

Le bloc MFCC vous permet de configurer la façon dont l'audio sera traité, ainsi qu'un spectrogramme montrant les fréquences de manière visuelle.

J'ai laissé les paramètres du réseau de neurones par défaut, mais j'ai également apporté quelques modifications. Tout d'abord, j'ai changé le seuil de confiance minimum de 0,80 à 0,70 et j'ai ajouté un peu d'augmentation des données sous la forme de bandes de temps supplémentaires pour le bruit et le masquage. Cela aide le NN à éviter de surajuster le modèle, car il dispose de données plus diverses avec lesquelles travailler.

Déploiement sur l'Arduino Nano 33 BLE Sense

L'Arduino Nano 33 BLE Sense agit comme un microphone permanent qui échantillonne en continu l'audio et détecte si l'un des mots-clés a été prononcé. Une fois trouvé, le mot-clé est converti en un index qui est utilisé pour décoder la couleur désirée. Pour le mot-clé on ou off, le voyant est réglé sur noir ou sur gris clair.

J'ai téléchargé le modèle en tant que bibliothèque et l'ai ajouté à l'IDE Arduino, puis j'ai compilé et flashé le code sur le Nano.

Code

  • Détection de mots-clés RVBLED
RGBLEDKeywordDetectionC/C++
/* Exemples Edge Impulse Arduino * Copyright (c) 2020 EdgeImpulse Inc. * * L'autorisation est par la présente accordée, gratuitement, à toute personne obtenant une copie * de ce logiciel et des fichiers de documentation associés (le "Logiciel"), de traiter * dans le logiciel sans restriction, y compris, sans limitation, les droits * d'utiliser, copier, modifier, fusionner, publier, distribuer, sous-licencier et/ou vendre * des copies du logiciel, et d'autoriser les personnes à qui le logiciel est * fourni pour ce faire, sous réserve des conditions suivantes :* * L'avis de droit d'auteur ci-dessus et cet avis d'autorisation doivent être inclus dans * toutes les copies ou parties substantielles du logiciel. * * LE LOGICIEL EST FOURNI « EN L'ÉTAT », SANS GARANTIE D'AUCUNE SORTE, EXPRESSE OU * IMPLICITE, Y COMPRIS MAIS NON LIMITÉ AUX GARANTIES DE QUALITÉ MARCHANDE, * D'ADAPTATION À UN USAGE PARTICULIER ET D'ABSENCE DE CONTREFAÇON. EN AUCUN CAS LES * AUTEURS OU TITULAIRES DE DROITS D'AUTEUR NE SERONT RESPONSABLES DE TOUTE RÉCLAMATION, DOMMAGES OU AUTRE * RESPONSABILITÉ, QUE CE SOIT DANS UNE ACTION DE CONTRAT, DÉLIT OU AUTRE, DÉCOULANT DE, * DE OU EN CONNEXION AVEC LE LOGICIEL OU L'UTILISATION OU AUTRE AFFAIRES DANS LE * LOGICIEL. */// Si votre cible est limitée en mémoire supprimez cette macro pour économiser 10K RAM#define EIDSP_QUANTIZE_FILTERBANK 0/** * Définit le nombre de tranches par fenêtre de modèle. Par exemple. une fenêtre de modèle de 1000 ms * avec tranches par fenêtre de modèle définie sur 4. Donne une taille de tranche de 250 ms. * Pour plus d'informations :https://docs.edgeimpulse.com/docs/continuous-audio-sampling */#define EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW 3/* Comprend ------------------- ---------------------------------------------- */#include #include #include 
#define CONFIDENCE_THRESHOLD 0.7static const uint32_t colours[] ={0x00ff0000, 0x0000ff00, 0x000000ff} ; // rouge, vert, bleuenum 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 actionToFunctionMap ={ {LED_ON, CHANGE_LED_ON_OFF}, {LED_OFF, CHANGE_LED_ON_OFF}, {LED_RED, CHANGE_LED_GREEN}, {LED_LED_GREEN}, }, {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}} ;/** Tampons audio, pointeurs et sélecteurs */typedef struct { short signé *buffers[2] ; caractère non signé buf_select ; caractère non signé buf_ready ; int buf_count non signé ; unsigned int n_samples;} inference_t;static inference_t inference;static bool record_ready =false;static signé short *sampleBuffer;static bool debug_nn =false; // Définissez ceci sur true pour voir par exemple fonctionnalités générées à partir du signal statique brut int print_results =-(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW);/** * @brief Arduino setup function */void setup(){ // mettez votre code de configuration ici, à exécuter une fois :Serial.begin(115200); Serial.println("Inférence d'impulsion de bord"); setPixelColor(0xaaee00); // résumé des paramètres d'inférence (à partir de model_metadata.h) ei_printf("Paramètres d'inférence :\n"); ei_printf("\tInterval:%.2f ms.\n", (float)EI_CLASSIFIER_INTERVAL_MS); ei_printf("\tTaille du cadre :%d\n", EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE); ei_printf("\tLongueur de l'échantillon :%d ms.\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT / 16); ei_printf("\tNombre de 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 :échec de la configuration de l'échantillonnage audio\r\n"); retourner; }}/** * Fonction principale @brief Arduino. Exécute la boucle d'inférence. */void loop(){ bool m =microphone_inference_record(); if (!m) { ei_printf("ERR :échec de l'enregistrement audio...\n"); retourner; } signal_t ​​signal ; signal.total_length =EI_CLASSIFIER_SLICE_SIZE ; signal.get_data =µphone_audio_signal_get_data; résultat ei_impulse_result_t ={0} ; EI_IMPULSE_ERROR r =run_classifier_continuous(&signal, &result, debug_nn); if (r !=EI_IMPULSE_OK) { ei_printf("ERR :échec de l'exécution du classificateur (%d)\n", r); retourner; } if (++print_results>=(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)) { // imprime les prédictions ei_printf("Prédictions "); ei_printf("(DSP :%d ms., Classification :%d ms., Anomaly :%d ms.)", result.timing.dsp, result.timing.classification, result.timing.anomaly); ei_printf(":\n"); pour (size_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(" score d'anomalie :%.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); Pause; case CHANGE_LED_COLOR :{ uint32_t pixelColor =couleurs[itr->second - 2] ; setPixelColor(pixelColor); } Pause; cas CHANGE_LED_NONE :pause ; }}/** * La fonction @brief Printf utilise vsnprintf et la sortie en utilisant Arduino Serial * * @param[in] format Liste d'arguments variables */void ei_printf(const char *format, ...) { static char print_buf[1024] ={ 0 } ; va_list arguments ; va_start(args, format); int r =vsnprintf(print_buf, sizeof(print_buf), format, args); va_end(args); if (r> 0) { Serial.write(print_buf); }}/** * @brief PDM buffer full callback * Obtenir les données et appeler le rappel du thread audio */static void pdm_data_ready_inference_callback(void){ int bytesAvailable =PDM.available(); // lecture dans le tampon d'échantillons 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 Init inferencing struct et setup/start PDM * * @param[in] n_samples Les n échantillons * * @return { description_of_the_return_value } */static bool microphone_inference_start(uint32_t n_samples){ inference.buffers[ 0] =(signé court *)malloc(n_samples * sizeof(signé court)); 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]); renvoie faux ; } sampleBuffer =(signed short *)malloc((n_samples>> 1) * sizeof(signed short)); if (sampleBuffer ==NULL) { free(inference.buffers[0]); free(inference.buffers[1]); renvoie faux ; } inference.buf_select =0; inference.buf_count =0; inférence.n_samples =n_samples ; inference.buf_ready =0; // configurer le rappel de réception de données PDM.onReceive(&pdm_data_ready_inference_callback); // éventuellement définir le gain, la valeur par défaut est 20 PDM.setGain(80); PDM.setBufferSize((n_samples>> 1) * sizeof(int16_t)); // initialiser PDM avec :// - un canal (mode mono) // - une fréquence d'échantillonnage de 16 kHz if (!PDM.begin(1, EI_CLASSIFIER_FREQUENCY)) { ei_printf("Impossible de démarrer PDM!"); } record_ready =vrai; return true;}/** * @brief Attendre les nouvelles données * * @return True une fois terminé */static bool microphone_inference_record(void){ bool ret =true; if (inference.buf_ready ==1) { ei_printf( "Erreur de dépassement de la mémoire tampon d'échantillon. Diminuer le nombre de tranches par fenêtre de modèle " "(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)\n"); ret =faux ; } while (inference.buf_ready ==0) { delay(1); } inference.buf_ready =0; return ret;}/** * Obtenir les données brutes du signal audio */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 , longueur); return 0;}/** * @brief Arrête PDM et libère les tampons */static void microphone_inference_end(void){ PDM.end(); free(inference.buffers[0]); free(inference.buffers[1]); libre(sampleBuffer);}#if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR !=EI_CLASSIFIER_SENSOR_MICROPHONE#error "Modèle invalide pour le capteur actuel."#endif

Processus de fabrication

  1. Conseils et tendances de sécurité IIoT pour 2020
  2. Cloud et edge computing pour l'IoT :un bref historique
  3. Pourquoi l'informatique de pointe pour l'IoT ?
  4. Avantages de l'Edge Computing pour la cristallisation de l'IA
  5. Quatre étapes pour garantir le succès de l'Edge Computing
  6. Microsoft lance Azure Edge Zones pour les applications 5G
  7. Le besoin d'open source à la périphérie (eBook)
  8. Système de détection de produits chimiques pour les faibles niveaux de concentration
  9. 3 raisons d'entretenir les dispositifs de détection de gaz