GET Fachpraktikum 2021 Stimmgerät

Aus HSHL Mechatronik
Zur Navigation springen Zur Suche springen

Autoren: Orience Charnelle Mefenya, Jan Henrik Steltenkamp
Betreuer: Prof. Mirek Göbel


Einleitung

Dieser Artikel beschreibt den Aufbau eines Prototyps für ein Stimmgerät. Dieses wird von Musikern verwendet, um ihr Instrument korrekt einzustellen bzw. zu stimmen. Dabei wird die Frequenz im Raum durch das Gerät gemessen und an einer Skala angezeigt. Sollte das Instrument nicht korrekt gestimmt sein, wird dies auf der Skala deutlich und ermöglicht so das Justieren des Musikinstrumentes. Solche Geräte sind günstig im Handel verfügbar. Allerdings ist es nicht üblich, dass solche Geräte auch die Lautstärke im Raum angeben können. Diese Funktion soll zusätzlich durch das Gerät abgedeckt werden.

Verschiedene Musikinstrumente erzeugen unterschiedlich hohe Tonfrequenzen, welche in Herz gemessen werden. Das Stimmgerät ist darauf ausgelegt, die Frequenzen einer Gitarre analysieren zu können. Bei einer Gitarre werden unterschiedlich lange und unterschiedlich dicke Saiten angeschlagen. Über die Beschaffenheit der einzelnen Saiten ergibt sich so eine gezielt hervorgerufene Schwingung mit klar definierter Frequenz. Über die insgesamt 6 Saiten können so 6 Grundtöne erzeugt werden.

Zuordnung der Frequenzen zu den verschiedenen Grundtönen wird in Tabelle 1 dargestellt.

Tabelle 1: Frequenzverteilung der Grundtöne
Saite Nr. Grundton Frequenz
1 E 329.63 Hz
2 H 246.94 Hz
3 G 196.00 Hz
4 D 146.83 Hz
5 A 110.00 Hz
6 E 82.41 Hz

Projektplan

Abb. 1: Projektplan


Anforderungen

Tabelle 2: Anforderungen
ID Inhalt Ersteller Datum
1 Das Gerät muss ein Mikrofon besitzen Jan Henrik Steltenkamp, Orience Charnelle Mefenya 02.10.2021
2 Das Mikrofon muss die Schwingungen bzw. den Schall im Raum messen. Jan Henrik Steltenkamp, Orience Charnelle Mefenya 02.10.2021
3 Das Signal des Mikrofons muss auf die Frequenzen und die Amplituden aufgeteilt werden. Jan Henrik Steltenkamp, Orience Charnelle Mefenya 02.10.2021
4 Die Frequenz mit dem größten Anteil an den Schwingungen muss ermittelt werden. Jan Henrik Steltenkamp, Orience Charnelle Mefenya 02.10.2021
5 Die im Raum vorherrschende Frequenz und die Lautstärke muss auf dem Bildschirm angezeigt werden. Jan Henrik Steltenkamp, Orience Charnelle Mefenya 02.10.2021
6 Sollte die Frequenz zu niedrig oder zu hoch liegen, muss dies per LED angezeigt werden. Jan Henrik Steltenkamp, Orience Charnelle Mefenya 02.10.2021
7 Sollte die Lautstärke für das menschliche Gehöhr schädlich sein, muss dies per LED angezeigt werden. Jan Henrik Steltenkamp, Orience Charnelle Mefenya 16.12.2021
8 Das Gerät muss in einem tragbaren Gehäuse verbaut werden. Jan Henrik Steltenkamp, Orience Charnelle Mefenya 16.12.2021
9 Das Gerät muss über eine mobile Stromversorgung verfügen. Jan Henrik Steltenkamp, Orience Charnelle Mefenya 16.12.2021

Tabelle 1 zeigt die funktionalen Anforderungen

Funktionaler Systementwurf / Technischer Systementwurf

