mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP CIC interpolation


Autor: Chrysler001 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich bin gerade dabei mit einem DSP c6713 über den Lin Eingang mit 48KHz 
ein Audiosignal einzulesen. Die diskreten Werte möchte ich gerne 
oversampeln und gleichzeitig die spektralanteile über fs/2 vermeiden. 
dafür ist ein CIC Interpolations Filter bestens geeignet. oversampling 
soll mit Faktor 8 oder 16 laufen. Danach werde ich das Signal mit einer 
Delta Sigma Modulation verarbeiten.
die Delta Sigma Modulation funktioniert und das einlesen auch. nun fehlt 
nur noch der CIC Filter. Da hängt es bei dem oversampling.
unsigned const oversampling = 8;

comb1 = input - last_input;
comb2 = comb1 - last_comb1;

last_input = input ;
last_comb1 = comb1;


for (s = 0; s < oversampling; ++s) {
        integrator1 = integrator1 + comb2;
        yn = integrator2 + integrator1 ;
}
Output =yn/4;

das soll ein CIC Filter mit zwei Comb filter dann oversamplig und da 
zwei integrations filter darstellen.
Ist dies richtig umgesetzt mit der überabtastung? Bin mir nicht ganz 
sicher. der DSP hat einen 12bit ADC.

LG

Autor: Dergute Weka (derguteweka)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

Nee, das tut so nicht. Dein Ausgang ist ja schonmal ausserhalb der 
Schleife, wie sollen da dann 8 Werte fuer jedes Eingangssample 
rauskommen. Auch die Arithmetik haut so sicher nicht hin.
Biste dir sicher, dass CIC auf einem DSP fuer deine Anwendung so eine 
tolle Wurst ist? Ich glaub's naemlich nicht. Das ist fuer FPGAs prima, 
wo die Bitbreiten der Rechungen beliebig einstellbar sind. Weder 
Sperrdaempfung noch passband-flatness sind bei CIC prickelnd. Aufm DSP 
werden dich doch MAC Operationen sicher weniger Schmerzen kosten als auf 
einem FPGA, also nimm lieber "normale" Filter.


Gruss
WK

Autor: Jürgen Schuhmacher (engineer) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube, hier stimmt so ziemlich nichts!

 Weder macht es Sinn, den AD zu oversamplen, noch muss oder kann man 
dann noch Frequenzen fs/2 zu vermeiden (wo sollen die herkommen bei der 
8/2-Situation) und auch das anschließende Delta-Sigma bringt nichts 
Neues. Damit kann auch der CIC-Filter dahinter nichts Interessantes 
liefern ausser Filterartefakten.

Wenn, dann muss eine fs/2 Dämpfung dem 48kHz ADC erfolgen und dann gfs 
nochmal eine Filterung runter auf das benötigte Band, wenn es weniger 
sind, als 20kHz -

oder

man benutzt gleich einen Delta-Sigma-Modulator und einen entsprechenden 
Filter, um genau das obige manuell zu tun. In dem Fall baut man hinter 
den CIC noch einen FIR. Das ist dann in Summe optimal.

Autor: Robert1301 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

vielen Dank für eure Antworten.

Ich erzähle mal kurz etwas zu meinem Vorhaben.
Ich möchte ein Audio Signal einlesen mit 44.1 oder 48 KHz. Dieses möchte 
ich dann mit einer Delta Sigma Modulation (in einem 2. Interrupt welcher 
mit einer 8 fach höheren frequenz läuft) in ein 1 bitstream auf den Pin 
40 vom HPI Steckport ausgeben. An den Ausgang vom Port schalte ich meine 
PWM Verstärker Schaltung und vor dem Lautsprecher einen Tiefpass filter 
der mir das Audio Signal wieder erstellt.
Soweit läuft das alles auch. Auch die Ausgabe funktioniert recht gut.
Aber ein Problem habe ich.
Ich habe leichte Störgeräusche auf meinem Ton Signal(siehe Bild, einmal 
1KHz Eingangssignal und dann mein Ausgangssignal)
Aber wenn ich die Musik beziehungsweise mein input Ausschalte oder 
abmache, dann habe ich auch die ganze Zeit Störsignale drauf. Ích dachte 
mir das ich diese mit einem Filter vor dem Delta Sigma Modulator raus 
bekomme. Leider weis ich nicht genau wo die Störsignale herkommen 
sollen. Liegt ja kein input Signal mehr an. An der Verstärker Schaltung 
liegt es nicht.
Habt Ihr eine ahn ung wo das Störsignal herkommt oder wie ich dies 
entfernen könnte?

