Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen....

25
1 1 Einleitung Tiefpass-Filter-Projekt Beispielprojekt für die Verwendung der Mikro-Controller-Plattform mit Hilfe der initDevice-Klasse Ort: Hochschule Karlsruhe - Technik und Wirtschaft Fakultät für Elektro- und Informationstechnik Name: Florian Kanis Zeitraum: Wintersemester 2015/16

Transcript of Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen....

Page 1: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

1 1 Einleitung

Tiefpass-Filter-Projekt

Beispielprojekt für die Verwendung der

Mikro-Controller-Plattform

mit Hilfe der initDevice-Klasse

Ort: Hochschule Karlsruhe - Technik und Wirtschaft

Fakultät für Elektro- und Informationstechnik

Name: Florian Kanis

Zeitraum: Wintersemester 2015/16

Page 2: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

Inhaltsverzeichnis

1 Einleitung .............................................................................................................. 3

2 Implementierungsablauf ........................................................................................ 4

3 Konfiguration von Timer2, ADC1, DAC1 und der Zusatzbeschaltung ...................... 5

3.1 Konfiguration von Timer2 .............................................................................................. 5

3.2 Konfiguration von ADC1 ............................................................................................... 6

3.3 Implementierung der ADC-Interrupt-Service-Routine ................................................... 6

3.4 Test der ADC-Interrupt-Service-Routine........................................................................ 7

3.5 Konfiguration von DAC1 ............................................................................................... 7

3.6 Konfiguration der Zusatzbeschaltung von ADC1 und DAC1 ........................................ 8

3.7 Test mit Signalgenerator und Oszilloskop ...................................................................... 8

4 Implementierung der digitalen Tiefpass-Filter .................................................. 9

4.1 Rekursives Tiefpass-Filter ............................................................................................ 10

4.2 Moving-Average-Filter ................................................................................................. 10

4.3 Test der Filter mit Signalgenerator und Oszilloskop .................................................... 11

5 UART-Kommunikation zwischen Mikro-Controller-Plattform und PC ........... 13

5.1 Konfiguration der USART1-Schnittstelle ..................................................................... 13

5.2 Implementierung der USART1-Interrupt-Service-Routine .......................................... 14

5.3 Definition der Funktion USART_SEND() ................................................................... 15

5.4 Test der USART-Interrupt-Service-Routine ................................................................. 15

5.5 Implementierung der Filtersteuerung ............................................................................ 16

5.6 Test der UART-Kommunikation mit Hyperterminal .................................................... 17

5.7 Test der Filter mit Hilfe der MATLAB GUI ................................................................ 18

6 Abbildungsverzeichnis ..................................................................................... 21

7 Anhang 1: Quellcode ........................................................................................ 22

Page 3: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

Einleitung 3

1 Einleitung

In diesem Dokument wird ein Beispielprojekt für die Verwendung der Mikro-Controller-

Plattform mit Hilfe der initDevice-Klasse beschrieben. Die beschriebene Vorgehensweise ba-

siert auf dem Dokument ´Mesysto Mikro-Controller-Plattform.pdf´, auf welches sich in diesem

Dokument mit [1] bezogen wird. Auf die verwendeten Funktionen der initDevice-Klasse in der

Datei initDevice.cpp wird sich mit [2] bezogen.

Implementiert wurde ein Programm, welches ein analoges Signal einliest, dieses digitalisiert,

digital filtert und zum Schluss wieder in ein analoges Signal wandelt. Es kann zwischen einem

rekursiven Tiefpass-Filter und einem Moving-Average-Filter, jeweils mit anpassbaren Filterko-

effizienten, gewählt werden. Die Steuerung der Filter, also die Auswahl des Filters und die An-

passung der Filterkoeffizienten, kann entweder mit Hilfe eines Terminalprogramms oder der

bereitgestellten MATLAB GUI durchgeführt werden. Es ist zu beachten dass sie Verwendung

der MATLAB GUI nur in Kombination mit der Messkarte BNC-2110 von National Instruments

durchgeführt werden kann. Über diese Messkarte werden die benötigten Signale von der MAT-

LAB GUI an die Mikro-Controller-Plattform übergeben und die Ausgabewerte wiederum einge-

lesen, um diese dann in der MATLAB GUI darzustellen.

Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche den

zeitlichen Ablauf der Implementierung dieses Programms wiederspiegelt.

In Kapitel 2 wird zu Beginn dieser generelle Ablauf besprochen.

Kapitel 3 diskutiert die Schritte, die benötigt werden, um ein Eingangssignal zu digitalisieren,

das digitale Signal für die Signalverarbeitung bereitzustellen und es schließlich wieder in ein

analoges Signal umzuwandeln. Dabei werden die einzelnen Implementierungsschritte sowie

deren Testmöglichkeiten in der Reihenfolge diskutiert, in der sie implementiert wurden.

In Kapitel 4 wird daraufhin auf die Implementierung der beiden digitalen Filter und die Mög-

lichkeit, deren Verhalten zu testen, eingegangen. Bis zu diesem Punkt kann dieses Dokument

als Grundlage für jegliche Signalverarbeitung mit digitalen Filtern verwendet werden.

In Kapitel 5 wird auf die Kommunikation zwischen PC und Mikro-Controller-Plattform mittels

Universal Asynchronous Synchronous Receive Transmit-Schnittstelle (USART) eingegangen.

Zu Beginn wird diese generell diskutiert und im späteren Verlauf des Kapitels speziell auf die

USART-Kommunikation zum Test der Implementierung der Filtersteuerung eingegangen. Für

andere Projekte, die eine USART-Kommunikation benötigen, ist Kapitel 5 daher auch von Inte-

resse.

Kapitel 6 enthält den kompletten implementierten Quellcode und kann als Referenz verwendet

werden, da in den vorigen Kapiteln nur die grundlegenden Funktionalitäten besprochen werden.

Page 4: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

4 Implementierungsablauf

2 Implementierungsablauf

In diesem Kapitel wird der generelle Ablauf der Implementierung beschrieben und ist in Abbil-

dung 1 dargestellt. In den folgenden Kapiteln wird daraufhin auf die einzelnen Schritte detail-

liert eingegangen. Auf den ersten Schritt, dem Erstellen des Projektes, wird dabei verzichtet, da

[1] hierfür alle notwendigen Information bereitstellt.

Der erste Arbeitsschritt, der in diesem Dokument diskutiert wird, ist daher die Konfiguration der

Peripherie, um ein analoges Signal zu digitalisieren (ADC1), dieses zwischen zu speichern und

dann wieder in ein analoges Signal umzuwandeln (DAC1). Die Abtastfrequenz der AD-

Wandlung wird hierbei mit Timer2 gesteuert. Des Weiteren muss die Zusatzbeschaltung der

Mikro-Controller-Plattform konfiguriert werden.

Der nächste Schritt ist die Implementierung der digitalen Tiefpass-Filter mittels Differenzen-

gleichung. Er wird in Kapitel 4 diskutiert. Hier wird die Implementierung eines rekursiver Tief-

pass-Filters und eines Moving-Average-Filters besprochen.

Zum Schluss wird in Kapitel 5 die Konfiguration der USART1-Schnittstelle diskutiert. Diese

wird verwendet, um die Filtersteuerung, also die Auswahl des Filters sowie die Festlegung der

jeweiligen Filtereigenschaften, von einem Terminalprogramm oder einer MATLAB GUI aus zu

steuern. Die Kommunikation via USART wird außerdem verwendet, um Messwerte von der

Mikro-Controller-Plattform an die MATLAB GUI zu senden.

Abbildung 1: Reihenfolge der Implementierung

Page 5: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

Konfiguration von Timer2, ADC1, DAC1 und der Zusatzbeschaltung 5

