Forum: Mikrocontroller und Digitale Elektronik Audioausgabe auf Mikrocontroller mit 8-Bit DAC


von Ralf (Gast)


Lesenswert?

Hallo,

ich möchte auf einem PSoC 5LP Klänge wiedergeben. Leider hat der 
Controller nur einen 8-Bit DAC :( Ich bin mir also bewusst, dass es 
nicht so arg berauschend sein wird.
Um zu sehen, ob das überhaupt einigermaßen akzeptabel klingt, habe ich 
das Beispielprogramm für eine USB-Soundkarte ausprobiert. Die 
Audiosignale werden über die internen OpAmps geleitet, 470R + 100uF in 
Reihe, um DC zu entkoppeln und dann an ganz normale passive 
16R-Kopfhörer.

Ein paar Lieder abgespielt, und sooo schlecht fand ich's gar nicht. Also 
hab ich für erste Tests eine Sinustabelle mit 512 Einträgen angelegt, 
und gebe diese mit 512kHz aus, also 1kHz Sinus. Hört sich auch noch 
soweit gut an.
Im zweiten Schritt habe ich versucht, das Signal mit einer 
Dreieckspannung mit etwa 0.5Hz zu multiplizieren, um die Lautstärke 
einstellen zu können. Und hier habe ich nun das Problem, dass ich bei 
Verwendung der Kopfhörer eine Art Sirren mit drin habe. Das habe ich 
ohne Lautstärkeänderung nicht.

Ich wollte das ganze dann am PC aufnehmen, damit ich "zeigen" kann, was 
ich meine. Aber da taucht das Sirren nicht auf, also ist auf dem Weg in 
den Rechner wohl was drin, was bei den Kopfhörern fehlt.
Interessanterweise taucht das Sirren auch bei Verwendung der Schaltung 
als USB-Soundkarte nicht auf - per NAudio/C# habe ich das 1kHz 
Sinussignal mit einer Dreieckspannung von 0.5Hz multipliziert und 
ausgegeben, kein Sirren. Wie bereits erwähnt, auch das Abspielen von 
Liedern klang relativ gut, ebenfalls kein Sirren.
Hat jemand eine Idee, woran das liegen könnte? Zwischen Beispielprogramm 
und meiner Implementierung ist wie gesagt die Samplingrate 
unterschiedlich (32kHz im Beispiel vs. 512kHz zu meiner 
Implementierung).

Ralf

von Ralf (Gast)


Lesenswert?

Vergessen zu erwähnen:
die Amplitude beträgt ca. 1V direkt am Controller, d.h. über den 470R 
Widerstand wird der Strom weit genug begrenzt, damit die OpAmps nicht 
klippen.

Ralf

von S. Landolt (Gast)


Lesenswert?

> Dreieckspannung mit etwa 0.5Hz zu multiplizieren,
> um die Lautstärke einstellen zu können

Dreieckspannung?
Also ich multipliziere mit einem (festen) Wert kleiner 1, um die 
Lautstärke abzuschwächen.
  Und ja, 8 bit klingen nicht schlecht, nur ist das 
Quantisierungsrauschen recht hoch, und das wird mit abgeschwächter 
Lautstärke nur noch störender.

von Ralf (Gast)


Lesenswert?

Hi,

>> Dreieckspannung mit etwa 0.5Hz zu multiplizieren,
>> um die Lautstärke einstellen zu können
> Dreieckspannung?
> Also ich multipliziere mit einem (festen) Wert kleiner 1, um die
> Lautstärke abzuschwächen.
Ja, das ist wie gesagt als erster Test, damit ich sehe, wie sich 
Änderungen der Lautstärke auswirken.

Ralf

von S. Landolt (Gast)


Lesenswert?

Mir ist zwar nicht klar, was man bei 0.5 Hz testen kann, aber okay.

> eine Art Sirren mit drin habe
Da hätte ich gesagt (und selbst oft genug erlebt), das kann aus mehreren 
Quellen stammen, aber da gilt

> Das habe ich ohne Lautstärkeänderung nicht.
bin ich jetzt etwas ratlos.

von Cornelius (Gast)


Lesenswert?

Hat der PSOC nicht auch programmirbare Logik? Da sollte sich ziemlich 
einfach ein Sigma-Delta Wandler realisieren lassen.
Ansonsten gäbe es noch die Möglichkeit, die SPI für Sigma-Delta zu 
missbrauchen. Das dürfte einen deutlich besseren Klang als der 8Bit-DAC 
geben.

von Ralf (Gast)


Lesenswert?

@ S. Landolt:
> Mir ist zwar nicht klar, was man bei 0.5 Hz testen kann, aber okay.
Was ist nicht klar? Jede Sekunde bin ich auf 0% oder 100% der 
Signalamplitude.

@Cornelius:
> Hat der PSOC nicht auch programmirbare Logik? Da sollte sich ziemlich
> einfach ein Sigma-Delta Wandler realisieren lassen.
> Ansonsten gäbe es noch die Möglichkeit, die SPI für Sigma-Delta zu
> missbrauchen. Das dürfte einen deutlich besseren Klang als der 8Bit-DAC
> geben.
Ja, er hat programmierbare Logik. Mit der will ich es auch 
implementieren, bzw. hab ich bereits. Da diese aber das Sirren hat, hab 
ich es erstmal weitgehend in Software gemacht, um Fehler in der 
Implementierung auszuschließen - nur um festzustellen, dass es da 
genauso ist :)
Also wird es die Implementierung sein, aber ich kann's mir halt nicht 
erklären - A*B ist nun ja nicht wirklich schwer...

