Аудиопроцессор TDA7313 (Arduino)

На аудиопроцессоре TDA7313 с использованием Arduino, можно сделать простой но функциональный регулятор тембра и громкости. Микросхема TDA7313 имеет три стерео входа, регуляторы тембра НЧ и ВЧ, тонкомпенсация и четыре выхода (псевдоквадро). Управление осуществляется с помощью I2C. Обвязка минимальная — несколько конденсаторов и два резистора. Номинальное напряжение питания 9В.

Основные характеристики TDA7313

  • Напряжение питания 6…10 В (9 В рекомендуемое)
  • КНИ не более 0,01 %
  • Отношение сигнал / шум 106 дБ
  • Разделение каналов на частоте 1 кГц 103 дБ
  • Регулировка громкости от -78.75 до 0 дБ (0…63 уровня)
  • Регулировка тембра НЧ и ВЧ ±14 дБ (-7…+7)
  • Регулировка аттенюаторов независимое для каждого выхода от -38.75 до 0 дБ (шаг 1,25  дБ)
  • Регулировка предусилителя от 0 до 11.25 дБ (шаг 3,75 дБ)

Для упрощения регулировки параметрами аудиопроцессора при помощи Arduino можно воспользоваться библиотекой — https://github.com/liman324/TDA7313.git , TDA7313.zip

Тестовый скетч

#include <Wire.h>
#include <TDA7313.h>
  TDA7313 tda;
 
void setup(){ 
  Serial.begin(9600);Wire.begin();
  audio();
}
 
void loop(){}
 
void audio(){
  tda.setVolume(55); // громкость 0...63
  tda.setAttLR(0);   // аттенюатор LR 0...31
  tda.setAttRR(0);   // аттенюатор RR 0...31
  tda.setAttLF(0);   // аттенюатор LF 0...31
  tda.setAttRF(0);   // аттенюатор RF 0...31
  tda.setSwitch(0,0,0); // вход 0...2, тонкомпенсация 1 вкл 0 выкл, усиление 0...3
  tda.setBass(0);    // тембр НЧ -7...+7
  tda.setTreble(0);  // тембр ВЧ -7...+7
}

Далее показан пример скетча в котором в качестве регулировки всех основных параметров используется энкодер KY-040 и одна кнопка. При помощи энкодера осуществляется регулировка громкости и тембра в основном меню, и регулировка предусиления (для каждого входа отдельно), включение режима тонкомпенсации, аттенюатор выходов в дополнительном меню, которое активируется при удержании кнопки энкодера. Кнопка которая подключена к цифровому входу Arduino используется для переключения входа.

Информация о состоянии основных параметров выводится на LCD дисплея LCD1602 на базе контроллера HD44780.

Плата Arduino Nano аудиопроцессор TDA7313 обмениваются данными на шине I2C по линиям SDA (data — данные) и SCL (clock — синхронизация).

Плата Пин SDA Пин SCL
Arduino Uno, Nano, Pro и Pro Mini A4 A5

Все параметры заносятся в энергонезависимую память.

MsTimer2.ZIP

Encoder.zip

TDA7313.zip

#include <Wire.h>
#include <MsTimer2.h>
#include <LiquidCrystal.h>
#include <Encoder.h>
#include <EEPROM.h>
#include <TDA7313.h>
  TDA7313 tda;
  Encoder myEnc(9, 8);//CLK, DT подключение энкодера
  LiquidCrystal lcd(7, 6, 2, 3, 4, 5);// RS,E,D4,D5,D6,D7 подключение LCD
   byte a1[8]={0b00000,0b11011,0b11011,0b11011,0b11011,0b11011,0b11011,0b00000};
   byte a2[8]={0b00000,0b11000,0b11000,0b11000,0b11000,0b11000,0b11000,0b00000};
   unsigned long newPosition,time,oldPosition  = -999;
   int vol,vol_d,menu,w,z,bass_d,bass,treb_d,treb,i,menu1,in,gain,gain1,gain2,gain3,loud,lr,rr,lf,rf;
 
