ИМС TDA7439 – регулятор громкости и трехполосный регулятор тембра, разработан для использования в HI-FI аппаратуре и качественных автомобильных аудиосистемах, обладает низким уровнем шумов и искажений.
Основные технические характеристики ИМС TDA7439:
- Громкость 48 уровней от -48 до 0 дБ
- Регулировка тембра НЧ, СЧ, ВЧ ±14 дБ (±7 уровней)
- Коммутация входов — 4 стерео канала
- Усиление от 0 до 30 дБ независимое для каждого канала
- Регулировка баланса ±8 дБ (ограниченно программно)
- Напряжение питания от 6 до 10,2 В (типовое значение 9 В)
- КНИ на частоте 1 кГц не более 0,01%
Плата микроконтроллера и аудиопроцессор TDA7439 обмениваются данными на шине I2C по линиям SDA (data — данные) и SCL (clock — синхронизация).
В качестве органов управления регулятором громкости и тембра три используются кнопки, энкодер KY-040 и ИК-модуля VS1838B. Информация о настройках выводится на OLED дисплей с разрешением 128 на 64 точки, диагональ дисплея 1,3 дюйма, чип драйвера — SH1106 I2C. В проекте используется плата контроллера LGT8F328, но можно использовать Atduino Nano.
Меню управления регулятором громкости и тембра
Громкость
Тембр ВЧ
Тембр СЧ
Тембр НЧ
Баланс
Выбор входа и усиления
MUTE
STANDBY
Подачи питания регулятор громкости и тембра переходит в режим STANDBY, вывод D13 используется для управления режимом STANDBY УМЗЧ. В регулятор громкости и тембра так же предусмотрены цифровые выходы режима работы селектора входов, к ним при необходимости можно подключить светодиоды диоды (через резистор 200 Ом) для индикации активности входа, использовать как управляющий сигнал для подачи питания на источник звукового сигнала.
#define ENC_DT 8 #define ENC_CLK 9 #define ENC_SW 10 #define IR 12 #define MENU 0x33B820DF // button encoder #define UP 0x33B810EF // >>> #define DW 0x33B8E01F // <<< #define INPUT_IR 0x33B88877 // IN #define POWER_IR 0x33B800FF // POWER #define MUTE_IR 0x33B811FF // MUTE #define IN 2 #define POWER 6 #define POWER_OUT_PIN 13 #define MUTE 3 #define IN1_OUT A0 #define IN2_OUT A1 #define IN3_OUT A2 #define IN4_OUT A3 #include <Wire.h> #include <U8glib.h> // https://github.com/olikraus/u8glib/ #include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip #include <TDA7439.h> // http://rcl-radio.ru/wp-content/uploads/2019/01/TDA7439.zip #include <Encoder.h> // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip #include <EEPROM.h> #include <boarddefs.h> // входит в состав библиотеки IRremote #include <IRremote.h> // http://rcl-radio.ru/wp-content/uploads/2019/06/IRremote.zip TDA7439 tda; Encoder myEnc(ENC_DT, ENC_CLK); U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST); IRrecv irrecv(IR); decode_results ir; long oldPosition = -999,newPosition, times; int vol_reg,balans,treb_reg,bass_reg,mid_reg,in_reg,gain0,gain1,gain2,gain3,gain4,menu,vol_old; bool gr1,gr2,w=1,w1,www,power,power_off=1,mute; void setup() { Wire.begin();Serial.begin(9600); irrecv.enableIRIn(); pinMode(ENC_SW,INPUT); pinMode(IN,INPUT_PULLUP); pinMode(MUTE,INPUT_PULLUP); pinMode(POWER,INPUT_PULLUP); pinMode(POWER_OUT_PIN,OUTPUT); pinMode(IN1_OUT,OUTPUT); pinMode(IN2_OUT,OUTPUT); pinMode(IN3_OUT,OUTPUT); pinMode(IN4_OUT,OUTPUT); if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}// очистка памяти при первом включении MsTimer2::set(1, to_Timer);MsTimer2::start(); vol_reg = EEPROM.read(0);treb_reg = EEPROM.read(1)-7;mid_reg = EEPROM.read(2)-7;bass_reg = EEPROM.read(3)-7; in_reg = EEPROM.read(4);gain1 = EEPROM.read(5);gain2 = EEPROM.read(6);gain3 = EEPROM.read(7);gain4 = EEPROM.read(8);balans = EEPROM.read(9)-8; switch(in_reg){ case 1: gain0=gain1;break; case 2: gain0=gain2;break; case 3: gain0=gain3;break; case 4: gain0=gain4;break; } audio(); } void loop() { if(power==0){ if(in_reg==1){digitalWrite(IN1_OUT,HIGH);}else{digitalWrite(IN1_OUT,LOW);} if(in_reg==2){digitalWrite(IN2_OUT,HIGH);}else{digitalWrite(IN2_OUT,LOW);} if(in_reg==3){digitalWrite(IN3_OUT,HIGH);}else{digitalWrite(IN3_OUT,LOW);} if(in_reg==4){digitalWrite(IN4_OUT,HIGH);}else{digitalWrite(IN4_OUT,LOW);} } else{digitalWrite(IN1_OUT,LOW);digitalWrite(IN2_OUT,LOW);digitalWrite(IN3_OUT,LOW);digitalWrite(IN4_OUT,LOW);} // IR //////////////////////////////////////// if ( irrecv.decode( &ir )) {Serial.print("0x");Serial.println( ir.value,HEX);irrecv.resume();}// IR приемник - чтение, в мониторе порта отображаются коды кнопок if(ir.value==0){gr1=0;gr2=0;}// запрет нажатий не активных кнопок пульта // BUTTON /////////////////////////////////////////////////// if((digitalRead(POWER)==LOW||ir.value==POWER_IR||power_off==1)&&power==0&&mute==0){power_off=0;power=1;menu=100;cl();vol_old=vol_reg;vol_reg=0;audio(); u8g.firstPage();do {u8g.setFont(u8g_font_profont12r);u8g.drawStr(40,30,"POWER OFF");} while( u8g.nextPage() ); delay(1500); u8g.firstPage();do {} while( u8g.nextPage() );} if((digitalRead(POWER)==LOW||ir.value==POWER_IR)&&power==1){power=0;menu=0;vol_reg=vol_old;times=millis();w=1;w1=1; u8g.firstPage();do {u8g.drawStr(42,30,"POWER ON");} while( u8g.nextPage() );delay(1500);audio();} if(power==0){digitalWrite(POWER_OUT_PIN,HIGH);}else{digitalWrite(POWER_OUT_PIN,LOW);} if(power==0){ if(digitalRead(ENC_SW)==LOW||ir.value==MENU){menu++;cl();if(menu>4){menu=0;}times=millis();w=1;w1=1;delay(200);} if(digitalRead(IN)==LOW||ir.value==INPUT_IR){menu=10;cl();in_reg++;times=millis();w=1;w1=1;www=1;if(in_reg>4){in_reg=1;};delay(200);} if((digitalRead(MUTE)==LOW||ir.value==MUTE_IR)&&mute==0){mute=1;menu=100;cl();vol_old=vol_reg;vol_reg=0;audio(); u8g.firstPage();do {u8g.setFont(u8g_font_profont12r);u8g.drawStr(53,30,"MUTE");} while( u8g.nextPage() );} if((digitalRead(MUTE)==LOW||ir.value==MUTE_IR)&&mute==1){mute=0;times=millis();w=1;w1=1;menu=0;cl();vol_reg=vol_old;audio();} } //////// VOLUME ////////////////////////////////////////////////////////////////////////////////////////////////////////////// if(menu==0){ if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;} vol_reg=vol_reg+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;vol_func();audio();} if(ir.value==UP){vol_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;vol_func();audio();}// кнопка > if(ir.value==0xFFFFFFFF and gr1==1){vol_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;vol_func();audio();}// кнопка >>>>>> if(ir.value==DW){vol_reg--;gr1=0;gr2=1;cl();times=millis();w=1;w1=1;vol_func();audio();}// кнопка < if(ir.value==0xFFFFFFFF and gr2==1){vol_reg--;gr1=0;cl();times=millis();w=1;w1=1;vol_func();audio();}// кнопка <<<<<< if(w==1){w=0; u8g.firstPage(); do { u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"VOLUME");u8g.drawStr(0,18,"IN"); u8g.setPrintPos(20, 18);u8g.print(in_reg);u8g.drawStr(0,28,"GAIN");u8g.setPrintPos(30, 28);u8g.print(gain0); u8g.drawLine(0, 32, 128, 32); u8g.drawStr(0,44,"TREBLE");u8g.setPrintPos(80, 44);u8g.print(treb_reg*2);u8g.drawStr(95,44,"dB"); u8g.drawStr(0,54,"MIDDLE");u8g.setPrintPos(80, 54);u8g.print(mid_reg*2);u8g.drawStr(95,54,"dB"); u8g.drawStr(0,64,"BASS");u8g.setPrintPos(80, 64);u8g.print(bass_reg*2);u8g.drawStr(95,64,"dB"); u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 22);u8g.print(vol_reg); } while( u8g.nextPage() ); }} ///////////////////////////////////////////////////////////////// //////// TRABLE ////////////////////////////////////////////////////////////////////////////////////////////////////////////// if(menu==1){ if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;} treb_reg=treb_reg+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;treb_func();audio();} if(ir.value==UP){treb_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;treb_func();audio();}// кнопка > if(ir.value==0xFFFFFFFF and gr1==1){treb_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;treb_func();audio();}// кнопка >>>>>> if(ir.value==DW){treb_reg--;gr1=0;gr2=1;cl();times=millis();w=1;w1=1;treb_func();audio();}// кнопка < if(ir.value==0xFFFFFFFF and gr2==1){treb_reg--;gr1=0;cl();times=millis();w=1;w1=1;treb_func();audio();}// кнопка <<<<<< if(w==1){w=0; u8g.firstPage(); do { u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 22);u8g.print(treb_reg*2); u8g.drawLine(0, 32, 128, 32); u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"TREBLE");u8g.drawStr(0,44,"MIDDLE");u8g.setPrintPos(80, 44);u8g.print(mid_reg*2);u8g.drawStr(95,44,"dB"); u8g.drawStr(0,54,"BASS");u8g.setPrintPos(80, 54);u8g.print(bass_reg*2);u8g.drawStr(95,54,"dB"); u8g.drawStr(0,64,"BALANCE");u8g.setPrintPos(80, 64);u8g.print(balans);u8g.drawStr(95,64,"dB"); } while( u8g.nextPage() ); }} ///////////////////////////////////////////////////////////////// //////// MIDDLE ////////////////////////////////////////////////////////////////////////////////////////////////////////////// if(menu==2){ if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;} mid_reg=mid_reg+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;mid_func();audio();} if(ir.value==UP){mid_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;mid_func();audio();}// кнопка > if(ir.value==0xFFFFFFFF and gr1==1){mid_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;mid_func();audio();}// кнопка >>>>>> if(ir.value==DW){mid_reg--;gr1=0;gr2=1;cl();times=millis();w=1;w1=1;mid_func();audio();}// кнопка < if(ir.value==0xFFFFFFFF and gr2==1){mid_reg--;gr1=0;cl();times=millis();w=1;w1=1;mid_func();audio();}// кнопка <<<<<< if(w==1){w=0; u8g.firstPage(); do { u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 22);u8g.print(mid_reg*2); u8g.drawLine(0, 32, 128, 32); u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"MIDDLE");u8g.drawStr(0,44,"BASS");u8g.setPrintPos(80, 44);u8g.print(bass_reg*2);u8g.drawStr(95,44,"dB"); u8g.drawStr(0,54,"BALANCE");u8g.setPrintPos(80, 54);u8g.print(balans);u8g.drawStr(95,54,"dB"); u8g.drawStr(0,64,"VOLUME");u8g.setPrintPos(80, 64);u8g.print(vol_reg);u8g.drawStr(95,64,"dB"); } while( u8g.nextPage() ); }} ///////////////////////////////////////////////////////////////// //////// BASS ////////////////////////////////////////////////////////////////////////////////////////////////////////////// if(menu==3){ if(newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;} bass_reg=bass_reg+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;bass_func();audio();} if(ir.value==UP){bass_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;bass_func();audio();}// кнопка > if(ir.value==0xFFFFFFFF and gr1==1){bass_reg++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;bass_func();audio();}// кнопка >>>>>> if(ir.value==DW){bass_reg--;gr1=0;gr2=1;cl();times=millis();w=1;w1=1;bass_func();audio();}// кнопка < if(ir.value==0xFFFFFFFF and gr2==1){bass_reg--;gr1=0;cl();times=millis();w=1;w1=1;bass_func();audio();}// кнопка <<<<<< if(w==1){w=0; u8g.firstPage(); do { u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 22);u8g.print(bass_reg*2); u8g.drawLine(0, 32, 128, 32); u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"BASS"); u8g.drawStr(0,44,"BALANCE");u8g.setPrintPos(80, 44);u8g.print(balans);u8g.drawStr(95,44,"dB"); u8g.drawStr(0,54,"VOLUME");u8g.setPrintPos(80, 54);u8g.print(vol_reg);u8g.drawStr(95,54,"dB"); u8g.drawStr(0,64,"TREBLE");u8g.setPrintPos(80, 64);u8g.print(treb_reg*2);u8g.drawStr(95,64,"dB"); } while( u8g.nextPage() ); }} ///////////////////////////////////////////////////////////////// //////// BALANCE ////////////////////////////////////////////////////////////////////////////////////////////////////////////// if(menu==4){ if (newPosition != oldPosition){oldPosition = newPosition;balans=balans+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;ball_func();audio();} if(ir.value==UP){balans++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;ball_func();audio();}// кнопка > if(ir.value==0xFFFFFFFF and gr1==1){balans++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;ball_func();audio();}// кнопка >>>>>> if(ir.value==DW){balans--;gr1=0;gr2=1;cl();times=millis();w=1;w1=1;ball_func();audio();}// кнопка < if(ir.value==0xFFFFFFFF and gr2==1){balans--;gr1=0;cl();times=millis();w=1;w1=1;ball_func();audio();}// кнопка <<<<<< if(w==1){w=0; u8g.firstPage(); do { u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"BALANCE");u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 22);u8g.print(abs(balans)); u8g.setFont(u8g_font_profont12r); if(balans<=0){u8g.drawStr(50,20,"LCH");} if(balans>=0){u8g.drawStr(105,20,"RCH");} u8g.drawLine(0, 32, 128, 32); u8g.drawStr(0,44,"VOLUME");u8g.setPrintPos(80, 44);u8g.print(vol_reg);u8g.drawStr(95,44,"dB"); u8g.drawStr(0,54,"TREBLE");u8g.setPrintPos(80, 54);u8g.print(mid_reg*2);u8g.drawStr(95,54,"dB"); u8g.drawStr(0,64,"MIDDLE");u8g.setPrintPos(80, 64);u8g.print(treb_reg*2);u8g.drawStr(95,64,"dB"); } while( u8g.nextPage() ); }} ////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////// INPUT GAIN /////////////////////////////////////////////////////////////////// if(menu==10){ switch(in_reg){ case 1: gain0=gain1;break; case 2: gain0=gain2;break; case 3: gain0=gain3;break; case 4: gain0=gain4;break; } if (newPosition != oldPosition){oldPosition = newPosition;if(newPosition>1){newPosition=1;}if(newPosition<-1){newPosition=-1;} gain0=gain0+newPosition;myEnc.write(0);newPosition=0;times=millis();w=1;w1=1;www=1;gain_func();} if(ir.value==UP){gain0++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;gain_func();www=1;}// кнопка > if(ir.value==0xFFFFFFFF and gr1==1){gain0++;gr1=1;gr2=0;cl();times=millis();w=1;w1=1;gain_func();www=1;}// кнопка >>>>>> if(ir.value==DW){gain0--;gr1=0;gr2=1;cl();times=millis();w=1;w1=1;gain_func();www=1;}// кнопка < if(ir.value==0xFFFFFFFF and gr2==1){gain0--;gr1=0;cl();times=millis();w=1;w1=1;gain_func();www=1;}// кнопка <<<<<< switch(in_reg){ case 1: gain1=gain0;break; case 2: gain2=gain0;break; case 3: gain3=gain0;break; case 4: gain4=gain0;break; } if(www==1){audio();www=0;} if(w==1){w=0; u8g.firstPage(); do { u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 22);u8g.print(in_reg); u8g.drawLine(0, 32, 128, 32); u8g.setFont(u8g_font_profont12r);u8g.drawStr(0,8,"INPUT");u8g.drawStr(0,44,"GAIN"); u8g.setFont(u8g_font_profont29r); u8g.setPrintPos(78, 60);u8g.print(gain0); } while( u8g.nextPage() ); }} if(millis()-times>5000 && w1==1 && power==0 && mute==0){ EEPROM.update(0,vol_reg);EEPROM.update(1,treb_reg+7);EEPROM.update(2,mid_reg+7);EEPROM.update(3,bass_reg+7); EEPROM.update(4,in_reg);EEPROM.update(5,gain1);EEPROM.update(6,gain2);EEPROM.update(7,gain3);EEPROM.update(8,gain4);EEPROM.update(9,balans+8); menu=0;w1=0;w=1;myEnc.write(0);} } void to_Timer(){newPosition = myEnc.read()/4;} void cl(){ir.value=0;delay(200);} void vol_func(){if(vol_reg<0){vol_reg=0;}if(vol_reg>48){vol_reg=48;}} void treb_func(){if(treb_reg<-7){treb_reg=-7;}if(treb_reg>7){treb_reg=7;}} void mid_func(){if(mid_reg<-7){mid_reg=-7;}if(mid_reg>7){mid_reg=7;}} void bass_func(){if(bass_reg<-7){bass_reg=-7;}if(bass_reg>7){bass_reg=7;}} void gain_func(){if(gain0>15){gain0=15;}if(gain0<0){gain0=0;}} void ball_func(){if(balans>8){balans=8;}if(balans<-8){balans=-8;}} void audio(){ tda.setInput(in_reg); // 1 to 4 // номер канала tda.inputGain(gain0); // 0 to 15 // усиление tda.setVolume(vol_reg); // 0 to 48 ( 0 is mute) // громкость tda.setSnd(bass_reg, 1); //-7 to +7 , 1 - Bass | 2 - Mids | 3 - Trebble tda.setSnd(mid_reg, 2); tda.setSnd(treb_reg, 3); tda.spkAtt(8 + balans ,8 - balans); // баланс R L от 0 to 79 (db) }
ИК пульт дублирует работу энкодера и кнопок. Для управления регулятором подойдет практически любой пульт ИК, для поддержки Вашего пульта необходимо прописать коды кнопок в скетч:
#define MENU 0x33B820DF // button encoder #define UP 0x33B810EF // >>> #define DW 0x33B8E01F // <<< #define INPUT_IR 0x33B88877 // IN #define POWER_IR 0x33B800FF // POWER #define MUTE_IR 0x33B811FF // MUTE
Для получения кодов кнопок Вашего пульта загрузите скетч и откройте монитор порта, при нажатии кнопки пульта его код будет отображен в мониторе порта.
Все очень здорово получилось слушаю и наслаждаюсь.
Автору большой «РЕСПЕКТ» и простое человеческое СПАСИБО.
Удачи.
P.S. Нa входах TDA7439 ставте пленку 0,47мкФ, электоролиты немного хуже, осциллограф показывает.
Здравствуйте, поставил ваш скетч, и экран начинает сам переключаться без энкодера.
Подскажите пожалуйста в чем проблема?
Нет энкодера
Он подключен.
Hw-040.
На плате энкодера должно быть 3 подтягивающих резистора к +5В по 10 кОм
Сзади энкодера распаяны только 2 резиста по 10ком , но в других проектах, он работал
У Вас скорее всего нет резистора на выходе SW, его надо установить или подключить внутренний программно.
pinMode(ENC_SW,INPUT_PULLUP);
Заработало, спасибо
Как по схеме вашей.
так резисторы на плате энкодера есть?
Здравствуйте,собрал все, но при подключении совместно с экраном, ничего не работает, пробовал 2 тдахи и сканером они тоже не определятся, на форуме в переделках написал подробнее (Arduino+tda+анализатор спектра)
sir, I am arduino Nano code upload time arduino IDE verify and uploading time so let, but code upload latter rotary encoder not work, but remote is work and TDA7439 circuit board to sound not output, please solve the problem?