3 Konfiguration von Timer2, ADC1, DAC1 und der Zusatzbeschal-

tung

In diesem Kapitel wird beschrieben, wie das analoge Eingangssignal mit Hilfe des AD-

Wandlers (ADC1) digitalisiert wird, die Abtastfrequenz mit Timer2 festgelegt wird und das

digitale Signal wieder mit Hilfe des DA-Wandlers (DAC1) wieder in ein analoges Signal ge-

wandelt wird. Des Weiteren wurde die Zusatzbeschaltung der Mikro-Controller-Plattform für

ADC1 und DAC1 konfiguriert. Die Reihenfolge dieses Prozesses, sowie die Möglichkeit den

jeweiligen Implementierungsstatus zu testen, ist in Abbildung 2 dargestellt

Abbildung 2:Konfiguration von Timer2, ADC1, DAC1 und der Zusatzbeschaltung

3.1 Konfiguration von Timer2

Die Abtastfrequenz von ADC1 wurde, entsprechend Kapitel 2.2 in [1], durch die Initialisierung

von Timer2 mit folgendem Code durchgeführt:

device.setTimer(2);

device.setfTimer(22050);

device.setTimerOutput(Trigger);

device.timerInit();

Mit der Funktion setTimer(2) wird zu Beginn Timer2 ausgewählt. fTimer() stellt daraufhin die

Abtastfrequenz auf 44,1kHz ein. Hierbei ist zu beachten, dass wenn Timer2 als Trigger für

ADC1 verwendet wird, die Funktion setfTimer() nicht auf 44100 sondern auf die Hälfte, also

22050, eingestellt werden muss. Der Faktor 0,5 ist zu verwenden, wenn der Timer Output als

Page 6: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

6 Konfiguration von Timer2, ADC1, DAC1 und der Zusatzbeschaltung

Trigger für eine andere Peripherie verwendet wird. setTimerOutput(Trigger) definiert daraufhin,

dass das ausgelöste Event von Timer2 als Trigger für eine andere Peripherieeinheit verwendet

wird. Die Verknüpfung von Timer2 und ADC1 wird im kommenden Kapitel 3.2 beschrieben.

Zum Schluss werden die Einstellungen mit der Funktion timerInit() übernommen. Die von [2]

bereitgestellten Funktionen setTimer(), setfTimer(), setTimerOutput() und timerInit() konfigurie-

ren im Hintergrund automatisch alle relevanten Elemente. Für genauere Informationen zu den

verwendeten Funktionen sind in [2] die Funktionsdefinitionen einzusehen.

3.2 Konfiguration von ADC1

Die Konfiguration des ADC1 wurde, wie in Kapitel 2 in [1] beschrieben, mit folgendem Code

durchgeführt:

device.setAdc(1);

device.setADCTrigger(timer2ADC_TRGO);

device.adcInit();

device.setIRQChannel(adcInterrupt);

device.nvicInit();

Zu Beginn wurde mit der Funktion setAdc(1) die Verwendung von ADC1 definiert. Daraufhin

wurde mit setADCTrigger(timer2ADC_TRGO) festgelegt, dass der Ausgang von Timer2 als

Trigger für ADC1 verwendet wird. Mit der Funktion adcInit() werden diese Einstellungen über-

nommen. Da mit jedem neu gewandelten Wert ein Interrupt ausgelöst wird, wird im Nested

Vector Interrupt Controller (NVIC) der Kanal für den ADC-Interrupt freigegeben. Das wird mit

setIRQChannel(adcInterrupt) bewerkstelligt, woraufhin die Einstellung mit der Funktion nvi-

cInit() übernommen wird. Die von [2] bereitgestellten Funktionen setAdc(), setADCTrigger(),

adcInit(), setIRQChannel() und nvicInit() konfigurieren im Hintergrund automatisch alle rele-

vanten Elemente (GPIOs, Prescaler, Triggereigenschaften, usw.). Für genauere Informationen

zu den verwendeten Funktionen sind in [2] die Funktionsdefinitionen einzusehen.

3.3 Implementierung der ADC-Interrupt-Service-Routine

Die ADC-Interrupt-Service-Routine wird aufgerufen, sobald ADC1 einen neuen Wert gewan-

delt hat und dieser zur Verfügung steht. Dies wird durch das End-Of-Conversion-Flag (EOC)

anzeigt. Abgesehen von dem regelmäßigen Aufrufen im laufenden Betrieb wird die ADC-

Interrupt-Service-Routine einmal zu Beginn, bei der Ausführung des Befehls adcInit(), aufgeru-

fen. Die ADC-Interrupt-Service-Routine wurde wie in Kapitel 2 in [1] beschrieben, mit folgen-

dem Code implementiert:

extern "C" void ADC_IRQHandler(void)

{

If(ADC_GetITStatus(ADC1, ADC_IT_EOC) == SET)

{

ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);

//hier folgt später der weitere Code

//siehe Kapitel 3.5 Konfiguration von DAC1

}

}

Zu Beginn wird abgefragt, ob das EOC-Flag gesetzt ist. Ist das der Fall, so wird es zurückge-

setzt, sodass nach der nächsten Wandlung die ADC-Interrupt-Service-Routine erneut aufgerufen

werden kann. An dieser Stelle wird später die Signalverarbeitung mit den digitalen Filtern und

die Ausgabe über den DAC implementiert. Die Funktionen ADC_GetITStatus() und

Page 7: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

Konfiguration von Timer2, ADC1, DAC1 und der Zusatzbeschaltung 7

ADC_ClearITPendingBit() werden von der STM-Bibliothek, siehe Kapitel 1.1 in [1] bereitge-

stellt und wurden nicht eigens in [2] definiert.

3.4 Test der ADC-Interrupt-Service-Routine

Wenn Timer2 und ADC1 fertig initialisiert sind, muss getestet werden, ob das Programm im

laufenden Betrieb wie gewünscht in die ADC-Interrupt-Service-Routine springt. Für einen ers-

ten Test wird daher der Debugger von Keil uVision genutzt. Führen Sie folgende Schritte nach-

einander aus:

Klicken Sie auf ‘F7‘, um den geschriebenen Code in die Target-Files umzusetzen

Klicken Sie auf , um den Debugger zu starten

Setzten Sie einen Breakpoint in die ADC-Interrupt-Service-Routine

Klicken Sie auf , um den Programmcode vom Debugger in den Kontroller zu laden

Klicken Sie auf , um das Programm zu starten

Das Programm sollte nun bei dem Breakpoint in der ADC-Interrupt-Service-Routine stoppen.

Falls das Programm nicht an dieser Stelle stoppt, muss die Initialisierung von Timer2 und

ADC1 sowie die Definition der ADC-Interrupt-Service-Routine auf Fehler untersucht werden.

3.5 Konfiguration von DAC1

Mit dem folgenden Code wurde, entsprechend Kapitel 3 in [1], der DAC1 konfiguriert:

device1.setDac(1);

device1.setDacTrigger(None);

device1.dacInit();

Analog zu der Initialisierung des ADC1 wurde DAC1 mit der Funktion setDac(1) ausgewählt.

setDacTrigger(None) definiert daraufhin, dass der DAC nicht durch einen externen Trigger

gesteuert wird. Bei dieser Konfiguration werden Daten ausgegeben, sobald die Ausgabe per

Funktionsaufruf gestartet wird und nicht per externem Trigger. Diese Initialisierung wurde

schließlich wieder mit der Funktion dacInit() übernommen. Die von [2] bereitgestellten Funkti-

onen setDac(), setDacTrigger() und dacInit() konfigurieren im Hintergrund automatisch alle

relevanten Elemente (GPIOs, Prescaler, Triggereigenschaften, usw.). Für genauere Informatio-