void setup(){ 
  Serial.begin(9600);Wire.begin();
  lcd.begin(16, 2);lcd.createChar(0,a1); lcd.createChar(1,a2);
   pinMode(A0,INPUT);// КНОПКА ЭНКОДЕРA
   pinMode(12,INPUT);// КНОПКА IN
     MsTimer2::set(1, to_Timer);MsTimer2::start();
     vol = EEPROM.read(0);bass = EEPROM.read(1)-7;treb = EEPROM.read(2)-7;in = EEPROM.read(3);
     gain1 = EEPROM.read(4);gain2 = EEPROM.read(5);gain3 = EEPROM.read(6);loud = EEPROM.read(7);
     lr = EEPROM.read(8);rr = EEPROM.read(9);lf = EEPROM.read(10);rf = EEPROM.read(11);
      if(in==0){gain=gain1;}
      if(in==1){gain=gain2;}
      if(in==2){gain=gain3;}
     audio();
}
 
void to_Timer(){ //функция таймера
 newPosition = myEnc.read()/4;}
 
void loop(){
  if((analogRead(A0)<900)&&menu1==0){menu++;cl();myEnc.write(0);i++;time=millis();w=1;if(menu>2){menu=0;}}// меню
  if((analogRead(A0)>900)){i=0;}if(i>3){cl();lcd.print("     MENU 2     ");delay(500);cl();menu1=1;menu=100;}
  if((analogRead(A0)<900)&&menu1>0){menu1++;cl();myEnc.write(0);time=millis();w=1;if(menu1>6){cl();menu1=0;menu=0;}}// меню 1
  //////////////////////////////////////// Volume 0...63 дБ //////////////////////////////////////
 if(menu==0){
    if (newPosition != oldPosition) {
    oldPosition = newPosition;
    vol=vol+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w=1;if(vol>63){vol=63;}if(vol<0){vol=0;}audio();}
 
  lcd.setCursor(0,0);lcd.print("Volume   ");
  lcd.print(-63+vol);lcd.setCursor(13,0);lcd.print("dB");vol_d=vol/3;
   if(vol_d>=0){for(z=0;z<=vol_d;z++){lcd.setCursor(z/2,1);lcd.write((uint8_t)0);}}
   if((vol_d)%2==0){lcd.setCursor(z/2,1);lcd.write((uint8_t)1);}
  lcd.setCursor(13,1);lcd.print(vol);}
//////////////////////////////////////////////////////////////////////////////////////////////////////
 
 /////////////////////// индикация тембр НЧ -14...14 дБ ///////////////////
   if(menu==1){
     if (newPosition != oldPosition) {
    oldPosition = newPosition;
    bass=bass+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w=1;if(bass>7){bass=7;}if(bass<-7){bass=-7;}audio();} 
 
  lcd.setCursor(0,0);lcd.print("Bass     ");
  lcd.print(bass*2);lcd.setCursor(13,0);lcd.print("dB");bass_d=bass+7;
   if(bass_d>=0){for(z=0;z<=bass_d;z++){lcd.setCursor(z,1);lcd.write((uint8_t)0);}}
 }
/////////////////////////////////////////////////////////////////////////////////////
 
 /////////////////////// индикация тембр ВЧ -14...14 дБ ///////////////////
   if(menu==2){
     if (newPosition != oldPosition) {
    oldPosition = newPosition;
    treb=treb+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w=1;if(treb>7){treb=7;}if(treb<-7){treb=-7;}audio();} 
 
  lcd.setCursor(0,0);lcd.print("Treble   ");
  lcd.print(treb*2);lcd.setCursor(13,0);lcd.print("dB");treb_d=treb+7;
   if(treb_d>=0){for(z=0;z<=treb_d;z++){lcd.setCursor(z,1);lcd.write((uint8_t)0);}}
 }
/////////////////////////////////////////////////////////////////////////////////////
 
  if(digitalRead(12)==HIGH){in++;lcd.clear();time=millis();w=1;if(in>2){in=0;}if(in<0){in=2;}audio();lcd.setCursor(0,0);lcd.print("IN ");lcd.print(in+1);delay(1000);}
 
///////////////////////////////////// GAIN //////////////////////////////////////////
 
 if(menu1==1){
      if(in==0){gain=gain1;}
      if(in==1){gain=gain2;}
      if(in==2){gain=gain3;}
 
    if (newPosition != oldPosition) {
    oldPosition = newPosition;
    gain=gain+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w=1;if(gain>3){gain=3;}if(gain<0){gain=0;}audio();} 
 
      if(in==0){gain1=gain;}
      if(in==1){gain2=gain;}
      if(in==2){gain3=gain;}
 
  lcd.setCursor(0,0);lcd.print("IN ");lcd.print(in+1);lcd.print(" Gain ");lcd.print(gain);
 }
 /////////////////////////////// LOUDNESS //////////////////////////////////////////
 
  if(menu1==2){
    if (newPosition != oldPosition) {
    oldPosition = newPosition;
    loud=loud+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w=1;if(loud>1){loud=0;}if(loud<0){loud=1;}audio();}
    lcd.setCursor(0,0);lcd.print("LOUDNESS ");if(loud==1){lcd.print("ON ");}else{lcd.print("OFF");}
} 
////////////////////////////////// att  LR //////////////////////////////////////////////
 
   if(menu1==3){
     if (newPosition != oldPosition) {
    oldPosition = newPosition;
    lr=lr+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w=1;if(lr>31){lr=31;}if(lr<0){lr=0;}audio();} 
    lcd.setCursor(0,0);lcd.print("Speaker LR ");lcd.print(lr);
 }
 ////////////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////// att  LF //////////////////////////////////////////////
 
   if(menu1==4){
     if (newPosition != oldPosition) {
    oldPosition = newPosition;
    lf=lf+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w=1;if(lf>31){lf=31;}if(lf<0){lf=0;}audio();} 
    lcd.setCursor(0,0);lcd.print("Speaker LF ");lcd.print(lf);
 }
 ////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////// att  RF //////////////////////////////////////////////
 
   if(menu1==5){
     if (newPosition != oldPosition) {
    oldPosition = newPosition;
    rf=rf+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w=1;if(rf>31){rf=31;}if(rf<0){rf=0;}audio();} 
    lcd.setCursor(0,0);lcd.print("Speaker RF ");lcd.print(rf);
 }
 ////////////////////////////////////////////////////////////////////////////////////////
   ////////////////////////////////// att  RR //////////////////////////////////////////////
 
   if(menu1==6){
     if (newPosition != oldPosition) {
    oldPosition = newPosition;
    rr=rr+newPosition;myEnc.write(0);newPosition=0;lcd.clear();time=millis();w=1;if(rr>31){rr=31;}if(rr<0){rr=0;}audio();} 
    lcd.setCursor(0,0);lcd.print("Speaker RR ");lcd.print(rr);
 }
 ////////////////////////////////////////////////////////////////////////////////////////
 
 
 if(millis()-time>10000 && w==1){
     EEPROM.update(0,vol);
     EEPROM.update(1,bass+7);
     EEPROM.update(2,treb+7);
     EEPROM.update(3,in);
     EEPROM.update(4,gain1);EEPROM.update(5,gain2);EEPROM.update(6,gain3);
     EEPROM.update(7,loud);
     EEPROM.update(8,lr);EEPROM.update(9,rr);EEPROM.update(10,lf);EEPROM.update(11,rf);
     cl();menu=0;menu1=0;w=0;}
}
 
