Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

TinyML-zoekwoorddetectie voor het regelen van RGB-verlichting

Componenten en benodigdheden

Arduino Nano 33 BLE Sense
× 1

Apps en online services

Edge Impulse Studio

Over dit project

Het pand

Machine learning aan de rand is uiterst nuttig voor het maken van apparaten die "intelligente" taken kunnen uitvoeren met veel minder programmering en logische stroomdiagrammen in vergelijking met traditionele code. Daarom wilde ik een uiterst geavanceerde zoekwoorddetectie gebruiken die bepaalde woorden kan herkennen en vervolgens een taak kan uitvoeren op basis van wat er is gezegd.

Hardware

Dit project heeft slechts één onderdeel:een Arduino Nano 33 BLE Sense. De echte magie vindt plaats in het machine learning-model. De Arduino Nano 33 BLE Sense zit vol met sensoren, waaronder een microfoon, 9-assige IMU, omgevingssensor en een gebaar/nabijheid/kleur/omgevingslichtsensor (APDS-9960). De microcontroller erop is een nRF52840 die draait op 64 MHz en 1 MB flash-geheugen en 256 KB RAM bevat. Dit project gebruikt ook de ingebouwde RGB-LED om de huidige kleur weer te geven.

Edge Impuls instellen

Ik begon met het maken van een nieuw project op Edge Impulse en installeerde vervolgens de Edge Impulse CLI-tool. Ga naar de pagina met installatie-instructies voor meer instructies over hoe u dat moet doen. Hierdoor kan de Arduino Nano communiceren met de cloudservice om automatisch opdrachten te ontvangen en sensorgegevens te verzenden. Ik heb de meest recente Edge Impulse-firmware gedownload en naar het bord geflitst door op de resetknop te dubbelklikken om het naar de bootloader-modus te laten gaan. Daarna heb ik flash_windows.bat uitgevoerd om het over te dragen.

Op de opdrachtprompt heb ik edge-impulse-daemon uitgevoerd en volgde de wizard om het in te stellen. Nu verschijnt de Nano in de apparaatlijst van het project, waarmee monsters kunnen worden genomen en geüpload als onderdeel van de trainings-/testdataset.

Monsters verzamelen

Het trainen van een machine learning-model vereist gegevens, en nogal wat. Ik wilde de volgende modi hebben voor de RGB LED-strip:

  • Aan
  • Uit
  • Rood
  • Groen
  • Blauw

Ik kreeg ongeveer 1 minuut geluid voor elke modus waarbij ik het woord herhaaldelijk met tussenpozen van 1-2 seconden zei en ze splitste.

Maar alleen het hebben van deze samples is niet genoeg, aangezien achtergrondgeluid en andere woorden een verkeerde aflezing geven. Gelukkig biedt Edge Impulse al een vooraf gebouwde dataset voor ruis en 'onbekende' woorden, dus heb ik hun tool "Bestaande gegevens uploaden" gebruikt om deze audiobestanden naar de trainingsgegevens te uploaden.

Ten slotte heb ik de dataset opnieuw in evenwicht gebracht om de aanbevolen 80-20-verdeling te krijgen voor respectievelijk trainings- en testgegevens.

Het model trainen

Nu gewapend met een uur aan trainingsgegevens en veel labels, was het tijd om een ​​model te trainen. De impuls die ik heb ontworpen, neemt audio op als tijdreeksgegevens met een venstergrootte van 1 seconde en een venstertoename van 500 ms. Vervolgens gaat het door een MFCC-blok naar een Keras neuraal netwerkblok.

Met het MFCC-blok kunt u configureren hoe de audio wordt verwerkt, samen met een spectogram dat de frequenties op een visuele manier weergeeft.

Ik heb de instellingen van het neurale netwerk grotendeels als standaard gelaten, maar heb ook een paar wijzigingen aangebracht. Ten eerste heb ik de minimale betrouwbaarheidsdrempel gewijzigd van 0,80 in 0,70, en een beetje gegevensvergroting toegevoegd in de vorm van extra ruis en maskeertijdbanden. Dit helpt de NN om te voorkomen dat het model te veel wordt aangepast, omdat het meer diverse gegevens heeft om mee te werken.

Implementeren op de Arduino Nano 33 BLE Sense

De Arduino Nano 33 BLE Sense fungeert als een always-on microfoon die continu de audio samplet en detecteert of een van de trefwoorden is uitgesproken. Zodra er een is gevonden, wordt het trefwoord omgezet in een index die wordt gebruikt om de gewenste kleur te decoderen. Voor het trefwoord aan of uit is de LED ingesteld op zwart of lichtgrijs.

Ik heb het model gedownload als een bibliotheek en toegevoegd aan de Arduino IDE, vervolgens gecompileerd en de code naar de Nano geflitst.

Code

  • RGBLEDKeywordDetection