Die folgende Abbildung zeigt die grundsätzlichen Funktionen, welche durch das Gerät abgedeckt werden sollen. Der Grundsatz ist nach dem Prinzip Eingabe, Verarbeitung, Ausgabe (EVA) konzipiert.

Abb. 2: Systementwurf [1]


In der nächsten Abbildung (Abb. 3) wird der Verkabelungsplan dargestellt. Dieser Plan wurde mit der Software Fritzing erstellt. Zu sehen sind die verwendeten Bauelemente, der Schallsensor (Abbildung weicht von dem verwendeten Sensor ab) und das 2X16 LCD Display (Abbildung weicht von dem verwendeten Display ab). Die dargestellten Linien zeigen, welche Anschlüsse elektrisch miteinander verbunden wurden und um welche Art Verbindung es sich handelt. Die Anschlüsse zur Versorgungsspannung VCC werden rot dargestellt, Anschlüsse zu Ground sind blau eingezeichnet. Leitungen, die der Signalübertragung dienen, werden gelb dargestellt.

Abb. 3: Fritzing Verkabelungsplan


Komponentenspezifikation

Programmierung

Die Programmierung des Stimmgerätes mit seinen zwei Hauptfunktionen Frequenzmessung und Lautstärkemessung basiert auf einem Zustandsautomat. Diese Vorgehensweise ermöglicht, dass für das Umschalten zwischen den beiden Hauptprogrammen lediglich ein Tastersignal ausgelesen werden muss.

Die folgende Abbildung zeigt den Programmablaufplan des Stimmgerätes.

Abb. 4: Programmablaufplan


Programmcode

Die Programmierung des Stimmgerätes wurde mit der Arduino IDE Software erstellt. Der Programmcode des Stimmgerätes ist in dem nachfolgenden Fenster zu sehen.

Um die Frequenzmessung mittels Fourier Transformation realisieren zu können, wurde ein verfügbares Arduino IDE Skript als Grundlage verwendet. Dieses Skript ist unter folgender Adresse verfügbar: https://clydelettsome.com/blog/2019/12/18/my-weekend-project-audio-frequency-detector-using-an-arduino/