interrupt void c_int11(void){ //48KHz abtastung des Audio Signals
  //einlesen des audio Signals 
  union { Uint32 combo; short channel[2]; } AIC23_data;
  DSK6713_AIC23_read(hAIC23_handle, &AIC23_data.combo);
  int input = AIC23_data.channel[RIGHT]; // output to buffer

  yn = input;
  //Test ausgabe auf den Kopförer Ausgang um die Qualität des Eingangs zu testen
  short output_value = (short) yn;
  AIC23_data.channel[LEFT]  = output_value;
  AIC23_data.channel[RIGHT] = output_value;
  DSK6713_AIC23_write(hAIC23_handle, AIC23_data.combo);

}


// Variablen für die Delta-Sigma-Modulation
int output = 0;
int integration = 0;

interrupt void c_int14(void){ // Interrupt wird 16 mal öfter aufgerufen

  //Delta Sigma Modulation
  int const DAC = (output == 1 ? max : min);
  int const difference = yn - DAC;
  integration += difference;
  int const comperator = integration > 0 ? 1 : 0;
  output = comperator;
  // Ausgabe auf den digital Pin
  GPIO_pinWrite(gpio_handle, GPIO_PIN2, output);
}

Autor: W.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also dein 1 kHz Tonsignal (nicht der vergleichs-Sinus) sieht ja 
grauenvoll aus. Da war die simple Audioausgabe der Lernbetty ja bereits 
besser...

Ich habe den Eindruck, daß dein gesamtes Ansinnen nicht stimmig ist. 
Worum geht es dir denn tatsächlich? Wenn du nur fernübertragen willst, 
wäre eine Kombination aus Stereo-ADC -- I2S -- Stereo-DAC -- Verstärker 
eigentlich sinnvoller. Ob du nun einen normalen Verstärker oder nen 
"Klasse-D" oder sonstwas als Verstärker nimmst, ist ne andere Sache.

W.S.