nen zu den verwendeten Funktionen sind in [2] die Funktionsdefinitionen einzusehen.

Das Auslesen der digitalisierten Werte des ADC1 und die Ausgabe dieser Werte mit dem DAC1

wurden mit folgendem Code in der ADC-Interrupt-Service-Routine implementiert:

convValue = ADC_GetVonversionValue(ADC1);

DAC_SetChannel1Data(DAC_Align_12b_R, convValue);

Der vom ADC1 bereitgestellte digitale Wert wird mit der Funktion ADC_GetConversionValue()

erfasst, in der Variablen convValue zwischengespeichert und dann mit der Funktion

DAC_SetChannel1Data() über den DAC1 wieder ausgegeben. Diese beiden Funktionen werden

von der STM-Bibliothek, siehe Kapitel 1.1 in [1], bereitgestellt und wurden nicht eigens in [2]

definiert. Der Parameter DAC_Align_12b_R definiert, dass eine 12 Bit-Variable mit linksbündi-

ger Datenausrichtung an den DAC1 übergeben wird.

Page 8: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

8 Konfiguration von Timer2, ADC1, DAC1 und der Zusatzbeschaltung

3.6 Konfiguration der Zusatzbeschaltung von ADC1 und DAC1

Die Konfiguration der Zusatzbeschaltung wurde, entsprechend Kapitel 8 in [1], mit folgendem

Code implementiert:

device1.setADCInputPath(1,Bypass);

device1.setDACOutputPath(1,Bypass);

Mit der Funktion setADCInputPath() wird der jeweilige ADC-Eingangspfad ausgewählt, in

diesem Fall der Pfad 1 und als Bypass konfiguriert. Analog dazu wurde der DAC-Ausgangspfad

von DAC1 konfiguriert. Diese von [2] bereitgestellten Funktionen konfigurieren im Hintergrund

die Multiplexer auf dem analogen Frontend der Mikro-Controller-Plattform. Für genauere In-

formationen zu den verwendeten Funktionen sind in [2] die Funktionsdefinitionen einzusehen. Für detaillierte Informationen zu der verwendeten Hardware wird auf Kapitel 8 in [1] verwie-

sen.

3.7 Test mit Signalgenerator und Oszilloskop

Mit der aktuellen Konfiguration wird ein Signal zwischen 0V und 3V vom ADC1 eingelesen, in

der ADC-Interrupt-Service-Routine zwischengespeichert und daraufhin vom DAC1 wieder

ausgegeben. Das Ausgangssignal deckt dabei ebenfalls einen Spannungsbereich von 0V bis 3V

ab. Um diese Konfiguration zu testen, wurden ein Signalgenerator und ein Oszilloskop verwen-

det. Dabei wurden folgenden Werte am Signalgenerator eingestellt:

Frequenz 1kHz

Amplitude 100mV

Offset 750mV

Der Ausgang des Signalgenerators wurde mit einem T-Stücks ausgesplittet und einmal direkt

auf das Oszilloskop und einmal auf den Eingang des ADC1 der Mikro-Controller-Plattform

gegeben. Des Weiteren wurde der Ausgang DAC1 mit dem Oszilloskop verbunden. Somit

konnte das digital bearbeitete Signal mit dem Originalsignal verglichen werden.

Da die Implementierung auf der Mikro-Controller-Plattform das Signal lediglich abtastet und

wieder ausgibt, muss das Ausgangssignal der diskretisierten Form des Eingangssignals entspre-

chen. Bei genauer Betrachtung ist ein geringer Zeitverzug des diskretisierten Signals im Ver-

gleich zum Originalsignal zu erkennen. Dieser Zeitverzug ist der Verarbeitungszeit der AD-

Wandlung, der internen Speicherzugriffe und der abschließenden DA-Wandlung zu schulden.

Falls, wie in Abbildung 2 dargestellt, dieser Test nicht erfolgreich verlaufen ist, muss die Kon-

figuration von DAC und Zusatzbeschaltung, sowie die Funktionsaufrufe in der ADC-Interrupt-

Service-Routine überprüft werden.

Page 9: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

Implementierung der digitalen Tiefpass-Filter 9

4 Implementierung der digitalen Tiefpass-Filter

In diesem Kapitel wird die Implementierung der digitalen Tiefpass-Filter diskutiert. Dabei wird,

wie in Abbildung 3 dargestellt, zuerst auf die Implementierung des rekursiven Tiefpass-Filters

und des Moving-Average-Filters in Kapitel 4.1 und 4.2 eingegangen. In Kapitel 4.3 wird dann

eine Möglichkeit für das Testen des Filterverhaltens präsentiert. An dieser Stelle ist zu erwäh-

nen, dass lediglich einer der beiden Filter zu einem Zeitpunkt verwendet werden kann, der je-

weils andere Filter muss in diesem Moment auskommentiert sein. In Kapitel 5.5 wird dann be-

schrieben, wie beide Filter verwendet werden können und per USART-Kommunikation der zu

verwendende Filter ausgewählt werden kann.

Abbildung 3: Implementierung der digitalen Tiefpass-Filter

Generell kann die Implementierung eines digitalen Filters mit einer Differenzengleichung und

einem Flussdiagramm dargestellt werden. Die Differenzengleichung beschreibt, wie sich der

aktuelle Ausgangswert aus gewichteten Werten vorhergegangener Eingangs- und Ausgangswer-

te zusammensetzt. Das rekursive Tiefpass-Filter und das Moving-Average-Filter werden in Ka-

pitel 4.1 und 4.2 anhand von ihrer Differenzengleichung charakterisiert und diskutiert. Das

Flussdiagramm ist generell für Filterimplementierungen gleich und ist in Abbildung 4 darge-

stellt.

Abbildung 4: Flussidagramm einer Filterimplementierung

Zu Beginn werden die Variablen, die den aktuellen Eingangswert sowie vorhergegangene Ein-

gangs- und Ausgangswerte speichern, initialisiert. Im zweiten Schritt wird die, für den jeweili-

Page 10: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

10 Implementierung der digitalen Tiefpass-Filter

gen Filter repräsentative, Differenzengleichung berechnet und somit der aktuelle Ausgangswert

bestimmt. In Schritt drei und vier wird eine Speicherverwaltung durchgeführt, bei der die zu

Beginn initialisierten Variablen mit den aktuellen Werten beschrieben werden und der aktuelle

Ausgangswert ausgegeben wird. Dieser Prozess der Berechnung der Differenzengleichung, der

Speicherverwaltung und der Ausgabe der Ausgangsgröße wiederholt sich im laufenden Betrieb

zyklisch. Mit welchem Takt diese zyklische Verarbeitung durchgeführt wird, hängt von der

Position des zugehörigen Codes ab. In diesem Bespiel findet die Verarbeitung in der ADC-

Interrupt-Service-Routine statt und wird also 44100 Mal pro Sekunde ausgeführt.

4.1 Rekursives Tiefpass-Filter

Das implementierte rekursive Tiefpass-Filter kann mit Formel 1 beschrieben werden:

y k 1 GF u k GF y k 1

(1)

Der aktuelle Ausgangswert y[k] wird dabei aus dem aktuellen Eingangswert u[k] und dem vor-

hergegangenen Ausgangswert y[k-1] berechnet, wobei u[k] und y[k-1] verschieden gewichtet

werden können. Die Gewichtung dieser beiden Faktoren wird mit dem Gewichtungsfaktor GF

bestimmt, der Werte zwischen 0 und 1 annehmen kann.

Wenn GF = 0 gewählt wird, bedeutet dies, dass der aktuellen Eingangswert u[k] mit 1 gewichtet

wird und der vorhergegangene Ausgangswert y[k-1] mit 0. y[k] entspricht also u[k], was bedeu-