Ralf

von Cornelius (Gast)


Lesenswert?

>Ja, er hat programmierbare Logik. Mit der will ich es auch
>implementieren, bzw. hab ich bereits.

Da ist mir nicht ganz klar, was Du jetzt implementiert hast: Den Sigma 
Delta DAC?

von Ralf (Gast)


Lesenswert?

>> Ja, er hat programmierbare Logik. Mit der will ich es auch
>> implementieren, bzw. hab ich bereits.
> Da ist mir nicht ganz klar, was Du jetzt implementiert hast: Den Sigma
> Delta DAC?
Ich verwende den internen 8-Bit DAC im Stromquellenbetrieb. Die 
programmierbare Logik habe ich verwendet, um die Multiplikation 
durchzuführen. Die Sinustabelle kommt per DMA rein und die eingestellte 
Lautstärke wird per Control Register eingegeben.
Aber wie gesagt: die Hardware-Implementierung hab ich wieder komplett 
rausgenommen, da ich das Sirren drin habe. D.h. jetzt läuft es so, wie 
es auf den meisten Controllern läuft, in Software:
1) Interrupt 512kHz: holt Wert aus Sinustabelle, multipliziert mit 
aktueller Lautstärke, raus auf den DAC
2) Interrupt 250Hz: inkrementiert/dekrementiert die Lautstärke

zu 2) Die Lautstärke ist ebenfalls ein 8-Bit Wert, dieser wird im 
Interrupt inkrementiert, wenn er kleiner 255 ist, ansonsten wird die 
Richtung umgekehrt, also dekrementiert, wenn 0 erreicht ist, wird wieder 
inkrementiert, etc., das ergibt somit eine Dreieckspannung mit ca. 
0,5Hz.

Ralf

von Dumdi D. (dumdidum)


Lesenswert?

Ralf schrieb:
> Interrupt 512kHz: holt Wert aus Sinustabelle, multipliziert mit
> aktueller Lautstärke, raus auf den DAC
> 2) Interrupt 250Hz: inkrementiert/dekrementiert die Lautstärke
>
> zu 2) Die Lautstärke ist ebenfalls ein 8-Bit Wert, dieser wird im
> Interrupt inkrementiert, wenn er kleiner 255

Wenn Lautstärke bis 255 geht, was ist dann der Wertebereich für die 
Sinustabelle mit der Du multiplizierst? 0 bis 1? Was machst Du wenn Dein 
Produkt nicht in 8 bit darstellbar ist?

von Ralf (Gast)


Lesenswert?

Hi Dumdi,

