Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

TinyML-Schlüsselworterkennung zur Steuerung von RGB-Lichtern

Komponenten und Verbrauchsmaterialien

Arduino Nano 33 BLE Sense
× 1

Apps und Onlinedienste

Edge Impulse Studio

Über dieses Projekt

Die Prämisse

Maschinelles Lernen am Edge ist äußerst nützlich, um Geräte zu erstellen, die im Vergleich zu herkömmlichem Code „intelligente“ Aufgaben mit weit weniger Programmierung und logischen Flussdiagrammen erledigen können. Aus diesem Grund wollte ich eine moderne Schlüsselworterkennung integrieren, die bestimmte Wörter erkennt und dann eine Aufgabe basierend auf dem Gesagten ausführt.

Hardware

Dieses Projekt hat nur eine Komponente:einen Arduino Nano 33 BLE Sense. Die eigentliche Magie geschieht im Modell des maschinellen Lernens. Der Arduino Nano 33 BLE Sense ist voller Sensoren, darunter ein Mikrofon, eine 9-Achsen-IMU, ein Umgebungssensor und ein Gesten-/Näherungs-/Farb-/Umgebungslichtsensor (APDS-9960). Der Mikrocontroller darauf ist ein nRF52840, der mit 64 MHz läuft und 1 MB Flash-Speicher und 256 KB RAM enthält. Dieses Projekt verwendet auch seine integrierte RGB-LED, um die aktuelle Farbe anzuzeigen.

Kantenimpuls einrichten

Ich begann mit der Erstellung eines neuen Projekts auf Edge Impulse und installierte dann das Edge Impulse CLI-Tool. Weitere Anweisungen dazu finden Sie auf der Seite mit den Installationsanweisungen. Dadurch kann der Arduino Nano mit dem Cloud-Dienst kommunizieren, um Befehle zu empfangen und Sensordaten automatisch zu senden. Ich habe die neueste Edge Impulse-Firmware heruntergeladen und auf das Board geflasht, indem ich auf die Reset-Taste doppelklicke, um sie in den Bootloader-Modus zu versetzen. Dann habe ich flash_windows.bat ausgeführt es zu übertragen.

Drüben auf der Eingabeaufforderung habe ich edge-impulse-daemon . ausgeführt und folgen Sie dem Assistenten, um es einzurichten. Jetzt wird der Nano in der Geräteliste des Projekts angezeigt, wodurch Proben entnommen und als Teil des Trainings-/Testdatensatzes hochgeladen werden können.

Proben sammeln

Das Trainieren eines Modells für maschinelles Lernen erfordert Daten, und zwar eine ganze Menge davon. Ich wollte die folgenden Modi für den RGB-LED-Streifen haben:

  • Ein
  • Aus
  • Rot
  • Grün
  • Blau

Ich bekam ungefähr 1 Minute Ton für jeden Modus, in dem ich das Wort wiederholt in 1-2-Sekunden-Intervallen sagte und sie aufteilte.

Es reicht jedoch nicht aus, nur diese Samples zu haben, da Hintergrundgeräusche und andere Wörter einen falschen Messwert liefern. Zum Glück bietet Edge Impulse bereits einen vorgefertigten Datensatz für Rauschen und "unbekannte" Wörter, daher habe ich das Tool "Vorhandene Daten hochladen" verwendet, um diese Audiodateien in die Trainingsdaten hochzuladen.

Schließlich habe ich den Datensatz neu ausbalanciert, um die empfohlene Aufteilung von 80-20 für Trainings- bzw. Testdaten zu erhalten.

Trainieren des Modells

Ausgerüstet mit einer Stunde Trainingsdaten und vielen Labels war es nun an der Zeit, ein Modell zu trainieren. Der von mir entworfene Impuls nimmt Audio als Zeitreihendaten mit einer Fenstergröße von 1 Sekunde und einer Fenstererhöhung von 500 ms auf. Es geht dann durch einen MFCC-Block in einen neuronalen Netzwerkblock von Keras.

Mit dem MFCC-Block können Sie konfigurieren, wie das Audio verarbeitet wird, zusammen mit einem Spektogramm, das die Frequenzen visuell anzeigt.

Ich habe die neuronalen Netzwerkeinstellungen größtenteils als Standard belassen, aber auch ein paar Änderungen vorgenommen. Zuerst habe ich den minimalen Konfidenzschwellenwert von 0,80 auf 0,70 geändert und ein wenig Datenerweiterung in Form von zusätzlichem Rauschen und Maskierungszeitbändern hinzugefügt. Dies hilft dem NN, eine Überanpassung des Modells zu vermeiden, da es über vielfältigere Daten verfügt, mit denen es arbeiten kann.

Bereitstellung auf dem Arduino Nano 33 BLE Sense