tet, dass die Zeitkonstante gleich null ist. Wenn GF = 1 gewählt wird, wird u[k] mit 0 gewichtet

und y[k-1] mit 1. In diesem Fall hat der aktuelle Eingangswert keinen Einfluss und das Aus-

gangssignal bleibt für immer auf dem Initialwert, der für gewöhnlich null ist. Die Zeitkonstante

ist daher unendlich. Werte zwischen 0 und 1 der Variablen GF definieren also die Zeitkonstante

des Filters, welche mit steigendem GF ebenfalls steigt.

Die Implementierung, deren generelle Struktur in Abbildung 4 dargestellt ist, wurde mit folgen-

dem Code durchgeführt:

// Variablen initialisieren (ADC-Wert lesen)

u = ADC_GetVonversionValue(ADC1);

// Differenzengleichung berechnen

y = (int16_t)((1-GF)*u+GF*yOld);

// Speicherverwaltung

yOld = y;

// Ausgabe der Ausgangsgröße

DAC_SetChannel1Data(DAC_Align_12b_R, y);

4.2 Moving-Average-Filter

Das Moving-Average-Filter wurde mit Formel 2 beschrieben:

15

nn 0

1y k d u k n

16

(2)

Der aktuelle Ausgangswert y[k] setzt sich dabei aus dem aktuellen und den vorhergegangenen

Eingangswerten u[k-n] zusammen. Da die Summe für einen Wertebereich von n = 0 bis n = 15

berechnet wird, wird der aktuelle Wert (n = 0) und die 15 vorherigen Eingangswerte (n = 1..15)

Page 11: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

Implementierung der digitalen Tiefpass-Filter 11

berücksichtigt. Um jeden dieser 16 Werte gleich stark zu gewichten, wird das Ergebnis der

Summe schließlich durch 16 geteilt. Im Gegensatz zum rekursiven Tiefpass-Filter wird beim

Moving-Average-Filter lediglich der aktuelle und vergangene Eingangswert für die Berechnung

der Differenzengleichung berücksichtigt.

Die Implementierung, deren generelle Struktur in Abbildung 4 dargestellt ist, wurde mit folgen-

dem Code durchgeführt:

// Variablen initialisieren (ADC-Wert lesen)

u = ADC_GetVonversionValue(ADC1);

// Differenzengleichung berechnen

Ue[0]=u;

sum=0;

for(int i=0;i<M;i++){

sum = sum+(int)Ue[i];

}

y = (int16_t)(1/(float)M*sum);

// Speicherverwaltung

for(int i=M-1;i>0;i--){

Ue[i]=Ue[i-1];

}

// Ausgabe der Ausgangsgröße

DAC_SetChannel1Data(DAC_Align_12b_R, y);

4.3 Test der Filter mit Signalgenerator und Oszilloskop

Der Test der beiden Tiefpass-Filter ist ähnlich aufgebaut wie der in Kapitel 3.7 beschriebene

Test. Der jeweils nicht zu testende Filter muss dazu auskommentiert sein. Im Signalgenerator

wird ein Signal, das symmetrisch um 1,5V schwingt und eine Amplitude kleiner gleich 1,5V

hat, erzeugt und zusammen mit dem Ausgangssignal der Mikro-Controller-Plattform auf dem

Oszilloskop betrachtet und verglichen. Um das Frequenzverhalten des Filters darzustellen, gibt

es zwei Möglichkeiten. In beiden Fällen wird im Signalgenerator die Frequenz des erzeugten

Signals mit einem Sweep zwischen 1Hz und 20kHz variiert. Im Signalgenerator sind folgende

Einstellungen vorzunehmen:

Sine:

o Amplitude 100mV

o Offset 750mV

Sweep:

o Start 1Hz

o Stop 20kHz

o Sweep Time 10s

Der Ausgang des Signalgenerators wird mit einem T-Stück aufgesplittet und auf den ADC1–

Anschluss der Mikro-Controller-Plattform sowie auf das Oszilloskop gegeben. Der Ausgang des

DAC1 der Mikro-Controller-Plattform wird ebenfalls mit dem Oszilloskop verbunden, um Ein-

gangs- und Ausgangssignal des Filters miteinander zu vergleichen.

Die erste Möglichkeit besteht nun darin, das Zeitverhalten der beiden Signale miteinander zu

vergleichen. Dafür werden am Oszilloskop folgende Einstellungen vorgenommen:

Channel 1&2:

o Time/Division 1s/ -> Es können 10 Sekunden angezeigt werden

Page 12: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

12 Implementierung der digitalen Tiefpass-Filter

o Voltage/Division 50mV/

o Kopplung AC -> Der Offset von 1,5V wird entfernt

Wenn nun Kanal 1 und 2 übereinander gelegt werden, wird dargestellt, wie das Filter das Ein-

gangssignal im Frequenzbereich von 1Hz bis 20kHz verändert. Da die Sweep Time auf 10s

eingestellt und auf dem Oszilloskop 1s/Division eingestellt wurde, wird jeweils der komplette

Sweep dargestellt. Innerhalb einer Division wird die Frequenz also um

(20000 - 1)/10Hz = 1999,9Hz ≈ 2kHz erhöht. Für die Implementierung des rekursiven Tiefpass-

Filters und des Moving-Average-Filters ergibt sich das Frequenzverhalten in Abbildung 5.

Abbildung 5: Darstellung des Frequenzverhalten im Zeitbereich

Auf der linken Seite von Abbildung 5 ist das rekursive Tiefpass-Filter mit einem Gewichtungs-

faktor von GF = 0.98 dargestellt. Wie erwartet entspricht das Verhalten dem eines Tiefpasses.

Auf der rechten Seite ist das Ausgangssignal des Moving-Average-Filters dargestellt mit einer

Länge von M = 16. Das sinx/x-Verhalten (Rechteck im Zeitbereich) ist deutlich zu erkennen.

Die zweite Möglichkeit besteht darin, mit einer FFT das Spektrum des Ausgangssignals darzu-

stellen. Dafür werden am Oszilloskop folgende Einstellungen vorgenommen:

Spanne 20kHz

Mitte 9kHz

Fenster Rechteck

Die Verschiebung um 1kHz (Mitte = 9kHz) wurde durchgeführt, um das Verhalten um eine

Frequenz von 0Hz besser beurteilen zu können. Das Ergebnis der FFT für das Ausgangssignal

des rekursiven Tiefpasses und des Moving-Average-Filters ist in Abbildung 6 dargestellt.

Abbildung 6: Darstellung des Frequenzverhaltens mittels FFT

Es ist zu sehen, dass das Ergebnis der FFT (pink) in Abbildung 6 der logarithmischen Darstel-

lung des Ergebnisses des Zeitverhaltens (grün) in Abbildung 5 entspricht.

Page 13: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

UART-Kommunikation zwischen Mikro-Controller-Plattform und PC 13

5 UART-Kommunikation zwischen Mikro-Controller-Plattform

und PC

Auf dem zugrunde liegenden Mikro-Controller STM32F4 ist eine USART-Schnittstelle verfüg-

bar. Im Rahmen der verwendeten Mikro-Controller-Plattform und der verwendeten initDevice

Klasse wird diese Schnittstelle als Universal Asynchronous Receive Transmit (UART) verwen-

det. Das bedeutet, dass lediglich ein Kabel für das Empfangen und ein Kabel für das Versenden

zur Verfügung steht, jedoch kein Kabel für die Übertragung des Clock-Singals. Sie ermöglicht

die Kommunikation zwischen der Mikro-Controller-Plattform und dem PC.

Somit kann zum Beispiel die Filtersteuerung, also die Auswahl des Filters und die Anpassung

der Koeffizienten, vom PC durchgeführt werden und umkehrt Abtastwerte an den PC gesendet