Autor: Robert1301 (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Hallöchen,

jup das 1KHz Sinus Signal sieht echt nicht gut aus.
Ich möchte eine digitale Delta Sigma modulation aufbauen und 
schauen/untersuchen wie gut man dies auf einem DSP board hinbekommt. Und 
ich möchte eine normale Pulsweitenmodulation auf einem DSP und eine 
Delta Sigma modulation auf dem DSP untersuchen/ vergleichen. Und es 
sollte auch etwas bei raus kommen(class d verstärker). Das signal soll 
ein Pulssignal sein was ich mir wie gesagt aus dem Port geben lasse. und 
dann einen analogen tiefpass filter wieder umwandle und verstärke.

Ich verstehe halt nicht ganz wo mein Fehler liegt. Theoretisch sollte es 
funktionieren. Ich taste das Signal mit 48KHz ab. Jetzt sollte ein 
oversampling kommen wo ich es auf ca. 800KHz komme. das schaffe ich in 
dem ich ein Interrupt mit 16 facher geschwindigkeit auslöse. In diesem 
Interrupt wird die Delta Sigma modulation durchgeführt und ausgegeben. 
somit habe ich meine höhere Schaltfreqeuenz.
Was aber jetzt fehlt, wäre ein CIC Filter oder ein normaler FIR Filter. 
Weil ich kann ja nicht in dem schnellen Interrupt immer den gleichen 
ingelesenen wert nehmen. den darf ich nur einmal nehmen und dann die 
restlichen 15 mal den eingang mit null füllen. Aber um die nullwerte an 
das signal anzunähern muss ich einen FIR Filter von der Modulation 
anwenden. dieser Filter erstellt mir die passenden zwischen werte von 
dem oversampling.
so die theorie. Theorie und Paxis ist aber meist ein sehr weiter 
unterschied.  Leider.

LG

Autor: Andi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert1301 schrieb:
> Ich habe leichte Störgeräusche auf meinem Ton Signal(siehe Bild,

Wenn das leicht ist, hast du aber sehr tiefe Ansprüche an die 
Tonqualität.

Dein Delta Modulator sieht irgendwie nicht richtig aus, ich würde mal 
sowas probieren (ist natürlich ungetestet):
interrupt void c_int14(void)  // Interrupt wird 16 mal öfter aufgerufen
{
  //Delta Sigma Modulation
  static int filter;
  GPIO_pinWrite(gpio_handle, GPIO_PIN2, yn > filter);
  filter += (yn > filter ? 0x7FFF : -0x7FFF) - filter) >> 3;
}

Da ich nicht weiss wie min und max definiert sind habe ich Hex-Zahlen 
genommen. Die Filterfrequenz wird durch das >> 3 bestimmt und du musst 
etwas damit experimentieren (>>2, >>4, >>5 ...).
Ohne Eingangssignal (yn=0) solltest du ein dauerndes toggeln des 
Ausgangspins erhalten, also etwa 400 kHz Rechteck.

Andi

Autor: W.S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert1301 schrieb:
> so die theorie.

Moment mal, was redest du von "Oversampling"? Wenn du zwischen deinen 
echten Abtastwerten Zwischenschritte benötigst, dann mußt du 
interpolieren. Bei Faktoren im 2er-System geht das relativ leicht, da 
brauchst du bloß Rechtsverschiebungen.

Und irgendwelche zusätzlichen Interrupts (mit 800 kHz !!) halte ich für 
dezent daneben. Sowas mußt du im Interrupt deines Empfangszweiges, also 
mit den 48 kHz machen, dort einen Ausgangs-Fifo füllen und den dann per 
DMA herausbringen. Fragt sich nur, WIE? Immerhin hast du ja allzeit 
keinen Bitstream, sondern Samples mit 16 oder 24 Bit Breite. Die bis zum 
nächsten Sample in einen repräsentativen Bitstream verwandeln zu wollen, 
schaffst du nur per Hardware und du landest bei den Bitzeiten vermutlich 
jenseits von Gut und Böse.

Mach doch erstmal eine Rechnung auf, was du für eine 
Amplituden-Auflösung überhaupt haben willst, dazu dann die finale 
quasi-Samplerate, mit der du ausgeben willst und dann sehen wir weiter. 
Bei schlichter PWM  kommt an Muttertakt für den PWM so etwa 
Samplefrequenz*Amplitudenauflösung heraus - und das ist auch schon 
ziemlich viel.

W.S.

Autor: Robert1301 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallöchen,

vielen dank für eure Antworten.

Andi schrieb:
> Dein Delta Modulator sieht irgendwie nicht richtig aus, ich würde mal
> sowas probieren (ist natürlich ungetestet):

Ich habe deinen Code mal probiert. Im anhang habe ich die Aufzeichnung 
vom Oszi. Also es sieht schonmal besser aus, dass muss ich sagen :)
Aber es ist noch ein Rauschen zu hören was du in dem Anderen Bild 
siehst. Dieses Bild ist bei yn=0. Das rauschen pegelt wirklich um ca. 
400KHz.
Könnt Ihr mir erklären warum bei yn = 0 eine solche Frequenz entsteht, 
obwohl yn=0? Bekommt man diese reduziert, in dem man einen Delta Sigma 
modulator 2. Ordnung implementiert?

W.S. schrieb:
> Wenn du zwischen deinen
> echten Abtastwerten Zwischenschritte benötigst, dann mußt du
> interpolieren.