Der darauf aufbauende Programmcode übernimmt die Lautstärkemessung, sowie die Verarbeitung und Ausgabe der zyklisch ermittelten Schallfrequenz und Lautstärke Werte. Der Wechsel von verwendetem Skript zu selbst erstellten Programmcode ist mit Platzhaltern (////) im Programmcode markiert.

Initialisierung

Überschrift des Abschnittes:

////////////////////////////////////////////////////////////////
//                    Hochschule Hamm-Lippstadt               //
////////////////////////////////////////////////////////////////
//                                                            //
// Modul            : Angewandte Elektrotechnik               //
//                                                            //
// Autoren          : Jan Henrik Steltenkamp                  //
//                    Orience Charnelle Mefenya               //
//                                                            //
// Beschreibung     : Dieses Programm nutzt ein Mikrofon,     //
//                    um aus dem Umgebungsgeräusch wahlweise  //
//                    die Tonhöhe in Hz oder die Lautstärke   //
//                    zu ermitteln und diese via LEDs und     //
//                    auf einem LCD Display auszugeben        //
//                                                            //
// Letzte Änderung  : 26.11.2021                              // 
//                                                            //
////////////////////////////////////////////////////////////////


#include <Wire.h>                         // Bibliothek für Display
#include <LiquidCrystal_I2C.h>            // Bibliothek für Display
LiquidCrystal_I2C lcd(0x27, 16, 2);       // Verwendetes Display: 16 Zeichen, 2 Zeilen, Hex Adresse 27

#define STATE1 1    // Zustand 1 angelegt
#define STATE2 2    // Zustand 2 angelegt
#define STATE3 3    // Zustand 3 angelegt
#define STATE4 4    // Zustand 4 angelegt

int taster = 7;         // Variable für den Taster am Pin 7
int tasterstatus = 0;   // initial wird Taster nicht gedrückt
char state = STATE1;    // STATE1 als Startzustand festgelegt

int Ton_aus_Skala;        // Variable für den jeweiligen Skalenton angelegt
signed int tondifferenz;  // Variable für die differenz zwischen Messung und Skalenton angelegt

//////////////////////////////////////////////////////////
#include "arduinoFFT.h"           // Hier wird die FFT Bibliothek eingebunden
#define SAMPLES 128               //SAMPLES-pt FFT. Must be a base 2 number. Max 128 for Arduino Uno.
#define SAMPLING_FREQUENCY 2048   //Ts = Based on Nyquist, must be 2 times the highest expected frequency.

arduinoFFT FFT = arduinoFFT();
 
unsigned int samplingPeriod;      //Periodendauer der Messungen

Setup

Überschrift des Abschnittes:

void setup() 
{
     
    Serial.begin(115200); //Baud rate for the Serial Monitor
    samplingPeriod = round(1000000*(1.0/SAMPLING_FREQUENCY)); //Periodendauer der Messungen in Mikrosekunden
//////////////////////////////////////////////////////////

    pinMode(taster, INPUT); // Der Pin7 mit dem Taster als Eingang festgelegt

    pinMode(8,OUTPUT);  // Pin 8: rote LED zu tief
    pinMode(12,OUTPUT); // Pin 12: grüne LED
    pinMode(13,OUTPUT); // Pin 13: rote LED zu hoch

    lcd.init();                               // LCD wird gestartet
    lcd.backlight();                          // Hintergrundbeleuchtung wird eingeschaltet    
}

zyklische Werteermittlung von Frequenz und Lautstärke

Überschrift des Abschnittes:

void loop() 
{  

tasterstatus = digitalRead(taster); // Pin7 wird ausgelesen und als "HIGH" für 5V oder "LOW" für 0V gespeichert

//////////////////////////////////////////////////////////
unsigned long microSeconds;
double vReal[SAMPLES]; //create vector of size SAMPLES to hold real values
double vImag[SAMPLES]; //create vector of size SAMPLES to hold imaginary values

      /*Sample SAMPLES times*/
      for(int i=0; i<SAMPLES; i++)
      {
          microSeconds = micros();    //Returns the number of microseconds since the Arduino board began running the current script. 
     
          vReal[i] = analogRead(0); //Reads the value from analog pin 0 (A0), quantize it and save it as a real term.
          vImag[i] = 0; //Makes imaginary term 0 always

          /*remaining wait time between samples if necessary*/
          while(micros() < (microSeconds + samplingPeriod))
          {
            //do nothing
          }
      }
 
      /*Perform FFT on samples*/
      FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
      FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
      FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);

      /*Find peak frequency and print peak*/
      double peak = FFT.MajorPeak(vReal, SAMPLES, SAMPLING_FREQUENCY);    // Frequenz ermitteln
//////////////////////////////////////////////////////////
      
      int frequenz = lround(peak);   // Frequenzwert gerundet

Zustandsautomat zur Verwaltung der Ausgaben

Überschrift des Abschnittes:

  switch(state) //Zustandsautomat, Zustand 1 = Stimmerät, Zustand 3 = Lautstärkemesser
    {
      case STATE1:    //Zustand 1: Stimmgerät
        
        if(frequenz < 96)                           //Ton E2, 82Hz
        {
        Ton_aus_Skala = 82;                         //Referenzton hat 82Hz
        tondifferenz = Ton_aus_Skala - frequenz;  //berechne Abweichung
          if(tondifferenz < -10)    // wenn Frequenz zu hoch
            {
            digitalWrite(13, HIGH); //schalte LED an
            }
          else if((tondifferenz >= -10) & (tondifferenz <= 10))// wenn Frequenz passend
            {
            digitalWrite(12, HIGH); //schalte LED an
            }
          else if (tondifferenz > 10)// wenn Frequenz zu tief
            {
            digitalWrite(8, HIGH);  //schalte LED an
            }    
        lcd.setCursor(0, 0);            // Erste Zeile des LCD Displays ansprechen
        lcd.print("                ");  // vorherige Anzeige löschen
        lcd.setCursor(0, 0);            //zugeordneten Ton in 1. Zeile anzeigen
        lcd.print("Ton e =  82  Hz");     //zugeordneten Ton in 1. Zeile anzeigen
        }
        
        else if((frequenz > 97) & (frequenz < 128)) //Ton A2, 110Hz
        {
        Ton_aus_Skala = 110;                         //Referenzton hat 110Hz
        tondifferenz = Ton_aus_Skala - frequenz;  //berechne Abweichung
          if(tondifferenz < -10)    // wenn Frequenz zu hoch
            {
            digitalWrite(13, HIGH); //schalte LED an
            }
          else if((tondifferenz >= -10) & (tondifferenz <= 10))// wenn Frequenz passend
            {
            digitalWrite(12, HIGH); //schalte LED an
            }
          else if (tondifferenz > 10)// wenn Frequenz zu tief
            {
            digitalWrite(8, HIGH);  //schalte LED an
            } 
        lcd.setCursor(0, 0);            // Erste Zeile des LCD Displays ansprechen
        lcd.print("                ");  // vorherige Anzeige löschen
        lcd.setCursor(0, 0);            //zugeordneten Ton in 1. Zeile anzeigen
        lcd.print("Ton A =  110 Hz");    //zugeordneten Ton in 1. Zeile anzeigen
        }
        
        else if((frequenz > 128) & (frequenz < 171)) //Ton D3, 147Hz
        {
        Ton_aus_Skala = 147;                         //Referenzton hat 147Hz
        tondifferenz = Ton_aus_Skala - frequenz;  //berechne Abweichung
          if(tondifferenz < -10)    // wenn Frequenz zu hoch
            {
            digitalWrite(13, HIGH); //schalte LED an
            }
          else if((tondifferenz >= -10) & (tondifferenz <= 10))// wenn Frequenz passend
            {
            digitalWrite(12, HIGH); //schalte LED an
            }
          else if (tondifferenz > 10)// wenn Frequenz zu tief
            {
            digitalWrite(8, HIGH);  //schalte LED an
            } 
        lcd.setCursor(0, 0);            // Erste Zeile des LCD Displays ansprechen
        lcd.print("                ");  // vorherige Anzeige löschen
        lcd.setCursor(0, 0);            //zugeordneten Ton in 1. Zeile anzeigen
        lcd.print("Ton D =  147 Hz");    //zugeordneten Ton in 1. Zeile anzeigen
        }
        
        else if((frequenz > 171) & (frequenz < 221)) //Ton G3, 196Hz
        {
        Ton_aus_Skala = 196;                         //Referenzton hat 196Hz
        tondifferenz = Ton_aus_Skala - frequenz;   //berechne Abweichung
          if(tondifferenz < -10)    // wenn Frequenz zu hoch
            {
            digitalWrite(13, HIGH); //schalte LED an
            }
          else if((tondifferenz >= -10) & (tondifferenz <= 10))// wenn Frequenz passend
            {
            digitalWrite(12, HIGH); //schalte LED an
            }
          else if (tondifferenz > 10)// wenn Frequenz zu tief
            {
            digitalWrite(8, HIGH);  //schalte LED an
            } 
        lcd.setCursor(0, 0);            // Erste Zeile des LCD Displays ansprechen
        lcd.print("                ");  // vorherige Anzeige löschen
        lcd.setCursor(0, 0);            //zugeordneten Ton in 1. Zeile anzeigen
        lcd.print("Ton G =  196 Hz");    //zugeordneten Ton in 1. Zeile anzeigen
        }
        
        else if((frequenz > 221) & (frequenz < 288)) //Ton H3, 247Hz
        {
        Ton_aus_Skala = 247;                         //Referenzton hat 247Hz
        tondifferenz = Ton_aus_Skala - frequenz;  //berechne Abweichung
          if(tondifferenz < -10)    // wenn Frequenz zu hoch
            {
            digitalWrite(13, HIGH); //schalte LED an
            }
          else if((tondifferenz >= -10) & (tondifferenz <= 10))// wenn Frequenz passend
            {
            digitalWrite(12, HIGH); //schalte LED an
            }
          else if (tondifferenz > 10)// wenn Frequenz zu tief
            {
            digitalWrite(8, HIGH);  //schalte LED an
            } 
        lcd.setCursor(0, 0);            // Erste Zeile des LCD Displays ansprechen
        lcd.print("                ");  // vorherige Anzeige löschen
        lcd.setCursor(0, 0);            //zugeordneten Ton in 1. Zeile anzeigen
        lcd.print("Ton H =  247 Hz");    //zugeordneten Ton in 1. Zeile anzeigen
        }
        
        else if(frequenz > 288)                      //Ton E4, 330Hz
        {
        Ton_aus_Skala = 330;                         //Referenzton hat 330Hz
        tondifferenz = Ton_aus_Skala - frequenz;  //berechne Abweichung
          if(tondifferenz < -10)    // wenn Frequenz zu hoch
            {
            digitalWrite(13, HIGH); //schalte LED an
            }
          else if((tondifferenz >= -10) & (tondifferenz <= 10))// wenn Frequenz passend
            {
            digitalWrite(12, HIGH); //schalte LED an
            }
          else if (tondifferenz > 10)// wenn Frequenz zu tief
            {
            digitalWrite(8, HIGH);  //schalte LED an
            } 
        lcd.setCursor(0, 0);            // Erste Zeile des LCD Displays ansprechen
        lcd.print("                ");  // vorherige Anzeige löschen
        lcd.setCursor(0, 0);            //zugeordneten Ton in 1. Zeile anzeigen
        lcd.print("Ton E =  330 Hz");    //zugeordneten Ton in 1. Zeile anzeigen
        }
        
        lcd.setCursor(0, 1);            // Zweite Zeile des LCD Displays ansprechen
        lcd.print("                ");  // vorherige Anzeige löschen
        lcd.setCursor(0, 1);            // Zweite Zeile des LCD Displays ansprechen
        lcd.print("aktuell: ");         // Text anzeigen           
        lcd.setCursor(9, 1);            // Zweite Zeile des LCD Displays ansprechen
        lcd.print(frequenz);            // Gemessene Frequenz anzeigen
        lcd.setCursor(13, 1);           // Zweite Zeile des LCD Displays ansprechen
        lcd.print("Hz");                // Text anzeigen   
        delay(1000);                    // nächsten Wert nach 1 Sekunde erzeugen und ausgeben
        digitalWrite(13, LOW); //schalte LED aus
        digitalWrite(12, LOW); //schalte LED aus
        digitalWrite(8, LOW); //schalte LED aus
            
   
      if(tasterstatus==HIGH)//Abfrage, ob Taster gerade gedrück wird
      {
      state = STATE2; //Wechsle in den Zustand 2
      }
      break;

      case STATE2:    //Zustand 2: Übergang von Stimmgerät zu Lautstärkemesser
      lcd.setCursor(0, 0);
      lcd.print("                ");              // Bildschirm leeren
      lcd.setCursor(0, 1);
      lcd.print("Lautstaerke                ");   // Umschaltvorgang anzeigen
      if(tasterstatus==LOW)//Abfrage, ob Taster gerade losgelassen wird
      {
      state = STATE3; //Wechsle in den Zustand 3
      }
      break;

      case STATE3:    //Zustand 3: Lautstärkemesser
      //Hier Programmcode des States einfügen!
      lcd.setCursor(0, 0);                  // löschen!
      lcd.print("State 3                ");       // löschen!
      lcd.setCursor(0, 1);                  // löschen!
      lcd.print("Lautstaerke");              // löschen!
      if(tasterstatus==HIGH)//Abfrage, ob Taster gerade gedrück wird
      {
      state = STATE4; //Wechsle in den Zustand 4
      }
      break;

      case STATE4:    //Zustand 4: Übergang von Lautstärkemesser zu Stimmgerät
      lcd.setCursor(0, 0);
      lcd.print("                ");              // Bildschirm leeren
      lcd.setCursor(0, 1);
      lcd.print("Stimmgeraet                ");   // Umschaltvorgang anzeigen
      if(tasterstatus==LOW)//Abfrage, ob Taster gerade losgelassen wird
      {
      state = STATE1; //Wechsle in den Zustand 1
      }
      break;  
    }
}