void cl(){delay(300);lcd.clear();}
void audio(){
  tda.setVolume(vol); // громкость 0...63
  tda.setAttLR(lr);   // аттенюатор LR 0...31
  tda.setAttRR(rr);   // аттенюатор RR 0...31
  tda.setAttLF(lf);   // аттенюатор LF 0...31
  tda.setAttRF(rf);   // аттенюатор RF 0...31
  tda.setSwitch(in,loud,gain); // вход 0...2, тонкомпенсация 1 вкл 0 выкл, усиление 0...3
  tda.setBass(bass);    // тембр НЧ -7...+7
  tda.setTreble(treb);  // тембр ВЧ -7...+7
}

Дополнительный материал:


Обновленный скетч — TDA7313_IR.zip

Исправления:

delay(1000);audio();

заменить на:

delay(1000);lcd.clear();audio();

Улучшена работа энкодера, изменено графическое исполнение шкал регулировок, добавлен ИК пульт (прокрутка меню, кнопки <> и IN).  В мониторе порта Вы сможете посмотреть коды кнопок и вписать в скетч свои значения.

Скетч не тестировался!!! 

Для нормальной работы скетча необходимо скачать дополнительные библиотеку:

IRremote.zip — библиотека изменена


Требуется тестирование:

TDA7313 + энкодер + ИК пульт + анализатор спектра (протестировано) — http://forum.rcl-radio.ru/viewtopic.php?id=32

Аудиопроцессор TDA7313 + LCD дисплей 84×48 Nokia 5110 (протестировано) — http://forum.rcl-radio.ru/viewtopic.php?id=102