> Wenn Lautstärke bis 255 geht, was ist dann der Wertebereich für die
> Sinustabelle mit der Du multiplizierst? 0 bis 1? Was machst Du wenn Dein
> Produkt nicht in 8 bit darstellbar ist?
Die Sinustabelle geht natürlich auch bis 255 :)
Ich verwende das Highbyte vom Ergebnis. Die Sinustabelle selbst ist 
vorzeichenbehaftet abgelegt, die Lautstärke ist vorzeichenlos. Die 
Multiplikation erfolgt ohne Vorzeichen, berücksichtigt das aber 
entsprechend - zumindest sieht es auf dem Oszi nicht verkehrt aus:
1
if(Value < 0x80) {
2
  Value = (Value * Ampl) >> 8;
3
}
4
else {
5
  Value = ((Value * Ampl) >> 8) - Ampl;
6
}
7
Value ^= 0x80;
Der "Ruhepegel" ist also bei 128 (0x80). Die Sinuswerte gehen von 1 bis 
255 (127 symmetrisch um 128).

Ralf

von Dumdi D. (dumdidum)


Lesenswert?

Ralf schrieb:
> Die Sinustabelle geht natürlich auch bis 255 :)
> Ich verwende das Highbyte vom Ergebnis. Die Sinustabelle selbst ist
> vorzeichenbehaftet abgelegt, die Lautstärke ist vorzeichenlos. Die
> Multiplikation erfolgt ohne Vorzeichen,

Ist das ein Ratespiel?
Welche Datentype verwendest Du? Int_8 fuer den Sinus? Int_16? Uint?

Mach ein 'vollstaendiges' Beispiel.

Lass Dir mal die berechneten Daten in einer Tabelle ausgeben.

von soso... (Gast)


Lesenswert?

Was du hörst könnte auch Quantisierungsrauschen sein.

Dein 8-Bit-DAC hat ja 255 diskrete Stufen. Und das Umschalten zwischen 
denen hört man. Im Prinzip hast du bei 8 Bit einen sehr geringen 
Dynamikumfang. Die Reduktion der Lautstärke auf 50% verringert deine 
Auflösung um 1 Bit.

bei 25% Lautstärke hast du nur noch 6Bit Auflösung. Und das ist 
mieserabel.

Helfen tut dagegen eben nur eine höhere Auflösung, oder eine analoge Art 
der Lautstärkeneinstellung.

Tipp:
Ich habe mir mal einen MP3-Player mit µC gebaut, und dort halt einen 
UDA1334 verwendet und mittels I2S gefüttert. PIC32 bieten das nativ.
Mit der Tonqualität bin ich zufrieden.

von CPU Historiker (Gast)


Lesenswert?

Bei der heutigen ekelhaften Rumsbums-Musik brauchst eh nicht mehr als 
8-Bit. Volle 16 Bit hat man früher für Klassik-Musik benötigt.

Zudem kannst du mit den heutigen schnellen CPUs noch oversamling machen, 
das bringt dann nochmal ein paar Bit.

Und ich glaube auch dass das Sirren vom Oversampling her kommt. Dreh mal 
runter obs weg geht.

von Christian S. (roehrenvorheizer)


Lesenswert?

CPU Historiker schrieb:
> Bei der heutigen ekelhaften Rumsbums-Musik brauchst eh nicht mehr
> als 8-Bit. Volle 16 Bit hat man früher für Klassik-Musik benötigt.
>

Hallo,

also hierfür benötigt man 16 Bits oder früher haben die Vorfahren diese 
Musik von einer schlecht gepressten Schallplatte gehört, die extra für 
Schall gemacht war:

https://m.youtube.com/watch?v=uPRetJ-xyio

MfG

von Ralf (Gast)


Lesenswert?

@Dumdi D:
> Ist das ein Ratespiel?
Nein.

> Welche Datentype verwendest Du? Int_8 fuer den Sinus? Int_16? Uint?
Ja, ist int8.

> Mach ein 'vollstaendiges' Beispiel.
Was ist ein vollständiges Beispiel für dich? Oben gezeigt ist der Teil 
der Interruptroutine. Wobei ich da vergessen habe zu erwähnen, dass 
'Value' und 'Ampl' beide uint8 sind, d.h. in Value landet der int8 Wert 
der Sinustabelle. Von daher Asche auf mein Haupt. Vollständiger wird das 
als Beispiel aber m.E. nicht.