Komponententest

Nachdem der Programmcode für die Softwarekomponente "Stimmgerät" erstellt wurde und das Messgerät testweise auf einem Breadboard aufgebaut wurde (Siehe Fritzing Plan in Abb. 3), ist die Frequenzmessung überprüft worden. Dazu wurde zunächst ein Programm heruntergeladen, welches auf dem Mobiltelefon ermöglicht, Geräusche in Form von Sinuskurven mit definierter Schallfrequenz auszugeben. Die Überprüfung der vom Mobiltelefon ausgegebenen Schallfrequenz mit einem handelsüblichen Stimmgerät für Gitarren hat ergeben, dass keine relevante Abweichung der eingestellten Frequenzwerte von der ausgegebenen Schallfrequenz zu beobachten waren.

Somit wurde die anschließende Kalibrierung des selbst erstellten Stimmgerätes mit diesem Programm durchgeführt.

Dabei wurde, beginnend mit einer Frequenz von 400Hz, die entsprechende Schallfrequenz erzeugt über das Arduino Mikrofon eingelesen. Der auf dem Bildschirm ausgegebene Frequenzwert wurde dann notiert und die Frequenz um 10Hz verringert.

Dieser Versuch hat ergeben, dass bei dem bisherigen Programmcode eine systematische Messabweichung vorliegt, welche mit höher werdender Schallfrequenz entsprechend ansteigt. Die Messabweichung wurde linearisiert und anschließend in dem Programmcode von dem Messwerten abgezogen.

