Bluetooth Audio Receiver mit PCM5102A

Bluetooth Audio Receiver mit PCM5102A

Bei uns im Wohnzimmer steht ein Receiver, der ziemlich genau 50 Jahre auf dem Buckel hat. Der Sony STR-V5 hat richtig Wumms, ist mit Wire-Wrap Verbindungen verkabelt wie frühere Raumfahrttechnik und wird sicher auch noch weitere 50 Jahre funktionieren. Das Problem war nur, dass er mit seinen Cinch-Eingängen nicht mehr mit aktuellen Geräten kompatibel ist, die drahtlos übertragen. Daraus entstand die Idee, für den Receiver einen etwas besseren Bluetooth-Empfänger zu bauen im Passenden Retro-Look. Das Endergebnis ist hier schon mal zu sehen.

Receiver betriebsbereit
Receiver betriebsbereit

Bluetooth-Audio

Vor diesem Projekt hatte ich keine Ahnung von Bluetooth. In meiner Vorstellung klang es recht einfach, die Audiodaten zu übertragen und dann abzuspielen. Leider ist es nicht ganz so. Aufgrund der begrenzten Datenrate einer Bluetooth-Funkverbindung müssen die Daten komprimiert werden. Das übernimmt ein „Codec“. Der muss natürlich der gleiche sein auf der Sender- und der Empfangsseite. Die ältesten und derzeit am weitesten verbreiteten Codecs sind „AAC“ und „SBC“. Audiophile Nutzer waren mit der Qualität dieser Kompression nicht zufrieden, sodass eine Reihe neuer Standards versuchen den Markt zu erobern. Neben „SBC“ und „AAC“ wetteifern nun auch “ aptX“, „aptX HD“ und „LDAC“ um die Gunst des Kunden. Nicht vergessen: Sender und Empfänger müssen den gleichen Codec unterstützen. Wenn man sich z.B. einen Bluetooth-Kopfhörer mit „aptX“ kauft, der Receiver aber „LDAC“ spricht, kommt nur eine Verbindung mit „SBC“ zustande, falls es überhaupt klappt.

Insgesamt ist der Bluetooth-Standard ziemlich komplex und mein Interesse hält sich in Grenzen da noch weiter einzutauchen. Die Software benutzt „SBC“, was von quasi allen Geräten unterstützt wird.

Lautstärkeregelung

Während der Programmierung ist mir aufgefallen, dass die Lautstärkeregelung bei Bluetooth der Knackpunkt ist. Das Grundproblem besteht darin, dass die Audio-Samples mit 16 Bit und üblicherweise 100% Lautstärke übertragen werden. Im Empfänger wird nun die Lautstärke reduziert auf sagen wir mal 35%. Das bedeutet, dass wir die Audio-Samples ungefähr durch 16 teilen müssen. Als Ergebnis haben wir Audiodaten mit einer Auflösung von nur noch 12 Bit. Und genauso hört sich das dann an.

Eine einfache Lösung für das Problem ist ein 32 Bit D/A-Wandler. Die empfangenen 16 Bit Samples werden in 32 Bit Werte umgewandelt, indem einfach Nullen angehängt werden. Das macht erst mal keinen Unterschied. Im zweiten Schritt können wir aber die Lautstärke mit dem 32 Bit-Wert berechnen und diesen dann direkt an den D/A-Wandler senden. Dadurch gibt es keinen Informationsverlust bei geringer Lautstärke, die 16 Bit Information bleiben erhalten.

Über die Geheimnisse einer gefälligen Lautstärkeregelung hatte ich kürzlich einen Artikel geschrieben.

Bauteile

Herzstück der Schaltung ist ein Mikrocontroller ESP32 der Firma Espressif. Das System bietet nicht nur reichlich Rechenleistung für 3,50 Euro, sondern ist auch noch stromsparend. Es gibt sehr viele Code-Beispiele vom Hersteller und lebhafte Diskussionen in Foren, was Anwendungsentwicklung und Fehlersuche erleichtern.

ESP-WROOM-32D Modul
ESP-WROOM-32D Modul