Ach stimmt, das meinte ich doch, interpolieren.
Also ich habe am TMS320c6713 einen ADC dran mit einer Auflösung von 
16Bit und taste mein Signal mit 48KHz ab. Meine finale samplefrequenz 
sollte um das 14- 16 fache also ca.672 bis 768KHz liegen.
Ich kann doch in meinem zweiten interrupt meine Berechnung durchführen 
und durch die delta sigma modulation meinen bitstream erzeugen. Dort 
kann ich diesen gleichzeitig auf den output pin ausgeben und habe somit 
meine PWM auf dem pin. ich schaffe bei 48KHz meinen zweiten 
interruptabarbeitung 20- 22 mal durchführen zu lassen mit der Delta 
Sigma berechnung.

Autor: Audiomann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du benötigst eine PDM, die das Signal des AD-Wertes richtig übersetzt. 
Das muss kontinuierlich erfolgen und darf nicht an einen INT gebunden 
sein, es sei denn er ist vollkommen synchron!

Autor: Jürgen Schuhmacher (engineer) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Robert:

Ich mir schon sowas gedacht und nun verstehe Ich auch, wozu der CIC sein 
soll: Der macht nämlich genau die benötigte Umsetzung auf die erhöhte 
Frequenz, aber ganz so einfach geht das nicht. Du musst den digitalen 
Ein-Bit-Datenstrom so steuern, dass er dem Eingangswert entspricht, 
brauchst also ein Modell Deiner Last. Ansonsten geht das nur pauschal 
mit einer (linearen) Annahme.

Du must die Pulsdichtemodulation mit dem Ausgang des CIC beschicken 
und davor Filtern, wie Ich es oben beschrieben habe. Der CIC wirkt als 
Interpolationsfilter, generiert aber Knicke und damit Oberwellen. Du 
hast dann ein DSD8 Signal mit 384kHz.

Um da die volle Audioqualität in 16 Bit rauszubringen, braucht man aber 
wenigstens mal das 10fache. Die MEMS-Mikros arbeiten auf etwa der 
Frequenz. Richtig gutes Audio bekommts Du mit dem 100fachen. Meine 
PLD-Orgel arbeitet mit einer nichtlinearen, geregelten PDM direkt aus 
dem FPGA:
http://www.96khz.org/htm/virtualpldorgan07spartan3e.htm

Um das per Interrupt zu steuern, muss das synchron passieren, kann also 
mit 800kHz abgesampelt werden und dann am Ausgang synchronisert werden. 
sowas kann man aussen mit einem Gate machen. Wenn Du das IM Controller 
machen willst, geht das nur voll synchron mit einem programmierbaren 
Timer, der den Ausgang latchet.

Autor: Chrysler001 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe es mal mit einem CIC Filter versucht, aber irgendwie kommt da 
nur müll raus.
// CIC state variables
long integrator1 = 0;
long integrator2 = 0; 
long last_input = 0; 
long last_comb1 = 0;
long last_comb2 = 0;
floata yn;
//aufruf mit 48KHz
interrupt void c_int11(void){
  //int number = 1;
  union { Uint32 combo; short channel[2]; } AIC23_data;
  DSK6713_AIC23_read(hAIC23_handle, &AIC23_data.combo);
  int input = AIC23_data.channel[RIGHT]; // output to buffer

  yn=input;
}


// Variablen für die Delta-Sigma-Modulation
int output = 0;
int integration = 0;

//aufruf mir rund 800KHz
interrupt void c_int14(void){
//CIC Filter 
    long comb1 = yn - last_input;
    long comb2 = comb1 - last_comb1;
    long comb3 = (int)(comb2 - last_comb2)>>16;
    
    last_input = yn;
    last_comb1 = comb1;
    last_comb2 = comb2;
    integrator1 = integrator1 + comb3;
    integrator2 = integrator2 + integrator1;
          yn = yn + integrator2 ;
     
  //Beispiel für einen FIR Filter
  /*  x[0] = yn;
    unsigned i=0;
    for(i=0 ; i<BL ; i++)
      y += B[i]*x[i];
  
    for (i=(BL-1);i>0;i--)
      x[i] = x[i-1];
    yn=y;
  */

  // PWM modulation (Delta-Sigma-Modulation)
    static int filter;
    GPIO_pinWrite(gpio_handle, GPIO_PIN2, yn > filter);
      filter += ((yn > filter ? 0x0400 : -0x0400) - filter) >>3 ;

}