werden. Der generelle Ablauf der Konfiguration der DAC1-Schnittstelle ist in Abbildung 7

dargestellt und wird in den folgenden Kapiteln im Detail beschrieben.

Abbildung 7: Konfiguration und Test der USART1-Schnittstelle

5.1 Konfiguration der USART1-Schnittstelle

Die Konfiguration wurde, entsprechend Kapitel 7.2 in [1] mit folgendem Code durchgeführt:

device1.setUsartChannel(1);

device1.setUsartDmaConnection(usartDmaOff);

device1.usartInit();

device1.setIRQChannel(usartInterrupt);

device1.nvicInit();

Page 14: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

14 UART-Kommunikation zwischen Mikro-Controller-Plattform und PC

Die Verwendung der DAC1- Schnittstelle wird mit der Funktion setUsartChannel(1) definiert.

Mit der Funktion setUsartDmaConnection(usartDmaOff) wird daraufhin definiert, dass die Pe-

ripherie Direct Memory Access (DMA) nicht verwendet wird. Die DMA wird verwendet, wenn

beabsichtigt wird, den Datentransfer zwischen verschiedenen Peripherien untereinander, zwi-

schen einer Peripherie und dem Speicher oder speicherintern zu optimieren. Bei Verwendung

der DMA wird der Prozessor erheblich weniger belastet. Da dieses Programm recht kurz ist,

wurde diese Optimierung der Laufzeit nicht benötigt und die DMA nicht verwendet. Weitere

Informationen zur DMA sind in Kapitel 9 in [1] verfügbar. Mit dem Aufruf der Funktion usar-

tInit() werden schließlich die Einstellungen für die USART-Kommunikation übernommen.

Da die USART-Kommunikation mit Interrupts gesteuert wird, muss im NVIC der Kanal für den

USART1-Interrupt freigegeben werden. Das wird mit der Funktion setIRQChan-

nel(usartInterrupt) bewerkstelligt, woraufhin die Einstellung mit der Funktion nvicInit() über-

nommen wird.

Die von [2] bereitgestellten Funktionen setUsartChannel(), setUsartDmaConnection(), usar-

tInit(), setIRQChannel() und nvicInit() konfigurieren im Hintergrund automatisch alle relevan-

ten Elemente (GPIOs, Prescaler, USART-Einstellungen, usw.). Für genauere Informationen zu

den verwendeten Funktionen sind in [2] die Funktionsdefinitionen einzusehen. Die Einstellun-

gen, die mit diesem Code festgelegt wurden, sind in Tabelle 2 in [1] aufgelistet und werden an

dieser Stelle kurz wiederholt:

Übertragungsrate /Bit pro sek. 57600

Datenbits 8

Paritätsbit keine

Stoppbits 2

Flusssteuerung keine

Diese Werte werden in Kapitel 5.6 wieder benötigt. Dort wird die Kommunikation mit Hilfe des

Terminalprogramms Hyperterminal getestet wird.

5.2 Implementierung der USART1-Interrupt-Service-Routine

Die USART-Interrupt-Service-Routine wird aufgerufen, sobald ein UART-Interrupt ausgelöst

wird, z.B. im Falle eines neu empfangenen Datenwortes. Abgesehen von den Aufrufen im lau-

fenden Betrieb wird die USART1-Interrupt-Service-Routine einmal zu Beginn, bei der Ausfüh-

rung des Befehls usartInit(), aufgerufen.

Die USART1-Interrupt-Service-Routine wurde, angelehnt an Kapitel 7.2 in [1], mit folgendem

Code implementiert:

extern "C" void USART1_IRQHandler(void)

{

uint8_t signalFromGUI;

if(readyToSend){

ADC_Cmd(ADC1,DISABLE);

USART_SEND(char);

ADC_Cmd(ADC1,ENABLE);

readyToSend=0;

}

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){

USART_ClearITPendingBit(USART1,USART_IT_RXNE);

signalFromGUI = (USART_ReceiveData(USART1) & 0x7F);

}

}

Page 15: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

UART-Kommunikation zwischen Mikro-Controller-Plattform und PC 15

Zu Beginn wird eine 8-Bit Variable definiert, in der im späteren Verlauf der empfangene Wert

gespeichert wird. Falls das Programm beabsichtigt, einen Wert via USART zu senden, wird

zuvor die Variable readyToSend gesetzt und der Code in der if-Abfrage ausgeführt. Zu Beginn

wird für den Zeitraum, in dem der Sendeprozess stattfindet, der ADC1 mit dem Befehl

ADC_Cmd(ADC1,DISABLE) deaktiviert. Das Senden der 8-Bit Daten wird mit der Funktion

USART_SEND(char) durchgeführt, woraufhin danach der ADC1 mit dem Befehl

ADC_Cmd(ADC1,ENABLE) wieder aktiviert wird. Zum Schluss wird die Variable readyToSend

zu Null gesetzt, sodass erst wieder wenn das Bit gesetzt wird diese Befehle erneut ausführt.

Die zweite if-Abfrage testet ob das ReceiveNotEmpty (RXNE) Bit gesetzt ist. Ist das der Fall,

wurde ein neuer Wert via USART empfangen und kann ausgelesen werden. Zu Beginn muss

das RXNE-Bit zurückgesetzt werden, sodass ein erneutes Setzen dieses Bits erneut einen Inter-

rupt auslöst. Das Zurücksetzten wird mit dem Befehl US-

ART_ClearITPendingBit(USART1,USART_IT_RXNE) durchgeführt. Schließlich wird der neu

empfangene Wert binär maskiert und in der zu Beginn deklarierte Variablen signalFromGUI

gespeichert.

5.3 Definition der Funktion USART_SEND()

Die Funktion USART_SEND() wurde mit folgendem Code implementiert:

void USART_SEND(char byte)

{

USART_SendData(USART1,byte);

while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)

{

}

}

USART_SEND() sendet pro Aufruf jeweils eine 8-Bit Variable, die übergeben werden kann.

Das Senden an sich wird dabei von der Funktion USART_SendData(USART1,byte) durchge-

führt. Die darauffolgende while-Schleife fragt mit der Funktion US-

ART_GetFlagStatus(USART1, USART_FlAG_TC) kontinuierlich ab, welchen Wert das Trans-

mission Complete Flag (USART_FLAG_TC) hat. Dieses Flag kann die Werte SET und RESET

annehmen. Solange USART_FLAG_TC nicht gesetzt ist (RESET), verweilt das Programm in der

while-Schleife. Wird USART_FLAG_TC gesetzt (SET), springt das Programm aus der Schleife

und setzt die kommende Programmausführung fort.

5.4 Test der USART-Interrupt-Service-Routine

Analog zu der Implementierung der ADC-Interrupt-Service-Routine wird auch an dieser Stelle

getestet, ob das Programm wie gewünscht in die USART-Interrupt-Service-Routine springt.

Dazu wird ebenfalls der Debugger von Keil uVision verwendet. Führen Sie erneut die folgen-

den Schritte durch:

Klicken Sie auf ‘F7‘, um den geschriebenen Code in die Target-Files umzusetzen

Klicken Sie auf , um den Debugger zu starten

Setzten Sie einen Breakpoint in die DAC1-Interrupt-Service-Routine

Klicken Sie auf , um den Programmcode vom Debugger in den Kontroller zu laden

Klicken Sie auf , um das Programm zu starten

Page 16: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

16 UART-Kommunikation zwischen Mikro-Controller-Plattform und PC

Das Programm sollte nun bei dem Breakpoint in der DAC1-Interrupt-Service-Routine stoppen.

Falls dem nicht so ist, muss die Konfiguration der DAC1-Schnittstelle sowie die Implementie-

rung der DAC1-Interrupt-Service-Routine auf Fehler untersucht werden.

