Um das Programm nun auch ohne den Serial Output bei Arduino IDE nutzen zu können, muss das Programm erweitert werden. Als nächstes ist das vollständig ergänzte Programm zu sehen. Im Verlauf des Artikels wir auf die Funktion der ergänzten Programmteile eingegangen und wie diese für andere KI-Modelle angepasst werden können.

#include <Projekt_inferencing.h> 
#include <eloquent_esp32cam.h>
#include <eloquent_esp32cam/edgeimpulse/fomo.h>

using eloq::camera;
using eloq::ei::fomo;
/**
 * 
 */
    // Output soll auf #IO12, #IO13 und #IO15 gelegt werden
    int pink = 12;
    int silber =13;
    int schwarz =15;

    /**
    fuer die Objekterkennung folgt:
    liegt an Pin 12 ein high wurde ein Objekt mit dem Namen "pink" erkannt
    liegt an Pin 13 ein high wurde ein Objekt mit dem Namen "silber" erkannt
    liegt an Pin 15 ein high wurde ein Objekt mit dem Namen "schwarz" erkannt
    ein low an den Pins bedeutet folglich, dass dieses Objekt im aktuellen
    Frame nicht erkannt wurde
    sind mehrere Pins high, wurden mehrere Objekte erkannt
    ist kein pin auf high wurde kein Objekt gefunden
    **/
void setup() {
    // Pins werden als Output auf dem Board gesetzt
    pinMode (pink,OUTPUT);
    pinMode (silber,OUTPUT);
    pinMode (schwarz,OUTPUT);

    delay(1000);
    Serial.begin(115200);
    Serial.println("__EDGE IMPULSE FOMO (NO-PSRAM)__");

    // camera settings
    // replace with your own model!
    camera.pinout.aithinker();
    camera.brownout.disable();
    // NON-PSRAM FOMO only works on 96x96 (yolo) RGB565 images
    camera.resolution.yolo();
    camera.pixformat.rgb565();

    // init camera
    while (!camera.begin().isOk())
        Serial.println(camera.exception.toString());

    Serial.println("Camera OK");
    Serial.println("Put object in front of camera");
}

void loop() {
    //pins zu anfang auf low setzten
    digitalWrite (pink,LOW);
    digitalWrite (silber,LOW);
    digitalWrite (schwarz,LOW);

    // capture picture
    if (!camera.capture().isOk()) {
        Serial.println(camera.exception.toString());
        return;
    }
    // run FOMO
    if (!fomo.run().isOk()) {
      Serial.println(fomo.exception.toString());
      return;
    }
    // how many objects were found?
    Serial.printf(
      "Found %d object(s) in %dms\n", 
      fomo.count(),
      fomo.benchmark.millis()
    );
    // if no object is detected, return
    if (!fomo.foundAnyObject())
      return;
    // if you expect to find a single object, use fomo.first
    Serial.printf(
      "Found %s at (x = %d, y = %d) (size %d x %d). "
      "Proba is %.2f\n",
      fomo.first.label,
      fomo.first.x,
      fomo.first.y,
      fomo.first.width,
      fomo.first.height,
      fomo.first.proba
    );
    // Zuweisung bei einem Objekt
    if (fomo.first.label== "pink"){
      digitalWrite (pink,HIGH); 
    }
    else if (fomo.first.label== "silber"){
      digitalWrite (silber,HIGH);
    }
    else if (fomo.first.label== "schwarz"){
      digitalWrite (schwarz,HIGH);
    }
    // if you expect to find many objects, use fomo.forEach
    if (fomo.count() > 1) {
      fomo.forEach([](int i, bbox_t bbox) {
        Serial.printf(
          "#%d) Found %s at (x = %d, y = %d) (size %d x %d). "
          "Proba is %.2f\n",
          i + 1,
          bbox.label,
          bbox.x,
          bbox.y,
          bbox.width,
          bbox.height,
          bbox.proba
        );
        //Zuweisung fuer einzelne Objekt, wird fuer jedes Objekt ausgefuehrt (.forEach)
         if (bbox.label== "pink"){
            digitalWrite (pink,HIGH);
          }
          else if (bbox.label== "silber"){
            digitalWrite (silber,HIGH);
          }
          else if (bbox.label== "schwarz"){
            digitalWrite (schwarz,HIGH);
          }
      });
    }
  //Outout von Pink testen
  if (digitalRead(pink)==HIGH){
    Serial.print("Pink ist high\n");
  }
  else{
    Serial.print("Pink ist low\n");
  }
  //Outputvon silber testen
  if (digitalRead(silber)==HIGH){
    Serial.print("Silber ist high\n");
  }
  else{
    Serial.print("Silber ist low\n");
  }
  //Output von schwarz testen
  if (digitalRead(schwarz)==HIGH){
    Serial.print("Schwarz ist high\n");
  }
  else{
    Serial.print("Schwarz ist low\n");
  }
}

