B.5  Aufgaben aus Kapitel 5

1.
Wozu benötigt man ein Anti-Aliasing-Filter?
Ein Anti-Aliasing-Filter verhindert, dass in einem Signal bei der Abtastung noch Frequenzen enthalten sind, die im Signalspektrum des Abtastsignals später in das Signal-Nutzband gespiegelt werden.

 
 

2.
Gibt es auch digitale Anti-Aliasing-Filter? Wann benötige ich diese?
Auch in zeitdiskreten Systemen kann es zu einem Übergang von einer Abtastfrequenz in eine andere kommen. Z.B. indem man nur jeden n-ten Wert verwendet (sog. Resampling). An diesen Stellen ist gleichermaßen das Abtasttheorem zu berücksichtigen und eben ein digitales Anti-Aliasing-Filter zu entwerfen.

 
 

3.
Entwerfe ein Aliasing-Filter für einen 12-Bit-Wandler, der ein Signal mit 2kHz abtastet, wobei die Signal-Nutzbandbreite bis 100Hz geht.
Die Eckfrequenz des Filters liegt bei 100Hz. Der Signal-Rausch-Abstand eines 12-Bit-Wandlers liegt bei 1.76 + m 6.02 also 74dB. Nominell muss dann also bei 1900Hz die Dämpfung des Filters 74dB betragen. Pro Ordnung hat ein Tiefpass-Filter 20dB Dämpfung pro Dekade. Die Ordnung kann jetzt berechnet werden nach: n20(log(1900)-log(100)) > 74. Daraus folgt n > 2.89. Mit einem Filter 3. Ordnung ist man also auf der sicheren Seite.

 
 

4.
Schreibe ein Programm, das mit acht LEDs einen Pegelmesser für ein Audiosignal realisiert. Wie erhält man eine logarithmische oder eine lineare Anzeige?
#include <msp430x14x.h> 
int main(void) 
{ 
  int ad_wert,index; 
 
  WDTCTL = WDTPW + WDTHOLD;  // Watchdog-Timer deaktivieren 
  P6SEL=BIT0;                // P6.0 als A/D-Eingang 
  ADC12CTL0 = ~ENC;          // ADC12 deaktivieren 
  ADC12CTL0 = ADC12ON + SHT0_15 + REFON + REF2_5V; 
  ADC12CTL1 = SHP;           // Pulse-Sample-Mode benutzen 
  ADC12MCTL0 = SREF_1;       // Kanal A0 (P6.0) 
  ADC12CTL0 |= ENC;          // Einstellungen übernehmen 
  P3DIR   = 0xFF;            // Ausgabe Port 3 
  P3SEL   = 0x00;            // normale I/O-Funktion 
  while(1)                   // Endlosschleife 
  { 
   ADC12CTL0 |= ADC12SC;     // Konvertierung durchführen 
   while(ADC12CTL0 & ADC12SC) {}// warte bis fertig 
   ad_wert = ADC12MEM0;      // Ergebnis auslesen 
 
// Acht LEDs entsprechen drei Bits, so dass wir für eine 
// lineare Teilung einfach die höchsten drei Bits der 
// AD-Wandlung nehmen. 
   P3OUT = 1 << (ad_wert>>9); 
 
// Für eine LOG-Anzeige nehmen wir das Wandlerergebnis 
// direkt, wir müssen nur den Balken bis zum höchsten 
// gesetzten Bit auffüllen. 
   for (index=0; index<8; index++) 
   { ad_wert = ad_wert | ad_wert >>1; } 
   P3OUT = ad_wert; 
  } 
}
5.
Messe die schnellste Abtastrate, die du mit deinem MSP430 erreichen kannst.
Dazu können wir erneut Listing 5.7 aus Kapitel 5.4.1 mit einer einfachen Zählfunktion erweitern. Zur Zeitmessung verwenden wir den in Aufgabe B.4.6 implementierten 1-Sekunden-Timer.

 
 

#pragma vector=TIMERA0_VECTOR 
__interrupt void TIMERA0(void){ 
  samplerate = ad_count;        // merken der Abtastrate 
  ad_count = 0;                 // Reset des Counters 
} 
int main(void) 
{ 
... 
  while(1)                      // Endlosschleife 
  { 
   ADC12CTL0 |= ADC12SC;        // Konvertierung durchführen 
   while(ADC12CTL0 & ADC12SC) {}// warte bis fertig 
   ad_wert = ADC12MEM0;         // Ergebnis auslesen 
   ad_count++;                  // Sample-Counter hochzählen 
  } 
}
6.
Baue ein digitales Thermometer, das die Temperatur in oC messen kann. Verwende einen NTC. Dessen temperaturabhängiger Widerstand ist gegeben durch
R(T) = 100kΩ eA+B∕T+C∕T2+D∕T3 .
Mit A=-16.0349, B= 5459.339, C= -191141 und D=-3328322
Die Messung von NTC-Widerständen erfolgt üblicherweise mit einem konstanten Strom, den wir über dem Widerstand einprägen. Die dazu erzeugte Spannung wird mit dem A/D-Wandler gemessen. Wollen wir bis hinunter zu -15°C messen, beträgt der Widerstand maximal 1 MΩ. Bei einer maximalen Wandlerspannung von 2.5V ist somit ein Strom von 2.5μA notwendig. Die A/D-Wandlung erfolgt in gewohntem Muster gemäß Listing 5.7 aus Kapitel 5.4.1. Lediglich die Berechnungsfunktion der Temperatur ist zu implementieren. Dazu lösen wir die Formel nach T auf und skalieren mit dem A/D-Wandler.
R(T) = RrefeA+B∕T+C∕T2+D∕T3
T(R) = (                                        )
  A1 + B1ln -R--+ C1ln2 -R---+ D1ln3 -R---
            Rref        Rref         Rref-1
R = Umess∕Imess = ADC *Uref∕4095
 2.5μA = ADC4095 106
Rref = 100k

A1 = 3.354016 B1 = 2.460380C1 = 3.40538E - 06 D1 = 1.03424E - 07
Diesmal verwenden wir Float-Arithmetik, da Temperaturmessungen meist so langsam sind, dass wir auch für aufwändige Rechnungen Zeit haben.

 
 

include math.h 
double temperatur, hilf; 
const double A_1 = 3.354016; 
const double B_1 = 2.460380; 
const double C_1 = 3.40538E-06; 
const double D_1 = 1.03424E-07; 
... 
hilf = log((double)(ad_wert * 10) / 4095); 
temperatur = 1/ (A_1 + B_1 * hilf 
               + C_1 * hilf^2 + D_1 * hilf^3);