Als hochwertiger D/A-Wandler kommt ein PCM5102A von Texas Instruments mit 32 Bit und 112dB Signal-Rausch-Abstand zum Einsatz. Eigentlich ist der für Bluetooth-Audio viel zu gut, die Vorteile der 32 Bit zahlen sich aber bei der Lautstärkeregelung aus.

D/A-Wandler Board
D/A-Wandler Board

Das ganze wird noch ergänzt durch zwei Taster für Lautstärke und Reset, ein 128×64 Pixel OLED-Display und eine Lochraster-Platine. Bei diesem Projekt verwende ich fertige Module, die nur noch miteinander verbunden werden müssen. Das geht natürlich viel schneller, als ein eigener Platinen-Entwurf.

Bauteile
Bauteile

Schaltung

Da ich für das Projekt fertige Module verwendet habe, beschränkt sich die Schaltung auf wenige Verbindungen des zentralen ESP32 Moduls mit dem OLED-Display, dem D/A-Wandler und den zwei Tastern. Das ganze ist in einer Stunde zusammengelötet.

Verdrahtung Unterseite
Verdrahtung Unterseite
Schaltbild
Schaltbild

Das Schaltbild steht hier als pdf zur Verfügung.

Prototyp
Prototyp
Funktionstest
Funktionstest

Gehäuse

Aus verleimten Sperrholzresten habe ich ein kleines Gehäuse gebaut, was ganz chic geworden ist und für meinen Geschmack und gut zum Sony-Receiver passt.

Gehäuse aus Sperrholz - Vorderseite

Gehäuse aus Sperrholz - Unterseite
Gehäuse aus Sperrholz, Vorder- und Unterseite

Software

Die Software ist abgeleitet vom Beispiel „A2DP-SINK“ des ESP32-Herstellers Espressif. Das hat die Entwicklungszeit sehr verkürzt für mich, da die komplette und ziemlich komplexe Bluetooth-Kommunikation bereits im Beispiel implementiert ist. Ich habe noch eine Verarbeitung der Audio Samples für die Lautstärkeregelung und die Umwandlung von 16 zu 32 Bit hinzugefügt wie oben beschrieben. Außerdem habe ich die Routinen für das OLED-Display ergänzt. Auf dem Display wird der Betriebszustand, das verbundene Gerät und eine logarithmische Pegelanzeige dargestellt.

Am Ende hat die Programmierung und Fehlersuche dann doch deutlich länger als ein Wochenende gedauert, da noch eine Menge Bugs zu finden und zu beseitigen waren.

Den kompletten Quellcode, die Bedienungsanleitung und Anweisungen zum Compilieren des Projektes habe ich auf Github veröffentlicht.

https://github.com/uhucrew/bt-receiver-pcm5102a

 

 

Bekomme Updates per Email

Loading

Digital Audio Lautstärke Berechnung

Kurven geeigneter Lautstärkefunktionen

Kürzlich habe ich als Wochenendprojekt einen Bluetooth Audio Empfänger zusammengebastelt. Dabei kam ich irgendwann an den Punkt, die Lautstärke zu regulieren und musste feststellen, dass es gar nicht so einfach ist, das gut zu machen. Ich habe wie immer eine Weile im Internet recherchiert, am Ende musste ich selbst experimentieren getreu dem Motto, dass man nichts vernünftig programmieren kann, was man nicht versteht.

Lautstärke und Gehör

Unser Ohr ist ein eindrucksvolles Organ. Der Hörbereich vom leisestem Ton bis zum größten Krach umfasst etwa 6 Dekaden. Das bedeutet, dass das leiseste Geräusch eine Million mal leiser ist als das lauteste, was wir wahrnehmen können. Da es bei Lärm physikalisch keine Obergrenze gibt, wird beim Gehör die Lautstärke als Maximum festgelegt, welche wir kurzzeitig ohne bleibenden Schaden hören können.

Ein weiterer wichtiger Fakt ist, dass wir leisere Töne viel besser in der Lautstärke differenzieren können. Das macht sich daran bemerkbar, dass wir bei leisen Tönen sehr gut Unterschiede in der Lautstärke hören. Je lauter es wird, umso weniger bemerken wir eine Veränderung.