int main(void){

TIMER_configArgs(hTimer1,
    TimerControl, /* use predefined control value  */
    0x00000005,   /* set period                    */
    0x00000000    /* start count value at zero     */
 );
while(1){
}
}

Durch das CIC Filter wird das Signal entweder total schlimm oder es 
kommt nur rauschen und sowas alles raus. Aber das Signal wird nicht 
besser.
Ist in der Implementierung des FIlters was falsch?
Ich habes es auch mal mit einem FIR Filter versucht. Aber da wird es 
auch nciht wirklich besser. Die Filter Koeffizienten habe ich in Matlab 
mit dem Filter tool erstellt.

Autor: Manfred M. (bittbeisser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ist in der Implementierung des FIlters was falsch?
Keine Ahnung, ich habe manchmal Probleme fremden Code nachzuvollziehen 
und meine eigenen Experimente mit CIC Filtern sind schon einige Tage 
her.

Ich kann jetzt auch nicht direkt erkennen welche Ordnung Dein Filter 
hat. Aber eines macht mich stutzig:
 > floata yn;
floats haben bei CIC Filtern eigentlich nichts zu suchen, ausser am 
Eingang.

Ich erinnere mich, das meine Filtersimulation (bei höheren Ordnungen) 
erst brauchbar war, nachdem ich auf "uint64_t" umgestiegen war. Die 
Anzahl der benötigten Datenbits ist von den Filterdaten abhängig. Bei 
"float", wenn man die Exponenten Bits abzieht, kann das schnell zu wenig 
sein.
http://www.informit.com/articles/article.aspx?p=36...

BTW, CIC Filter sind irgendwie blöd zu implementieren (finde ich), da 
sie nicht in das übliche Schema passen. Ich habe 4 Anläufe gebraucht und 
auch das ist eigentlich nur ein Hack. Das hat mir aber gezeigt, das 
diese Dinger nicht immer die eigentlich erhoffte geniale Lösung sind.

: Bearbeitet durch User
Autor: Jürgen Schuhmacher (engineer) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eigentlich ist ein CIC recht einfach zu implementieren - Datenbereiche 
und Überläufe müssen natürlich beachtet werden. Kann es sein, dass Deine 
Daten nicht symmetrisch sind?

Baue Dir das Ding mal in Excel und gibt Integrator und Divisor getrennt 
aus.

Beitrag #5070367 wurde von einem Moderator gelöscht.
Autor: Edi. M. (Firma: Industrie 1.0) (elektromeister)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, dass das Problem darin besteht, dass er erst differenziert 
und dann integriert? Damit bewegt er sich in der Domäne ja abwärts, 
statt aufwärts - hat also keine Summierung über die Eingangswerte und 
Differenz von Integralen wie Ich das kenne.

??

Autor: Audiomann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Chrysler001 schrieb:
> ich bin gerade dabei mit einem DSP c6713 über den Lin Eingang mit 48KHz
> ein Audiosignal einzulesen. Die diskreten Werte möchte ich gerne
> oversampeln und gleichzeitig die spektralanteile über fs/2 vermeiden.
Das erfordert ein anti-alias-filter VOR dem Wandler

> dafür ist ein CIC Interpolations Filter bestens geeignet.
Sagt wer?

> Ist dies richtig umgesetzt mit der überabtastung?
CIC-filter werden unterabgetastet, oder?

Autor: Jürgen Schuhmacher (engineer) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>CIC-filter werden unterabgetastet, oder?

Beim Runtersampeln, ja. Beim Interpolieren- Nein.

Autor: An Fi (chefdesigner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert1301 schrieb:
> Ich verstehe halt nicht ganz wo mein Fehler liegt.

CIC-Filter sind für soetwas nicht unbedingt geeignet, wenigstens nicht 
ohne zugeschalteten FIR-Filter, der die vielen Problemchen eines CIC 
beseitigt. Für Interpolation wiederum würde Ich zu splines oder wavelets 
raten. Ein wavelet hätte den symphytischen Vorteil einer genau 
definierten Grenzfrequenz.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.