Аудиопроцессор TDA7313 + LCD дисплей 84×48 Nokia 5110 + ИК пульт —  http://forum.rcl-radio.ru/viewtopic.php?pid=534#p534

Comments

  1. Здравствуйте, собрал девайс. И такая картина, меню крутится без остановки,на валкондер и кнопку нет реакции. Схему проверил компоненты тоже. И как я понял дело в скейче, грешу на таймер. Подскажите пожалуйста или направте где искать.

    1. Здравствуйте! Вы библиотеку энкодера скачивали со страницы сайта? Проверьте полярность питания поданного на энкодер. Кнопка энкодера отвечает за перебор меню, при нажатом состоянии с выхода SW на аналоговый вход арудуино поступает логический ноль. Для проверки скетча на вход А0 подайте +5 В, меню не должно переключаться.

      1. У человека модуле энкодера не припаян подтягивающий резистор. У меня такая же байда была, когда прислали не глянул.
        liman28 возможно ли подключение экрана от Nokia 5110 как вы делали с TDA7449?
        и OLED на базе контроллера SSD1306

              1. картика есть, курсор двигается, контрастность у меня нормальная на 60.
                п.с. в настройках сайта есть подтверждение на почту, когда новое сообщение, или лучше писать на форуме?

      2. В общем подключил энкодер и у меня меню крутиться без остановки, на кондер не реагирует, In1, in2, in3, Loundless и так по кругу, скетч пробовал тот что на сайте, так же пробовал обновлённый скетч, всегда одно и то же, подтяжки к 5в сделаны, так же кнопка SW подтянуть через 10к к 5в,проьовал к массе подтягивать, пробовал без подтяжки все одно и то же, подклбченно 100% все правильно
        Пробовал прописывать вместо input менял на input_pullup бесполезно, что же такое может быть, уже всю голову сломал((((так же пробовал повесить SW на цивровой вход арлуинки, беспооезняк((((

  2. Доброго времени. Столкнулся с одной необычной проблемкой. Все работает, на экране переключаются менюшки, регулировка частоты и прочее, НО нет звука на выходе TDA7313…При этом на выводах Treble, Bout, Loud есть сигнал. Если подать с генератора синус на вход схемы, то при регулировки НЧ амплитуда синусоиды меняется т.е. по SDA SCL сигнал идет нормальный. Такое чувство, что задействован Mute в самой TDA7313. Было подозрение на бракованную микросхему, но впаял ее в автомагнитолу и там все прекрасно работает. Почему здесь нет звука не могу понять…Надеюсь на вашу помощь

    1. Загрузите тестовый скетч, звук должен появиться, если нет по проверьте подключение i2c используя i2c сканер — http://forum.rcl-radio.ru/viewtopic.php?id=64
      Так же в основной скетч в начало setup() добавьте строчку
      if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении
      для очистки EEPROM, так как при старте аудиопроцессор берет настройки из EEPROM, то в ней могут быть значения вне диапазона регулировки которые могут блокировать нормальную работу аудиопроцессора.

      1. Так что все в порядке, в кодере 3 резистора по 10 кОм. будут ли какие-либо проблемы в конфигурации моего arduino? Так как я проверил, что кодировщик будет работать с кодом tda (7449), и кодировщик работал хорошо.

          1. Я уже переустанавливал библиотеку ir, но роторный кодировщик все еще не работает для меня. Это позволяет мне только перемещаться между меню, но не увеличивать или уменьшать прибыль.

            1. В папке библиотеки IRremote найдите файл boarddefs.h, далее найдите в файле блок кода:
              // MightyCore - ATmega164, ATmega324, ATmega644
              #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
              || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
              || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
              || defined(__AVR_ATmega164P__)
              #define IR_USE_TIMER1 // tx = pin 13
              //define IR_USE_TIMER2 // tx = pin 14

              обратите внимание на эти 2 строчки

              #define IR_USE_TIMER1 // tx = pin 13
              //define IR_USE_TIMER2 // tx = pin 14

              вторая строка должна быть закомментирована, а первая нет

  3. Собрал , прошил и получил цикличную смену лоудлесс-меню 2 . Все резисторы впаяны . Проблему решил так : выпаял один резистор на 10к от кнопки энкодера , в строке pinMode(A0,INPUT);// КНОПКА ЭНКОДЕРA изменил pinMode(A0,INPUT); на pinMode(A0,INPUT_PULLUP);
    Это решило проблеми с беребирание меню и кнопка работает .

Добавить комментарий

Войти с помощью: