Внешний ЦАП состоит из недорогих и доступных компонентах, ресивер S/PDIF на базе DIR9001, ЦАП на TDA1543, регулятор громкости выполнен на PT2259. Так как вход DIR9001 имеет вход уровня TTL, сигнал S/PDIF подается через преобразователь интерфейса MAX485. Цифровой регулятор громкости PT2259 под управлением Arduino имеет 79 шагов уровней громкости, режим MUTE, управление громкостью осуществляется при помощи энкодера ky-040 (модуль), кнопка энкодера используется для активации режима MUTE. Уровень громкости выводится на семисегментный четырех разрядный индикатор TM1637 (модуль).
Ресивер аппаратно настроен на выходной формат 24-Bit I2S с частотой дискретизации 96 кГц. ЦАП TDA1543 16 бит с токовым выходом. Каждый компонент внешнего ЦАПа имеет свое собственное питание которое подается от отдельного стабилизатора. Общий источник питания имеет напряжение 12 В, которое подается на пять стабилизаторов и дополнительно используется для питания платы Arduino.
Напряжение питания PT2259 от 4 до 10 В, 9 В рекомендуемое, входное сопротивление 33 кОм, минимальное сопротивление нагрузки 6 кОм. Отношение сигнал/шум не менее 120 дБ, коэффициент нелинейных искажений не более 0.003% при уровне выходного сигнала 200mVrms.
Схема ресивера на DIR9001
Схема ЦАП на TDA1543 и регулятора громкости на PT2259
Схема стабилизаторов напряжения
- Энкодер
- CLK — D9
- DT — D8
- SW — D10
- Питание +5 В
- Индикатор TM1637
- CLK — D2
- DIO — D3
- Питание +5 В
#include <Wire.h> #include <PT2259.h> #include <Encoder.h> // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip #include <EEPROM.h> // Входит в состав Arduino IDE #include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip #include <STM32_TM1637.h> // http://forum.rcl-radio.ru/misc.php?action=pan_download&item=452&download=1 STM32_TM1637 tm(2,3);// CLK, DIO PT2259 pt; Encoder myEnc(8, 9);// DT, CLK int vol,w,w1,mute; unsigned long time,oldPosition = -999,newPosition; void setup(){ pinMode(10,INPUT); // МЕНЮ КНОПКА SW энкодера MsTimer2::set(1, to_Timer);MsTimer2::start(); if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении tm.brig(7); // ЯРКОСТЬ 0...7 tm.print_float(0,0, 0b01000000,0b01110011,0b01111000,0b01000000); delay(2000); tm.print_float(2259,0, 0,0,0,0); delay(2000); vol = EEPROM.read(0); audio(); } void loop(){ ////////// VOLUME ////////////// if(newPosition != oldPosition&&mute==0){oldPosition = newPosition;vol=vol+newPosition;myEnc.write(0);newPosition=0;time=millis();w=1;w1=1;vol_func();} if(w==1){w=0;audio();tm.print_float(vol*10,0, 0b00001000,0,0,0b00001000);} ///////// MUTE //////////// if(digitalRead(10)==LOW&&mute==0){mute=1; audio();tm.print_float(0,0, 0b01000000,0b01000000,0b01000000,0b01000000);delay(200);} if(digitalRead(10)==LOW&&mute==1){mute=0; audio();w=1;delay(200);} ///////// EEPROM ///////////// if(millis()-time>5000 && w1==1){w1=0;EEPROM.update(0,vol);} delay(10); }// loop void audio(){ pt.setVol_ch2(mute, vol); // mute, vol // mute on === 1 // mute off === 0 // vol === -79...0 dB === int 0...79 // channel-by-channel adjustment // pt.setVol_left(0, 79); // pt.setVol_right(0, 79); } void to_Timer(){newPosition = myEnc.read()/4;} void vol_func(){if(vol<0){vol=0;}if(vol>79){vol=79;}}