Daraus ergeben sich folgende Forderungen an eine gute Lautstärkeregelung: Im leisen Bereich muss man in sehr kleinen Schritten sehr genau einstellen können. Je lauter es wird, umso größer werden Schritte und Änderung.

Das hat man natürlich auch schon vor fast 100 Jahren gewusst und selbst in uralter Analogelektronik sind Lautstärkeregler bzw. Potentiometer mit sogenanntem logarithmischen Verlauf eingebaut. Auf alten Potentiometern steht z.B. noch „100kΩ log“ für 100 Kiloohm mit logarithmischen Verlauf oder z.B. „1M lin“ für 1 Megaohm und linearen Verlauf. Auf aktuellen Modellen wird normalerweise der Verlauf mit dem ersten Buchstaben gekennzeichnet:

    • „A20k“ entspricht logarithmisch, 20kΩ
    • „B2k“ bedeutet linear 2kΩ
    • „C50k“ heißt anti-logarithmisch 50kΩ

Mit Einzug der Digitaltechnik haben einige Ingenieure aber nicht ihre Hausaufgaben gemacht und es gibt viele (digitale) Geräte, in denen die Lautstärkeregelung mangelhaft funktioniert. Oft ist die Abstufung im unteren Bereich zu grob, manchmal sind es zu wenige Stufen mit 32 oder noch weniger Einstellstufen.

Vergleich verschiedener Funktionen

Ein logarithmischer Verlauf bei einer Lautstärkeregelung bzw. einem Potentiometer ist meines Wissens nach gar nicht exakt mathematisch definiert. Den Datenblättern einiger Hersteller nach zu urteilen sind die Widerstandsverläufe zum Teil linear mit sanften Übergängen. Ein Hersteller für hochwertige Audio-Potentiometer (Alps Alpine) hat z.B. einen Verlauf mit drei linearen Bereichen; flach bis knapp 25%, etwas steiler bis 65% und sehr steil bei mehr als 65% Drehwinkel.

ALPS_RK271_curves
Quelle: https://tech.alpsalpine.com/prod/e/pdf/potentiometer/rotarypotentiometers/rk271/rk271.pdf

Das könnte man natürlich digital nachempfinden, was aber relativ aufwändig wäre. Eine mathematische Funktion ist natürlich viel einfacher zu programmieren.

Der gewünschte Kurvenverlauf, also Anfangs flach, am Ende steil, folgt ja eher einer Exponentialfunktion oder Potenzfunktionen. Je höher die Potenz, umso flacher der Anstieg im unteren Bereich und umso steiler am Ende. Ich habe verschiedene Funktionen ausprobiert, zunächst die Kurven dargestellt, danach per Gehör getestet.

Kurven geeigneter Lautstärkefunktionen
Kurven geeigneter Lautstärkefunktionen

Optimale Funktion

Nach meinem Gehör beurteilt hat sich die Funktion y=x³ als optimal herausgestellt. Dabei addiere ich noch einen kleinen Offset, damit die Regelung im unteren Bereich etwa bei der Hörschwelle beginnt.

Berechnung der Lautstärke

Für die Regulierung der Lautstärke wird bei digitalen Audiodaten normalerweise ein Faktor benutzt, mit dem jedes Audio-Sample multipliziert wird. Falls man mit Fließkommazahlen arbeitet, liegt der Faktor üblicherweise zwischen 0 und 1. Bei Festpunktarithmetik kann der Faktor ganz unterschiedlich sein. Im Folgenden ein Beispiel als C-Code, wo der Lautstärkefaktor ein 16 Bit Wert zwischen 0 und 65536 ist und mit der Funktion y=x³ errechnet wird.

Wenn man diesen Wert nun mit 16 Bit Audio Samples multipliziert, bekommt man 32 Bit Werte als Ergebnis. Ich verwende das so in einem Bluetooth-Empfänger, wo 16 Bit Audio über Bluetooth empfangen wird und nach Lautstärkeberechnung ohne Qualitätsverlust an einen 32 Bit D/A-Wandler PCM5102A ausgegeben wird.