Zuerst muss jedem Objekt des Modelles ein Pin zugeordnet werden, der für den Input und Output geeignet ist. Um diese Pins zu identifizieren, muss die Pinbelegung des verwendeten Boards betrachtet werden.

Diese findet ihr hier:

https://www.xplore-dna.net/mod/page/view.php?id=11414

In dem Beispielmodell gibt es drei Objekte mit den Namen „pink“, „schwarz“ und „silber“.  Folglich werden drei #IO Pins benötigt (hier: #IO12, #IO13, #IO15). Die Zuordnung erfolgt global, also vor dem „setup“ und vor dem „loop“. Nach der Zuordnung haben die Pins einen „Namen“, über welchen der Zugriff möglich ist.


Quelle: BBS2 Wolfsburg

Als nächstes werden die Pins in dem Programmteil „setup“ definiert. Das Ziel ist, dass an den Pins das Ergebnis des KI-Modells abzulesen ist. Der Gedanke dabei ist, dass der entsprechende Pin auf HIGH liegt, wenn das zugehörige Objekt detektiert wurde. Daraus folgt auch, dass die Pins natürlich als Output dienen sollen. Um dies einzustellen, wird der Befehl „pinMode“ genutzt. Hierbei muss in den folgenden Klammern der „Name“ des betreffenden Pins und die gewünschte Funktion genannt werden.


Quelle: BBS2 Wolfsburg

Es soll sichergestellt werden, dass alle Pins zuerst auf LOW liegen, sodass es nicht zu einer falschen Auswertung kommt. Um das zu gewährleisten muss am Anfang jeder Wiederholung der betreffende Pin „zurückgesetzt“ werden. Am einfachsten ist dies zu implementieren, indem alle Pins zurückgesetzt werden. Hierfür wird der Befehl „digitalWrite“ genutzt, mit dem die Pins beschrieben werden können. In den auf den Befehl folgenden Klammern wird wieder der betreffende Pin ausgewählt und anschließend bestimmt, ob der Pin auf LOW oder HIGH gelegt werden soll.


Quelle: BBS2 Wolfsburg

Im nächsten Schritt beginnt die Auswertung. In dem Programmteil „loop“ ist die Objekterkennung programmiert. Zuerst wird nach dem Teil geschaut, in dem die Erkennung eines einzelnen Objektes definiert ist. Dahinter werden if-Befehle ergänzt, welche abfragen, ob das erkannte Label des KI-Modells den gleichen Namen hat, wie die Bezeichnungen des Objektes. Dies bedeutet, dass einmal abgefragt wird, ob es sich bei dem erkannten Objekt um „pink“, „schwarz“ oder „silber“ handelt. Wenn eine der Bedingungen erfüllt ist, wird in dem if-Element der passende Pin über den Befehl „digitalWrite“ auf HIGH gesetzt.


Quelle: BBS2 Wolfsburg

Nun fehlt noch die Auswertung, wenn mehrere Objekte erkannt werden. Für die Erkennung ist schon eine Schleife vorhanden, welche jedes Objekt nacheinander mit dem KI-Modell betrachtet. Nach dieser Betrachtung können wieder die if-Blöcke ergänzt werden. Hierbei muss jedoch darauf geachtet werden, dass auf den Namen des Objekts dieses Mal mit der Anweisung „bbox.lable“ zugegriffen wird.


Quelle: BBS2 Wolfsburg

Letztlich wird noch ein Programmteil ergänzt, mit welchem es möglich ist, die verschiedenen Pins zu überwachen. Um den Zustand eines Pins abzufragen, existiert der Befehl „digitalRead“. In den Klammern hinter dem Befehl wird der Pin eingetragen, bei welchem der Zustand abgefragt werden soll. Es werden wieder if-Blöcke genutzt. Als Bedingung wird die Abfrage mit „HIGH“ verglichen. Ist die Bedingung wahr, so erscheint auf dem Monitor „*** ist high“. Wenn die Abfrage nicht erfüllt ist wird die Ausgabe „*** ist low“ generiert.


Quelle: BBS2 Wolfsburg

Die Ausgabe kann dann zum Beispiel so aussehen:


Quelle: BBS2 Wolfsburg


Quelle: BBS2 Wolfsburg

Unser Arduino IDE-Projekt findet ihr hier:

https://www.xplore-dna.net/mod/resource/view.php?id=11471&forceview=1