5.5 Implementierung der Filtersteuerung

Nachdem getestet wurde, ob das Programm in die USART-Interrupt-Service-Routine springt,

kann mit der Implementierung der Filtersteuerung fortgefahren werden. Die Implementierung

der Filtersteuerung wurde in den Interrupt-Service-Routinen der USART1-Schnittstelle und des

ADC1 durchgeführt. In der USART-Interrupt-Service-Routine werden Steuersignale vom PC

empfangen und dazugehörige Steuervariablen gesetzt. Diese Variablen definieren, welcher Fil-

ter mit welchen Filtereigenschaften in der ADC-Interrupt-Service-Routine verwendet wird. Der

Test der Filter benötigt daher lediglich ein Terminalprogramm, mit welchem USART-Daten

vom PC an die Mikro-Controller-Plattform gesendet werden können und wird im Detail in Ka-

pitel 5.6 beschrieben.

An dieser Stelle wird auf Kapitel 6 verwiesen, wo der komplette Code aufgeführt ist. Der Ein-

fachheit halber wird in diesem Kapitel lediglich eine Kurzfassung der Filtersteuerung vorge-

stellt. Um die komplette Funktionsweise mit der MATLAB GUI zu testen, muss der Code, iden-

tisch wie er in Kapitel 7 aufgeführt ist, implementiert werden.

Zu Beginn des Programms wurden die folgenden Variablen definiert, die die Filtersteuerung

übernehmen:

volatile bool moving_avr = false; // 'i' (ASCII: 105)

volatile bool filter_rec = true; // 'j' (ASCII: 106)

volatile float GF = 0.5; // Gewichtungsfaktor GF

von 'filter_rec'

volatile int8_t M = 8; // Filterlänge M

von 'moving_avr'

Die Auswahl, welcher Filter aktuell verwendet wird, wurde über die bool-Variablen moving_avr

und filter_rec definiert. Bei dem Start des Programms ist das rekursive Tiefpass-Filter aktiv

(true) und der Moving-Average-Filter inaktiv (false). Die Variablen GF und M bestimmen das

jeweilige Übertragungsverhalten des aktuellen Filters.

Die Auswertung des empfangenen USART-Signals wurde, wie zuvor erwähnt, in der USART-

Interrupt-Service-Routine durchgeführt:

if(signalFromGUI==105){ // ASCII 'i'

filter.resetFilterCoefficients();

moving_avr=true;

filter_rec=false;

}

else if(signalFromGUI==106){ // ASCII 'j'

filter.resetFilterCoefficients();

filter_rec=true;

moving_avr=false;

}

else if((signalFromGUI>=0)&&(signalFromGUI<=100)){

if((filter_rec==true)&&(moving_avr==false))

GF=((float)signalFromGUI/100);

else if((filter_rec==false)&&(moving_avr==true))

M=(int8_t)((uint8_t)signalFromGUI-65);

}

Page 17: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

UART-Kommunikation zwischen Mikro-Controller-Plattform und PC 17

Entspricht das via USART empfangene Signal dem ASCII-Wert ‘i‘ wird damit der Moving-

Average-Filter mit ‘true‘ ausgewählt , mit ‘j‘ dementsprechend das Tiefpass-Filter. Der jeweils

andere Filter wird mit ‘false‘ als inaktiv definiert. Zu Beginn wird in beiden Fällen jedoch erst-

mal die Funktion resetFilterCoefficients() aufgerufen, mit der die Speicherzellen der Filter in

den Ausgangszustand gesetzt werden. Ist das empfangene Signal ungleich dem ASCII-Wert für

‘i‘ oder ‘j‘ und in dem Wertebereich [0, 100], wird das empfangene Signal als eine Veränderung

der Filterkoeffizienten ausgewertet. Je nachdem, welcher Filter aktuell aktiv ist, wird das Signal

entsprechend ausgewertet. Ist das rekursive Tiefpass-Filter aktiv, wird das empfangene Signal

als Gewichtungsfaktor GF interpretiert. Ist wiederum der Moving-Average-Filter aktiv, wird das

empfangene Signal als Filterlänge M interpretiert.

Das angepasste Filter wird dann, wie bereits erwähnt, in der ADC-Interrupt-Service-Routine

verwendet.

5.6 Test der UART-Kommunikation mit Hyperterminal

Mit der Erklärung in Kapitel 5.5 kann nun die UART-Kommunikation zwischen dem PC und

der Mikro-Controller-Plattform getestet werden. Für diesen Test bietet sich ein Terminalpro-

gramm an. In diesem Projekt wurde dafür Hyperterminal verwendet. Die verwendete Version

von Hyperterminal ist unter folgendem Link zu finden:

http://www.eit.hs-karlsruhe.de/mesysto/teamorientierte-lehrmethoden/teamorientierte-

lehrmethoden/student-project-teams/zeitdiskrete-signale-und-systeme.html

Führen Sie folgende Schritte durch:

Verbinden Sie die USART-Schnittstelle der Mikro-Controller-Plattform mit dem PC

Überprüfen Sie welcher COM-Port reserviert wurde

o Start -> Systemsteuerung -> Geräten Manager -> Anschlüsse (COM &

LPT) -> Silicon Labs CP210x USB to UART Bridge (COMxx)

Öffnen Sie Hyperterminal und erstellen Sie eine Verbindung mit den folgenden Para-

metern:

o Connect using: COMxx

o Bits pro Sekunde: 57600

o Datenbits 8

o Parität keine

o Stoppbits 2

o Flusssteuerung keine

Page 18: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

18 UART-Kommunikation zwischen Mikro-Controller-Plattform und PC

Abbildung 8: UART-Kommunikation via Hyperterminal

Die Verbindung sollte nun erstellt und aktiv sein. Laden Sie das Programm auf den Mikro-

Controller. Bei dem Start des Programms ist das rekursive Tiefpass-Filter aktiv. Sie können nun

mit ‘i‘ das Moving-Average-Filter aktivieren und mit ‘j‘ dementsprechend wieder das rekursi-

ven-Tiefpass-Filter. Die Filterkoeffizienten der Filter sind in diesem Moment noch auf dem

Standartwerten GF = 0,5 und M = 8. Funktioniert des Wechseln zwischen den Filtern wie er-

wartet, kann das Verändern der Koeffizienten getestet werden.

Ist das rekursive Tiefpass Filter aktiv wird das empfangene Signal als Gewichtungsfaktor GF

interpretiert. Dieser Gewichtungsfaktor kann Werte zwischen 0 und 1 in 0.01-Schritten anneh-

men. Das empfangene Signal für GF kann ASCII-Werte von 0 bis 100 annehmen die dement-

sprechend durch 100 geteilt werden. Aktivieren Sie das rekursive Tiefpass-Filter mit ‘j‘ und

senden Sie ein ‘Z‘ (ASCII: 90); GF wird daraufhin auf 0,9 gesetzt. Damit steigt die Zeitkonstan-

te des Filters an. Mit ‘Space‘ wird GF dementsprechend auf 0,32 gesetzt, wodurch die Zeitkon-

stante gesenkt wird. Die ersten 32 ASCII-Zeichen sind Steuersignale, können aber trotzdem für

den Test verwendet werden.

Ist das Moving-Average-Filter aktiv, wird das empfangene Signals als Filterlänge M interpre-

tiert. Die Filterlänge kann Werte zwischen 1 und 16 annehmen. Das empfangene Signal darf

ASCII-Werte von ‘B‘ (dez. 66) bis ‘Q‘ (dez. 81) annehmen, da von dem empfangenen Signal

der dezimal Wert 65 abgezogen wird. Stellen Sie sicher, dass Sie diesen Wertebereich nicht