> Lass Dir mal die berechneten Daten in einer Tabelle ausgeben.
Ist das jetzt auch ein Ratespiel? :) Welche, der reine Sinus oder nach 
der Multiplikation?

@soso:
> Was du hörst könnte auch Quantisierungsrauschen sein.
> ...
> bei 25% Lautstärke hast du nur noch 6Bit Auflösung. Und das ist
> mieserabel.
>
> Helfen tut dagegen eben nur eine höhere Auflösung, oder eine analoge Art
> der Lautstärkeneinstellung.
Warum habe ich das Sirren dann nicht, wenn ich das 
USB-Soundkartenbeispiel verwende? Da habe ich "nur" das 
Hintergrundrauschen, welches man noch von den Walkmans vom Anfang der 
90er kennt :)

@CPU Historiker:
> Und ich glaube auch dass das Sirren vom Oversampling her kommt. Dreh mal
> runter obs weg geht.
Verstehe ich nicht :o welches Oversampling? Du meinst, die 512kHz sind 
zu schnell?

Ralf

von Jim M. (turboj)


Lesenswert?

Ralf schrieb:
> Der "Ruhepegel" ist also bei 128 (0x80). Die Sinuswerte gehen von 1 bis
> 255 (127 symmetrisch um 128).

Dann ist Deine Berchnungsfunktion leider kompletter Murks.