Die ursprüngliche Messgenauigkeit und die Messgenauigkeit nach der Anpassung des Programmcodes werden in folgender Abbildung dargestellt.

Abb. 6: Kalibrierung der Frequenzmessung


Die rote Kurve zeigt die ursprünglichen Messwerte. Die Messwerte nach der Anpassung sind blau eingefärbt.

Wie zu sehen ist, konnte das "Abdriften" der Messwerte beseitigt werden. Die restliche Abweichungen bei dem Messen der Schallfrequenz ist für die Anwendung des Stimmgerätes von zu vernachlässigender Bedeutung.

Allerdings hat die Messung auch Grenzen der Messung aufgezeigt. In unteren Bereichen der Schallfrequenz, besonders ab ca. 60Hz abwärts, neigt das Stimmgerät zu starken Schwankungen bei der Ausgabe. Da der tiefste Ton, der erfolgreich gemessen werden soll, oberhalb von diesem Bereich liegt, ist die Schwankung bei besonders tiefen Frequenzen nicht kritisch für die Funktionalität des Stimmgerätes.

Die Frequenzmessung hat somit eine Genauigkeit erreicht, die für dieses Projekt als ausreichend zu bewertend ist.

Zusammenfassung

Literaturverzeichnis



→ zurück zur Übersicht: WS 21/22: Angewandte Elektrotechnik (BSE)