RGBLEDKeywordDetectionC/C++
/* Edge Impulse Arduino-voorbeelden * Copyright (c) 2020 EdgeImpulse Inc. * * Hierbij wordt gratis toestemming verleend aan eenieder die een kopie* van deze software en bijbehorende documentatiebestanden (de "Software") verkrijgt, om zonder beperking * in de Software te handelen, inclusief maar niet beperkt tot de rechten * om kopieën van de Software te gebruiken, kopiëren, wijzigen, samenvoegen, publiceren, distribueren, in sublicentie te geven en/of * te verkopen, en om personen toe te staan ​​aan wie de Software is * verstrekt om dit te doen, met inachtneming van de volgende voorwaarden:* * De bovenstaande copyrightkennisgeving en deze toestemmingskennisgeving zullen worden opgenomen in * alle kopieën of substantiële delen van de Software. * * DE SOFTWARE WORDT GELEVERD "AS IS", ZONDER ENIGE GARANTIE, EXPLICIET OF * IMPLICIET, INCLUSIEF MAAR NIET BEPERKT TOT DE GARANTIES VAN VERKOOPBAARHEID, * GESCHIKTHEID VOOR EEN BEPAALD DOEL EN NIET-INBREUK. IN GEEN GEVAL ZULLEN DE * AUTEURS OF AUTEURSRECHTHOUDERS AANSPRAKELIJK ZIJN VOOR ENIGE CLAIM, SCHADE OF ANDERE * AANSPRAKELIJKHEID, ZOWEL UIT CONTRACT, ONRECHTMATIGE OF ANDERSZINS, VOORTVLOEIEND UIT * UIT OF IN VERBAND MET DE SOFTWARE OF HET GEBRUIK OF HANDELINGEN IN DE * SOFTWARE. */// Als uw doel beperkt is in het geheugen, verwijdert u deze macro om 10K RAM te besparen#define EIDSP_QUANTIZE_FILTERBANK 0/** * Definieert het aantal segmenten per modelvenster. bijv. een modelvenster van 1000 ms * met slices per modelvenster ingesteld op 4. Resulteert in een slice-grootte van 250 ms. * Voor meer info:https://docs.edgeimpulse.com/docs/continuous-audio-sampling */#define EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW 3/* Inclusief ------------------- --------------------------------------------- */#inclusief #include #include 
#define CONFIDENCE_THRESHOLD 0.7static const uint32_t colors[] ={0x00ff0000, 0x0000ff00, 0x000000ff}; // rood, groen, blueenum Acties {LED_ON =1, LED_OFF =0, LED_RED =2, LED_GREEN =3, LED_BLUE =4, NONE =5};enum Functies{ 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}, {LED_HAN_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}};/** Audiobuffers, pointers en selectors */typedef struct { ondertekend kort *buffers[2]; niet-ondertekende char buf_select; niet-ondertekende char buf_ready; niet-ondertekende int buf_count; unsigned int n_samples;} inference_t;static inference_t inference;static bool record_ready =false;static ondertekend short *sampleBuffer;static bool debug_nn =false; // Zet dit op true om b.v. functies gegenereerd op basis van de onbewerkte signalstatic int print_results =-(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW);/** * @brief Arduino setup-functie */void setup(){ // plaats hier uw setup-code om een ​​keer uit te voeren:Serial.begin(115200); Serial.println("Edge Impulse Inferentie"); setPixelColor (0xaeae00); // samenvatting van inferentie-instellingen (van model_metadata.h) ei_printf("Inferencing-instellingen:\n"); ei_printf("\tInterval:%.2f ms.\n", (float)EI_CLASSIFIER_INTERVAL_MS); ei_printf("\tFrame-grootte:%d\n", EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE); ei_printf("\tVoorbeeldlengte:%d ms.\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT / 16); ei_printf("\tAantal 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:Kan audiosampling niet instellen\r\n"); opbrengst; }}/** * @brief Arduino hoofdfunctie. Voert de inferentielus uit. */void loop(){ bool m =microfoon_inference_record(); if (!m) { ei_printf("ERR:Kan geen audio opnemen...\n"); opbrengst; } signaal_t signaal; signal.total_length =EI_CLASSIFIER_SLICE_SIZE; signal.get_data =µphone_audio_signal_get_data; ei_impulse_result_t resultaat ={0}; EI_IMPULSE_ERROR r =run_classifier_continuous(&signal, &result, debug_nn); if (r !=EI_IMPULSE_OK) { ei_printf("ERR:Kan classificatie niet uitvoeren (%d)\n", r); opbrengst; } if (++ print_results>=(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)) { // print de voorspellingen ei_printf("Voorspellingen"); ei_printf("(DSP:%d ms., Classificatie:%d ms., Anomalie:%d ms.)", result.timing.dsp, resultaat.timing.classification, resultaat.timing.anomaly); ei_printf(":\n"); for (size_t ix =0; ix  CONFIDENCE_THRESHOLD) {performAction(result.classification[ix].label); } ei_printf(" %s:%.5f\n", resultaat.classificatie[ix].label, resultaat.classificatie[ix].value); }#if EI_CLASSIFIER_HAS_ANOMALY ==1 ei_printf(" anomaliescore:%.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* classificatieLabel){ auto itr =labelToActionMap.find(classificationLabel); if(itr ==labelToActionMap.end()) return; auto itr2 =actionToFunctionMap.find(itr->seconde); if(itr2 ==actionToFunctionMap.end()) return; switch (itr2->seconde) { case CHANGE_LED_ON_OFF:setPixelColor ((itr->second) ? 0x5c5c5c:0x00); pauze; case CHANGE_LED_COLOR:{ uint32_t pixelColor =kleuren [itr-> tweede - 2]; setPixelColor (pixelColor); } pauze; geval CHANGE_LED_NONE:pauze; }}/** * @brief Printf functie gebruikt vsnprintf en output met Arduino Serial * * @param[in] formaat Variabele argumentlijst */void ei_printf(const char *format, ...) { static char print_buf[1024] ={ 0 }; va_list argumenten; va_start(args, formaat); int r =vsnprintf(print_buf, sizeof(print_buf), formaat, argumenten); va_end(args); if (r> 0) { Serial.write(print_buf); }}/** * @brief PDM-buffer volledig terugbellen * Gegevens ophalen en audiothread terugbellen */static void pdm_data_ready_inference_callback(void){ int bytesAvailable =PDM.available(); // lees in de voorbeeldbuffer 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; gevolgtrekking.buf_count =0; gevolgtrekking.buf_ready =1; } } }}/** * @brief Init inferencing struct en setup/start PDM * * @param[in] n_samples The n samples * * @return { description_of_the_return_value } */static boolmicrofoon_inference_start(uint32_t n_samples){ inference.buffers[ 0] =(ondertekend kort *) malloc (n_samples * sizeof (ondertekend kort)); if (inference.buffers [0] ==NULL) { return false; } inference.buffers[1] =(kort ondertekend *) malloc (n_samples * sizeof (kort ondertekend)); if (inference.buffers[0] ==NULL) { free(inference.buffers[0]); onwaar retourneren; } sampleBuffer =(kort ondertekend *)malloc((n_samples>> 1) * sizeof(kort ondertekend)); if (sampleBuffer ==NULL) {free(inference.buffers[0]); gratis(inferentie.buffers[1]); onwaar retourneren; } gevolgtrekking.buf_select =0; gevolgtrekking.buf_count =0; gevolgtrekking.n_samples =n_samples; gevolgtrekking.buf_ready =0; // configureer de data ontvangen callback PDM.onReceive(&pdm_data_ready_inference_callback); // stel optioneel de versterking in, standaard ingesteld op 20 PDM.setGain(80); PDM.setBufferSize((n_samples>> 1) * sizeof(int16_t)); // initialiseer PDM met:// - één kanaal (monomodus) // - een samplefrequentie van 16 kHz if (!PDM.begin(1, EI_CLASSIFIER_FREQUENCY)) { ei_printf("Kan PDM niet starten!"); } record_ready =waar; return true;}/** * @brief Wacht op nieuwe gegevens * * @return True als u klaar bent */static bool microfoon_inference_record(void){ bool ret =true; if (inference.buf_ready ==1) { ei_printf( "Fout monsterbuffer overschreden. Verlaag het aantal segmenten per modelvenster " "(EI_CLASSIFIER_SLICES_PER_MODEL_WINDOW)\n"); ret =onwaar; } while (inference.buf_ready ==0) { delay(1); } gevolgtrekking.buf_ready =0; return ret;}/** * Krijg onbewerkte audiosignaalgegevens */static int microfoon_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 , lengte); return 0;}/** * @brief Stop PDM en laat buffers vrij */static void microfoon_inference_end(void){ PDM.end(); gratis (inferentie.buffers[0]); gratis(inferentie.buffers[1]); free(sampleBuffer);}#if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR !=EI_CLASSIFIER_SENSOR_MICROPHONE#error "Ongeldig model voor huidige sensor."#endif

Productieproces

  1. IIoT-beveiligingstips en trends voor 2020
  2. Cloud en edge computing voor IoT:een korte geschiedenis
  3. Waarom edge computing voor IoT?
  4. Kontrons KBox A-150-WKL voor data-intensieve IoT Edge-applicaties
  5. Armkernen ontworpen voor TinyML-apparaten
  6. Edge Computing-voordelen voor AI Crystallizing
  7. Vier stappen voor succes in edge computing
  8. Microsoft lanceert Azure Edge Zones voor 5G-toepassingen
  9. De noodzaak van open source aan de rand (eBook)
  10. Chemisch detectiesysteem voor lage concentratieniveaus
  11. 3 redenen om gasdetectieapparatuur te onderhouden