Betrachten wir den Fall Value < 128, AMP klein,sagen wir mal 1 (eins):
1
if(Value < 0x80) {
2
  Value = (Value * Ampl) >> 8;

Das Ergebnis liegt nahe Null unabhängig von Value. Was ungünstig ist, 
denn es müsste ja eigentlich nahe des Ruhepegels von 128 liegen.

Implementiere das mal auf dem PC und gebe es an der Konsole als CSV aus 
(jeweils Value und Value * AMP).

Das kann man in Excel (LibreOffice) einlesen und plotten.

von Ralf (Gast)


Lesenswert?

@Jim:
> Das Ergebnis liegt nahe Null unabhängig von Value. Was ungünstig ist,
> denn es müsste ja eigentlich nahe des Ruhepegels von 128 liegen.
Deswegen:
1
Value ^= 0x80;
Damit stelle ich quasi den Ruhepegel wieder her.

Ralf

von Toli B. (tolifox)


Lesenswert?

Könnte es sein, dass Dein Mikrocontroller einfach Probleme hat den 
niedrigohmigen Kopfhörer zu treiben? Wenn das Signal an der Soundkarte 
(LineIn 10kOhm / MicIn 3kOhm) sauber ist und mit dem Kopfhörer (ca. 
80-200 Ohm) merkwürdige Geräusche auftreten, dann ist da vielleicht 
intern irgendeine Schaltung ausgelastet den Strom zu regeln und streut 
ein.

Schließe doch mal den Kopfhörer an und greife davor mit dem Oszilloskop 
ab. Vielleicht bekommst Du dann was zu Gesicht.

Evtl. könntest Du auch mal vor dem Kopfhörer das Signal abgreifen und 
parallel an die Soundkarte weitergeben. Wenn du dann auch Nebengeräusche 
hörst, könnte könnte man das Problem weiter eindämmen. Und Du könntest 
es für uns hörbar machen.

von Ralf (Gast)


Lesenswert?

Hallo Toli,

> Könnte es sein, dass Dein Mikrocontroller einfach Probleme hat den
> niedrigohmigen Kopfhörer zu treiben? Wenn das Signal an der Soundkarte
> (LineIn 10kOhm / MicIn 3kOhm) sauber ist und mit dem Kopfhörer (ca.
> 80-200 Ohm) merkwürdige Geräusche auftreten, dann ist da vielleicht
> intern irgendeine Schaltung ausgelastet den Strom zu regeln und streut
> ein.
Der Kopfhörer hat 16R, und momentan sind 470R vorgeschaltet. Der interne 
OpAmp kann 25mA. Der Spitze-Spitze-Wert direkt am OpAmp-Ausgang liegt 
bei etwa 0,6V-1,0V. Also sind's etwa 2mA, die fließen.

> Schließe doch mal den Kopfhörer an und greife davor mit dem Oszilloskop
> ab. Vielleicht bekommst Du dann was zu Gesicht.
Gute Idee, ich hatte nur mal direkt am OpAmp-Ausgang gemessen.

> Evtl. könntest Du auch mal vor dem Kopfhörer das Signal abgreifen und
> parallel an die Soundkarte weitergeben. Wenn du dann auch Nebengeräusche
> hörst, könnte könnte man das Problem weiter eindämmen. Und Du könntest
> es für uns hörbar machen.
Du meinst, der Kopfhörer erzeugt die Störgeräusche selbst? Ich schau 
mal, ob ich das so hingebastelt bekomme, um beides abgreifen zu können. 
Aber wie gesagt, Kopfhörer + USB-Audio hat keine Störungen.

Ralf

von Toli B. (tolifox)


Lesenswert?

Ralf schrieb:
> Du meinst, der Kopfhörer erzeugt die Störgeräusche selbst?

War nur eine Vermutung und Einlassung, da Du Dich ja gewundert hattest, 
was der Unterschied zwischen Soundkarteneingang und Kopfhörer ist. Wenn 
sich die Störgeräusche reproduzierbar verhindern lassen, wenn du an den 
Soundkarteneingang anschließt, wäre es zumindest lohnenswert da mal 
einzugrenzen.

Evtl. ist Dein Problem aber auch völlig woanders zu suchen. Wie gesagt, 
wäre gut, wenn man das ganze mal hören könnte.

von Ralf (Gast)


Lesenswert?

Hallo Toli,

>> Du meinst, der Kopfhörer erzeugt die Störgeräusche selbst?
> War nur eine Vermutung und Einlassung, da Du Dich ja gewundert hattest,
> was der Unterschied zwischen Soundkarteneingang und Kopfhörer ist. Wenn
> sich die Störgeräusche reproduzierbar verhindern lassen, wenn du an den
> Soundkarteneingang anschließt, wäre es zumindest lohnenswert da mal
> einzugrenzen.
Werd ich machen, aber ich muss erst Material besorgen, das gibt die 
Bastelkiste nicht mehr her :D

> Evtl. ist Dein Problem aber auch völlig woanders zu suchen. Wie gesagt,
> wäre gut, wenn man das ganze mal hören könnte.
Ich hab die Testsoftware mal modifiziert. Anstatt per Dreieckspannung 
die Amplitude zu modifizieren, kann ich nun per UART schrittweise den 
Multiplikator hoch/runter zählen und damit für jeden Wert die Ausgabe 
anhören.
Hätte ich vorher schon tun sollen, denn dabei sind zwei Sachen 
aufgefallen:
1) beim Ändern der Werte tritt mitunter eine Störung auf. Hier muss ich 
schauen, ob das bei jeder Änderung vorkommt. Ich ändere die Amplitude 
nur beim Nulldurchgang, das scheint jedoch nicht zu helfen.
2) nicht alle Kombination hören sich sauber an. Bei ganz kleinen 
Amplituden ist es natürlich klar, da besteht das Signal ja nur aus ein 
oder zwei Stufen. Ich hab auch mal eine FFT über verschiedene Amplituden 
laufen lassen, da sehe ich mitunter Oberwellen der 1kHz Frequenz. Ich 
werd da mal eine ordentliche Messreihe machen.

Ich will auch mal schauen, dass ich das USB-Audio Beispiel so herrichten 
kann, dass die Werte vom eingangs erwähnten Testprogramm, die im PSoC 
ankommen, erfassen kann. Dann sehe ich, ob das noch in irgendeiner Weise 
durch eine Audio-API modifiziert wird.

Sehr interessantes und lehrreiches Thema, wie ich finde :)

Ralf

von Dumdi D. (dumdidum)


Lesenswert?

Ralf schrieb:
> Ist das jetzt auch ein Ratespiel? :) Welche, der reine Sinus oder nach
> der Multiplikation?

Nach der Multiplikation.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.