überschreiten, da in dieser Implementierung keine Abfrage existiert, ob der empfangene Wert

zwischen 66 und 81 liegt.

5.7 Test der Filter mit Hilfe der MATLAB GUI

In Kapitel 4.3 und 5.6 wird der Funktionstest der Filter an sich, sowie der Test der Filtersteue-

rung beschrieben. Der in Kapitel 6 angehängte Code enthält jedoch noch weitere Funktionalitä-

ten, die an dieser Stelle kurz beschrieben werden. Zum Schluss wird dann die Steuerung dieser

Implementierung mittels MATLAB GUI diskutiert. Wie bereits in Kapitel 1 beschrieben wurde

Page 19: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

UART-Kommunikation zwischen Mikro-Controller-Plattform und PC 19

ist die Verwendung der MATLAB GUI nur in Kombination mit der Messkarte BNC-2110 von

National Instruments möglich.

Der Hauptunterschied zu der bisher beschriebenen Funktionalität ist, dass die vollständige Im-

plementierung eine Messung des Filterverhaltens im Zeitbereich sowie im Frequenzbereich

erlaubt. Das Aktivieren der jeweiligen Messung erfolgt via UART-Schnittstelle. Eine Messung

im Zeitbereich wird gestartet wenn ein ‘g‘ empfangen wird. In diesem Fall wird die bool-

Variable start_zeitbereich auf true gesetzt. Eine Messung im Frequenzbereich wird dementspre-

chend mit dem Empfang eines ‘h‘ gestartet, woraufhin die bool-Variable start_frequenzbereich

auf true gesetzt wird. Bei Start des Programms sind beide Variablen auf false.

Bei einer Messung im Zeitbereich wird das aktuell empfangene Eingangssignal der Mikro-

Controller-Plattform außer Betracht gelassen. Anstelle dessen wird für eine Dauer von 60 bzw.

300 Abtastwerten ein konstanter Wert von 1375 an den Filter übergeben. Dies entspricht einem

Sprung von 0V auf 1V. Während der Dauer von 60 bzw. 300 Abtastwerten, wird der Aus-

gangswert des Filters in einem Array gespeichert. Dieses Array wird daraufhin Byte-weise via

USART1 an die MATLAB GUI gesendet, welche die Sprungantwort dann darstellt.

Abbildung 9: MATLAB GUI; rekursives Tiefpass-Filter, Messung Zeitbereich

Eine Messung im Frequenzbereich wird mit Hilfe der Messkarte BNV-2110 von National In-

struments durchgeführt. Dabei wird der Ausgang AO 0 der Messkarte mit ADC1 der Mikro-

Controller-Plattform verbunden und der DAC1 der Plattform mit dem Eingang AI 0 der Mess-

karte. Mit Hilfe der MATLAB GUI wird daraufhin eine Frequenz Sweep erzeugt, der über die

Messkarte an die Mirko-Controller-Plattform übergeben wird. Die Ausgangswerte des aktuell

verwendeten Filters werden mit Hilfe der Messkarte von MATLAB aufgezeichnet und in der

GUI als Amplituden- und Phasengang darstellt.

Page 20: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

20 UART-Kommunikation zwischen Mikro-Controller-Plattform und PC

Abbildung 10: MATLAB GUI; rekursives Tiefpass-Filter, Messung Frequenzbereich

Page 21: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

Abbildungsverzeichnis 21

6 Abbildungsverzeichnis

Abbildung 1: Reihenfolge der Implementierung 4

Abbildung 2:Konfiguration von Timer2, ADC1, DAC1 und der Zusatzbeschaltung 5

Abbildung 3: Implementierung der digitalen Tiefpass-Filter 9

Abbildung 4: Flussidagramm einer Filterimplementierung 9

Abbildung 5: Darstellung des Frequenzverhalten im Zeitbereich 12

Abbildung 6: Darstellung des Frequenzverhaltens mittels FFT 12

Abbildung 7: Konfiguration und Test der USART1-Schnittstelle 13

Abbildung 8: UART-Kommunikation via Hyperterminal 18

Abbildung 9: MATLAB GUI; rekursives Tiefpass-Filter, Messung Zeitbereich 19

Abbildung 10: MATLAB GUI; rekursives Tiefpass-Filter, Messung Frequenzbereich 20

Page 22: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

22 Anhang 1: Quellcode

7 Anhang 1: Quellcode

#include "stm32f4xx.h"

#include <stdio.h>

#include "stm32f4xx_dac.h"

#include "stm32f4xx_adc.h"

#include "stm32f4xx_gpio.h"

#include "stm32f4xx_dma.h"

#include "initDevice.h"

#include "Filter.h"

#include "stm32f4xx_usart.h"

#include "initTypes.h"

using namespace initTypes;

// Wert der Sprungantwort der via USART an die GUI gesendet wird

// 'Zeitbereich'

char Ua_Out[5];

// Zähler für die Zeitspanne in der 'Sprungantwort'/'Frequenzgang' aufgezeichnet wird

volatile uint16_t i_glob1 = 0;

// Zähler um 60/300 Werte (NbrOfSamples) im 'Zeitbereich' via USART an die GUI zu senden

volatile uint16_t i_glob2 = 0;

// Variablen um die Art der Messung zu definieren

volatile bool start_zeitbereich = false; // 'g' (ASCII: 103)

volatile bool start_frequenzbereich = false; // 'h' (ASCII: 104)

volatile bool zeitbereich_fertig = false;

// wird auf 'true' gesetzt, wenn 50/300 Werte (NbrOfSamples) konvertiert wurden

// wird auf 'false' gesetzt, wenn 50/300 Werte (NbrOfSamples) via USART versendet wurden

// Variablen um 'filter_rec' oder 'moving_avr' zu aktivieren

volatile bool moving_avr = false; // 'i' (ASCII: 105)

volatile bool filter_rec = true; // 'j' (ASCII: 106)

// Variablen, die das Verhalten von 'filter_rec' und moving_avr' definieren

// Diese Variablen können via USART von der GUI verändert werden

volatile float GF = 0.5; // Gewichtungsfaktor GF von 'filter_rec'

volatile int8_t M = 8; // Filterlänge M von 'moving_avr'

uint16_t NbrOfSamples = 60; // Anzahl der Abtastwerte der Sprungantwort

// Wird je nach Wert von GF zwischen 60 und 300 variiert

// Variablen für den ADC-Input und DAC-Output

static int16_t in=0;

uint16_t out;

// Puffer in dem 60/300 Werte (NbrOfSamples) der abgetasteten Sprungantwort gespeichert sind

// Werte sind als char[5] gespeichert -> 0.000

char Ua_Out_buffer[300][5];

// Variable um den Ausgang auf 1,5V anzuheben

int16_t offset = 0;

// DAC Flag

bool dacFlag;

// Testobjekt Filter

Filter filter;

//////////////////////////////////////////////////

// Funktionen für das Versendet von USART-Daten //

//////////////////////////////////////////////////

// 1 Byte versenden

void USART_SEND(char byte)

{

USART_SendData(USART1,byte);

while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET){

// Loop until the end of transmission

}

// Wait until Transmission Complete (TC)

}

// Versenden eines Puffers von Bytes

void USART_SEND_TEXT(char *buffer)

{

while (*buffer)

{

USART_SEND(*buffer);

buffer++;

}

}

Page 23: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

Anhang 1: Quellcode 23

int main()