Das Arduino Nano 33 BLE Sense fungiert als ständig eingeschaltetes Mikrofon, das kontinuierlich den Ton abtastet und erkennt, ob eines der Schlüsselwörter gesprochen wurde. Sobald eine gefunden wurde, wird das Schlüsselwort in einen Index umgewandelt, der verwendet wird, um die gewünschte Farbe zu entschlüsseln. Für das Schlüsselwort on oder off wird die LED entweder auf schwarz oder hellgrau eingestellt.

Ich habe das Modell als Bibliothek heruntergeladen und der Arduino-IDE hinzugefügt, dann den Code kompiliert und auf den Nano geflasht.

Code

  • RGBLEDKeyword-Erkennung
RGBLEDKeywordDetectionC/C++
/* Edge Impulse Arduino Beispiele * Copyright (c) 2020 EdgeImpulse Inc. * * Hiermit wird jeder Person kostenlos die Erlaubnis erteilt, eine Kopie * dieser Software und der zugehörigen Dokumentationsdateien (die "Software") zu erhalten, ohne Einschränkung * mit der Software zu handeln, einschließlich und ohne Einschränkung der Rechte * zur Nutzung, zum Kopieren, Modifizieren, Zusammenführen, Veröffentlichen, Verteilen, Unterlizenzieren und/oder Verkaufen * von Kopien der Software, und Personen zu gestatten, denen die Software * dazu bereitgestellt, vorbehaltlich der folgenden Bedingungen:* * Der obige Urheberrechtshinweis und dieser Erlaubnishinweis müssen in * allen Kopien oder wesentlichen Teilen der Software enthalten sein. * * DIE SOFTWARE WIRD "WIE BESEHEN" BEREITGESTELLT, OHNE JEGLICHE AUSDRÜCKLICHE ODER * STILLSCHWEIGENDE GEWÄHRLEISTUNG, EINSCHLIESSLICH, ABER NICHT BESCHRÄNKT AUF DIE GEWÄHRLEISTUNG DER MARKTFÄHIGKEIT, * EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND NICHTVERLETZUNG VON VERLETZUNGEN. IN KEINEM FALL HABEN DIE * AUTOREN ODER URHEBERRECHTSINHABER FÜR JEGLICHE ANSPRÜCHE, SCHÄDEN ODER ANDERE * HAFTUNG, OB AUS VERTRAGLICHEM, SCHLECHTER ODER ANDERWEITIGEM, DIE AUS ODER IN VERBINDUNG MIT DER SOFTWARE ODER DER NUTZUNG ODER ANDEREM HERGESTELLT WERDEN HANDELN IN DER * SOFTWARE. */// Wenn Ihr Zielspeicher begrenzt ist, entfernen Sie dieses Makro, um 10K RAM zu sparen#define EIDSP_QUANTIZE_FILTERBANK 0/** * Definieren Sie die Anzahl der Slices pro Modellfenster. Z.B. ein Modellfenster von 1000 ms * mit Schnitten pro Modellfenster auf 4 gesetzt. Ergibt eine Schnittgröße von 250 ms. * Weitere Informationen:https://docs.edgeimpulse.com/docs/continuous-audio-sampling */#define EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW 3/* Enthält ------------------- --------------------------------------------------------- */#include #include #include 
#define CONFIDENCE_THRESHOLD 0.7static const uint32_t colors[] ={0x00ff0000, 0x0000ff00, 0x000000ff}; // rot, grün, blueenum Aktionen { 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_COLOR_COEN, CHANGE_LED_COLOR}, }, {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}};/** Audiopuffer, Zeiger und Selektoren */typedef struct { Vorzeichen kurz *Puffer[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; // Setzen Sie dies auf true, um z.B. Funktionen, die aus dem Rohsignal generiert werdenstatic int print_results =-(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW);/** * @brief Arduino-Setup-Funktion */void setup () {// Geben Sie Ihren Setup-Code hier ein, um ihn einmal auszuführen:Serial.begin(115200); Serial.println ("Edge Impulse Inferencing"); setPixelColor(0xaeae00); // Zusammenfassung der Inferenzeinstellungen (von model_metadata.h) ei_printf("Inferencing settings:\n"); ei_printf("\tInterval:%.2f ms.\n", (float)EI_CLASSIFIER_INTERVAL_MS); ei_printf("\tFramegröße:%d\n", EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE); ei_printf("\tProbenlänge:%d ms.\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT / 16); ei_printf("\tAnzahl der Klassen:%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:Audio-Sampling konnte nicht eingerichtet werden\r\n"); Rückkehr; }}/** * @brief Arduino-Hauptfunktion. Führt die Inferenzschleife aus. */void loop () { bool m =microphone_inference_record (); if (!m) { ei_printf("ERR:Audioaufnahme fehlgeschlagen...\n"); Rückkehr; } signal_t-Signal; signal.total_length =EI_CLASSIFIER_SLICE_SIZE; signal.get_data =µphone_audio_signal_get_data; ei_impulse_result_t Ergebnis ={0}; EI_IMPULSE_ERROR r =run_classifier_continuous(&signal, &result, debug_nn); if (r !=EI_IMPULSE_OK) { ei_printf("ERR:Klassifizierer (%d) konnte nicht ausgeführt werden\n", r); Rückkehr; } if (++print_results>=(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)) { // drucke die Vorhersagen ei_printf("Predictions"); ei_printf("(DSP:%d ms., Klassifizierung:%d ms., Anomalie:%d ms.)", result.timing.dsp, result.timing.classification, result.timing.anomaly); ei_printf(:\n"); for (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(" Anomalie-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* KlassifizierungLabel){ auto itr =labelToActionMap.find(classificationLabel); if(itr ==labelToActionMap.end()) zurück; auto itr2 =actionToFunctionMap.find(itr->second); if(itr2 ==actionToFunctionMap.end()) zurück; switch(itr2->second) { case CHANGE_LED_ON_OFF:setPixelColor((itr->second) ? 0x5c5c5c:0x00); brechen; case CHANGE_LED_COLOR:{ uint32_t pixelColor =colors[itr->second - 2]; setPixelColor (PixelColor); } brechen; Fall CHANGE_LED_NONE:Pause; }}/** * @brief Printf-Funktion verwendet vsnprintf und Ausgabe mit Arduino Serial * * @param[in] format Variable Argumentliste */void ei_printf(const char *format, ...) { static char print_buf[1024] ={0}; va_list-Argumente; 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-Puffer vollständiger Callback * Hole Daten und rufe Audio-Thread-Callback auf */static void pdm_data_ready_inference_callback(void){ int bytesAvailable =PDM.available(); // in den Sample-Puffer einlesen 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 und setup/start PDM * * @param[in] n_samples Die n Samples * * @return { description_of_the_return_value } */static bool microphone_inference_start(uint32_t n_samples){ inference.buffers[ 0] =(Short mit Vorzeichen *)malloc(n_samples * sizeof(Short mit Vorzeichen)); 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]); falsch zurückgeben; } SampleBuffer =(Short mit Vorzeichen *)malloc((n_samples>> 1) * sizeof(Short mit Vorzeichen)); if (sampleBuffer ==NULL) { free(inference.buffers[0]); frei(inference.buffers[1]); falsch zurückgeben; } inference.buf_select =0; inference.buf_count =0; schlussfolgerung.n_samples =n_samples; inference.buf_ready =0; // Datenempfangs-Callback konfigurieren PDM.onReceive(&pdm_data_ready_inference_callback); // optional die Verstärkung einstellen, standardmäßig auf 20 PDM.setGain(80); PDM.setBufferSize((n_samples>> 1) * sizeof(int16_t)); // PDM initialisieren mit:// - einem Kanal (Monomodus) // - einer Abtastrate von 16 kHz if (!PDM.begin(1, EI_CLASSIFIER_FREQUENCY)) { ei_printf("Fehler beim Starten von PDM!"); } record_ready =wahr; return true;}/** * @brief Auf neue Daten warten * * @return True wenn fertig */static bool microphone_inference_record(void){ bool ret =true; if (inference.buf_ready ==1) { ei_printf( "Fehler Sample Buffer Overrun. Verringern Sie die Anzahl der Slices pro Modellfenster " "(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)\n"); ret =falsch; aufrechtzuerhalten. Während (inference.buf_ready ==0) { Verzögerung (1); } inference.buf_ready =0; return ret;}/** * Rohdaten des Audiosignals abrufen */static int microfon_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 , Länge); return 0;}/** * @brief PDM stoppen und Puffer freigeben */static void microphone_inference_end(void){ PDM.end(); free(inference.buffers[0]); frei(inference.buffers[1]); free(sampleBuffer);}#if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR !=EI_CLASSIFIER_SENSOR_MICROPHONE#error "Ungültiges Modell für Stromsensor."#endif

Herstellungsprozess

  1. Tipps und Trends zur IIoT-Sicherheit für 2020
  2. Cloud- und Edge-Computing für das IoT:eine kurze Geschichte
  3. Warum Edge Computing für das IoT?
  4. Kontrons KBox A-150-WKL für datenintensive IoT Edge-Anwendungen
  5. Edge-Computing-Vorteile für die KI-Kristallisation
  6. Vier Schritte für den Erfolg beim Edge Computing
  7. Microsoft führt Azure Edge Zones für 5G-Anwendungen ein
  8. Die Notwendigkeit von Open Source am Edge (eBook)
  9. System zum Nachweis von Chemikalien für geringe Konzentrationen
  10. 3 Gründe für die Wartung von Gaswarngeräten