#include <stdint.h>
#include <stdlib.h>
#include <math.h>

//use x^3 function
#define VOL_POWER 3.0
//upper/lower limit of factor to multiply with samples
#define VOL_MIN 30.0
#define VOL_MAX 65536.0

//precalculate constants once
static const float vol_pow_min = pow(VOL_MIN, (1.0 / VOL_POWER));
static const float vol_pow_diff = pow(VOL_MAX, (1.0 / VOL_POWER)) - pow(VOL_MIN, (1.0 / VOL_POWER));

//calculate volume factor with power function
//argument vol: 0..100%
static uint32_t vol_calc(uint8_t vol) {
    if (vol == 0) return 0;
    if (vol >= 100) return VOL_MAX;

    return floor(pow((vol_pow_min + vol_pow_diff / 100 * vol), VOL_POWER));
}

Als kleine Berechnungshilfe und für eigene Experimante kann hier noch meine Tabelle mit den Zahlenreihen und Versuchen heruntergeladen werden: volume_calc.ods

 

Bekomme Updates per Email

Loading

Wochenendprojekt: Fledermausdetektor

Seit Jahren beobachte ich eine Menge Fledermäuse am Abend und schon seit langem hat mich deren Art der Orientierung und der Kommunikation mittels Ultraschall interessiert. Vorvorletztes Wochenende hatte ich endlich mal wieder etwas Zeit, um einen Fledermausdetektor zu bauen.

Es sollte ein schneller Aufbau auf einer Lochraster-Platine werden und daher habe ich nach einer fertigen Schaltung gesucht. Eine kurze Recherche im Internet liefert einiges an Anleitungen. Nach ein paar Stunden lesen und dem Abgleich der notwendigen Bauteile mit dem Vorhandenen in der Bastelkiste, habe ich mich für eine Analogschaltung entscheiden, die mit einem 4-fach OPV auskommt.

Blockschaltbild

Das Prinzip ist ähnlich einem Superhet-Empfänger: Das hochfrequente Eingangssignal wird etwa 140.000-fach verstärkt und mit einem Oszillatorsignal auf eine niedrigere Frequenz gemischt. Das Prinzip eines Mischers ist umfassend bei Wikipedia erklärt. An der originalen Schaltung habe ich nur wenige Modifikationen vorgenommen. So habe ich den 62kΩ  Widerstand durch ein 68kΩ Exemplar aus der E12 Reihe ersetzt, was die Verstärkung unwesentlich erhöht hat. Außerdem hatte ich kein 50kΩ Poti parat und habe deshalb ein 100kΩ eingesetzt, was zum Ausgleich mit einem weiteren 68kΩ Widerstand überbrückt wurde. Das vollständige Schaltbild ohne die Modifikationen ist hier zu sehen:


Bat Detector, Quelle: https://www.nutsvolts.com/

Auf der o.g. Seite ist alles wunderbar beschrieben, auch ein paar Hintergrundinformationen zu Fledermäusen findet man dort. Um den Detektor richtig anwenden zu können, sollte man den Artikel unbedingt lesen.

Im Folgenden noch eine kleine Bildergeschichte des Aufbaus. Da mir das Projekt sehr gefallen hat, habe ich ein adäquates chices Gehäuse aus Sperrholz gebaut. Das Mikrofon ist steckbar, sodass man mit verschiedenen Mikrofonen experimentieren kann.

Gehäuse Einzelteile, verklebt und geölt
Gehäuse fertig zusammengebaut
Platine von oben
Platine von unten
Batteriefach
Einsatzbereit
Mikrofon (Piezo-Summer)

Erste Versuche haben gezeigt, dass man einiges an Geduld aufbringen muss, um eine Fledermaus zu hören. Die Geräusche sind recht leise und auch nur zu hören, wenn das Säugetier direkt auf einen zufliegt. In einem Berliner Innenhof, in dem in der Dämmerung fünf bis zehn Fledermäuse ihre Runden drehen kann man mit etwas Glück alle viertel Stunde so eine Art rhythmisches Glucksen vernehmen.

 

Bekomme Updates per Email

Loading