{

SystemInit();

initDevice device1;

///// Timer 2 /////

device1.setTimer(2);

device1.setfTimer(22050); //44kHz

device1.setTimerOutput(Trigger);

device1.timerInit();

///// ADC /////

device1.setAdc(1); // Wenn ADC1 ausgewählt wird, wird automatisch Kanal 13 festgelegt

device1.setADCTrigger(timer2ADC_TRGO);

device1.adcInit();

device1.setIRQChannel(adcInterrupt);

device1.nvicInit();

///// DAC /////

device1.setDac(1);

device1.setDacTrigger(None);

device1.dacInit();

dacFlag=false;

///// USART /////

device1.setUsartChannel(1);

device1.setUsartDmaConnection(usartDmaOff);

device1.usartInit();

device1.setIRQChannel(usartInterrupt);

device1.nvicInit();

///// Parametrisierung der Zusatzbeschaltung /////

device1.setADCInputPath(1,Bypass);

device1.setDACOutputPath(1,Bypass);

while(true)

{

}

return 0;

}

/*-------ADC Interrupt---------*/

extern "C" void ADC_IRQHandler(void)

{

static uint16_t count_uart = 0;

ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);

////////////////////////////////////

// Messung: Zeitbereich, Tiefpass //

////////////////////////////////////

if( start_zeitbereich == true && start_frequenzbereich == false &&

filter_rec == true && moving_avr == false)

{

in=1375;

out=filter.lowPassOrder1(in, GF);

snprintf(Ua_Out,6,"%f",(float)out); // Wandelt '(float)out' in einen String um "0.000"

for (int i=0; i<5;i++){

Ua_Out_buffer[i_glob1][i] = Ua_Out[i];

}

i_glob1++;

if(i_glob1==NbrOfSamples){

start_zeitbereich=false;

zeitbereich_fertig=true;

i_glob1=0;

}

}

else{

//////////////////////////////////////////

// Messung: Zeitbereich, Moving Average //

//////////////////////////////////////////

if( start_zeitbereich == true && start_frequenzbereich == false &&

filter_rec == false && moving_avr == true)

{

in=1375;

out=filter.movingAverage(in, M);

snprintf(Ua_Out,6,"%f",(float)out); // Wandelt '(float)out' in einen String um "0.000"

for (int i=0; i<5;i++){

Ua_Out_buffer[i_glob1][i] = Ua_Out[i];

}

Page 24: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

24 Anhang 1: Quellcode

i_glob1++;

if(i_glob1==NbrOfSamples){

start_zeitbereich=false;

zeitbereich_fertig=true;

i_glob1=0;

}

}

else{

////////////////////////////////////////

// Messung: Frequenzbereich, Tiefpass //

////////////////////////////////////////

if( start_zeitbereich == false && start_frequenzbereich == true &&

filter_rec == true && moving_avr == false)

{

in=ADC1->DR;

out=filter.lowPassOrder1(in, GF);

offset=0;

DAC_SetChannel1Data(DAC_Align_12b_R, out+offset);

}

else{

//////////////////////////////////////////////

// Messung: Frequenzbereich, Moving Average //

//////////////////////////////////////////////

if( start_zeitbereich == false && start_frequenzbereich == true &&

filter_rec == false && moving_avr == true)

{

in=ADC1->DR;

out=filter.movingAverage(in, M);

offset=0;

DAC_SetChannel1Data(DAC_Align_12b_R, out+offset);

}

else{

///////////////////////////////////////////////

// Keine Messung: Nur Filterung mit Tiefpass //

///////////////////////////////////////////////

if( start_zeitbereich == false && start_frequenzbereich == false &&

filter_rec == true && moving_avr == false)

{

in=ADC1->DR;

out=filter.lowPassOrder1(in, GF);

offset=0;

DAC_SetChannel1Data(DAC_Align_12b_R, out+offset);

}

else{

/////////////////////////////////////////////////////

// Keine Messung: Nur Filterung mit Moving Average //

/////////////////////////////////////////////////////

if( start_zeitbereich == false && start_frequenzbereich == false &&

filter_rec == false && moving_avr == true)

{

in=ADC1->DR;

out=filter.movingAverage(in, M);

offset=0;

DAC_SetChannel1Data(DAC_Align_12b_R, out+offset);

}

}

}

}

}

}

}

/*-------USART Interrupt---------*/

extern "C" void USART1_IRQHandler(void)

{

uint8_t signalFromGUI;

// 'zeitbereich_fertig' -> Es wurden 50/300 Werte (NbrOfSamples) aufgezeichnet

// Diese Werte werden via USART an die GUI gesendet

// In diesem Zeitraum wird der ADC1 inaktiv geschaltet (DISABLE)

if (zeitbereich_fertig){

ADC_Cmd(ADC1,DISABLE);

if (i_glob2<NbrOfSamples){

USART_SEND(Ua_Out_buffer[i_glob2][0]);

USART_SEND(Ua_Out_buffer[i_glob2][1]);

USART_SEND(Ua_Out_buffer[i_glob2][2]);

USART_SEND(Ua_Out_buffer[i_glob2][3]);

USART_SEND(Ua_Out_buffer[i_glob2][4]);

i_glob2++;

}

Page 25: Tiefpass-Filter-Projekt - EIT|EIT Intranet · lesen, um diese dann in der MATLAB GUI darzustellen. Dieses Dokument ist so aufgebaut, dass die Reihenfolge der diskutierten Themenbereiche

Anhang 1: Quellcode 25

}

// Wenn 50/300 Werte (NbrOfSamples) gesendet wurden wird als Schlusszeichen ':' gesendet

// ADC1 wird daraufhin wieder aktiv geschalten (ENBALE)

if(i_glob2==NbrOfSamples){

USART_SEND(':');

ADC_Cmd(ADC1,ENABLE);

i_glob2=0;

zeitbereich_fertig=false;

start_zeitbereich=false;

}

// RXNE == 0 -> RESET -> Es wurden keine Daten empfangen

// RXNE != 0 -> Es wurden Daten empfangen und diese können gelesen werden

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

{

// Pendig Bit 'USART_IT_RXNE' löschen

USART_ClearITPendingBit(USART1,USART_IT_RXNE);

signalFromGUI = (USART_ReceiveData(USART1) & 0x7F);

// In der GUI wurde Sprungantwort ausgewählt 'g'

if(signalFromGUI==103){

// 50/300 Werte (NbrOfSamples) aufzeichnen und via USART and die GUI senden

filter.resetFilterCoefficients();

start_zeitbereich=true;

start_frequenzbereich=false;

}

// In der GUI wurde Frequenzgang ausgewählt 'h'

else if(signalFromGUI==104){

if(start_frequenzbereich==false){

start_frequenzbereich=true;

}

else{

start_frequenzbereich=false;

}

start_zeitbereich=false;

filter.resetFilterCoefficients();

}

// In der GUI wurde im Dropdownmenü 'Moving Average' ausgewählt 'i'

else if(signalFromGUI==105){

filter.resetFilterCoefficients();

moving_avr=true;

filter_rec=false;

}

// In der GUI wurde im Dropdownmenü 'Tiefpassfilter' ausgewählt 'j'

else if(signalFromGUI==106){

filter.resetFilterCoefficients();

filter_rec=true;

moving_avr=false;

}

// Der Wert für GF oder M wurde in der GUI verändert

// Der Datentyp des empfangenen Wertes wird angepasst

// Die Anzahl der Abtastwerte der Sprungantwort wird definiert (50/300)

else if((signalFromGUI>=0)&&(signalFromGUI<=100)){

if((filter_rec==true)&&(moving_avr==false)){

GF=((float)signalFromGUI/100); // 0/100 = 0

// 50/100 = 0.5

// 100/100 = 1

if(GF<=0.9)

NbrOfSamples=60;

else{

if((GF>0.9)&&(GF<=1))

NbrOfSamples=300;

}

}

else if((filter_rec==false)&&(moving_avr==true)){

M=(int8_t)((uint8_t)signalFromGUI-65); //(66-65) = 1

//(75-65) = 10

//(81-65) = 16

NbrOfSamples=60;

}

}

}

}