AVR basierter RS232 Dimmer

Warnung

Die Schaltung arbeitet mit Netzspannung und einige Teile sind direkt damit verbunden. Somit richtet sich dieser Beitrag nur an den erfahrenen Hobbyisten.

Beschreibung

Mit dieser Schaltung kann eine 230V Last (bis zu 1000W) mit den hier dokumentierten seriellen Kommandos geschaltet oder gedimmt werden.

Foto des Prototyps

Das Herzstück ist ein Atmel ATTINY2313 Controller mit gut dokumentierter Firmware, die komplett in AVR Assembler geschrieben ist. Neben den dimm- und einmaligen Schaltfunktionen können flexible Timer genutzt werden, um in Zyklen zu schalten, einmalig oder wiederholt. Verliert die Schaltung ihre Stromversorgung, sind alle Timer zurückgesetzt. Weitere Einzelheiten sind in der seriellen Protokollbeschreibung zu lesen.

Der im ATTINY2313 integrierte analoge Komparator dient der Erkennung des Nulldurchgangs der Netzspannung um damit den Triac zur richtigen Zeit zu zünden.

Der Quellcode steht unter der „GNU General Public License (GPL)“ frei zur Verfügung und kann hier heruntergeladen werden. Eine bereits assemblierte Version im hex-Format ist hier verfügbar.

Projektbesonderheiten

  • einfache reine Textkommandos, mit einem Terminal bedienbar
  • günstige Bauteile, weder ein Trafo noch ein RS232 Isolator IC sind notwendig
  • intelligente autonome einfache und zyklische Schaltfunktionen

Das Schaltbild kann hier heruntergeladen werden.

ATTiny2313-dimmer.sch_.pdf

 

Ein geprüftes 2 Lagen Platinenlayout ist zusätzlich verfügbar.

 

Bekomme Updates per Email

Loading

 

AVR 1-wire Slave mit DS18B20 Temperatursensor

In diesem Projekt fungiert ein ATTINY45 als 1-Wire Slave und verhält sich auf dem Bus wie ein DS18B20. Die Daten des lokal an den ATTINY45 angeschlossenen Temperatursensors werden auf einem ebenfalls lokalen 7-Segment Display angezeigt.

Foto des Prototyps

Der zentrale Punkt der Schaltung ist ein ATTINY45 Controller. Er arbeitet sowohl als 1-Wire Master wie auch als Slave. An den Master Bus ist ein DS18B20 digitales Thermometer angeschlossen. Ein DS18S20 kann ebenfalls genutzt werden. Auf dem Slave Bus agiert der Controller exakt wie der angeschlossene DS18B20. Es sind zwei Schieberegister mit dem Controller verbunden, um eine 3- oder 4-stellige 7-Segment Anzeige anzusteuern. Die aktuelle Firmware steuert 3 Stellen an, kann aber einfach für 4 Stellen angepasst werden.
Der ATTINY45 liest die Temperatur aus dem angeschlossenen DS18B20 in einer Schleife und stellt den aktuellen Wert auf dem 7-Segment Display dar. Für den Sensor wird „parasite power“ genutzt, weshalb eine Messung eine knappe Sekunde dauert. Auf der Slave-Seite steht der letzte Wert aber immer sofort zur Verfügung. Hier ist kein Warten auf das Auslesen notwendig, womit bestehende Systeme eventuell beschleunigt werden können.
Als zusätzliche Funktion kann auf den internen 2048 Bit EEPROM des ATTINY45 mit den Standard-Kommandos für iButtons zugegriffen werden.

Der Quellcode für den ATTINY45 kann hier heruntergeladen werden.

Projektbesonderheiten

  • Anzeige der Temperatur direkt am Sensor
  • kann DS18B20 in bestehenden System ersetzen ohne Änderung der Software
  • verhält sich wie ein Standard-Temperatursensor
  • schnelleres Auslesen, kein Warten auf Messung notwendig
  • interner ATTINY45 EEPROM nutzbar über iButton Protokoll

Das Schaltbild ist zum Download hier verfügbar.

1wire-slave-temperatur-schematics

 

Bekomme Updates per Email

Loading